npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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/betterrank

Quick 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 10

How It Works

  1. Parse: Native tree-sitter extracts definitions (functions, classes, types) and references (calls, imports) from source files
  2. Graph: graphology MultiDirectedGraph with typed edges (DEFINES, REFERENCES, IMPORTS)
  3. Rank: PageRank scores every symbol by structural importance — heavily-imported utilities rank higher than leaf files
  4. 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 ./backend

Example 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 callers

Typical 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 --count

search — 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 function

symbols — 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 function

callers — 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 3

Example 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-source

Example 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.py

history — 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 5

Example 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 ValuePredictor

trace — 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 5

Example 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/project

Example 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 symbols

deps — What does this file import

betterrank deps src/auth.ts --root /path/to/project

dependents — What imports this file

betterrank dependents src/auth.ts --root /path/to/project

neighborhood — 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 10

orphans — 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/project

structure — File tree with symbol counts

betterrank structure --root /path/to/project --depth 3

reindex — Force full rebuild

betterrank reindex --root /path/to/project

stats — Index statistics

betterrank stats --root /path/to/project

Global 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