project-index
Persistent, incrementally-updated code index. Replaces repeated re-analysis (grep + reading whole files) with cheap targeted queries. Typical savings: 90–98% of tokens on structural questions.
Script: scripts/project_index.py (run with python3, from repo root or with --root DIR).
Dependencies (auto-degrades to regex mode if missing):
pip install tree-sitter tree-sitter-python tree-sitter-javascript tree-sitter-typescript tree-sitter-go tree-sitter-rust tree-sitter-java --break-system-packages -q
Languages with full AST parsing: Python, JS/JSX, TS/TSX, Go, Rust, Java. Others (Ruby, PHP, C#, Kotlin, Swift): regex fallback, symbols only.
Workflow — follow this order
1. Session start (ALWAYS, before any grep/find/ls exploration):
python3 scripts/project_index.py update --root <repo> # builds or incrementally refreshes
python3 scripts/project_index.py map --root <repo> # ~1-2K token project overview
update is cheap: unchanged files are skipped by content hash. The map
output gives directories, entry points, and most-imported (core) modules —
usually enough to orient without reading any file.
2. Structural questions — query the index, do NOT grep:
| Question | Command |
|---|---|
| Where is symbol X defined? | where X (exact) / search X (substring) |
| What's in file F? (API surface) | file F — symbols with lines + imports |
| What does F import? | imports F |
| Who imports F? | importers F |
| What breaks if I change F? | impact F — transitive reverse deps by depth |
| Is index fresh? | stats |
File arguments accept suffixes: importers utils.js works if unambiguous.
3. Read code only after the index has narrowed the target. Use file F
to get the line number of the symbol, then Read that specific range —
not the whole file.
4. After editing files: run update again (fast) so later queries stay
correct. If stats reports stale files, run update before trusting queries.
When grep is still the right tool
The index knows structure (definitions, imports), not content. Use grep for: string literals, comments, config values, usage sites inside function bodies. Rule of thumb: "where is it defined / who depends on it" → index; "where does this exact text appear" → grep.
Artifacts
Index lives in <repo>/.claude/index/ — index.json (machine, queried by
script) and MAP.md (human/agent readable). Add .claude/index/ to
.gitignore or commit it — either works; update self-heals stale state.
MAP.md records the commit hash it was built at.