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, an MCP server, and an interactive terminal UI.
Working on the code? Read 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. > > | 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, and CSS/HTML use built-in pure-Go backends (symbols + name-based calls/imports, no server needed). With the listed language server installed, TypeScript + JavaScript and Python provide symbols + structure and a precise call graph under --precise; one typescript-language-server resolves calls across the .ts↔.js boundary. Base (non-precise) TS/JS indexing additionally extracts name-based import edges, 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.
- 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, then searched with vector + BM25 hybrid retrieval. --no-embed keeps codemap's own index structure-only.
- Impact analysis —
impactreturns 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;
projectslists 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 (a in Studio).
- 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 — which have no name-based call edges, so --precise is what gives them a call graph at all). 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.
- Three surfaces, one structural store — a Cobra CLI (with
--jsonfor agents), a stdio **MCP
server, and the studio** TUI for humans.
- Graph analytics —
map(subsystems, directed bridges, entrypoints, hubs),hotspots
(hubs), orphans (dead-code candidates), explore (intent → bounded exact neighborhoods), traverse (typed, heterogeneous graph walks), 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.
- 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.
studio (TUI)
codemap studio opens an interactive, full-screen explorer of your code (Charm v2 — Bubble Tea / Lip Gloss / Bubbles). Switch tabs with 1–5 or tab; navigate with ↑/↓.
codemap studio codemap · 509 nodes · 1849 edges · 35 files
1 Graph 2 Metrics 3 Impact 4 Search 5 Path
Hubs (164) │ lspsrc.Extractor.Close
57 lspsrc.Extractor.Close │ Called by (57)
56 app.Session.Close │ ▸ main.runInit cmd/codemap/init_status.go:64
56 graph.Store.Close │ main.runIndex cmd/codemap/index.go:24
26 app.NewService │ Calls (9)
19 app.Open │ app.Session.Close internal/app/session.go:126
▼ 159 more │ ⟩ func runInit(cmd *cobra.Command, ...) error
↑/↓ hub · → walk · enter → impact · s source · p precise · ctrl+c quit · ? help
Fully-qualified names disambiguate same-named symbols (six different Close methods above), and the selected node's signature is previewed (⟩ func runInit(...)).
- Graph — a call-graph explorer: hubs (most-referenced symbols) on the left as jump
points, the centered node's callers and callees on the right. Press → to focus the right pane and walk the graph — enter re-centers on a caller/callee so you can traverse the call chain; backspace steps back; s reads the selected symbol's source in a scrollable overlay, without leaving studio.
- Metrics — an overview dashboard: counts and bar charts (by kind/language) on the left;
the call graph's two extremes on the right — top hubs (most-referenced) and dead-code candidates (no callers). Both lists are navigable — enter drills a row into Impact, ctrl+s reads its source.
- Impact — type a symbol, see its callers, blast radius, and which tests cover it.
- Search — semantic search by meaning, falling back to fast name search when there are no
embeddings (so it works even without Ollama).
- Path — choose
FROMandTO, then inspect the shortest directed call chain.
The ordered nodes are keyboard-navigable and every answer shows its call_graph confidence, keeping “disconnected,” “unresolved,” and “missing endpoint” visibly distinct.
- Knowledge capture — press
aon an exact selected symbol in Graph, Search, Impact, or Path
to write an annotation without leaving Studio. The composer keeps typing isolated from global shortcuts and pins the note to the selected FQN.
Installation
Homebrew (recommended)
brew install abdul-hamid-achik/tap/codemap
Prerequisites
- Go 1.25+ (only to build from source)
- Ollama with the embedding model:
ollama pull nomic-embed-text (optional — without it, indexing is structure-only)
- gopls — optional, for one-off
callers/callees --preciseGo results - Optional: Task for the dev workflow
Supported language paths — Go, Ruby, Lua, 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 | typescript-language-server (one server, JSX/TSX-aware, resolves across the .ts↔.js boundary) + 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 edges by default; plain function calls via --precise only | | Python | pyright-langserver | .py .pyw .pyi | --precise only | | 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 | typescript-language-server via vuesrc — <script>/<script setup> block content is extracted and routed to the TS/JS delegate; 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 | built-in pure-Go scanner — class=/id= references into CSS selector nodes (template placeholders skipped) | .html | styles reference edges |
Vue SFCs: a
.vuefile's<script>/<script setup>block (withlang="ts"routing to TypeScript, unmarked/lang="js"to JavaScript) is delegated to the sametypescript-language-serverconnection that indexes plain.ts/.jsfiles. Template/style blocks are not indexed. A project with only.vuefiles (no plain.ts/.js) spawns the server itself to serve the script blocks.
The language servers auto-enable when installed — run codemap doctor 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; SQL; YAML; HTML/CSS. 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 for the T0–T4 admission gates, the Rust pilot, and the project-level SCIP importer design.
From source
git clone https://github.com/abdul-hamid-achik/codemap
cd codemap
task build # → ./bin/codemap (or: go build ./cmd/codemap)
Go install
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 for what changed in each version.
Quick start
# 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. 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 # stats + warns if the index is stale vs your files
# 6. 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
# 7. Explore visually
codemap studio
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 |
| Navigate | `read-order` / `map` / `explore` | ranked reading list, bounded architecture overview, or intent-to-structure orientation |
| 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 |
| 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` | wire codemap (MCP server + playbook) into an AI coding harness |
| Surfaces | `serve` / `studio` | MCP server (stdio) and interactive TUI |
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 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, plain function calls still come 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. Ordinary function calls (`foo()`) still have no name-based TS/JS
edges: `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.
Needs `typescript-language-server` on `PATH`.
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):
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 ```
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:
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):
{
"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 26-tool surface derived from the taught agent workflow (25 named tools plus codemap_docs). The compatible core profile has the same inventory today; the default full profile remains the explicit 44-tool expert/admin surface. See MCP tool profiles for the measured schema cost and precedence rules.
Tools (44): 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_secret_impact, codemap_required_keys, codemap_risk, codemap_hotspots, codemap_orphans, codemap_coverage, codemap_read_order, codemap_map, codemap_explore, codemap_traverse, 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_explore, and codemap_traverse are extended orientation surfaces registered only in the default full MCP 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. Override paths with CODEMAP_CONFIG / CODEMAP_DATA; contributors should also read AGENTS.md.
How it fits the ecosystem
codemap is built on veclite and shares conventions with vecgrep (semantic code search) and 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 · Quick start · CLI · Configuration · Agent guide · MCP · Languages. Contributor rules live in AGENTS.md.
License
MIT © 2026 Abdul Hamid Achik











