# How Egonex Language Auto‑Detection Works: First Run vs. Subsequent Runs

> Discover how Egonex language auto-detection works, comparing the initial scan to subsequent runs. Learn how it builds and utilizes a language registry for faster results.

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

---

**TLDR:** Egonex uses a two-stage detection system where the first run builds a language registry from file extensions and special filenames, caches the results in a knowledge graph, and subsequent runs reuse that persisted data to skip redundant lookups.

Egonex's language auto‑detection system in the Understand-Anything repository optimizes performance by distinguishing between initial project scans and follow-up analyses. The architecture centers on the `LanguageRegistry` class in [`packages/core/src/languages/language-registry.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/languages/language-registry.ts), which maps file paths to language configurations during the first run, while the persistence layer ensures subsequent executions avoid repeating this expensive work.

## First Run: Building the Language Registry

During the initial scan of a fresh project, Egonex constructs a comprehensive mapping of file paths to language identifiers using only filename and extension heuristics.

### Registry Initialization

The process begins by instantiating a default registry that loads every built‑in language configuration. According to the source code in [`packages/core/src/languages/language-registry.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/languages/language-registry.ts), the following call creates this registry:

```typescript
const registry = LanguageRegistry.createDefault();   // registers all builtin configs

```

The `createDefault` method populates the registry using the `builtinLanguageConfigs` array sourced from `packages/core/src/languages/configs/*`. Each configuration defines valid extensions, special filenames, and optional detection keywords.

### File‑to‑Language Mapping Logic

For each file encountered by the scanner, Egonex queries the registry to determine the appropriate language. The [`graph-builder.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/graph-builder.ts) implementation invokes:

```typescript
const lang = registry.getForFile(filePath);

```

The `getForFile` method performs a two‑stage lookup:

1. **Filename‑based match** – Checks for special filenames like `Dockerfile`, `Makefile`, or `Jenkinsfile`.
2. **Extension‑based match** – Falls back to file extensions such as `.ts`, `.py`, or `.json`.

This lookup is case‑insensitive and normalizes extensions so that `.ts` and `ts` are treated identically. The following utility function demonstrates the first‑run detection logic:

```typescript
import { LanguageRegistry } from "./languages/language-registry.js";

const registry = LanguageRegistry.createDefault();  // loads built‑ins

function detectLanguage(filePath: string): string | null {
  const config = registry.getForFile(filePath);
  return config?.id ?? null;
}

```

### Graph Population and Persistence

Once detected, the language ID is attached to the file node within the knowledge graph. The [`packages/core/src/analyzer/graph-builder.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/analyzer/graph-builder.ts) implementation stores this metadata:

```typescript
graph.addNode({
  type: "File",
  path: filePath,
  language: detectLanguage(filePath),
});

```

The complete graph is then persisted to [`.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json) via the persistence layer in [`packages/core/src/persistence/index.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/persistence/index.ts). This ensures that the language auto‑detection results survive between process executions.

## Subsequent Runs: Leveraging the Cached Knowledge Graph

When analyzing a project that has been scanned previously, Egonex bypasses the extension‑lookup entirely by loading the persisted state.

### Loading Persisted State

The scanner first checks for existing cached data using `loadKnowledgeGraphIfExists()` from [`packages/core/src/persistence/index.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/persistence/index.ts):

```typescript
const persisted = await loadKnowledgeGraphIfExists();   // from persistence/index.ts

```

If the knowledge graph exists, the language information is **reused directly**; the scanner does not repeat the `registry.getForFile` lookup for every file. This design makes subsequent runs substantially faster, as the language IDs are already attached to each file node.

### Incremental Analysis

The implementation typically loads the graph as follows:

```typescript
import { loadGraph } from "./persistence/index.js";

async function runScanner() {
  const graph = await loadGraph();            // reads .understand-anything/knowledge-graph.json
  if (graph) {
    // Language info already present, skip re‑detecting:
    console.log("Using cached language data for", graph.nodeCount, "files");
  } else {
    // Fallback to first‑run logic
    const registry = LanguageRegistry.createDefault();
    // ... perform full scan
  }
}

```

Only new or changed files trigger fresh detection calls, while existing files retain their previously determined language identifiers.

## Content‑Based Detection Hooks

While the current implementation relies solely on filename and extension matching, the architecture includes hooks for future content‑based refinement. The `LanguageConfig` type defined in [`packages/core/src/languages/types.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/languages/types.ts) includes an optional `detectionKeywords` array:

```typescript
interface LanguageConfig {
  id: string;
  extensions: string[];
  filenames?: string[];
  detectionKeywords?: string[];  // Hook for content analysis
}

```

This allows for a potential second‑pass detection that could scan file contents for specific keywords. Such analysis would only occur during the first run (or when adding new language configurations), as the results would be cached for subsequent runs.

## Summary

- **First run**: `LanguageRegistry.createDefault()` initializes built‑in configs, then `registry.getForFile()` matches files by filename or extension, storing results in the knowledge graph.
- **Subsequent runs**: `loadKnowledgeGraphIfExists()` retrieves cached language IDs from [`.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json), eliminating redundant lookups.
- **Performance**: The two‑stage design ensures heavy file‑system analysis only happens once, with subsequent runs reading from the persisted JSON cache.
- **Extensibility**: The `detectionKeywords` field in `LanguageConfig` provides a hook for future content‑based detection without breaking the caching mechanism.

## Frequently Asked Questions

### How does Egonex detect languages on the first scan?

On the first run, Egonex creates a `LanguageRegistry` instance via `createDefault()` and calls `getForFile(filePath)` for each discovered file. This method first checks for special filenames (like `Dockerfile` or `Makefile`), then falls back to extension matching (such as `.ts` or `.py`). The detection is case‑insensitive and stores the resulting language ID in the knowledge graph.

### Where does Egonex store language information between runs?

Language metadata is stored in the knowledge graph file located at [`.understand-anything/knowledge-graph.json`](https://github.com/Egonex-AI/Understand-Anything/blob/main/.understand-anything/knowledge-graph.json). The persistence layer in [`packages/core/src/persistence/index.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/persistence/index.ts) handles serialization and deserialization, allowing the `loadGraph()` function to retrieve cached language data on subsequent executions.

### Does Egonex analyze file content to determine language?

Currently, no. The implementation in [`packages/core/src/languages/language-registry.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/languages/language-registry.ts) uses only filename and extension heuristics. However, the `LanguageConfig` interface in [`packages/core/src/languages/types.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/core/src/languages/types.ts) includes a `detectionKeywords` array that provides a hook for future content‑based detection, which would run during the first scan and be cached for later runs.

### What happens if I add a new file type to my project?

When new files are added, the scanner detects them as changed entities during subsequent runs. While the cached graph provides language data for existing files, the system performs fresh `registry.getForFile()` lookups only for new or modified files, then updates the persisted knowledge graph to include the new language mappings.