Skip to content
Closed
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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Codegraph is **our own tool**. Use it to analyze this repository before making c
node src/cli.js build . # Build/update the graph (incremental)
node src/cli.js map --limit 20 # Module overview & most-connected nodes
node src/cli.js stats # Graph health and quality score
node src/cli.js fn <name> -T # Function call chain (callers + callees)
node src/cli.js query <name> -T # Function call chain (callers + callees)
node src/cli.js deps src/<file>.js # File-level imports and importers
node src/cli.js diff-impact main # Impact of current branch vs main
node src/cli.js complexity -T # Per-function complexity metrics
Expand Down
2 changes: 1 addition & 1 deletion FOUNDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ LLM-powered features (richer embeddings, semantic search, AI-enhanced analysis)

This dual-mode approach is unique in the competitive landscape. Competitors either require cloud APIs for core functionality (code-graph-rag, autodev-codebase) or offer no AI enhancement at all (CKB, axon, arbor). Nobody else offers both modes in one tool.

*Test: does every core command (`build`, `query`, `fn`, `deps`, `impact`, `diff-impact`, `cycles`, `map`) work with zero API keys? Are LLM features additive, never blocking?*
*Test: does every core command (`build`, `query`, `deps`, `impact`, `diff-impact`, `cycles`, `map`) work with zero API keys? Are LLM features additive, never blocking?*

### 5. Embeddable first, CLI second

Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ codegraph explain <function> # Function summary: signature, calls, callers, te

```bash
codegraph impact <file> # Transitive reverse dependency trace
codegraph fn <name> # Function-level: callers, callees, call chain
codegraph fn <name> --no-tests --depth 5
codegraph query <name> --no-tests # Function-level: callers, callees, call chain
codegraph query <name> --no-tests --depth 5
codegraph fn-impact <name> # What functions break if this one changes
codegraph path <from> <to> # Shortest path between two symbols (A calls...calls B)
codegraph path <from> <to> --reverse # Follow edges backward
Expand Down Expand Up @@ -287,7 +287,7 @@ codegraph embed # Build embeddings (default: nomic-v1.5)
codegraph embed --model nomic # Use a different model
codegraph search "handle authentication"
codegraph search "parse config" --min-score 0.4 -n 10
codegraph models # List available models
codegraph embed --models # List available models
```

#### Multi-query search
Expand Down Expand Up @@ -336,13 +336,13 @@ codegraph registry remove <name> # Unregister
| Flag | Description |
|---|---|
| `-d, --db <path>` | Custom path to `graph.db` |
| `-T, --no-tests` | Exclude `.test.`, `.spec.`, `__test__` files (available on `fn`, `fn-impact`, `path`, `context`, `explain`, `where`, `diff-impact`, `search`, `map`, `hotspots`, `roles`, `co-change`, `deps`, `impact`, `complexity`, `communities`, `manifesto`) |
| `-T, --no-tests` | Exclude `.test.`, `.spec.`, `__test__` files (available on `query`, `fn-impact`, `path`, `context`, `explain`, `where`, `diff-impact`, `search`, `map`, `hotspots`, `roles`, `co-change`, `deps`, `impact`, `complexity`, `communities`, `manifesto`) |
| `--depth <n>` | Transitive trace depth (default varies by command) |
| `-j, --json` | Output as JSON |
| `-v, --verbose` | Enable debug output |
| `--engine <engine>` | Parser engine: `native`, `wasm`, or `auto` (default: `auto`) |
| `-k, --kind <kind>` | Filter by kind: `function`, `method`, `class`, `struct`, `enum`, `trait`, `record`, `module` (`fn`, `context`, `search`) |
| `-f, --file <path>` | Scope to a specific file (`fn`, `context`, `where`) |
| `-k, --kind <kind>` | Filter by kind: `function`, `method`, `class`, `struct`, `enum`, `trait`, `record`, `module` (`query`, `context`, `search`) |
| `-f, --file <path>` | Scope to a specific file (`query`, `context`, `where`) |
| `--rrf-k <n>` | RRF smoothing constant for multi-query search (default 60) |

