This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CodeGraph is a local-first code intelligence library + CLI + MCP server. It parses any supported codebase with tree-sitter, stores symbols/edges/files in SQLite (FTS5), and exposes a knowledge graph to AI agents (Claude Code, Cursor, Codex CLI, opencode) over MCP. Per-project data lives in .codegraph/. Extraction is deterministic — derived from AST, not LLM-summarized.
Distributed as @colbymchenry/codegraph on npm; same binary serves as installer, indexer, and MCP server.
npm run build # tsc + copy schema.sql and *.wasm into dist/; chmods dist/bin/codegraph.js
npm run dev # tsc --watch
npm run clean # rm -rf dist
npm test # vitest run (all)
npm run test:watch
npm run test:eval # only __tests__/evaluation/
npm run eval # build then run __tests__/evaluation/runner.ts via tsx
npm run cli # build then run the local dist binary
# Single test file / pattern
npx vitest run __tests__/installer-targets.test.ts
npx vitest run __tests__/extraction.test.ts -t "TypeScript"copy-assets (called from build) copies src/db/schema.sql and all src/extraction/wasm/*.wasm files into dist/. Any new SQL or grammar wasm must be copied or it won't ship.
Node engines: >=18.0.0 <25.0.0. There is a hard exit on Node 25.x (see src/bin/node-version-check.ts).
files → ExtractionOrchestrator (tree-sitter) → DB (nodes/edges/files)
↓
ReferenceResolver (imports, name-matching, framework patterns)
↓
GraphQueryManager / GraphTraverser (callers, callees, impact)
↓
ContextBuilder (markdown/JSON for AI consumption)
The public API surface is src/index.ts — the CodeGraph class wires all the layers and re-exports types. Library users only touch this file; the MCP server and CLI also drive it.
src/index.ts—CodeGraphclass:init/open/close,indexAll,sync,searchNodes,getCallers/getCallees,getImpactRadius,buildContext,watch/unwatch.src/db/—DatabaseConnection,QueryBuilder(prepared statements),schema.sql. Backed bybetter-sqlite3(native) when available, transparently falls back tonode-sqlite3-wasm.codegraph statussurfaces which backend is live; wasm is the slow path.src/extraction/—ExtractionOrchestrator, tree-sitter wrappers, per-language extractors underlanguages/(one file per language), plus standalone extractors for non-tree-sitter formats (svelte-extractor.ts,vue-extractor.ts,liquid-extractor.ts,dfm-extractor.tsfor Delphi).parse-worker.tsruns heavy parsing off the main thread.src/resolution/—ReferenceResolverorchestratesimport-resolver.ts(withpath-aliases.tsfor tsconfig path aliases + cargo workspace member globs),name-matcher.ts, andframeworks/(Express, Laravel, Rails, FastAPI, Django, Flask, Spring, Gin, Axum, ASP.NET, Vapor, React Router, SvelteKit, Vue/Nuxt, Cargo workspaces). Frameworks emitroutenodes andreferencesedges.src/graph/—GraphTraverser(BFS/DFS, impact radius, path finding) andGraphQueryManager(high-level queries).src/context/—ContextBuilder+ formatter for markdown/JSON output.src/search/— full-text query parser and helpers for FTS5.src/sync/—FileWatcher(native FSEvents/inotify/RDCW) with debounce + filter, and git-hook helpers.src/mcp/— MCP server (MCPServer,tools.ts,transport.ts).server-instructions.tsis what the server returns in the MCPinitializeresponse — keep it in sync with the user-facing tool guidance.src/installer/— see below.src/bin/codegraph.ts— CLI (commander). Subcommands:install,init,uninit,index,sync,status,query,files,context,affected,serve --mcp.src/ui/— terminal UI (shimmer progress, worker).
Defined in src/types.ts. Both extractors and resolvers must use these exact strings.
- NodeKind:
file,module,class,struct,interface,trait,protocol,function,method,property,field,variable,constant,enum,enum_member,type_alias,namespace,parameter,import,export,route,component. - EdgeKind:
contains,calls,imports,exports,extends,implements,references,type_of,returns,instantiates,overrides,decorates.
src/installer/ is the entry point for codegraph install (and the bare codegraph/npx @colbymchenry/codegraph invocation). Architecture:
targets/registry.tslists every supported agent.targets/types.tsdefines theAgentTargetinterface — adding a 5th agent (Continue, Zed, Windsurf…) is one new file intargets/+ one entry inregistry.ts. Each target owns its config-file location, MCP-server JSON/TOML/JSONC writing, and instructions-file path.- Current targets:
claude.ts,cursor.ts,codex.ts,opencode.ts. targets/toml.tsis a hand-rolled TOML serializer scoped to[mcp_servers.codegraph](used by Codex). Sibling tables and[[array_of_tables]]are preserved verbatim. No new dependency.- opencode reads
opencode.jsoncby default; the installer prefers existing.jsonc, falls back to.json, and creates.jsoncfor greenfield installs. Edits are surgical viajsonc-parserso user comments and formatting survive install/re-install/uninstall round-trips. instructions-template.tsis the agent-agnostic instructions file written to each target (e.g.CLAUDE.md,.cursor/rules/codegraph.mdc,~/.codex/AGENTS.md,~/.config/opencode/AGENTS.md). It explicitly says "trust codegraph results, don't re-verify with grep" — earlier versions prescribed Claude-specific "spawn an Explore agent" and confused other agents.claude-md-template.tsis the legacy Claude-only template, retained for compatibility paths.- All installer changes need matching coverage in
__tests__/installer-targets.test.ts— there are ~47 parameterized contract tests covering install idempotency, sibling preservation, uninstall reverses install, byte-equal re-runs returningunchanged, and partial-state recovery for Codex.
Cursor launches MCP subprocesses with the wrong cwd and doesn't pass rootUri in initialize. The installer injects --path into Cursor's MCP args — absolute path for local installs, ${workspaceFolder} for global installs. If you touch Cursor wiring, preserve this.
src/mcp/server-instructions.ts is sent back to the agent in the MCP initialize response. This is the first thing every agent sees about how to use the tools — treat it as the authoritative tool guidance and keep it in sync with instructions-template.ts and .cursor/rules/codegraph.mdc.
Tests live in __tests__/ and mirror the module they cover. Notable ones beyond the obvious:
installer-targets.test.ts— parameterized contract suite across all 4 agent targets (see installer notes above).evaluation/—runner.ts+test-cases.tsexercise codegraph against synthetic projects and score the results; run vianpm run eval(builds first). Not part ofnpm test.sqlite-backend.test.ts— covers native + wasm backend selection and fallback.pr19-improvements.test.ts,frameworks-integration.test.ts— regression coverage for specific past PRs/incidents; don't rename these, the names anchor to git history.
Tests create temp dirs with fs.mkdtempSync and clean up in afterEach. They write real files and exercise real SQLite — there is no DB mocking.
Released to npm and mirrored as GitHub Releases. CHANGELOG.md is the source of truth; GitHub Release notes are extracted from it.
When asked for an entry for a new version:
- Add a new
## [X.Y.Z] - YYYY-MM-DDblock at the top ofCHANGELOG.md(under the intro, above the previous version). - Group under
### Added,### Changed,### Fixed,### Removed,### Deprecated,### Security— omit empty sections. - Write from the user's perspective, not the implementation's. Lead with the observable symptom or capability; mention internals only if a user needs them (e.g., to work around an existing bad install).
- Add the link reference at the bottom:
[X.Y.Z]: https://github.com/colbymchenry/codegraph/releases/tag/vX.Y.Z.
Releases are built and published by the GitHub Actions "Release" workflow
(.github/workflows/release.yml). It bundles a Node runtime per platform
(scripts/build-bundle.sh) and publishes both the GitHub Release and the npm
thin-installer (scripts/pack-npm.sh: a shim package + per-platform packages).
Publishing manually is wrong now — a plain npm publish ships the root
package (non-bundled), which breaks anyone on Node < 22.5.
After the changelog entry is written and package.json is bumped:
git add package.json package-lock.json CHANGELOG.md
git commit -m "release: X.Y.Z (<one-line summary>)"
git pushThen trigger Actions → Release → Run workflow (on main). It reads the
version from package.json, builds every platform bundle on one runner, creates
the GitHub Release with notes from the matching CHANGELOG.md section, and
publishes to npm. Requires the NPM_TOKEN repo secret.
Do not run npm publish, git push, or git tag yourself — these are
publish actions on shared state. Write the files, hand the user the commands.
- The
0.7.xline is in active multi-agent rollout. Any change tosrc/installer/(especiallytargets/) needs corresponding test coverage and a CHANGELOG entry — installer regressions break every new install silently. - When changing what the MCP tools do or how agents should use them, update all three of
src/mcp/server-instructions.ts,src/installer/instructions-template.ts, and.cursor/rules/codegraph.mdc— they're written to different places but say the same thing. - CodeGraph provides code context, not product requirements. For new features, ask the user about UX, edge cases, and acceptance criteria — the graph won't tell you.