codemap
Local-first code intelligence that gives AI agents and people structural awareness ofcodebases — combining a code graph (LSP + parsers) with semantic vector search (veclite),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 forconventions, architecture, and gotchas.
codemap answers questions that grep and a single LSP call can't: who calls this function andwhich tests cover it, what's the blast radius of changing this type, find auth-like code andthen show me everything that calls into it. It precomputes thestructure once, then serves narrow, structured answers — so an agent spends a few tool callsinstead of dozens of file reads.
Features
- Structural code graph — files, functions, types, methods, and tests as nodes; call edges(name-based by default, exact via
go/typeswith--precise) and defines edges (file → symbol).Test coverage is derived by walking the call graph to test nodes. Stored in pure-Go SQLite,queryable offline. Indexes Go (stdlibgo/parser, full call graph), TypeScript + JavaScript(onetypescript-language-server, calls resolving across the.ts↔.jsboundary), and Python(pyright-langserver) — the LSP-backed languages give symbols + structure always, plus a precisecall graph under--precise, socallers/impact/hotspots/pathwork for them too.Structure-only markup (Vue/HTML/CSS/Docker) is next. Semantic search islanguage-agnostic. - Semantic search — every node's source is embedded (Ollama
nomic-embed-text, 768-dim)into veclite; vector + BM25 hybrid search. - Impact analysis —
impactreturns a symbol's definition sites, direct callers, thetransitive blast radius (everything affected by a change), and which tests cover thosepaths (flagging untested code). - Built for agent harnesses —
context <symbol>bundles definition + callers + callees +tests + blast radius in one call (no four-round-trip stitching), andstatusreports indexfreshness (files changed since indexing) so an agent reindexes before trusting a stale answer. - Multi-project registry — one shared store indexes all your repos;
projectslists what'sindexed, and any query targets one project (resolved from cwd, or--path). - Annotations — pin notes and external data (DB rows from mongosh/postgres, vidtrace/vecgrepfindings, …) to a symbol or a call path; they persist across reindex. A knowledge layer over thegraph for agent harnesses (
annotate/annotations, also on MCP). - Precise call resolution — the fast name-based graph over-matches same-named methods(
x.Close()links to everyClose). Onecodemap index --preciseresolves each call to the oneit actually invokes and makes every query — callers, callees, impact, hotspots, path — exact atonce, no per-query flag (e.g. aClosemethod that name-matching credited with 71 callers shows onlyits real ones). It's the unified exact-resolution pass across languages: an in-process, pure-Gogo/typespass for Go, and the language server'scallHierarchyfor the LSP languages(TypeScript, JavaScript, Python — which have no name-based call edges, so--preciseis what givesthem a call graph at all). Opt-in and additive (name-based stays the default for Go); the Go passdegrades to name-based with a notewhen thegotoolchain or module isn't available. For a one-off exact answer without reindexing,callers/calleesalso take--lsp(goplscallHierarchy). CLI + MCP. - Incremental — hash-based reindex; an embedding-profile guard forces a rebuild when theprovider/model/dimension changes instead of corrupting the vector space.
- Three surfaces, one store — a Cobra CLI (with
--jsonfor agents), a stdio MCPserver, and the studio TUI for humans. - Graph analytics —
hotspots(hubs),orphans(dead-code candidates), andpath(shortest call path between two symbols). - Local-first & private — everything runs on your machine; no cloud, no uploads.
- Single binary — pure-Go,
CGO_ENABLED=0, cross-compiled and shipped via Homebrew.
studio (TUI)
codemap studio opens an interactive, full-screen explorer of your code (Charm v2 — BubbleTea / Lip Gloss / Bubbles). Switch tabs with 1–4 or tab; navigate with ↑/↓.
codemap studio codemap · 509 nodes · 1849 edges · 35 files
1 Graph 2 Metrics 3 Impact 4 Search
Hubs (164) │ lspsrc.Extractor.Close
57 lspsrc.Extractor.Close │ Called by (57)
56 app.Session.Close │ ▸ main.runInit cmd/codemap/main.go:186
56 graph.Store.Close │ main.runIndex cmd/codemap/main.go:209
26 app.NewService │ Calls (9)
19 app.Open │ app.Session.Close internal/app/session.go:80
▼ 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), andthe selected node's signature is previewed (⟩ func runInit(...)).
- Graph — a call-graph explorer: hubs (most-referenced symbols) on the left as jumppoints, the centered node's callers and callees on the right. Press
→to focus the rightpane and walk the graph —enterre-centers on a caller/callee so you can traverse thecall chain;backspacesteps back;sreads the selected symbol's source in ascrollable 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-codecandidates (no callers). Both lists are navigable —
enterdrills a row into Impact,ctrl+sreads 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 noembeddings (so it works even without Ollama).
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
--lspprecise Go results - Optional: Task for the dev workflow
Languages — structure + semantic search work for all of these; a precise call graph(callers/callees/impact/hotspots/path) needs --precise:
| Language | How | Extensions | Call graph |
|---|---|---|---|
| Go | built-in go/parser (+ go/types for --precise) |
.go |
name-based by default; exact with --precise |
| TypeScript / JavaScript | typescript-language-server (one server, JSX/TSX-aware, resolves across the .ts↔.js boundary) |
.ts .tsx .js .jsx .mjs .cjs |
--precise only |
| Python | pyright-langserver |
.py |
--precise only |
The language servers auto-enable when installed — run codemap doctor to see which aredetected, or --no-lsp to skip. Structure-only markup (Vue/HTML/CSS) is planned; other recognizedlanguages are reported as skipped. Semantic search is language-agnostic.
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
Quick start
# 1. Register and index a project
codemap init # registers the current directory
codemap index # extract graph + embed nodes (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)
# 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. Orient on a symbol — everything in one call (definition, callers, callees, tests)
codemap context authenticateUser # the one-call overview (agents: codemap_context)
# 3. Navigate the call graph
codemap callers authenticateUser # who calls it (fast, name-based)
codemap callers authenticateUser --lsp # exact callers via gopls (Go)
codemap callees authenticateUser # what it calls
codemap path Handler Login # shortest call path between two symbols
# 4. Analyze impact and structure
codemap impact authenticateUser --depth 3 # callers + blast radius + tests
codemap hotspots --top 20 # most-referenced symbols (hubs)
codemap orphans # functions with no callers (dead-code candidates)
codemap status # stats + warns if the index is stale vs your files
# 5. Search by meaning (needs an embedded index)
codemap semantic "jwt validation middleware" --top 10
# 6. 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: 3
blast radius: 11 (depth ≤ 2)
tests covering: 6
covering tests (run these):
graph.TestBlastRadius internal/graph/graph_test.go:305
graph.TestBlastRadiusCycleSafe internal/graph/graph_test.go:347
app.TestQueryResultsCarrySignature internal/app/app_test.go:175
app.TestImpactSurfacesAnnotations internal/app/app_test.go:343
app.TestImpactWarnsOnAmbiguousName internal/app/app_test.go:1250
app.TestServiceImpact internal/app/app_test.go:1427
affected (blast radius):
[1] app.Service.Impact internal/app/service.go:983
✓ [1] graph.TestBlastRadius internal/graph/graph_test.go:305
✓ [1] graph.TestBlastRadiusCycleSafe internal/graph/graph_test.go:347
[2] main.runImpact cmd/codemap/main.go:572
✓ [2] app.TestQueryResultsCarrySignature internal/app/app_test.go:175
✓ [2] app.TestImpactSurfacesAnnotations internal/app/app_test.go:343
✓ [2] app.TestImpactWarnsOnAmbiguousName internal/app/app_test.go:1250
✓ [2] app.TestServiceImpact internal/app/app_test.go:1427
[2] app.Service.Context internal/app/service.go:1322
[2] mcp.Server.handleImpact internal/mcp/server.go:320
[2] tui.Model.impactCmd internal/tui/model.go:522
Long lists are capped for readability (the nearest blast-radius nodes and thefirst covering tests, with a … (N more) line); --json always carries thecomplete set.
Commands
| Command | What it does |
|---|---|
init / index / status |
register, index (incremental; --reindex, --no-embed, --no-lsp, --precise), show stats |
doctor |
check the environment — toolchains, language servers, embeddings — with install hints |
projects |
list all registered projects and their index sizes |
callers / callees / path |
call-graph navigation (--lsp on callers/callees for exact gopls results) |
symbols |
list a file's symbols (structured alternative to reading it) |
find |
find symbols by name (offline) |
source |
print a symbol's source code (the body behind its signature) |
context |
one call, everything about a symbol: definition, callers, callees, covering tests, blast radius, notes |
docs |
print the agent guide to codemap (docs [topic]) |
annotate / annotations |
pin / list notes + external data on a symbol or call path |
impact |
blast radius + test coverage for a symbol (--depth) |
hotspots / orphans |
hubs / dead-code candidates (--top) |
semantic (alias search) |
meaning-based search (--top) |
serve |
run the MCP server (stdio) |
studio |
open the 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. Itresolves 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 nameresolves to multiple definitions, and hotspots marks name-collision inflation.
For an exact graph, reindex with codemap index --precise (Go). It runs an in-process, pure-Gogo/types pass that resolves every call to the one method it actually invokes and replaces thename-based call edges — so every query (callers, callees, impact, hotspots, path) becomesprecise at once, with no per-query flag. On the codemap repo itself this collapses the Close/Errorfan-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
gotoolchain and a buildable module. A package that doesn't type-check keeps itsname-based edges (per-package degrade); a project with nogo/go.modfalls back wholesale witha 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, notthe concrete implementors.
For TypeScript, --precise is the only source of call edges. The name-based pass extracts TSstructure (classes, methods, functions) but not calls, so a plain index gives TS no call graph;index --precise drives typescript-language-server callHierarchy to resolve them exactly, and thesame callers/callees/impact/hotspots/path queries then work for TS with no flag of their own.Needs typescript-language-server on PATH.
For a one-off exact answer without reindexing, callers/callees also accept --lsp (goplscallHierarchy), which likewise degrades to name-based with a note when gopls can't resolve.
orphans finds call-graph dead ends. It follows functions wired by value — handlers in atable like cobra's RunE: runInit, callbacks passed to a registrar — and excludes methods thatimplement well-known stdlib interfaces (error, fmt.Stringer, Unwrap, the JSON/textmarshalers), so those aren't flagged as dead (Go). It still can't see callers reached viacustom interface dispatch or reflection, so treat its output as candidates, not proof.
Use it from an agent (MCP)
codemap is a stdio MCP server. Register codemap serve with your agent — 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, orcontext_servers):
{
"mcpServers": {
"codemap": { "command": "codemap", "args": ["serve"] }
}
}
Once connected, an agent can call codemap_docs to learn the tools and workflow on its own.
Tools (20): codemap_init, codemap_index, codemap_status, codemap_doctor, codemap_semantic,codemap_callers, codemap_callees, codemap_impact, codemap_hotspots,codemap_orphans, codemap_path, codemap_symbols, codemap_find, codemap_source,codemap_context, codemap_projects, codemap_docs, codemap_annotate, codemap_annotations,codemap_unannotate. Each takes anoptional path (the project directory) and returns JSON. The two an agent reaches for first:codemap_context <symbol> bundles a symbol's definition, callers, callees, covering tests andblast radius in one call (instead of four), and codemap_status reports index freshness —a stale count of files changed/added/removed since indexing, so the agent knows to reindex beforetrusting results. codemap_callers / codemap_callees accept precise: true for exact,gopls-resolved results (Go); codemap_source returns a symbol's body; codemap_projects listswhat'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) tosymbols and call paths — a knowledge layer over the graph (see below).
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 areand 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, thetransitive 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 --localdrops a .codemap marker so a repo-local codemap.yaml is picked up from any subdirectory; theindex stays central (set CODEMAP_DATA to a path inside the repo for a repo-local index). Precedence and all keys are documented inAGENTS.md. Override paths with CODEMAP_CONFIG / CODEMAP_DATA.
How it fits the ecosystem
codemap is built on veclite and sharesconventions with vecgrep (semantic codesearch) and noted (code notes). An agent cancombine them: vecgrep/codemap to find code by meaning, codemap to learn what calls it andwhat breaks if it changes.
Documentation
Full docs: docs/ (VitePress). Design rationale: SPEC.md.
License
MIT © 2026 Abdul Hamid Achik