Model or dataset
bartolli/codanna avatar
bartolli/codanna

Codanna: a local code intelligence MCP server that folds five tools into one call

Local code intelligence MCP server and CLI for AI coding agents

742 stars70 forksRustApache-2.0

At a glance

What is it?
Codanna indexes a repository on disk and serves symbol search, call graphs, impact analysis and document RAG to MCP-compatible coding agents, either as a persistent server or as a one-shot CLI. The interesting part is the fused query; the parts to check before adopting are index freshness, embedding setup and language coverage.
Who is it for?
Adopt Codanna if your agent workflow is already shell-driven or MCP-based and you want call-graph and impact answers without sending source to a remote API. Skip it if your repository is dominated by languages outside its 15-language parser set, or if you cannot accept that the index under .codanna/ must be rebuilt as the tree changes.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The grep-and-read loop Codanna is trying to replace

A coding agent asked to change a function usually does the same thing: search for the name, open the file, read around it, search again for callers, open those files, and repeat. Each step is a round trip, and the agent reconstructs relationships from text it just read. Codanna's stated premise is that this loop can be collapsed. The README describes one MCP call returning symbol context, call graph and impact analysis, pre-correlated, and calls the result the grep-and-read loop "collapsed into a single response it can act on." The target user is whoever is wiring an agent into a real repository: Claude Code, Cursor, Windsurf, Codex and Gemini are named as compatible clients, plus any MCP-compatible client. The CLI path exists for a second audience, people who want the same answers inside slash-commands, bash hooks, scripts or CI without running a daemon. That second path matters more than it looks, because it means a skill can wrap codanna mcp commands in a harness that never speaks MCP at all.

What semantic_search_with_context actually returns

The README shows the headline command run against Codanna's own tree. A query for "recursively extract function calls" with limit:1 returns a single match, extract_calls_recursive, with a similarity score of 0.833, its docstring, its full Rust signature including lifetimes, three callees with the exact line where each is called, two callers, and an impact list naming one symbol at max depth 2. Every entry carries file:line coordinates and a symbol_id. That symbol_id is the piece that makes the output usable rather than decorative: it gives the agent a stable handle for disambiguating name collisions, so two functions called new in different modules are not confused. The output also ends with a guidance hint the README says the agent can chain on. The README frames this as five MCP tools fused into one query, and --json switches the response to a structured envelope for programmatic consumers. The honest reading is that the value is in the fusion, not in any single tool. A plain symbol lookup is something an LSP already does well.

Two run modes, and why the one-shot CLI is the more portable one

Codanna exposes the same tool surface two ways. The persistent server is started with codanna serve for stdio, codanna serve --http, or codanna serve --https, and is aimed at session-long agent work where keeping the index warm pays off. The one-shot path runs a single tool per process: codanna mcp find_symbol name:"my_function", codanna mcp analyze_impact symbol_name:"my_function", or codanna mcp semantic_search_with_context query:"recursively extract function calls". No daemon is required for the second form. The trade-off is straightforward and the README does not hide it: one-shot invocations pay process startup and index load on every call, which is fine for a slash-command or a CI check and wasteful inside a long agent session. The persistent server inverts that. If you are unsure which you need, the deciding question is whether the agent will ask more than a handful of questions in one sitting. The README's own framing, that the CLI is what makes Codanna skill-friendly, suggests the one-shot mode is not a fallback but a deliberate integration surface.

Install, init, index: the commands that matter

Installation is one line on macOS, Linux and WSL: curl -fsSL --proto '=https' --tlsv1.2 https://install.codanna.sh | sh. Homebrew users get brew install codanna, Nix users get nix run github:bartolli/codanna, and Windows users run the PowerShell installer from scripts/install.ps1. The README points to a separate installation guide for Cargo and other options, so the binary is not the only route. Setup is two commands: codanna init, then codanna index src. Note that the index command takes a path, so you can scope it to a subtree instead of the whole repository, which is the sensible first move on a large monorepo. Documentation RAG is a separate pipeline with its own state: codanna documents add-collection docs ./docs registers a collection, codanna documents index builds it, and codanna mcp search_documents query:"authentication flow" queries it. The index lives on disk under .codanna/. The embedding model downloads once on first use and then runs locally. Remote OpenAI-compatible embeddings are opt-in through remote_url under [semantic_search] in settings.toml, or through CODANNA_EMBED_* environment variables, with the API key supplied by environment only rather than written into the config file.

