Codanna explore
npx -y skills add antono/agent-skills --skill codanna-exploreAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Explore an indexed codebase on a specific topic using codanna's semantic search, symbol lookup, and call/dependency graphs. Use when the user asks to investigate, map, or understand a feature, subsystem, concept, or symbol.
SKILL.md
11.9 KB, as published. Nobody here has run it
Codanna Explore
Topic-driven codebase exploration via codanna's local code intelligence (semantic search + tree-sitter symbol graph + RAG over docs).
Docs: https://docs.codanna.sh/ · Repo: https://github.com/bartolli/codanna Workflow diagram & rationale: README.md
When to use
- User gives a topic: "explore the auth flow", "map the parser", "how does X work".
- Need call graph, callers, or impact analysis for a function / type.
- Need semantic ("find code that does Y") search, not just grep.
Don't use for: regex / text-pattern searches (use rg, fall back to
grep), nix lookups (search-nix-manix), or trivial single-file questions.
Tool surface (prefer MCP, fall back to CLI)
| Purpose | MCP tool | CLI |
|---|---|---|
| Status check | get_index_info | codanna mcp get_index_info --json | toon |
| Anchor in code | semantic_search_with_context | codanna mcp semantic_search_with_context query:"…" |
| Semantic over docstrings | semantic_search_docs | codanna mcp semantic_search_docs query:"…" limit:5 |
| Fuzzy symbol search | search_symbols | codanna retrieve search "…" --kind function --limit 10 |
| Exact symbol lookup | find_symbol | codanna retrieve symbol <name> |
| Symbol details | — | codanna retrieve describe <name> |
| Outgoing calls | get_calls | codanna retrieve calls <name|symbol_id:N> |
| Incoming callers | find_callers | codanna retrieve callers <name|symbol_id:N> |
| Trait implementors | — | codanna retrieve implementations <Trait> |
| Full dependency graph | analyze_impact | codanna mcp analyze_impact <name> |
| Docs RAG search | search_documents | codanna documents search "…" --collection <name> |
| List doc collections | — | codanna documents list |
Output flags: --json, --fields=<top-level-keys>, -k/--kind,
-l/--limit, -m/--module. Add --watch to codanna mcp … to reindex stale
files before the call.
--fields= only matches top-level JSON keys, not nested paths. For
retrieve search-style results the top level is symbol, file_path,
relationships — use --fields=symbol,file_path (not
--fields=name,symbol_id,file_path, which silently drops everything but
file_path). The symbol's ID lives at symbol.id, but the CLI/MCP input
parameter is symbol_id:N (name mismatch is intentional in codanna).
Default text output is often better than --json: codanna's default
formatter is compact, shows similarity scores, inlines relationships, and most
tools end with a 💡 hint pointing to the next useful call (e.g. "Explore
'get_calls' to see what it calls"). Read those hints — they save round-trips.
search_documents is the one exception that doesn't emit a 💡 line. Reach for
--json | toon only when you need to extract symbol.ids programmatically or
paginate large result sets.
Always suppress stderr when piping JSON through toon:
codanna ... --json 2>/dev/null | toon. Tantivy emits lock-busy warnings on
stderr that break toon's JSON parser.
Workflow
-
Status check —
get_index_infoandcodanna documents list. Branch into bootstrap ifsymbol_count: 0or no docs collections exist. Note:semantic_search.enabled: falseinget_index_infois misleading — the embedding model loads on demand. Trysemantic_search_*anyway; only fall back to fuzzysearch_symbolsif it actually errors. -
Bootstrap if missing (skip questions the user has already answered):
- 2a. Code — if not indexed, autodetect code dirs. Standard list:
src lib app cmd internal pkg. For JS/TS / web projects also considerpages components routes app server client. If nothing standard matches,lsthe repo root and ask the user which dirs to index. Thencodanna init+codanna index <dirs>. User refusal = stop; exploration needs code.codanna initalso drops a.codannaignore(gitignore-style file for codanna's indexer, with sensible defaults) — leave it committed. - 2b. Docs — if no collection, autodetect docs targets: directories
docs openspec ADRs adrs; or, if only a rootREADME.md(no docs/ directory), usecodanna documents add-collection readme . --pattern "README.md". Ask y/n, thencodanna documents index --all. User refusal or nothing detected = skip step 3. - 2c.
.gitignoretip — if any bootstrap actually ran, append (don't overwrite) these to the repo's.gitignore:.codanna/ .fastembed_cache.codanna/settings.tomlcontains absolute paths (workspace_root,indexed_paths) and machine-specific config, so the whole.codanna/directory must stay local..fastembed_cacheis a symlink into~/.codanna/models/— broken on every other machine. Leave.codannaignorecommitted (project-shared).
- 2a. Code — if not indexed, autodetect code dirs. Standard list:
-
Harvest concepts from docs (only when a docs collection exists) —
search_documents query:"<topic>". Read the previews and freeform-extract concepts and likely symbol names related to the query — no fixed schema, whatever looks useful. Feed into step 4. Note: enriching the anchor query often shifts the result set toward the harvested terms rather than simply boosting recall; compare with the bare query if you suspect drift. -
Anchor in code —
semantic_search_with_context query:"<topic + harvested terms>". Returns the highest-quality entry points (file + symbol + relationships). For top hits, call graph / callers / impact are inlined in the response — step 6 may be unnecessary for those symbols. No hits → rephrase once, then fall back to a regex search withrg/grep(step 8). -
Lock + disambiguate symbols —
find_symbol(exact) orsearch_symbols kind:function|struct|trait|class|method|interface. For same-name collisions, grab the symbol ID from--jsonoutput (the field path isdata[].symbol.idforretrieve search) and pass it assymbol_id:Ndownstream. You can shrink the payload with--fields=symbol,file_path(top-level keys only). -
Map relationships — treat as hints, not truth (codanna is static):
get_calls <sym|symbol_id:N>— outgoing dependencies.find_callers <sym|symbol_id:N>— incoming uses.analyze_impact <sym|symbol_id:N>— full blast radius. Usually small (10-30 lines in practice); call it freely and narrow withfind_callersonly ifdatais actually large. Often redundant when step 4 already inlined relationships.
-
Read source —
zat <file>for signatures-first skim, thenRead(offset, limit)into specific bodies. Usectx_readorReadwhen you need full text. -
Always-on regex sanity pass — run
rg(preferred) orgrepon the topic keyword + harvested terms from step 3. Catches what static analysis misses: macros, dynamic dispatch, FFI, generated code, string-based references. Run every time, not just when you suspect gaps. If new symbols surface, loop back to step 5. -
Report (text) — entry points as
path:line, call graph summary, surprising coupling, gaps where codanna's static view looked incomplete, plus any regex findings from step 8. -
Offer a markdown+mermaid report (only if the
mermaid-diagramsskill is listed as available) — after delivering the text report, ask the user whether they want a richer artifact with diagrams. Good candidates:- Call/dependency graph (flowchart) from
get_calls/find_callers/analyze_impactdata. - Sequence diagram for traced execution flow through the entry points.
- Component / module diagram when several modules are involved.
- Class diagram for struct / trait / impl relationships.
On yes → invoke the
mermaid-diagramsskill and emit a markdown file with embedded fenced```mermaidblocks. On no → done.
- Call/dependency graph (flowchart) from
Companion tools (prefer if installed)
Run command -v <tool> once per session, then route accordingly.
| Tool | Use for | Example |
|---|---|---|
toon | Codanna --json output you actually need to parse (extracting symbol.id, large result sets). Default text is usually better — see note above. | codanna retrieve search "parse" --json --fields=symbol,file_path 2>/dev/null | toon |
zat | Signature-first file reading (vs full cat / Read). Supports C, C++, C#, Go, Haskell, Java, JS, Kotlin, MD, Python, Ruby, Rust, Swift, TS/TSX. Exit 1 on unsupported. | zat src/parser.rs then Read(offset, limit) on interesting line numbers |
rg (ripgrep) | Default for any regex / text-pattern search — sanity pass for what codanna missed (macros, dynamic dispatch, FFI, generated code) | rg -nP --type rust 'macro_rules!\s*\w+' src/ |
grep | Regex fallback when rg not on PATH | grep -RnE 'pattern' src/ |
Routing rule: codanna first (structural understanding) → rg (or grep if
rg is unavailable) for any regex or text-pattern search.
Output shape
All MCP / retrieve JSON wraps results in
{type, status, code, exit_code, message, hint, data, meta}. The shape of
data varies by command — don't assume a single path:
| Command | data shape | How to extract |
|---|---|---|
get_index_info | object {symbol_count, file_count, ..., semantic_search:{}} | data.symbol_count |
find_symbol <name> (found) | object {symbol:{}, file_path, relationships:{}} | data.symbol.id, data.file_path |
find_symbol <name> (missing) | null (status: not_found) | read hint field |
retrieve search … / search_symbols | array [{symbol:{}, file_path, relationships:{}}, …] | data[N].symbol.id |
mcp get_calls / find_callers | array [{id, name, kind, file_path, …}, …] (flat — no symbol wrapper) | data[N].id |
search_documents | array [{chunk_id, collection, content_preview, source_path, …}, …] | data[N].source_path |
status: "not_found"→data: null; read thehintfield — it tells you the next useful move (e.g. "try semantic_search_docs"). Don't retry the identical query.- Most default-text outputs end with a
💡line carrying the same nudge.search_documentsis the exception — it has no trailing 💡.
Common pitfalls
| Pitfall | Fix |
|---|---|
| Semantic search returns nothing | Threshold is 0.6; rephrase, drop jargon, or fall back to search_symbols / rg. |
get_index_info says semantic_search.enabled: false | Misleading — the model loads on demand. Just call the semantic tool; only fall back if it errors. |
search_documents previews contain [1;36m...[0m garbage | ANSI escape codes (search-term highlighting) appear in both default text and --json content_preview fields. For machine reads, strip with sed 's/\x1b\[[0-9;]*m//g'. For human reads, accept the ANSI (terminals render it). Tantivy lock-busy warnings on stderr separately need 2>/dev/null. |
--fields=name,symbol_id,file_path returns only file_path | --fields matches top-level JSON keys only, not nested paths. Use --fields=symbol,file_path and dig into data[].symbol.id afterward. |
analyze_impact output worry | Often small (~20 lines). Just call it — check data.items length if it actually returns a lot, then narrow with find_callers. |
| Wrong symbol picked by name | Use symbol_id:N from a --json --fields=name,symbol_id,file_path search. |
| Macro / dynamic call missed | Codanna is static — verify with rg on suspicious gaps. |
Re-running same query after not_found | Read the hint field (or 💡 line) instead. |
| Stale index after edits | codanna index <dir> or codanna mcp … --watch. |
openspec/ folder ignored | Add it as an openspec documents collection (per global CLAUDE.md). |