Content
# codemap
Local-first code intelligence that gives AI agents and people **structural awareness** of
codebases — combining a code graph (LSP + parsers) with semantic retrieval
(local veclite, with an optional one-hop vecgrep CLI fallback or owner), exposed through a **CLI**
and an **MCP server**.
> Working on the code? Read [AGENTS.md](./AGENTS.md) first — it is the source of truth for
> conventions, architecture, and gotchas.
codemap answers questions that grep and a single LSP call can't: *who calls this function and
which tests cover it*, *what's the blast radius of changing this type*, *find auth-like code and
then show me everything that calls into it*. It precomputes the
structure once, then serves narrow, structured answers — so an agent spends a few tool calls
instead of dozens of file reads.
<!-- BENCH:START -->
> **DIRECTIONAL** — go-git/go-git @ `48a1ae05eec4`, claude-sonnet-5, N=3 (mean ± σ), api-key auth, playbook-injected, 2026-07-13. Not a controlled study; see [bench/README.md](bench/README.md).
>
> | metric (mean ± σ, per session) | baseline (Read/Grep/Glob) | with codemap | Δ |
> |---|---|---|---|
> | tool calls | 7.1 ± 6.9 | 4.0 ± 4.5 | -44% |
> | mcp tool calls | 0.0 ± 0.0 | 1.8 ± 3.4 | — |
> | sessions using codemap tools | 0/30 | 14/30 | — |
> | input tokens (incl. cache reads) | 56k ± 92k | 70k ± 75k | +25% |
> | output tokens | 2k ± 2k | 923 ± 1k | -47% |
> | wall-clock (s) | 29.9 ± 31.7 | 17.8 ± 17.8 | -40% |
> | cost (USD) | $0.063 ± $0.083 | $0.055 ± $0.059 | -13% |
> | tasks correct | 8/10 | 8/10 | +0 |
>
> One-time codemap index cost (disclosed, not per-session): **7s**. codemap is modelled as pre-indexed (the daemon keeps it fresh in real use), so the codemap arm pays query time, not index time.
<!-- BENCH:END -->
## Features
- **Structural code graph** — files, functions, types, methods, and tests as nodes; **call** edges
(name-based by default for Go, exact via `go/types` with `--precise`) and **defines** edges
(file → symbol). Test coverage is derived by walking the call graph to test nodes. The graph is
stored in pure-Go SQLite and remains queryable offline. **Go**, **Ruby**, **Lua**, **GDScript**, and **CSS/HTML** use
built-in pure-Go backends with language-specific relationships and no server needed, and so do
**TypeScript + JavaScript** and **Python**: a pure-Go tree-sitter parser extracts the same symbols
their language servers would, with no server installed. With the server installed, `--precise`
adds a **precise call graph**; one `typescript-language-server` resolves calls across the
`.ts`↔`.js` boundary. Base (non-precise)
TS/JS indexing additionally extracts name-based **import edges**, high-precision **call candidates** (same-file calls and calls through imported bindings), **JSX component-usage edges**
(`<Foo/>` in `.tsx`/`.jsx` — rendering *is* invocation for a function component, so React
codebases no longer read as disconnected), and **Next.js framework-wiring references** (App
Router special files, `route.ts` HTTP verbs, middleware, Pages Router), so framework-invoked
symbols stop appearing as orphans. **Vue SFCs** route
`<script>`/`<script setup>` blocks through that TS/JS server and currently provide symbols +
`defines` edges only, with source lines mapped back to the original `.vue` file. Semantic search
is language-agnostic.
- **Data and documentation** — SQL tables, views, and queries expose candidate read/write dependencies; sqlc maps generated Go methods to named queries. YAML exposes key paths and explicit task/service/job dependencies. Markdown exposes sections and local links. HTML adds local asset links and embedded styles. These relationships stay separate from calls. See [the format guide](docs/data-and-docs.md).
- **Optional semantic search** — with the local/fallback backend and embeddings enabled, node
source is embedded through the configured Ollama-compatible endpoint (`nomic-embed-text`,
768-dim by default) into [veclite](https://github.com/abdul-hamid-achik/veclite), then searched
with vector + BM25 hybrid retrieval. `--no-embed` keeps codemap's own index structure-only.
- **Impact analysis** — `impact` returns a symbol's definition sites, direct callers, the
transitive blast radius (everything affected by a change), and which tests cover those
paths (flagging untested code).
- **Built for agent harnesses** — `context <symbol>` bundles definition + callers + callees +
value-reference wiring + tests + blast radius in **one call** (no multi-round-trip stitching),
and `status` reports index
*freshness* (files changed since indexing) so an agent reindexes before trusting a stale answer.
- **Exact, reusable source selectors** — every symbol result already carries `file`, `start_line`,
`fqn`, and `kind`. Agents project those fields into a `selector` for `source`/`context`/`callers`/
`callees`/`references`/`impact`/`risk` (or paired path selectors), while people use
`--at file:line`. This picks
one same-named definition without persisting reindex-volatile database IDs.
- **Multi-project registry** — one shared store indexes all your repos; `projects` lists what's
indexed, and any query targets one project (resolved from cwd, or `--path`).
- **Annotations** — pin notes and external data (DB rows from mongosh/postgres, vidtrace/vecgrep
findings, …) to a symbol or a call path; they persist across reindex. A knowledge layer over the
graph for agent harnesses (`annotate` / `annotations`, also on MCP) and people.
- **Precise call resolution** — the fast name-based graph over-matches same-named methods
(`x.Close()` links to *every* `Close`). `codemap index --precise` attempts to resolve each call to
the one it actually invokes and records successful precise coverage per file. A query is reported
`resolved` only when every matched definition file completed that pass; partial failures remain
honestly `name`/`unresolved` instead of upgrading the whole project. It's the unified exact-resolution pass across languages: an in-process, pure-Go
`go/types` pass for **Go**, and the language server's `callHierarchy` for the **LSP languages**
(TypeScript, JavaScript, Python — whose base graph is partial or absent, so `--precise` is what gives
them complete calls). Opt-in and additive (name-based stays the default for Go); the Go pass
degrades to name-based **with a note**
when the `go` toolchain or module isn't available. For a one-off exact answer without reindexing,
`callers`/`callees` also take `--precise` (language-server `callHierarchy`). CLI + MCP.
- **Incremental** — hash-based reindex; an embedding-profile guard forces a rebuild when the
provider, model, dimensions, or distance changes instead of corrupting the vector space.
- **Two surfaces, one structural store** — a Cobra **CLI** (with `--json` for agents) and a stdio **MCP server**.
- **Learn a codebase** — `atlas` prints the repo as a described directory tree (summaries are
extracted from READMEs, package docs, and docstrings, never generated), `features` lists what the
software can do (CLI commands, routes, MCP tools, pages) with each handler and call footprint, and
`flow <handler>` shows how one feature works as an ordered call tree. See
[Learn a codebase](docs/learn.md).
- **Graph analytics** — `map` (subsystems, directed bridges, entrypoints, hubs), `hotspots`
(hubs; tests are ignored by default), `orphans` (dead-code candidates), `explore` (intent → bounded exact neighborhoods),
`traverse` (typed, heterogeneous graph walks), `task-context` (one-call, mode-scoped
orientation for a task: freshness + neighborhoods + impact + related files), and `path`
(shortest call path between two symbols).
- **Local-first by default** — the structural graph, local vectors, and default Ollama endpoint stay
on your machine. If you explicitly configure a remote Ollama-compatible endpoint, codemap sends
the source text being embedded to that endpoint; see the [configuration guide](docs/configuration.md).
- **Single core binary** — codemap is pure-Go (`CGO_ENABLED=0`), cross-compiled, and shipped via
Homebrew. Optional LSP-backed indexing and embeddings use separately installed language servers
or Ollama.
## Surfaces
codemap has three surfaces over one structural store:
- **CLI** — human commands, plus `--json` on query commands for machine output.
- **MCP server** — `codemap serve` (stdio) exposes `codemap_*` tools to agents.
- **Codemap Studio** — an Electron desktop app in [`desktop/`](desktop/) that runs `codemap … --json` behind a graph explorer, review desk, and architecture map. See [docs/desktop.md](docs/desktop.md).
## Installation
### Homebrew (recommended)
```bash
brew install abdul-hamid-achik/tap/codemap
```
### Prerequisites
- **Go 1.25+** (only to build from source)
- **[Ollama](https://ollama.com)** with the embedding model:
`ollama pull nomic-embed-text` (optional — without it, indexing is structure-only)
- **[gopls](https://pkg.go.dev/golang.org/x/tools/gopls)** — optional, for one-off `callers`/`callees --precise` Go results
- Optional: **[Task](https://taskfile.dev)** for the dev workflow
**Supported language paths** — Go, Ruby, Lua, GDScript, SQL, YAML, Markdown, and CSS/SCSS/Sass/Less/HTML work with built-in pure-Go backends. TypeScript,
JavaScript, Python, and Vue require the language server listed below on `PATH`; without it, codemap
recognizes and reports those files but skips their structural extraction. Semantic retrieval is
language-agnostic once symbols are indexed. A precise call graph
(`callers`/`callees`/`impact`/`hotspots`/`path`) needs `--precise`:
| Language | How | Extensions | Call graph |
|---|---|---|---|
| **Go** | stdlib `go/parser` (pure Go, always) · `--precise` adds exact edges via in-process `go/types` | `.go` | name-based by default; exact via `--precise` |
| **TypeScript / JavaScript** | built-in pure-Go tree-sitter parser (TS, TSX, JS/JSX) · `--precise` drives `typescript-language-server` `callHierarchy` (one server, resolves across the `.ts`↔`.js` boundary) · plus a name-based scan for imports, JSX component usage, and Next.js framework wiring | `.ts` `.tsx` `.mts` `.cts` `.js` `.jsx` `.mjs` `.cjs` | name-based JSX, import, framework, same-file call, and imported-binding edges by default (partial); complete calls via `--precise` |
| **Python** | built-in pure-Go tree-sitter parser · `--precise` drives `pyright-langserver` | `.py` `.pyw` `.pyi` | name-based same-file, self/cls-method, and imported-binding candidates (partial); complete via `--precise` |
| **Ruby** | built-in pure-Go scanner (modules/classes/defs incl. `def self.x`, endless defs, `private def`; heredoc-, `=begin`-, and string-safe) | `.rb` | name-based (calls + `require`/`require_relative` imports) |
| **Lua** | built-in pure-Go scanner (`function M.foo()`/`M:foo()`/`local function` and function assignments; long-string- and comment-safe) | `.lua` | name-based (calls + `require` imports) |
| **Vue SFC** | `vuesrc` — `<script>`/`<script setup>` block content is extracted and parsed by the TS/JS backend; symbol lines are mapped back onto the original `.vue` file | `.vue` | symbols + `defines` edges only (no `--precise` call graph yet) |
| **CSS / SCSS / Sass / Less** | built-in pure-Go scanner — selector nodes per class/id token, SCSS/Less nesting flattened, at-rule- and interpolation-safe; `className`/`class=` references from TSX/JSX and HTML resolve to selectors as `styles` edges | `.css` `.scss` `.sass` `.less` | `styles` + import edges (no call graph — not applicable) |
| **HTML** | HTML tokenizer — static class/id references, embedded style selectors, and local asset links | `.html` | `styles` + import edges |
| **SQL / sqlc** | Offline declarations and query references; configured sqlc Go mapping | `.sql` | `reads`, `writes`, `depends_on`; no calls |
| **YAML** | Key paths and explicit Task/Compose/workflow dependencies | `.yaml` `.yml` | `depends_on`; no calls |
| **Markdown** | CommonMark sections and local links | `.md` `.markdown` | `documents`; no calls |
> Vue SFCs: a `.vue` file's `<script>`/`<script setup>` block (with `lang="ts"` routing to TypeScript, unmarked/`lang="js"` to JavaScript) is parsed by the same backend that indexes plain `.ts`/`.js` files. Template/style blocks are not indexed.
The language servers auto-enable when installed — run [`codemap doctor`](docs/cli.md) to see which are
detected, or `--no-lsp` to skip. The next waves are tracked honestly at **T0 recognized**:
Rust; Java/Kotlin/Scala; C/C++/CUDA; C#/VB; PHP; Dart; Swift; Elixir;
Svelte/Astro/Razor; shell; HCL/Terraform. T0 means the file is detected
and reported with a planned/missing backend, but produces no graph nodes yet. Public support
advances per relation domain (symbols, references/imports, resolved calls) only after its
fixture and accuracy gates pass; optional SCIP import is the project-level path for several waves.
See the [language support plan](docs/languages.md) for the T0–T4 admission gates,
the Rust pilot, and the project-level SCIP importer design.
### From source
```bash
git clone https://github.com/abdul-hamid-achik/codemap
cd codemap
task build # → ./bin/codemap (or: go build ./cmd/codemap)
```
### Go install
```bash
go install github.com/abdul-hamid-achik/codemap/cmd/codemap@latest
```
### Changelog
Release notes are generated per tag by GoReleaser (`.github/workflows/release.yml`) — see the
[GitHub releases page](https://github.com/abdul-hamid-achik/codemap/releases) for what changed
in each version.
## Quick start
```bash
# 1. Register and index a project
codemap init # registers the current directory
codemap index # extract graph + attempt embeddings (incremental)
codemap index --no-embed # structure only (no Ollama needed)
codemap index --precise # exact call edges (Go via go/types; TS/JS/Python via callHierarchy)
codemap index --watch # index once, then hand off to the background daemon
# Indexes your code, not your dependencies: node_modules, venv, vendor, dist, build,
# __pycache__, .git (and any dotdir) are skipped by default — configurable via `exclude`.
# 2. Check the environment and inspect config
codemap doctor
codemap config show
# 3. Orient on a symbol — everything in one call (definition, callers, callees, tests)
codemap context authenticateUser # the one-call overview (agents: codemap_context)
codemap context --at auth.go:42 # exactly one same-named definition
# 4. Navigate the call graph
codemap callers authenticateUser # who calls it (fast, name-based)
codemap callers authenticateUser --precise # exact one-off callers via the language server
codemap callers --at auth.go:42 # exact definition from the indexed graph
codemap callees authenticateUser # what it calls
codemap references authenticateUser # where it is stored/passed as a callback or handler
codemap path Handler Login # shortest call path between two symbols
codemap traverse --at auth.go:42 --direction both --edge-types calls,references --depth 2
# 5. Learn an unfamiliar repo: shape, capabilities, one feature end to end
codemap atlas # described directory tree (--prefix internal --depth 1 to zoom)
codemap features --kind cli_command # what it can do, with each handler
codemap flow runReview --depth 2 # ordered call tree from one handler
# 6. Analyze impact and structure
codemap impact authenticateUser --depth 3 # callers + blast radius + tests
codemap map # architecture: subsystems + bridges + entrypoints + hubs
codemap hotspots --top 20 # most-referenced symbols (hubs)
codemap orphans # functions with no callers (dead-code candidates)
codemap review # diff-scoped impact + tests to run
codemap status # bounded-memory stats + warns if the index is stale
codemap status --full # include the local vector count (may use substantial memory)
# 7. Search by meaning (needs an embedded index)
codemap semantic "jwt validation middleware" --top 10
codemap semantic "jwt validation middleware" --backend vecgrep # one semantic owner
codemap explore "jwt validation middleware" --seeds 5 --edges 5 --depth 2
codemap task-context "jwt validation middleware" --mode change # freshness + contexts + impact + related files in one call
# 8. Inspect a symbol neighborhood
codemap context main.go:42 --json
```
Add `--json` to any query command for machine-readable output (for agents/scripts).
The flagship `impact` answers *what breaks if I change this, and what do I run to check?* in one call
(real output, from codemap on itself):
```
$ codemap impact BlastRadius --depth 2
Impact of BlastRadius (codemap)
defined: internal/graph/queries.go:140
direct callers: 4
blast radius: 22 (depth ≤ 2)
tests covering: 11
covering tests (run these):
graph.TestBlastRadius internal/graph/graph_test.go:377
graph.TestBlastRadiusCycleSafe internal/graph/graph_test.go:419
app.TestQueryResultsCarrySignature internal/app/app_test.go:226
app.TestImpactSurfacesAnnotations internal/app/app_test.go:394
app.TestImpactWarnsOnAmbiguousName internal/app/app_test.go:1309
app.TestServiceImpact internal/app/app_test.go:1486
app.TestImpactHeuristicTestCoverage internal/app/app_test.go:1693
app.TestImpactBlankSymbolRejected internal/app/app_test.go:1871
app.TestSecretImpact internal/app/secret_impact_test.go:79
app.TestSecretImpactOrphanKey internal/app/secret_impact_test.go:100
… (1 more — use --json for all)
affected (blast radius):
[1] app.Service.SecretImpact internal/app/secret_impact.go:50
[1] app.Service.Impact internal/app/service_impact.go:49
✓ [1] graph.TestBlastRadius internal/graph/graph_test.go:377
✓ [1] graph.TestBlastRadiusCycleSafe internal/graph/graph_test.go:419
[2] main.runImpact cmd/codemap/query.go:218
[2] main.runSecretImpact cmd/codemap/query.go:667
✓ [2] app.TestQueryResultsCarrySignature internal/app/app_test.go:226
✓ [2] app.TestImpactSurfacesAnnotations internal/app/app_test.go:394
✓ [2] app.TestImpactWarnsOnAmbiguousName internal/app/app_test.go:1309
✓ [2] app.TestServiceImpact internal/app/app_test.go:1486
✓ [2] app.TestImpactHeuristicTestCoverage internal/app/app_test.go:1693
✓ [2] app.TestImpactBlankSymbolRejected internal/app/app_test.go:1871
[2] app.Service.FileImpact internal/app/file_impact.go:39
[2] app.Service.Review internal/app/review.go:69
[2] app.Service.Risk internal/app/risk.go:37
✓ [2] app.TestSecretImpact internal/app/secret_impact_test.go:79
✓ [2] app.TestSecretImpactOrphanKey internal/app/secret_impact_test.go:100
✓ [2] app.TestSecretImpactNoValueLeak internal/app/secret_impact_test.go:114
[2] app.Service.Context internal/app/service_context.go:69
[2] mcp.Server.handleImpact internal/mcp/server.go:633
… (2 more — use --json for all, or lower --depth)
Long lists are capped for readability (the nearest blast-radius nodes and the
first covering tests, with a `… (N more)` line); `--json` always carries the
complete set.
## Commands
| Group | Command | What it does |
|---|---|---|
| Project | `init` / `index` / `status` | register, index (`--reindex`, `--no-embed`, `--no-lsp`, `--precise`), show stats + freshness + per-language precise coverage |
| Project | `doctor` | check the environment — toolchains, language servers, embeddings — with install hints |
| Project | `projects` | list all registered projects and their index sizes |
| Project | `config path` / `config show` | resolved config file path and values (`--json`) |
| Navigate | `callers` / `callees` | call-graph navigation (`--at file:line` selects one definition; `--precise` resolves on demand) |
| Navigate | `references` | where a function/method is used as a value (callbacks, handlers, registrations); partial-coverage confidence is explicit |
| Navigate | `path` | shortest call path; unique FQNs select exact endpoints and every result states call-graph confidence |
| Navigate | `symbols` / `symbol-at <file>:<line>` / `find` | outline a file, resolve a position, or find symbols by name |
| Navigate | `source` | print a symbol's source code |
| Navigate | `context` | **one call, everything about a symbol**: definition, callers, callees, value references, tests, blast radius |
| Learn | `atlas` / `features` / `processes` / `flow` | the repo as a described tree (`--prefix`, `--depth`, `--files`), the capability inventory (`--kind`, `--query`), every entry point's ordered flow (`processes`: `--kind`, `--query`, `--top`, `--depth`), and an ordered call tree from one handler (`--depth`, `--include-tests`) |
| Navigate | `read-order` / `map` / `explore` / `task-context` | ranked reading list, bounded architecture overview, intent-to-structure orientation, or one-call mode-scoped task orientation (`--mode understand\|change\|debug`, alias `brief`) |
| Navigate | `traverse --at <file>:<line>` | bounded walk from one exact definition across selected edge types and directions |
| Analyze | `impact` / `dependencies` / `file-impact` / `review` | exact symbol impact (repeat `impact --at` for a partial-success frame batch; `--batch` stabilizes the one-item envelope), file dependency evidence, or diff-scoped tests |
| Analyze | `hotspots` / `orphans` | hubs / dead-code candidates; `hotspots` and `read-order` ignore tests unless `--include-tests` |
| Analyze | `coverage` | per-file precise call-graph coverage: rollups by language/directory + bounded per-file detail |
| Analyze | `risk` | 0..1 change-risk score with factors |
| Analyze | `secret-impact` / `required-keys` | key-rotation blast radius and least-privilege key sets |
| Search | `semantic` (alias `search`) / `find` | meaning-based search, and offline name search |
| Search | `grep` | exact text search over indexed file content, joined to its enclosing symbol |
| Cache | `cache save` / `restore` / `list` / `drop` | fcheap content-addressed index snapshots |
| Cache | `cache export` / `import` | portable `tar.gz` index snapshots — no fcheap needed, for CI/team sharing |
| Branch | `branch-status` / `branch-switch` / `branch-snapshot` | per-branch index snapshots via fcheap |
| Daemon | `daemon start` / `status` / `stop` | background watcher that keeps the index fresh |
| Knowledge | `annotate` / `annotations` | pin / list notes and external data on symbols/paths; `--external-id` makes automated writes retry-safe |
| Agent harness | `agent setup` / `list` / `playbook` / `skill` | wire codemap (MCP server + playbook) into an AI coding harness; install the portable skill |
| Surfaces | `serve` | MCP server (stdio) |
All query commands accept `--json`.
## Accuracy: name-based vs precise
codemap's graph is **name-based by default** — instant, offline, and tolerant of broken code. It
resolves calls *within* a package precisely (Go), but a cross-package method call like `x.Close()`
links to *every* method named `Close`, because resolving the receiver's type needs a type-checker.
codemap is honest about this rather than hiding it: `callers`/`callees`/`impact` flag when a name
resolves to multiple definitions, and `hotspots` marks name-collision inflation.
**For precise graph coverage, reindex with `codemap index --precise`** (Go). It runs an in-process,
pure-Go `go/types` pass that replaces name-based edges in each package/file it resolves successfully.
Each query is `resolved` only when all definition files it matches have precise coverage; packages
that fail type-checking stay name-based, and an uncovered LSP-language definition stays `unresolved`.
On the codemap repo itself this collapses the `Close`/`Error`
fan-out (e.g. one `Close` method that name-matching credited with 71 callers drops to its real ~12)
and turns `hotspots` from name-collision noise into genuine hubs. Requirements and guarantees:
- Needs the `go` toolchain and a buildable module. A repo whose modules live in subdirectories (no
root `go.mod`) loads each module from its own directory. A package that doesn't type-check keeps its
name-based edges (per-package degrade); a project with no `go`/`go.mod` falls back wholesale **with
a note** — never a hard error, and never worse than name-based.
- Purely additive and opt-in: without `--precise`, indexing is byte-for-byte the fast name-based path.
- Interface dispatch is statically undecidable, so a precise edge points at the interface method, not
the concrete implementors.
**For TypeScript/JavaScript, complete call coverage comes only from `--precise`.** Base indexing
now extracts real name-based edges for TS/JS: import edges (`import`/`export … from`/`require`/
dynamic `import()`, comment-safe, with `@/` and `~/` alias and workspace-package resolution), JSX
component-usage call edges in `.tsx`/`.jsx` (`<Foo/>` — rendering is invocation; member expressions
like `<Foo.Bar/>` and `<motion.div/>` resolve to the root binding; lowercase intrinsics like
`<div>` never create edges; generics/comparisons are excluded, and commented-out or string-literal
JSX creates nothing), and Next.js framework-wiring references. Like all name-based extraction these
are *candidate* edges (same over-match contract as Go selector calls) — but a React codebase no
longer reads as disconnected. Base indexing also links same-file calls (`f()`, `new C()`, `await f()`, `this.m()`) and calls through
imported bindings (named, default, and namespace imports, `require`). Arbitrary `obj.method()` calls
are not linked (Python gets the same kind of candidates — same-file calls, `self`/`cls` methods,
imported bindings), so uncovered definitions stay `unresolved`.
`index --precise` drives `typescript-language-server` `callHierarchy`; files it resolves gain
exact edges that supersede the candidates per file, while any uncovered definition remains
explicitly `unresolved`. The same
`callers`/`callees`/`impact`/`hotspots`/`path` queries then use that indexed coverage with no flag of their own.
The precise pass needs `typescript-language-server` (Python: `pyright-langserver`) on `PATH`; plain
indexing needs neither.
For a one-off exact answer *without* reindexing, `callers`/`callees` also accept `--precise`
(`callHierarchy` through the language server), which degrades to the indexed graph with a note
when the server can't resolve.
Precise indexing makes the **edges** exact; a bare query such as `impact Close` still deliberately
unions every definition named `Close`. To keep a follow-up on one definition, use CLI `--at
file:line`, or pass MCP `selector:{file,start_line,fqn,kind}` projected from any symbol result.
Selectors prefer file+FQN+kind, so ordinary line shifts survive reindex; moves/renames return a
miss instead of silently selecting another node. Raw SQLite node IDs are never a public contract.
File dependency evidence is confidence-aware. Exact same-package or precise relationships are
`confirmed`; qualified name fan-out, package-scoped imports, and stale snapshots are `candidate`.
`file-impact` reports `delete_verdict:"unsafe"` only for fresh confirmed file-scoped evidence;
candidate-only or incomplete evidence remains `unknown`. `review` analyzes deleted definitions from
the last indexed snapshot when available and tells an agent to run selected tests before reindexing
prunes that historical evidence.
`orphans` finds call-graph dead ends. It follows functions wired by *value* — handlers in a
table like cobra's `RunE: runInit`, callbacks passed to a registrar — and excludes methods that
implement well-known stdlib interfaces (`error`, `fmt.Stringer`, `Unwrap`, the JSON/text
marshalers), so those aren't flagged as dead (Go). In TS/JS, JSX component usage and Next.js
framework wiring (App Router special files like `page.tsx`/`layout.tsx`, `route.ts` HTTP-verb
handlers, `middleware`, Pages Router modules) keep rendered components and framework-invoked
exports off the dead-code list — including wrapped default exports (`export default memo(Page)`,
`forwardRef(...)`, or a chain of both), whose innermost identifier is resolved as the wired
component. It still can't see callers reached via
*custom* interface dispatch or reflection, or a component passed only as a *prop*
(`<Nav Link={AuthLink}/>` — never JSX-rendered by name),
so treat its output as *candidates*, not proof.
## Use it from an agent (MCP)
codemap is a stdio MCP server. The fastest path is `codemap agent setup <harness>` — it merges the
codemap server into the harness's native config and drops a playbook that teaches agents *when* to
use the tools (no hand-editing config files):
```bash
codemap agent setup claude-code # installs the plugin (MCP server + using-codemap skill)
codemap agent setup cursor # or: codex, gemini, vscode, opencode, cline, roo, zed, aider
codemap agent setup agents-md # playbook-only fallback for any AGENTS.md-aware harness
codemap agent list # what's detected here, and whether codemap is registered
codemap agent skill # using-codemap skill → ~/.agents/skills, linked into Claude Code, Codex, OpenCode, Hermes; read natively by Muse and omp
```
In **Claude Code** you can also install the plugin directly:
`/plugin marketplace add abdul-hamid-achik/codemap` then `/plugin install codemap@codemap`.
Prefer to wire it yourself? Most CLIs have a one-liner:
```bash
claude mcp add codemap -- codemap serve # Claude Code (add --scope user for all projects)
codex mcp add codemap -- codemap serve # OpenAI Codex
copilot mcp add codemap -- codemap serve # GitHub Copilot CLI
```
For any other MCP client, add a stdio server to its config (the key may be `mcpServers`, `mcp`, or
`context_servers`):
```json
{
"mcpServers": {
"codemap": { "command": "codemap", "args": ["serve"] }
}
}
```
Once connected, an agent can call `codemap_docs` to learn the tools and workflow on its own.
`CODEMAP_MCP_PROFILE=agent` selects exactly the 28-tool surface derived from the taught agent
workflow (27 named tools plus `codemap_docs`). The compatible `core` profile has the same inventory
today; the default `full` profile remains the explicit 50-tool expert/admin surface. See
[MCP tool profiles](docs/mcp.md#tool-profiles) for the measured schema cost and precedence rules.
Tools (50): `codemap_init`, `codemap_index`, `codemap_status`, `codemap_doctor`, `codemap_semantic`,
`codemap_callers`, `codemap_callees`, `codemap_references`, `codemap_impact`, `codemap_file_impact`,
`codemap_file_context`, `codemap_refactor_plan`, `codemap_dependencies`, `codemap_review`, `codemap_affected`, `codemap_secret_impact`, `codemap_required_keys`,
`codemap_risk`, `codemap_hotspots`, `codemap_orphans`, `codemap_coverage`, `codemap_read_order`,
`codemap_map`, `codemap_atlas`, `codemap_features`, `codemap_processes`, `codemap_flow`, `codemap_explore`, `codemap_traverse`, `codemap_task_context`, `codemap_path`,
`codemap_related_files`, `codemap_symbols`, `codemap_symbol_at`, `codemap_find`, `codemap_grep`, `codemap_source`,
`codemap_context`, `codemap_context_batch`, `codemap_projects`, `codemap_docs`, `codemap_annotate`,
`codemap_annotations`, `codemap_unannotate`, `codemap_branch_status`, `codemap_branch_switch`,
`codemap_cache_save`, `codemap_cache_restore`, `codemap_cache_list`, `codemap_cache_drop`.
Project-scoped tools accept an optional `path` (the project directory) and return JSON;
`codemap_projects`, `codemap_docs`, and `codemap_doctor` are global/environment tools and take no
project path. The two an agent reaches for first:
**`codemap_context <symbol>`** bundles a symbol's definition, callers, callees, value references,
covering tests and blast radius in **one call**, and **`codemap_status`** reports index *freshness* —
a `stale` count of files changed/added/removed since indexing, so the agent knows to reindex before
trusting results. `codemap_callers` / `codemap_callees` accept `precise: true` for exact on-demand
language-server results (gopls for Go, `typescript-language-server` for TS/JS, and pyright for
Python); `codemap_source` returns a symbol's body; `codemap_projects` lists
what's indexed; **`codemap_docs`** returns an agent guide so a harness can learn the tool;
**`codemap_annotate` / `codemap_annotations`** pin notes and external data (DB rows, findings) to
symbols and call paths — a knowledge layer over the graph (see below). Automated writers can send
`external_id`; codemap upserts it within project + source and reports whether the row was created,
updated, or unchanged.
`codemap_map`, `codemap_traverse`, `codemap_refactor_plan`, and `codemap_task_context` are
extended surfaces registered only in the default `full` MCP profile; `codemap_explore` is part of
the taught workflow and ships in every profile. The CLI commands remain available regardless of MCP profile.
For same-named definitions, pass `selector:{file,start_line,fqn,kind}` to `codemap_source`,
`codemap_context`, `codemap_callers`, `codemap_callees`, `codemap_references`, `codemap_impact`,
`codemap_risk`, or full-profile `codemap_traverse`.
`codemap_path` accepts `from_selector` + `to_selector`. The fields are a direct projection of the
symbol objects these tools already return, so chaining adds no database-ID contract.
`codemap_context` uses the indexed graph only: it never launches language servers implicitly, and
reports `call_graph:"unresolved"` plus a precise-index action when the graph is incomplete.
`codemap_context_batch` caps aggregate source bodies at 64 KiB while retaining signatures, docs,
and locations; `source_budget` / `source_truncations` disclose any shortening. Optional component
failures appear in `partial_errors` without discarding the usable parts of the bundle.
Results carry each symbol's **signature** (e.g. `func (s *Store) Hotspots(projectID int64, limit
int) ([]Hotspot, error)`) and **docstring**, so an agent understands what callers/callees/hits are
and what they do without a follow-up file read — and same-named symbols are easy to tell apart.
The flagship is `codemap_impact` — one call returns a symbol's definition sites, callers, the
transitive blast radius, and which tests cover those paths, replacing many file reads.
## Configuration
XDG-style, with `CODEMAP_*` environment overrides and an ecosystem fallback:
```
$XDG_CONFIG_HOME/codemap/config.yaml # config (~/.config/codemap/…)
$XDG_DATA_HOME/codemap/ # graph DB, veclite, project registry
$XDG_CACHE_HOME/codemap/ # caches
```
If `~/.codemap/` already exists it is used (back-compat with vecgrep/noted). `codemap init --local`
drops a `.codemap` marker so a repo-local `codemap.yaml` is picked up from any subdirectory; the
index stays central (set `CODEMAP_DATA` to a path inside the repo for a repo-local index). Precedence
and all keys are documented in the public [configuration guide](docs/configuration.md). Override
paths with `CODEMAP_CONFIG` / `CODEMAP_DATA`; contributors should also read
[AGENTS.md](./AGENTS.md).
## How it fits the ecosystem
codemap is built on [veclite](https://github.com/abdul-hamid-achik/veclite) and shares
conventions with [vecgrep](https://github.com/abdul-hamid-achik/vecgrep) (semantic code
search) and [noted](https://github.com/abdul-hamid-achik/noted) (code notes). Set
`semantic.backend: vecgrep` to make vecgrep the sole retrieval owner while codemap keeps
structural identity, freshness, relations and impact. The boundary is a versioned one-hop CLI
contract—no shared packages or stores. In the other direction,
`codemap structural-manifest --json` gives vecgrep a source-free identity/freshness
preflight before `codemap export-symbols --json` emits the paginated
`codemap.structural-export.v1` feed used by vecgrep's
`structural_chunks: auto|off|required` modes; stale or unreadable symbol content is omitted
explicitly instead of being embedded as if it were current.
## Documentation
Product docs: **[codemap.tools](https://codemap.tools)** · [Quick start](docs/quick-start.md) · [Learn a codebase](docs/learn.md) ·
[CLI](docs/cli.md) · [Configuration](docs/configuration.md) · [Agent guide](docs/agents.md) ·
[MCP](docs/mcp.md) · [Languages](docs/languages.md). Contributor rules live in
[AGENTS.md](./AGENTS.md).
## License
[MIT](./LICENSE) © 2026 Abdul Hamid Achik
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available