assistgraph
v0.2.8
Published
File-level dependency knowledge graph CLI for JS/TS/Python codebases. Produces a JSON graph, an Obsidian vault, and an MCP server so agents like Claude and Codex can query your repo without grepping.
Maintainers
Readme
assistgraph
File-level dependency knowledge graph for JavaScript, TypeScript, and Python codebases. Produces a JSON graph, an Obsidian vault, and an MCP server so agents like Claude and Codex can query your repo without grepping.
The problem
Large codebases are expensive to reason about. Developers spend hours tracing imports before a migration, agents burn tokens grepping through dozens of files to answer "who uses this?", and shared components get refactored without understanding their blast radius.
assistgraph build solves this in under a second. One command scans every file, resolves every import, and produces a queryable dependency graph. That graph powers three things: an MCP server for AI agents, an Obsidian vault for humans, and a JSON file for anything else.
What this unlocks
For migrations and refactors
Instead of guessing which files belong to a feature, query the graph for the exact dependency tree. Planning to migrate pipelines? The graph tells you it's 10 components, 5 hooks, 1 store, and 3 type files — plus exactly which shared files they depend on and what depends on them.
- Precise scope —
get_dependencies(transitive) returns every file a feature touches, no manual tracing - Impact analysis —
get_dependentsshows what breaks before you move anything. A file likeapi-client.tswith 42 dependents needs careful handling; a leaf component with 1 dependent can move freely - Dead code exclusion — orphan detection separates genuinely unused files from legitimate entrypoints (
index.ts,main.py, etc.), so you skip or delete dead code rather than migrate it - Cycle detection — tangled features need decoupling before they can move independently. The graph finds these upfront
For AI agents (Claude Code, Codex, Cursor)
The MCP server exposes 12 query tools that turn expensive exploration into cheap lookups.
Without the graph, an agent answering "what does the auth feature depend on?" has to recursively open files, parse imports, grep for usages, and iteratively discover the file set — burning hundreds of thousands of tokens. With the graph, it's a single get_dependencies call returning the exact file list in a few hundred tokens.
The same applies to every structural question: "what imports this hook?", "are there cycles in this module?", "what's the shortest path between these two files?" — all O(1) graph lookups instead of O(N) file reads.
For codebase health
assistgraph audit gives you a snapshot of structural health:
- Hub files — the most-imported files in your codebase, ranked by dependents. These are your highest-risk shared dependencies
- Bloat candidates — files with the most outgoing imports (god files that know too much)
- Cross-folder coupling — exactly how many edges cross between
ui/andapi/, quantifying how tangled your architecture really is - Orphans — files with zero incoming edges, separated from entrypoints so you can confidently clean up dead code
For visual exploration
Open the generated Obsidian vault and see your entire dependency graph with colour-coded communities, wiki-linked imports, and pre-configured graph settings. Each file note includes exports, imports, reverse imports, and metrics — all cross-linked.
Quick start
cd your-project
npx -y assistgraph buildThat's it. You now have:
assistgraph/graph.json— the machine-readable dependency graphassistgraph/vault/— an Obsidian-compatible knowledge vault with wiki links and colour groups- An MCP server (via
assistgraph mcp) — 12 tools for Claude Code / Codex / Cursor
# Peek at the stats
npx -y assistgraph stats
# Show what a file imports and who imports it
npx -y assistgraph query src/features/auth/Login.tsx
# Full audit: cycles, orphans, hubs, coupling (writes assistgraph/audit.md)
npx -y assistgraph audit
# Install Claude + Codex skills so agents know to prefer the graph
npx -y assistgraph install-skills
# Start the MCP server
npx -y assistgraph mcpThen point Obsidian at ./assistgraph/vault/ to see the graph visually.
Install
The fastest way is npx — no install needed. Or install a persistent global binary:
# Node / npm
npm install -g assistgraph
# Bun
bun install -g assistgraphoxc-parser ships platform-specific native bindings that npm picks automatically on install. Once installed globally, drop the npx -y prefix from every command.
Features
- Languages: TypeScript, TSX, JavaScript, JSX, MJS, CJS, Python
- Strict
.gitignoreenforcement: anything in.gitignoreis invisible to assistgraph - CWD is the scan root: run it anywhere — at the repo root for the full picture, or in a subfolder for a focused graph
- Monorepo support: discovers
tsconfig.jsonin subdirectories and parent directories, withextendschain resolution. Each source file uses its nearest tsconfig for path alias resolution - Path alias resolution:
@/*,~/*, and custom tsconfigpathsall resolve correctly - Folder-based communities: folders become feature communities automatically, mirroring your codebase structure
- Cycle detection: iterative Tarjan SCC — handles deep dependency chains without blowing the stack
- Hub/bloat metrics: top imported files, top bloat candidates, cross-folder coupling
- Orphan detection with entrypoint heuristics: dead code is separated from legitimate entrypoints (
index.ts,main.py,manage.py, etc.) - Content hashing: every node has a stable hash for future incremental builds
- Obsidian colour groups: each top-level folder gets its own colour automatically
All parsing is deterministic and offline. Zero LLM calls, zero databases, zero Python runtime required.
Requirements
- Node 18+ or Bun 1.0+
- No Python runtime required even for Python projects — parsing is pure JavaScript
Claude Code / Codex integration
MCP server config
Add one of the following to your Claude Code / Codex / Cursor MCP config. The npx / bunx variants require no pre-install — the package is fetched on first run and cached for subsequent launches.
Node / npm (recommended):
{
"mcpServers": {
"assistgraph": {
"command": "npx",
"args": ["-y", "assistgraph", "mcp"]
}
}
}Bun:
{
"mcpServers": {
"assistgraph": {
"command": "bunx",
"args": ["assistgraph", "mcp"]
}
}
}Globally installed binary:
{
"mcpServers": {
"assistgraph": {
"command": "assistgraph",
"args": ["mcp"]
}
}
}The MCP server reads ./assistgraph/graph.json from its working directory and holds it in memory. If no graph exists yet, the server starts anyway — tools return a helpful message asking you to run assistgraph build, then call reload_graph. Re-run assistgraph build whenever you want the graph to reflect new or moved files, then call the reload_graph tool to swap the in-memory graph without restarting.
Skill install
npx -y assistgraph install-skillsWrites:
~/.claude/skills/assistgraph/SKILL.md~/.codex/skills/assistgraph/SKILL.md
The skills teach agents when and how to use the graph — they'll proactively suggest it for refactors, migrations, and audits, check freshness before rebuilding, and run assistgraph audit for codebase health checks instead of making many individual queries.
To update the skills after upgrading assistgraph, re-run with --force:
npx -y assistgraph install-skills --forceWithout --force, existing skill files are skipped. You can also install selectively with --claude-only or --codex-only.
MCP tools
| Tool | What it answers |
|---|---|
| graph_stats | How big is this codebase? How many files, edges, cycles? |
| list_files | What files exist? (paginated, filterable by language) |
| get_file | Full metadata for one file — imports, exports, dependents, community |
| get_dependencies | What does this file (or feature) depend on? (transitive, depth-limited) |
| get_dependents | What breaks if I change this file? (transitive, depth-limited) |
| find_path | How are these two files connected? (shortest dependency path) |
| search_files | Find a file by name (fuzzy substring match) |
| list_communities | What are the feature boundaries in this codebase? |
| get_community | What files belong to this feature/folder? |
| find_cycles | Where are the circular dependencies? |
| find_orphans | What files are unused? (with entrypoint detection) |
| reload_graph | Pick up a rebuild without restarting the server |
Obsidian integration
Point Obsidian at ./assistgraph/vault/ and open the graph view. Colour groups are pre-configured so each top-level folder gets its own colour, with language colours as a fallback.
To customise colours manually: Graph view → Settings (gear) → Groups. Your changes are preserved on subsequent assistgraph build runs — the default config is only written when no custom colour groups exist.
Each file note contains:
- YAML frontmatter (path, language, community, loc, exports, tags)
## Exports— named + default exports## Imports— wiki-linked to sibling files + external stubs## Imported By— reverse index## Metrics— LOC, size, import/dependent counts, content hash
CLI reference
assistgraph build [--root <dir>] [--no-vault] Scan CWD -> graph.json + vault/
assistgraph query <path> Deps + dependents for a file
assistgraph stats Graph stats
assistgraph audit [--out <path>] Cycles, orphans, hubs, coupling (+ audit.md)
assistgraph mcp Start MCP stdio server
assistgraph install-skills [--force] [--claude-only] [--codex-only]
Install Claude + Codex skill files
assistgraph init Create assistgraph.config.jsonOutput layout
<cwd>/
├── assistgraph.config.json <- optional, check into git
└── assistgraph/ <- generated, add to .gitignore
├── graph.json <- canonical graph
├── audit.md <- generated by `assistgraph audit`
└── vault/ <- Obsidian-compatible vault
├── .obsidian/graph.json <- pre-configured colour groups
├── README.md <- entry MOC
├── _communities/ <- one MOC per folder community
├── _externals/ <- one stub per external package
└── <mirror of your source tree>/*.mdConfiguration
Optional assistgraph.config.json at the scan root:
{
"include": ["**/*"],
"exclude": [
"assistgraph/**",
"node_modules/**",
"dist/**",
"build/**",
"__pycache__/**",
".venv/**"
],
"resolver": {
"tsconfig": null,
"pythonRoots": ["."]
},
"output": {
"dir": "assistgraph"
}
}Everything has sensible defaults. You only need this file if the defaults don't fit your project.
Running in a subfolder
cd src/features/auth
npx -y assistgraph buildThe scan root becomes the current folder. Imports that leave the scan root become external leaf nodes (with their absolute path preserved). This is useful for:
- Focused feature analysis — build a graph of just
src/features/pipelines/to see its internal structure without noise from the rest of the codebase - Shared component mapping — build from
src/shared/components/to see how shared components relate to each other - Pre-migration scoping — graph a feature folder to understand its internal dependencies before extracting it into a package
When scanning a subfolder, assistgraph still walks up to find the nearest tsconfig.json, stopping at any parent package.json — so @/... and @shared/... aliases keep resolving correctly.
Graph schema
interface Graph {
version: '1.0';
generatedAt: string;
scanRoot: string;
stats: { nodes; edges; orphans; cycles; languages };
nodes: Record<string, GraphNode>;
edges: GraphEdge[];
communities: Record<string, GraphCommunity>;
cycles: GraphCycle[];
}
interface GraphNode {
id: string; // scan-root-relative path
name: string; // basename
path: string;
absolutePath: string;
language: 'ts' | 'tsx' | 'js' | 'jsx' | 'mjs' | 'cjs' | 'py' | 'external';
isExternal: boolean;
loc: number;
sizeBytes: number;
exports: string[];
imports: ImportRef[];
community: string;
contentHash: string;
}
interface ImportRef {
raw: string; // the literal specifier, e.g. "./foo" or "@/lib/bar"
resolved: string | null;
symbols: string[]; // named bindings pulled in - symbol-aware, migration-ready
kind: 'static' | 'dynamic' | 'type' | 'require' | 'reexport' | 'python';
}
interface GraphEdge {
from: string;
to: string;
kind: ImportRef['kind'];
}
interface GraphCommunity {
id: string; // folder path, e.g. "src/features/auth"
members: string[];
parent: string | null;
}
interface GraphCycle {
members: string[];
length: number;
}What assistgraph does NOT do
- Function- or class-level resolution — file-level imports only
- Runtime analysis — static AST parsing only
- Type inference beyond what's declared in imports
- HTML or Vue SFC or Astro parsing
- Call graph construction
- LLM-based enrichment (roadmap)
FAQ
Why are all the files the same colour in Obsidian's graph view?
Obsidian starts every vault with no colour groups. assistgraph build writes .obsidian/graph.json with sensible defaults (one colour per top-level folder). If you already had the vault open, quit Obsidian fully (Cmd+Q), re-run assistgraph build, then reopen — Obsidian caches the settings in memory and overwrites the file on close.
Why aren't my ui/ and app/ folders visually split?
Obsidian uses a force-directed layout; folder structure isn't an input. If ui/ and app/ are intermingled, they're geometrically intertwined because of edges between them. Run assistgraph audit and check the "Cross-folder Coupling" section to see exactly how many edges cross the boundary.
Does this work in a monorepo?
Yes. Run assistgraph build at the repo root for a unified view, or in a specific package for a focused view. The resolver discovers tsconfig.json files in subdirectories and follows extends chains, so path aliases resolve correctly across packages.
How do I update the agent skills after upgrading assistgraph?
Run npx -y assistgraph install-skills --force. Without --force, existing skill files are preserved and the install is skipped.
Should I commit assistgraph/ to git?
No. Add assistgraph/ to your .gitignore. The graph is generated output — anyone can rebuild it with assistgraph build. The optional assistgraph.config.json at the project root should be committed if you customise it.
Does this replace dependency-cruiser / madge?
No — those are richer JS-only tools. assistgraph trades depth for breadth: one tool across JS/TS + Python, an Obsidian vault for humans, and an MCP server for agents.
License
MIT.