## 🌐 Language Support
Expand Down Expand Up @@ -485,7 +485,7 @@ This project uses codegraph. The database is at `.codegraph/graph.db`.
### Other useful commands
- `codegraph build .` — rebuild the graph (incremental by default)
- `codegraph map` — module overview
- `codegraph fn <name> -T` — function call chain
- `codegraph query <name> -T` — function call chain
- `codegraph path <from> <to> -T` — shortest call path between two symbols
- `codegraph deps <file>` — file-level dependencies
- `codegraph roles --role dead -T` — find dead code (unreferenced symbols)
Expand Down
1 change: 0 additions & 1 deletion scripts/lib/bench-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export async function resolveBenchmarkSource() {
cwd: tmpDir,
stdio: 'pipe',
timeout: 120_000,
shell: true,
});
break;
} catch (err) {
Expand Down
73 changes: 28 additions & 45 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
fnImpact,
impactAnalysis,
moduleMap,
queryName,
roles,
stats,
symbolPath,
Expand Down Expand Up @@ -95,16 +94,26 @@ program

program
.command('query <name>')
.description('Find a function/class, show callers and callees')
.description('Find a function/class callers, callees, and transitive call chain')
.option('-d, --db <path>', 'Path to graph.db')
.option('--depth <n>', 'Transitive caller depth', '3')
.option('-f, --file <path>', 'Scope search to functions in this file (partial match)')
.option('-k, --kind <kind>', 'Filter to a specific symbol kind')
.option('-T, --no-tests', 'Exclude test/spec files from results')
.option('--include-tests', 'Include test/spec files (overrides excludeTests config)')
.option('-j, --json', 'Output as JSON')
.option('--limit <number>', 'Max results to return')
.option('--offset <number>', 'Skip N results (default: 0)')
.option('--ndjson', 'Newline-delimited JSON output')
.action((name, opts) => {
queryName(name, opts.db, {
if (opts.kind && !ALL_SYMBOL_KINDS.includes(opts.kind)) {
console.error(`Invalid kind "${opts.kind}". Valid: ${ALL_SYMBOL_KINDS.join(', ')}`);
process.exit(1);
}
fnDeps(name, opts.db, {
depth: parseInt(opts.depth, 10),
file: opts.file,
kind: opts.kind,
noTests: resolveNoTests(opts),
json: opts.json,
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
Expand Down Expand Up @@ -161,30 +170,6 @@ program
fileDeps(file, opts.db, { noTests: resolveNoTests(opts), json: opts.json });
});

program
.command('fn <name>')
.description('Function-level dependencies: callers, callees, and transitive call chain')
.option('-d, --db <path>', 'Path to graph.db')
.option('--depth <n>', 'Transitive caller depth', '3')
.option('-f, --file <path>', 'Scope search to functions in this file (partial match)')
.option('-k, --kind <kind>', 'Filter to a specific symbol kind')
.option('-T, --no-tests', 'Exclude test/spec files from results')
.option('--include-tests', 'Include test/spec files (overrides excludeTests config)')
.option('-j, --json', 'Output as JSON')
.action((name, opts) => {
if (opts.kind && !ALL_SYMBOL_KINDS.includes(opts.kind)) {
console.error(`Invalid kind "${opts.kind}". Valid: ${ALL_SYMBOL_KINDS.join(', ')}`);
process.exit(1);
}
fnDeps(name, opts.db, {
depth: parseInt(opts.depth, 10),
file: opts.file,
kind: opts.kind,
noTests: resolveNoTests(opts),
json: opts.json,
});
});

program
.command('fn-impact <name>')
.description('Function-level impact: what functions break if this one changes')
Expand Down Expand Up @@ -489,39 +474,37 @@ registry

// ─── Embedding commands ─────────────────────────────────────────────────

program
.command('models')
.description('List available embedding models')
.action(() => {
const defaultModel = config.embeddings?.model || DEFAULT_MODEL;
console.log('\nAvailable embedding models:\n');
for (const [key, cfg] of Object.entries(MODELS)) {
const def = key === defaultModel ? ' (default)' : '';
const ctx = cfg.contextWindow ? `${cfg.contextWindow} ctx` : '';
console.log(
` ${key.padEnd(12)} ${String(cfg.dim).padStart(4)}d ${ctx.padEnd(9)} ${cfg.desc}${def}`,
);
}
console.log('\nUsage: codegraph embed --model <name> --strategy <structured|source>');
console.log(' codegraph search "query" --model <name>\n');
});

program
.command('embed [dir]')
.description(
'Build semantic embeddings for all functions/methods/classes (requires prior `build`)',
)
.option(
'-m, --model <name>',
'Embedding model (default from config or minilm). Run `codegraph models` for details',
'Embedding model (default from config or minilm). Use `--models` to list available models',
)
.option(
'-s, --strategy <name>',
`Embedding strategy: ${EMBEDDING_STRATEGIES.join(', ')}. "structured" uses graph context (callers/callees), "source" embeds raw code`,
'structured',
)
.option('--models', 'List available embedding models and exit')
.option('-d, --db <path>', 'Path to graph.db')
.action(async (dir, opts) => {
if (opts.models) {
const defaultModel = config.embeddings?.model || DEFAULT_MODEL;
console.log('\nAvailable embedding models:\n');
for (const [key, cfg] of Object.entries(MODELS)) {
const def = key === defaultModel ? ' (default)' : '';
const ctx = cfg.contextWindow ? `${cfg.contextWindow} ctx` : '';
console.log(
` ${key.padEnd(12)} ${String(cfg.dim).padStart(4)}d ${ctx.padEnd(9)} ${cfg.desc}${def}`,
);
}
console.log('\nUsage: codegraph embed --model <name> --strategy <structured|source>');
console.log(' codegraph search "query" --model <name>\n');
return;
}
if (!EMBEDDING_STRATEGIES.includes(opts.strategy)) {
console.error(
`Unknown strategy: ${opts.strategy}. Available: ${EMBEDDING_STRATEGIES.join(', ')}`,
Expand Down
6 changes: 3 additions & 3 deletions tests/integration/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ describe('CLI smoke tests', () => {
expect(data).toHaveProperty('results');
});

// ─── Fn ──────────────────────────────────────────────────────────────
test('fn --json returns valid JSON with results', () => {
const out = run('fn', 'add', '--db', dbPath, '--json');
// ─── Query (fn-level) ───────────────────────────────────────────────
test('query --json returns fn-level results with depth', () => {
const out = run('query', 'add', '--db', dbPath, '--json');
const data = JSON.parse(out);
expect(data).toHaveProperty('results');
});
Expand Down