codegraph
Reach for this whenever doing a task well depends on knowing how the codebase actually fits together — and getting that wrong would mean reasoning from a guess. The need is almost always buried inside
SKILL.mdskills/codegraph/SKILL.md
GitHubcodegraph
codegraph builds a real dependency graph of a codebase by parsing actual
import / require / #include statements — no LLM guessing, fully
deterministic. Once scanned, you query the graph instead of reconstructing
relationships in your head from greps. That distinction is the whole point: when
you hand-trace dependencies you reliably miss transitive chains, dynamic
import(), re-exports, and TypeScript path aliases. The graph already has them.
Reach for codegraph any time a question is fundamentally "how is this codebase wired together?" — impact, dependents, cycles, layers, dead code, doc-sync.
The one rule: scan first
Every query tool operates on an in-memory graph built by codegraph_scan.
Without a prior scan they return a "no graph loaded" error. So the first action
in any codegraph workflow is always:
codegraph_scan({ root_dir: "/abs/path/to/project" })
root_dir must be absolute. The scan returns counts by language, doc-file
count, and parse errors. The graph then persists for the whole session (and to
an on-disk cache keyed by the root path, so a later scan of the same root is an
incremental rescan — only changed files re-parse).
Re-scan after you've made significant edits. Incremental rescans are
mtime-based, which has one sharp edge: an unchanged file that gains a
newly-resolvable import to a newly-added file — or an edit to a non-tracked
config like tsconfig.json — is not picked up until the importer itself is
touched. When in doubt, force a clean rebuild:
codegraph_scan({ root_dir: "...", force: true })
Tools at a glance
Pick the tool by the job. Full parameters and return shapes are in
references/tools.md — read it when you need exact field names or are wiring
codegraph into a hook/script.
| Job | Tool |
|---|---|
| Build/refresh the graph | codegraph_scan (always first) |
| Keep graph live as files change | codegraph_watch_start / codegraph_watch_stop |
| What does X import? | codegraph_get_dependencies |
| What imports X? (who breaks if X changes) | codegraph_get_dependents |
| Full blast radius of changing file(s) | codegraph_get_change_impact |
| Local neighborhood around a file | codegraph_get_subgraph |
| Why does A depend on B? (shortest chain) | codegraph_get_path_between |
| Which docs must be reviewed after a change | codegraph_find_related_docs |
| Codebase overview / most-depended-on files | codegraph_get_stats |
| Architectural tiers (topological layers) | codegraph_get_layers |
| Circular dependencies | codegraph_find_cycles |
| Dead-code candidates (zero in, zero out) | codegraph_find_orphans |
| Roots (nothing imports them) | codegraph_find_entry_points |
| Enumerate code files | codegraph_list_files |
| Enumerate documentation files | codegraph_list_docs |
| Dependency diagram (Markdown/GitHub) | codegraph_export_mermaid |
| Dependency diagram (Graphviz → SVG/PNG) | codegraph_export_dot |
File arguments are fuzzy-resolved: you can pass an absolute path, a path
relative to the project root (src/auth/login.ts), or just a unique filename
(login.ts). If a bare filename is ambiguous, the tool tells you — qualify it
with more of the path.
Core workflows
These are the high-value sequences. They matter more than any single tool call.
Before you edit, refactor, rename, or delete a file
This is codegraph's primary use. Do not start changing a shared file until you know its blast radius — that knowledge changes how you make the edit (e.g. keeping a signature backward-compatible because 14 files depend on it).
1. codegraph_scan({ root_dir }) # if not already scanned
2. codegraph_get_change_impact({ files: ["src/api.ts"] })
→ directlyAffected, transitivelyAffected, totalImpacted,
blastRadius (a COUNT), coveragePercent
3. codegraph_get_subgraph({ file: "src/api.ts", depth: 2 }) # context to read first
4. codegraph_find_related_docs({ files: ["src/api.ts"] }) # docs to update too
Then make the change informed by what you found, and re-run
codegraph_get_change_impact if you want to confirm the surface you touched.
"Is this safe to delete?" / "What uses this?"
codegraph_get_dependents({ file: "src/legacy/helper.ts" })
dependentCount: 0 means nothing imports it — a deletion candidate, but verify
it isn't a legitimate entry point (CLI, test, route) before removing. For files
that are also importing nothing, codegraph_find_orphans surfaces the fully
isolated dead-code candidates in one shot.
Verify a completion claim (don't take "nothing else is affected" on faith)
When you — or another agent — claim a change was isolated, check it against the real graph instead of asserting it from memory:
codegraph_get_change_impact({ files: ["<the files that changed>"] })
If totalImpacted is larger than what was actually touched, the claim was
wrong. Pair with codegraph_find_related_docs to confirm no documentation was
left stale. This is exactly the check a completion-verification hook should run.
Architecture review of an unfamiliar codebase
1. codegraph_get_stats() # size, languages, most-depended-on (core) files
2. codegraph_get_layers() # tiers: layer 0 = leaf deps, up to entry points
3. codegraph_find_cycles() # circular dependencies (each ring reported once)
4. codegraph_find_orphans() # dead-code candidates
mostDependedOn from stats names the critical shared modules — the files where
a mistake propagates furthest. find_cycles and a deep get_layers together
tell you how tangled vs. cleanly-tiered the architecture is.
"Why does A depend on B?"
codegraph_get_path_between({ from: "src/index.ts", to: "src/db/pool.ts" })
Returns the shortest import chain from → … → to. If there's no forward path it
reports found: false plus a reverseExists hint (maybe B depends on A
instead).
Visualize the graph
codegraph_export_mermaid({ file: "src/api.ts", depth: 2 }) # paste into Markdown/GitHub
codegraph_export_dot({ max_nodes: 300 }) # pipe to `dot -Tsvg`
Omit file to export the whole graph (capped by max_nodes, default 200;
over the cap it keeps the highest-degree nodes and sets truncated: true).
Scope to a file + depth for a readable neighborhood diagram.
Things that will trip you up
Code index vs. docs index are separate.
codegraph_list_files,get_stats, and all dependency/impact tools operate only on code nodes (.ts,.js,.py,.cpp, …). Documentation (.md,.mdx,.rst,.txt) lives in a separate index. In a docs-only directorycodegraph_list_filesreturns nothing — usecodegraph_list_docs. (It will hint you towardlist_docsin that case.)blastRadiusmeans two different things. Incodegraph_get_change_impactit is a number (count of changed + impacted files). Incodegraph_find_related_docsit is an array of the affected code files. Read the field by the tool that returned it; don't assume it's a list.External packages are never pulled in. Manifests (
package.json,requirements.txt,go.mod) are graphed, but edges only go to local / workspace dependencies — the npm/PyPI/Go-module universe is deliberately excluded.Only local
#include "file.h"for C/C++. System includes (#include <vector>) are not edges.
When NOT to use codegraph
codegraph maps structural dependencies — who imports whom. It does not do semantic code search, "find me code that does X", or runtime/call-graph analysis. For "where is the function that validates emails" use grep/search or a semantic RAG tool, not codegraph. Use codegraph the moment the question turns to wiring: impact, dependents, cycles, layers, dead code, doc-sync.