Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,28 @@ JS source is plain JavaScript (ES modules) in `src/`. No transpilation step. The
|------|------|
| `cli.js` | Commander CLI entry point (`bin.codegraph`) |
| `index.js` | Programmatic API exports |
| `parser.js` | tree-sitter WASM wrapper; `LANGUAGE_REGISTRY` + per-language extractors for functions, classes, methods, imports, exports, call sites |
| `config.js` | `.codegraphrc.json` loading, env overrides, `apiKeyCommand` secret resolution |
| `constants.js` | `EXTENSIONS` (derived from parser registry) and `IGNORE_DIRS` constants |
| `native.js` | Native napi-rs addon loader with WASM fallback |
| `registry.js` | Global repo registry (`~/.codegraph/registry.json`) for multi-repo MCP |
| `paginate.js` | Pagination helpers for bounded query results |
| `logger.js` | Structured logging (`warn`, `debug`, `info`, `error`) |
| **`shared/`** | **Cross-cutting constants and utilities** |
| `shared/constants.js` | `EXTENSIONS` (derived from parser registry) and `IGNORE_DIRS` constants |
| `shared/errors.js` | Domain error hierarchy (`CodegraphError`, `ConfigError`, `ParseError`, etc.) |
| `shared/kinds.js` | Symbol and edge kind constants (`CORE_SYMBOL_KINDS`, `EVERY_SYMBOL_KIND`, `VALID_ROLES`) |
| `shared/paginate.js` | Pagination helpers for bounded query results |
| **`infrastructure/`** | **Platform and I/O plumbing** |
| `infrastructure/config.js` | `.codegraphrc.json` loading, env overrides, `apiKeyCommand` secret resolution |
| `infrastructure/logger.js` | Structured logging (`warn`, `debug`, `info`, `error`) |
| `infrastructure/native.js` | Native napi-rs addon loader with WASM fallback |
| `infrastructure/registry.js` | Global repo registry (`~/.codegraph/registry.json`) for multi-repo MCP |
| `infrastructure/update-check.js` | npm update availability check |
| **`db/`** | **Database layer** |
| `db/index.js` | SQLite schema and operations (`better-sqlite3`) |
| **`domain/`** | **Core domain logic** |
| `domain/queries.js` | Query functions: symbol search, file deps, impact analysis, diff-impact; `SYMBOL_KINDS` constant defines all node kinds |
| `domain/parser.js` | tree-sitter WASM wrapper; `LANGUAGE_REGISTRY` + per-language extractors for functions, classes, methods, imports, exports, call sites |
| `domain/queries.js` | Query functions: symbol search, file deps, impact analysis, diff-impact |
| `domain/graph/builder.js` | Graph building: file collection, parsing, import resolution, incremental hashing |
| `domain/graph/cycles.js` | Circular dependency detection (delegates to `graph/` subsystem) |
| `domain/graph/resolve.js` | Import resolution (supports native batch mode) |
| `domain/graph/watcher.js` | Watch mode for incremental rebuilds |
| `domain/graph/journal.js` | Change journal for incremental builds |
| `domain/graph/change-journal.js` | Change event tracking (NDJSON) |
| `domain/analysis/` | Query-layer analysis: context, dependencies, exports, impact, module-map, roles, symbol-lookup |
| `domain/search/` | Embedding subsystem: model management, vector generation, semantic/keyword/hybrid search, CLI formatting |
| **`features/`** | **Composable feature modules** |
Expand Down Expand Up @@ -87,7 +94,7 @@ JS source is plain JavaScript (ES modules) in `src/`. No transpilation step. The
- **Dual-engine architecture:** Native Rust parsing via napi-rs (`crates/codegraph-core/`) with automatic fallback to WASM. Controlled by `--engine native|wasm|auto` (default: `auto`)
- Platform-specific prebuilt binaries published as optional npm packages (`@optave/codegraph-{platform}-{arch}`)
- WASM grammars are built from devDeps on `npm install` (via `prepare` script) and not committed to git — used as fallback when native addon is unavailable
- **Language parser registry:** `LANGUAGE_REGISTRY` in `parser.js` is the single source of truth for all supported languages — maps each language to `{ id, extensions, grammarFile, extractor, required }`. `EXTENSIONS` in `constants.js` is derived from the registry. Adding a new language requires one registry entry + extractor function
- **Language parser registry:** `LANGUAGE_REGISTRY` in `domain/parser.js` is the single source of truth for all supported languages — maps each language to `{ id, extensions, grammarFile, extractor, required }`. `EXTENSIONS` in `shared/constants.js` is derived from the registry. Adding a new language requires one registry entry + extractor function
- **Node kinds:** `SYMBOL_KINDS` in `domain/queries.js` lists all valid kinds: `function`, `method`, `class`, `interface`, `type`, `struct`, `enum`, `trait`, `record`, `module`. Language-specific types use their native kind (e.g. Go structs → `struct`, Rust traits → `trait`, Ruby modules → `module`) rather than mapping everything to `class`/`interface`
- `@huggingface/transformers` and `@modelcontextprotocol/sdk` are optional dependencies, lazy-loaded
- Non-required parsers (all except JS/TS/TSX) fail gracefully if their WASM grammar is unavailable
Expand Down
4 changes: 2 additions & 2 deletions src/ast-analysis/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { bulkNodeIdsByFile } from '../db/index.js';
import { debug } from '../logger.js';
import { debug } from '../infrastructure/logger.js';
import { computeLOCMetrics, computeMaintainabilityIndex } from './metrics.js';
import {
AST_TYPE_MAPS,
Expand All @@ -45,7 +45,7 @@ const WALK_EXTENSIONS = buildExtensionSet(AST_TYPE_MAPS);

let _parserModule = null;
async function getParserModule() {
if (!_parserModule) _parserModule = await import('../parser.js');
if (!_parserModule) _parserModule = await import('../domain/parser.js');
return _parserModule;
}

Expand Down
4 changes: 2 additions & 2 deletions src/ast-analysis/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Shared utilities for AST analysis modules (complexity, CFG, dataflow, AST nodes).
*/

import { ConfigError } from '../errors.js';
import { LANGUAGE_REGISTRY } from '../parser.js';
import { LANGUAGE_REGISTRY } from '../domain/parser.js';
import { ConfigError } from '../shared/errors.js';

// ─── Generic Rule Factory ─────────────────────────────────────────────────

Expand Down
2 changes: 1 addition & 1 deletion src/cli.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

import { run } from './cli/index.js';
import { CodegraphError } from './errors.js';
import { CodegraphError } from './shared/errors.js';

run().catch((err) => {
if (err instanceof CodegraphError) {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/ast.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConfigError } from '../../errors.js';
import { ConfigError } from '../../shared/errors.js';

export const command = {
name: 'ast [pattern]',
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/batch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import fs from 'node:fs';
import { batch } from '../../commands/batch.js';
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
import { ConfigError } from '../../errors.js';
import { BATCH_COMMANDS, multiBatchData, splitTargets } from '../../features/batch.js';
import { ConfigError } from '../../shared/errors.js';

export const command = {
name: 'batch <command> [targets...]',
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/check.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EVERY_SYMBOL_KIND } from '../../domain/queries.js';
import { ConfigError } from '../../errors.js';
import { ConfigError } from '../../shared/errors.js';

export const command = {
name: 'check [ref]',
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/co-change.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnalysisError } from '../../errors.js';
import { AnalysisError } from '../../shared/errors.js';

export const command = {
name: 'co-change [file]',
Expand Down
4 changes: 2 additions & 2 deletions src/cli/commands/info.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ export const command = {
description: 'Show codegraph engine info and diagnostics',
async execute(_args, _opts, ctx) {
const { getNativePackageVersion, isNativeAvailable, loadNative } = await import(
'../../native.js'
'../../infrastructure/native.js'
);
const { getActiveEngine } = await import('../../parser.js');
const { getActiveEngine } = await import('../../domain/parser.js');

const engine = ctx.program.opts().engine;
const { name: activeName, version: activeVersion } = getActiveEngine({ engine });
Expand Down
4 changes: 2 additions & 2 deletions src/cli/commands/registry.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import fs from 'node:fs';
import path from 'node:path';
import { ConfigError } from '../../errors.js';
import {
listRepos,
pruneRegistry,
REGISTRY_PATH,
registerRepo,
unregisterRepo,
} from '../../registry.js';
} from '../../infrastructure/registry.js';
import { ConfigError } from '../../shared/errors.js';

export const command = {
name: 'registry',
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/triage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EVERY_SYMBOL_KIND, VALID_ROLES } from '../../domain/queries.js';
import { ConfigError } from '../../errors.js';
import { ConfigError } from '../../shared/errors.js';

export const command = {
name: 'triage',
Expand Down
6 changes: 3 additions & 3 deletions src/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import fs from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import { Command } from 'commander';
import { ConfigError } from '../errors.js';
import { setVerbose } from '../logger.js';
import { checkForUpdates, printUpdateNotification } from '../update-check.js';
import { setVerbose } from '../infrastructure/logger.js';
import { checkForUpdates, printUpdateNotification } from '../infrastructure/update-check.js';
import { ConfigError } from '../shared/errors.js';
import { applyQueryOpts, config, formatSize, resolveNoTests } from './shared/options.js';
import { outputResult } from './shared/output.js';

Expand Down
2 changes: 1 addition & 1 deletion src/cli/shared/options.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { loadConfig } from '../../config.js';
import { loadConfig } from '../../infrastructure/config.js';

const config = loadConfig(process.cwd());

Expand Down
2 changes: 1 addition & 1 deletion src/commands/check.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnalysisError } from '../errors.js';
import { checkData } from '../features/check.js';
import { outputResult } from '../infrastructure/result-formatter.js';
import { AnalysisError } from '../shared/errors.js';

/**
* CLI formatter — prints check results and sets exitCode 1 on failure.
Expand Down
4 changes: 2 additions & 2 deletions src/db/connection.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import fs from 'node:fs';
import path from 'node:path';
import Database from 'better-sqlite3';
import { DbError } from '../errors.js';
import { warn } from '../logger.js';
import { warn } from '../infrastructure/logger.js';
import { DbError } from '../shared/errors.js';

function isProcessAlive(pid) {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/db/migrations.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { debug } from '../logger.js';
import { debug } from '../infrastructure/logger.js';

// ─── Schema Migrations ─────────────────────────────────────────────────
export const MIGRATIONS = [
Expand Down
4 changes: 2 additions & 2 deletions src/db/query-builder.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DbError } from '../errors.js';
import { EVERY_EDGE_KIND } from '../kinds.js';
import { DbError } from '../shared/errors.js';
import { EVERY_EDGE_KIND } from '../shared/kinds.js';

// ─── Validation Helpers ─────────────────────────────────────────────

Expand Down
2 changes: 1 addition & 1 deletion src/db/repository/graph-read.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CORE_SYMBOL_KINDS } from '../../kinds.js';
import { CORE_SYMBOL_KINDS } from '../../shared/kinds.js';
import { cachedStmt } from './cached-stmt.js';

// ─── Statement caches (one prepared statement per db instance) ────────────
Expand Down
4 changes: 2 additions & 2 deletions src/db/repository/in-memory-repository.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConfigError } from '../../errors.js';
import { CORE_SYMBOL_KINDS, EVERY_SYMBOL_KIND, VALID_ROLES } from '../../kinds.js';
import { ConfigError } from '../../shared/errors.js';
import { CORE_SYMBOL_KINDS, EVERY_SYMBOL_KIND, VALID_ROLES } from '../../shared/kinds.js';
import { escapeLike } from '../query-builder.js';
import { Repository } from './base.js';

Expand Down
4 changes: 2 additions & 2 deletions src/db/repository/nodes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConfigError } from '../../errors.js';
import { EVERY_SYMBOL_KIND, VALID_ROLES } from '../../kinds.js';
import { ConfigError } from '../../shared/errors.js';
import { EVERY_SYMBOL_KIND, VALID_ROLES } from '../../shared/kinds.js';
import { escapeLike, NodeQuery } from '../query-builder.js';
import { cachedStmt } from './cached-stmt.js';

Expand Down
2 changes: 1 addition & 1 deletion src/domain/analysis/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
openReadonlyOrFail,
} from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { paginateResult } from '../../paginate.js';
import {
createFileLinesReader,
extractSignature,
Expand All @@ -24,6 +23,7 @@ import {
} from '../../shared/file-utils.js';
import { resolveMethodViaHierarchy } from '../../shared/hierarchy.js';
import { normalizeSymbol } from '../../shared/normalize.js';
import { paginateResult } from '../../shared/paginate.js';
import { findMatchingNodes } from './symbol-lookup.js';

function explainFileImpl(db, target, getFileLines) {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/analysis/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
openReadonlyOrFail,
} from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { paginateResult } from '../../paginate.js';
import { resolveMethodViaHierarchy } from '../../shared/hierarchy.js';
import { normalizeSymbol } from '../../shared/normalize.js';
import { paginateResult } from '../../shared/paginate.js';
import { findMatchingNodes } from './symbol-lookup.js';

export function fileDepsData(file, customDbPath, opts = {}) {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/analysis/exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import {
openReadonlyOrFail,
} from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { paginateResult } from '../../paginate.js';
import {
createFileLinesReader,
extractSignature,
extractSummary,
} from '../../shared/file-utils.js';
import { paginateResult } from '../../shared/paginate.js';

export function exportsData(file, customDbPath, opts = {}) {
const db = openReadonlyOrFail(customDbPath);
Expand Down
4 changes: 2 additions & 2 deletions src/domain/analysis/impact.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { loadConfig } from '../../config.js';
import {
findDbPath,
findDistinctCallers,
Expand All @@ -13,9 +12,10 @@ import {
import { evaluateBoundaries } from '../../features/boundaries.js';
import { coChangeForFiles } from '../../features/cochange.js';
import { ownersForFiles } from '../../features/owners.js';
import { loadConfig } from '../../infrastructure/config.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { paginateResult } from '../../paginate.js';
import { normalizeSymbol } from '../../shared/normalize.js';
import { paginateResult } from '../../shared/paginate.js';
import { findMatchingNodes } from './symbol-lookup.js';

export function impactAnalysisData(file, customDbPath, opts = {}) {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/analysis/module-map.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path from 'node:path';
import { openReadonlyOrFail, testFilterSQL } from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { LANGUAGE_REGISTRY } from '../../parser.js';
import { findCycles } from '../graph/cycles.js';
import { LANGUAGE_REGISTRY } from '../parser.js';

export const FALSE_POSITIVE_NAMES = new Set([
'run',
Expand Down
2 changes: 1 addition & 1 deletion src/domain/analysis/roles.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { openReadonlyOrFail } from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { paginateResult } from '../../paginate.js';
import { normalizeSymbol } from '../../shared/normalize.js';
import { paginateResult } from '../../shared/paginate.js';

export function rolesData(customDbPath, opts = {}) {
const db = openReadonlyOrFail(customDbPath);
Expand Down
4 changes: 2 additions & 2 deletions src/domain/analysis/symbol-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
openReadonlyOrFail,
} from '../../db/index.js';
import { isTestFile } from '../../infrastructure/test-filter.js';
import { ALL_SYMBOL_KINDS } from '../../kinds.js';
import { paginateResult } from '../../paginate.js';
import { ALL_SYMBOL_KINDS } from '../../shared/kinds.js';
import { getFileHash, normalizeSymbol } from '../../shared/normalize.js';
import { paginateResult } from '../../shared/paginate.js';

const FUNCTION_KINDS = ['function', 'method', 'class'];

Expand Down
4 changes: 2 additions & 2 deletions src/domain/graph/builder/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import { createHash } from 'node:crypto';
import fs from 'node:fs';
import path from 'node:path';
import { EXTENSIONS, IGNORE_DIRS } from '../../../constants.js';
import { purgeFilesData } from '../../../db/index.js';
import { warn } from '../../../logger.js';
import { warn } from '../../../infrastructure/logger.js';
import { EXTENSIONS, IGNORE_DIRS } from '../../../shared/constants.js';

export const BUILTIN_RECEIVERS = new Set([
'console',
Expand Down
6 changes: 3 additions & 3 deletions src/domain/graph/builder/incremental.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
*/
import fs from 'node:fs';
import path from 'node:path';
import { normalizePath } from '../../../constants.js';
import { warn } from '../../../logger.js';
import { parseFileIncremental } from '../../../parser.js';
import { warn } from '../../../infrastructure/logger.js';
import { normalizePath } from '../../../shared/constants.js';
import { parseFileIncremental } from '../../parser.js';
import { computeConfidence, resolveImportPath } from '../resolve.js';
import { BUILTIN_RECEIVERS, readFileSafe } from './helpers.js';

Expand Down
6 changes: 3 additions & 3 deletions src/domain/graph/builder/pipeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
*/
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { loadConfig } from '../../../config.js';
import { closeDb, getBuildMeta, initSchema, MIGRATIONS, openDb } from '../../../db/index.js';
import { info } from '../../../logger.js';
import { getActiveEngine } from '../../../parser.js';
import { loadConfig } from '../../../infrastructure/config.js';
import { info } from '../../../infrastructure/logger.js';
import { getActiveEngine } from '../../parser.js';
import { PipelineContext } from './context.js';
import { loadPathAliases } from './helpers.js';
import { buildEdges } from './stages/build-edges.js';
Expand Down
2 changes: 1 addition & 1 deletion src/domain/graph/builder/stages/build-edges.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { getNodeId } from '../../../../db/index.js';
import { loadNative } from '../../../../native.js';
import { loadNative } from '../../../../infrastructure/native.js';
import { computeConfidence } from '../../resolve.js';
import { BUILTIN_RECEIVERS, batchInsertEdges } from '../helpers.js';
import { getResolved, isBarrelFile, resolveBarrelExport } from './resolve-imports.js';
Expand Down
4 changes: 2 additions & 2 deletions src/domain/graph/builder/stages/build-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { normalizePath } from '../../../../constants.js';
import { debug } from '../../../../logger.js';
import { debug } from '../../../../infrastructure/logger.js';
import { normalizePath } from '../../../../shared/constants.js';
import { readFileSafe } from '../helpers.js';

/**
Expand Down
4 changes: 2 additions & 2 deletions src/domain/graph/builder/stages/collect-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/
import fs from 'node:fs';
import path from 'node:path';
import { normalizePath } from '../../../../constants.js';
import { info } from '../../../../logger.js';
import { info } from '../../../../infrastructure/logger.js';
import { normalizePath } from '../../../../shared/constants.js';
import { collectFiles as collectFilesUtil } from '../helpers.js';

/**
Expand Down
8 changes: 4 additions & 4 deletions src/domain/graph/builder/stages/detect-changes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
*/
import fs from 'node:fs';
import path from 'node:path';
import { normalizePath } from '../../../../constants.js';
import { closeDb } from '../../../../db/index.js';
import { readJournal, writeJournalHeader } from '../../../../journal.js';
import { debug, info } from '../../../../logger.js';
import { parseFilesAuto } from '../../../../parser.js';
import { debug, info } from '../../../../infrastructure/logger.js';
import { normalizePath } from '../../../../shared/constants.js';
import { parseFilesAuto } from '../../../parser.js';
import { readJournal, writeJournalHeader } from '../../journal.js';
import { fileHash, fileStat, purgeFilesFromGraph, readFileSafe } from '../helpers.js';

/**
Expand Down
Loading
Loading