@mishasinitcyn/betterrank
v0.2.3
Published
Structural code index with PageRank-ranked repo maps, symbol search, call-graph queries, and dependency analysis. Built on tree-sitter and graphology.
Maintainers
Readme
BetterRank
Structural code index with PageRank-ranked repo maps, symbol search, call-graph queries, and dependency analysis. Built on tree-sitter and graphology.
BetterRank parses your source files, builds a dependency graph, and ranks every symbol by structural importance using PageRank. Instead of grepping through thousands of files, ask questions like "what are the most important functions in this project?" or "who calls this function?" and get ranked, structured answers in seconds.
Install
npm install -g @mishasinitcyn/betterrankQuick Start
# Get a ranked overview of any project
betterrank map --root /path/to/project
# View a file's skeleton without reading the whole thing
betterrank outline src/auth.py
# Expand a specific function to see its full source
betterrank outline src/auth.py authenticate_user
# Search for symbols by name or parameter
betterrank search auth --root /path/to/project
# Who calls this function? (with call site context)
betterrank callers authenticateUser --root /path/to/project --context
# Everything about a function: source, types, deps, callers
betterrank context calculate_bid --root /path/to/project
# Trace the full call chain from entry point to function
betterrank trace calculate_bid --root /path/to/project
# What symbols changed and what might break?
betterrank diff --root /path/to/project
# What depends on this file?
betterrank dependents src/auth/handlers.ts --root /path/to/project
# What does this file import?
betterrank deps src/auth/handlers.ts --root /path/to/project
# Local subgraph around a file
betterrank neighborhood src/auth/handlers.ts --root /path/to/project --limit 10How It Works
- Parse: Native tree-sitter extracts definitions (functions, classes, types) and references (calls, imports) from source files
- Graph: graphology MultiDirectedGraph with typed edges (DEFINES, REFERENCES, IMPORTS)
- Rank: PageRank scores every symbol by structural importance — heavily-imported utilities rank higher than leaf files
- Cache: mtime-based incremental updates. Only re-parses changed files. Cache lives at the platform cache directory (
~/Library/Caches/code-index/on macOS,~/.cache/code-index/on Linux)
Supported Languages
JavaScript, TypeScript, Python, Rust, Go, Java, Ruby, C, C++, C#, PHP
Commands
outline — File skeleton with collapsed bodies
View a file's structure without reading the entire thing. Function and class bodies are collapsed to ... (N lines). Expand specific symbols by name. No --root required — works on any file standalone.
# Skeleton view: imports, signatures, constants — bodies collapsed
betterrank outline src/auth.py
# Expand a specific function to see its full source
betterrank outline src/auth.py authenticate_user
# Expand multiple symbols
betterrank outline src/auth.py validate,process
# Show caller counts next to each function (requires --root)
betterrank outline src/auth.py --annotate --root ./backend
# Resolve path relative to a root
betterrank outline src/auth.py --root ./backendExample output (with --annotate):
1│ from fastapi import APIRouter, Depends
2│ from core.auth import verify_auth
3│
4│ router = APIRouter(prefix="/api")
5│
6│ @router.get("/users")
7│ async def list_users(db = Depends(get_db)):
│ ... (25 lines) ← 2 callers
33│
34│ @router.post("/users")
35│ async def create_user(data: UserCreate, db = Depends(get_db)):
│ ... (40 lines) ← 5 callersTypical compression: 3-5x (a 2000-line file becomes ~400 lines of outline). Annotations show how many external files reference each function — instantly see what's critical vs dead code.
map — Repo map
Summary of the most structurally important definitions, ranked by PageRank. Default limit is 50 symbols.
betterrank map --root /path/to/project
betterrank map --root /path/to/project --limit 100
betterrank map --root /path/to/project --focus src/api/auth.ts,src/api/login.ts
betterrank map --root /path/to/project --countsearch — Find symbols by name or signature
Substring search across symbol names and full function signatures (including parameter names and types). Results ranked by PageRank.
betterrank search encrypt --root /path/to/project
betterrank search max_age --root /path/to/project # matches param names too
betterrank search imp --root /path/to/project --kind functionsymbols — List definitions
betterrank symbols --root /path/to/project
betterrank symbols --root /path/to/project --file src/auth.ts
betterrank symbols --root /path/to/project --kind functioncallers — Who calls this symbol
# File names only
betterrank callers authenticateUser --root /path/to/project
# With call site context lines (default 2 lines around each site)
betterrank callers authenticateUser --root /path/to/project --context
# Custom context window
betterrank callers authenticateUser --root /path/to/project --context 3Example output (with --context):
src/engine/pipeline.py:
16│ from app.engine.bidding import run_auction
17│
153│ return await run_auction(
154│ searched=campaigns,
155│ publisher=config.publisher,
src/api/serve.py:
145│ bid = await run_auction(searched, publisher=pub_id)context — Full function context in one shot
Everything you need to understand a function: its source, the types in its signature (expanded inline), the functions it calls (with signatures), and a callers summary. Eliminates the multi-command chase.
betterrank context calculate_bid --root /path/to/project
# Skip the source, just show deps/types/callers
betterrank context calculate_bid --root /path/to/project --no-sourceExample output (--no-source):
── calculate_bid (src/engine/bidding.py:489-718) ──
Types:
AuctionData2 (src/engine/bidding.py:74)
publisher_id: str
campaign_metrics: Dict[str, CampaignMetrics]
time_remaining_pct: float
References:
[function] def from_microdollars(microdollars) -> Decimal (src/core/currency.py:108)
[function] def get_config() -> ValuePredictorConfig (src/engine/predictor/config.py:316)
[function] def get_value_predictor() -> ValuePredictor (src/engine/predictor/persistence.py:123)
[class] class ValuePredictor (src/engine/predictor/predictor.py:43)
Callers (1 file):
src/engine/bidding.pyhistory — Git history of a specific function
Shows only commits that touched a function's lines. Uses tree-sitter line ranges for accuracy (better than git's heuristic :funcname: detection). Add --patch to include function-scoped diffs.
# Commit list (compact)
betterrank history calculate_bid --root /path/to/project
# With function-scoped diffs
betterrank history calculate_bid --root /path/to/project --patch --limit 3
# Paginate through older commits
betterrank history calculate_bid --root /path/to/project --offset 5 --limit 5Example output:
calculate_bid (src/engine/bidding.py:489-718)
082b9d5 2026-02-24 fix: restore GSP auction pricing
c75f5ff 2026-02-14 fix: resolve lint errors from main merge
623429c 2026-02-13 hot fix
5d236d3 2026-02-06 feat: wire ad_position to ValuePredictortrace — Recursive caller chain
Walk UP the call graph from a symbol to see the full path from entry points to your function. At each hop, resolves which function in the caller file contains the call site.
betterrank trace calculate_bid --root /path/to/project
betterrank trace calculate_bid --root /path/to/project --depth 5Example output:
calculate_bid (src/engine/bidding.py:489)
← run_auction (src/engine/bidding.py:833)
← handle_request (src/engine/pipeline.py:153)
← app (src/main.py:45)diff — Git-aware blast radius
Shows which symbols changed in the working tree and how many external files call each changed symbol. Compares current disk state against a git ref.
# Uncommitted changes vs HEAD
betterrank diff --root /path/to/project
# Changes since a specific commit or branch
betterrank diff --ref main --root /path/to/project
betterrank diff --ref HEAD~5 --root /path/to/projectExample output:
src/engine/bidding.py:
~ [function] calculate_bid (3 callers)
+ [function] compute_value_multi
- [function] old_quality_score (1 caller)
⚠ 4 external callers of modified/removed symbolsdeps — What does this file import
betterrank deps src/auth.ts --root /path/to/projectdependents — What imports this file
betterrank dependents src/auth.ts --root /path/to/projectneighborhood — Local subgraph around a file
betterrank neighborhood src/auth.ts --root /path/to/project --count
betterrank neighborhood src/auth.ts --root /path/to/project --hops 2 --limit 10orphans — Find disconnected files/symbols
betterrank orphans --root /path/to/project # orphan files
betterrank orphans --level symbol --root /path/to/project # orphan symbols
betterrank orphans --level symbol --kind function --root /path/to/projectstructure — File tree with symbol counts
betterrank structure --root /path/to/project --depth 3reindex — Force full rebuild
betterrank reindex --root /path/to/projectstats — Index statistics
betterrank stats --root /path/to/projectGlobal Flags
| Flag | Description |
|---|---|
| --root <path> | Project root. Always pass this explicitly. |
| --count | Return counts only (no content) |
| --offset N | Skip first N results |
| --limit N | Max results to return (default: 50) |
Programmatic API
import { CodeIndex } from '@mishasinitcyn/betterrank';
const idx = new CodeIndex('/path/to/project');
const map = await idx.map({ limit: 100, focusFiles: ['src/main.ts'] });
const results = await idx.search({ query: 'auth', kind: 'function', limit: 10 });
const callers = await idx.callers({ symbol: 'authenticate', context: 2 });
const counts = await idx.getCallerCounts('src/auth.ts');
const deps = await idx.dependencies({ file: 'src/auth.ts' });
const dependents = await idx.dependents({ file: 'src/auth.ts' });
const hood = await idx.neighborhood({ file: 'src/auth.ts', hops: 2, maxFiles: 10 });
const stats = await idx.stats();
await idx.reindex();Ignore Configuration
Built-in defaults ignore node_modules, dist, build, .venv, etc. To add project-specific ignores, create <project-root>/.code-index/config.json:
{
"ignore": ["experiments/**", "legacy/**"]
}Cache
Cache lives at the platform cache directory:
- macOS:
~/Library/Caches/code-index/ - Linux:
~/.cache/code-index/ - Windows:
%LOCALAPPDATA%/code-index/Cache/
Override with CODE_INDEX_CACHE_DIR env var. Cache files are disposable — delete anytime, they rebuild automatically.
License
MIT