Local-first is a real constraint, not just a slogan

The default posture is that no source code, symbols or queries leave the machine. That is the strongest argument for Codanna in codebases where sending source to a hosted embedding API is a non-starter. It also creates the first operational cost: the embedding model has to be downloaded once, and until that completes, semantic search has nothing to query against. On a locked-down network or an air-gapped build machine, that first fetch is the step that fails, and the README does not describe an offline model provisioning path. The remote embedding option exists but it is opt-in and it is precisely the thing the local-first claim is contrasting against, so enabling it changes the privacy story you started with. A second constraint follows from indexing a snapshot: the index is built by an explicit command and lives in .codanna/, so it reflects the tree at index time. The README does not describe a file watcher or incremental re-index behaviour, which means freshness is something you schedule rather than something you get. In an agent session that edits files as it works, that gap is worth understanding before you trust an impact analysis.

Where Codanna is the wrong tool

The README states 15 languages. Fifteen is a lot and it is also a boundary. If your repository is mostly in a language outside that set, the parser produces nothing useful for those files, and semantic search over them degrades toward text matching. The README does not enumerate the 15 languages, so the first thing to verify for your own codebase is whether your primary language is among them. A second case where Codanna is the wrong choice is a single-file or single-function question. If you want to know where one symbol is defined in a file you already have open, an LSP already answers that with no index, no model download and no .codanna/ directory to keep current. Codanna earns its setup cost when the question spans files and requires relationships: callers, callees, blast radius. A third case is a repository that changes faster than you are willing to re-index, since a stale call graph is worse than no call graph when an agent acts on it. Finally, the README does not make accuracy claims about the call graph itself. Dynamic dispatch, macros, generated code and reflection are the usual places static call graphs go incomplete, and nothing in the supplied material says how Codanna handles them. Treat the impact list as a strong hint, not a proof.

How it compares to LSP and to hosted code search

The nearest alternative is the language server you probably already run. An LSP answers definition, reference and hover queries with a live, editor-managed view of the project, and it does so without an embedding model or a persisted index. What an LSP does not do is answer a natural-language question like "where do we handle errors" or return a fused response containing a symbol, its documentation, its callees and a recursive impact list in one payload. Codanna's own framing is that the CLI is for "instant answers when LSP is too slow," which positions the two as complements rather than substitutes. The other alternative is a hosted code search or RAG service. Those remove the local index and model download from your plate and usually add cross-repository search, but they require your source to leave the machine, which is exactly the property Codanna is built to avoid. The choice between them is a data-handling decision before it is a feature decision. Codanna is Apache-2.0 licensed, so the licence permits commercial and closed-source use and modification; the usual obligations around attribution and notice files apply, and if you redistribute a modified binary you should read the licence text rather than a summary of it.

Maintenance cost and what to check before you commit

The release cadence visible in the repository is fast: v0.14.0, v0.15.0 and v0.16.0 all landed within roughly four days in late August 2026. Fast iteration on a tool that writes an index format into your working tree is a real consideration, because a format change between minor versions can mean a re-index, and the README does not describe index format stability guarantees. Pin a version in CI rather than tracking latest, and expect to re-run codanna index after upgrades. The other recurring cost is the index itself: it lives under .codanna/, so it needs to be added to .gitignore, and it consumes disk proportional to the repository. Two things are worth verifying on your own code before wider rollout. First, whether the languages you care about are in the supported set, by indexing one representative subdirectory and running codanna mcp find_symbol against a function whose callers you already know by hand. Second, whether the call graph is complete enough for your code's idioms, by running codanna mcp analyze_impact on a symbol with dynamic or generated call sites and comparing the result against what you know. If those two checks pass, the fused query is genuinely more useful than a sequence of greps. If they do not, no amount of setup will fix it.

Editorial conclusion

Adopt Codanna if your agent workflow is already shell-driven or MCP-based and you want call-graph and impact answers without sending source to a remote API. Skip it if your repository is dominated by languages outside its 15-language parser set, or if you cannot accept that the index under .codanna/ must be rebuilt as the tree changes. Before committing, run codanna init, index a single subdirectory rather than the whole repo, and confirm that codanna mcp find_symbol returns real call sites for your language; then check whether the first-run embedding model download is acceptable on your network.

Official sources

  1. bartolli/codanna on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes