# How the Understand-Anything Plugin Resolves Its Project Root Across Installation Methods

> Discover how the Understand Anything plugin resolves its project root across diverse installation methods. Learn its efficient approach to locating the knowledge-graph.json file.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-06-23

---

**The plugin locates the [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json) file using environment-specific candidate paths and derives the absolute project root by stripping the last two directory components from the discovered graph file's location.**

The Egonex-AI/Understand-Anything dashboard plugin must reliably identify where a knowledge graph's source project lives, whether running from source, via CLI, or as an installed dependency. This root path resolution logic, implemented in [`packages/dashboard/vite.config.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/vite.config.ts), ensures the plugin serves files relative to the correct project directory without exposing absolute filesystem paths to the client.

## The Three-Step Root Resolution Strategy

The resolution logic operates in three distinct phases to handle varying execution contexts, from local development to packaged npm installations.

### Step 1: Locating the Graph File via Candidate Paths

The `graphFileCandidates` function generates a prioritized list of possible locations for the graph artifacts. It checks three specific paths to accommodate different installation methods:

```typescript
function graphFileCandidates(fileName: string): string[] {
  const graphDir = process.env.GRAPH_DIR;
  return [
    ...(graphDir ? [path.resolve(graphDir, `.understand-anything/${fileName}`)] : []),
    path.resolve(process.cwd(), `.understand-anything/${fileName}`),
    path.resolve(process.cwd(), `../../../.understand-anything/${fileName}`),
  ];
}

```

The first candidate respects a user-supplied `GRAPH_DIR` environment variable, common when the plugin is run from a CLI. The second candidate works when the plugin runs from the repository root in default dev mode. The third candidate handles the case where the plugin is installed as an npm package inside another project, where `process.cwd()` points to the package's `node_modules` folder.

### Step 2: Deriving the Root from the Graph Location

Once a candidate file exists, the `projectRootFromGraphFile` function computes the project root by stripping the last two path components. Since the graph file lives at [`PROJECT_ROOT/.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/PROJECT_ROOT/.understand-anything/knowledge-graph.json), removing the `.understand-anything` directory and the filename yields the original project root:

```typescript
function projectRootFromGraphFile(candidate: string): string {
  return path.dirname(path.dirname(candidate));
}

```

This approach is robust because the graph file's location is deterministic relative to the project root, regardless of where the plugin code itself resides.

### Step 3: Applying the Root When Serving Files

Functions that read source files, such as `readSourceFile`, call `projectRootFromGraphFile` to establish the base directory. They resolve requested paths against this computed root to guarantee that only files inside the original project are served:

```typescript
const projectRoot = projectRootFromGraphFile(graphFile);
const absoluteFile = path.resolve(projectRoot, normalizedPath);

```

This validation prevents directory traversal attacks by ensuring `absoluteFile` always resides within `projectRoot`.

## Handling Different Installation Methods

The candidate path strategy specifically addresses three distinct execution scenarios.

### Local Development Mode

When running `pnpm dev:dashboard` from the repository root, `process.cwd()` points directly to the project directory. The second candidate path resolves to [`PROJECT_ROOT/.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/PROJECT_ROOT/.understand-anything/knowledge-graph.json), allowing immediate development without configuration.

### CLI Execution with GRAPH_DIR

When invoked via a CLI tool with an explicit `--graph-dir` flag or `GRAPH_DIR` environment variable, the first candidate path takes precedence. This allows the plugin to locate graphs stored in arbitrary directories outside the current working directory.

### Installed as an npm Package Dependency

When consumed as a dependency (e.g., `understand-anything` inside another project's `node_modules`), `process.cwd()` points to the plugin's package directory. The third candidate climbs two levels up (`../../../`) to reach the host project's root, where the `.understand-anything` directory actually resides.

## Implementation Example

Here is the complete resolution flow when serving a file request:

```typescript
import path from "path";

// Locate the graph file using the candidate strategy
const graphFile = graphFileCandidates("knowledge-graph.json")
  .find(candidate => fs.existsSync(candidate));

if (!graphFile) {
  throw new Error("Could not locate knowledge graph");
}

// Derive the project root
const projectRoot = projectRootFromGraphFile(graphFile);
// e.g., "/home/user/my-app" from "/home/user/my-app/.understand-anything/knowledge-graph.json"

// Resolve the requested file against the root
const safePath = path.normalize(req.query.path as string);
const absolutePath = path.resolve(projectRoot, safePath);

// Verify the file is within the project root
if (!absolutePath.startsWith(projectRoot)) {
  throw new Error("Access denied: path outside project root");
}

```

## Summary

- The `graphFileCandidates` function in [`packages/dashboard/vite.config.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/vite.config.ts) (lines 15-23) checks three possible locations for [`knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/knowledge-graph.json) to handle different installation contexts.
- The `GRAPH_DIR` environment variable takes precedence for CLI usage, enabling explicit graph location specification.
- When installed as a dependency, the plugin automatically climbs two directory levels up from `node_modules` to reach the host project root.
- `projectRootFromGraphFile` (lines 30-32) derives the root by stripping the `.understand-anything` directory and filename from the graph file path.
- All file serving operations resolve paths against this computed root to prevent directory traversal and ensure security.

## Frequently Asked Questions

### How does the plugin find the project root when installed via npm?

When installed as an npm dependency, the plugin assumes `process.cwd()` points to its location inside `node_modules`. It searches three levels up (`../../../.understand-anything/`) to locate the graph file in the host project's root directory, then derives the root by stripping the last two path components from that location.

### What happens if the GRAPH_DIR environment variable is set?

If `GRAPH_DIR` is defined, the `graphFileCandidates` function uses it as the first and highest-priority search location. The plugin resolves the path [`GRAPH_DIR/.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/GRAPH_DIR/.understand-anything/knowledge-graph.json) before checking the standard `process.cwd()` locations, allowing users to specify arbitrary graph locations via CLI.

### Why does the plugin look three levels up from node_modules?

The path `../../../` accounts for the typical npm package structure: `node_modules/package-name/current-working-directory`. Climbing two levels reaches the `node_modules` folder itself, and the third level reaches the actual host project root where the `.understand-anything` directory is stored.

### How does the plugin prevent serving files outside the project directory?

After computing the `projectRoot` from the graph file location, the plugin uses `path.resolve(projectRoot, requestedPath)` to create absolute paths. It validates that the resolved path starts with the `projectRoot` string, rejecting any requests that resolve to parent directories or absolute paths outside the project scope.