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

ucn

v3.7.3

Published

Universal Code Navigator — AST-based call graph analysis for AI agents. Find callers, trace impact, detect dead code across JS/TS, Python, Go, Rust, Java, and HTML. CLI, MCP server, and agent skill.

Readme

UCN - Universal Code Navigator

UCN gives AI agents call-graph-level understanding of code. Instead of reading entire files, agents ask structural questions like: "who calls this function", "what breaks if I change it", "what's unused", and get precise, AST-verified answers. UCN parses JS/TS, Python, Go, Rust, Java, and HTML inline scripts with tree-sitter, then exposes 28 navigation commands as a CLI tool, MCP server, or agent skill.

Designed for large codebases where agents waste context on reading large files. UCN's surgical output means agents spend tokens on reasoning, not on ingesting thousands of lines to find three callers, discourages agents from cutting corners, as without UCN, agents working with large codebases tend to skip parts of the code structure, assuming they have "enough data".


Three Ways to it: ucn mcp, ucn skill, ucn cli

  ┌──────────────────────────────────────────────────────────────────────┐
  │                                                                      │
  │   1. CLI                    Use it directly from the terminal.       │
  │      $ ucn about myFunc     Works standalone, no agent required.     │
  │                                                                      │
  │   2. MCP Server             Any MCP-compatible AI agent connects     │
  │      $ ucn --mcp            and gets 28 tools automatically.         │
  │                                                                      │
  │   3. Agent Skill            Drop-in skill for Claude Code and        │
  │      /ucn about myFunc      OpenAI Codex CLI. No server needed.      │
  │                                                                      │
  └──────────────────────────────────────────────────────────────────────┘

How agents understand code today

AI agents working with code typically do this:

  grep "functionName"      →  47 matches, 23 files
       │
       ▼
  read file1.ts            →  2000 lines... wrong function
       │
       ▼
  read file2.ts            →  1500 lines... still not it
       │
       ▼
  read file3.ts            →  found it, finally
       │
       ▼
  grep "whoCallsThis"      →  start over
       │
       ▼
  ┌─────────────────────────────────────────┐
  │  Half the context window is gone.       │
  │  The agent hasn't changed a single line.│
  └─────────────────────────────────────────┘

How UCN works: tree-sitter, locally

  ┌──────────────────────────────────────────────┐
  │              Any AI Agent                    │
  │  Claude Code · Cursor · Windsurf · Copilot   │
  └───────────────────────┬──────────────────────┘
                          │
                         MCP
                          │
                          ▼
                 ┌───────────────────┐
                 │   UCN MCP Server  │
                 │   28 tools        │
                 │   runs locally    │
                 └────────┬──────────┘
                          │
                    tree-sitter AST
                          │
        ┌─────────────────┴───────────────────┐
        │          Supported Languages        │
        │ JS/TS, Python, Go, Rust, Java, HTML │
        └─────────────────────────────────────┘

No cloud. No API keys. Parses locally, stays local.


Before and after UCN

  WITHOUT UCN                              WITH UCN
  ──────────────────────                   ──────────────────────

  grep "processOrder"                      ucn_impact "processOrder"
       │                                        │
       ▼                                        ▼
  34 matches, mostly noise                 8 call sites, grouped by file,
       │                                   with actual arguments passed
       ▼                                        │
  read service.ts  (800 lines)                  │
       │                                        │
       ▼                                        │
  read handler.ts  (600 lines)             ucn_smart "processOrder"
       │                                        │
       ▼                                        ▼
  read batch.ts    (400 lines)             function + all dependencies
       │                                   expanded inline
       ▼                                        │
  read orders.test (500 lines)                  │
       │                                        ▼
       ▼                                   Done. Full picture.
  grep "import.*processOrder"              Ready to make the change.
       │
       ▼
  read routes.ts   (300 lines)
       │
       ▼
  ... still not sure about full impact


  8+ tool calls                            2 tool calls
  Reads thousands of lines                 Reads zero full files
  Context spent on file contents           Context spent on reasoning

After editing code, before committing:

  WITHOUT UCN                              WITH UCN
  ──────────────────────                   ──────────────────────

  git diff                                 ucn_diff_impact
       │                                        │
       ▼                                        ▼
  see changed lines, but which             13 modified functions
  functions do they belong to?             8 new functions
       │                                   22 call sites across 9 files
       ▼                                        │
  read each file to map hunks                   ▼
  to function boundaries                   Each function shown with:
       │                                     • which lines changed
       ▼                                     • every downstream caller
  ucn_impact on each function                • caller context
  you identified (repeat 5-10x)                 │
       │                                        ▼
       ▼                                   Done. Full blast radius.
  hope you didn't miss one                 One command.


  10+ tool calls                            1 tool call

Text search vs AST

  Code: processOrder(items, user)


  ┌─────────────────────────────────────────────────────────────────┐
  │  grep "processOrder"                                            │
  │                                                                 │
  │    ✓  processOrder(items, user)          ← the actual call      │
  │    ✗  // TODO: refactor processOrder     ← comment, not a call  │
  │    ✗  const processOrder = "label"       ← string, not a call   │
  │    ✗  order.processOrder()               ← different class      │
  │    ✗  import { processOrder }            ← import, not a call   │
  │                                                                 │
  │  5 results. 1 is what you wanted.                               │
  └─────────────────────────────────────────────────────────────────┘


  ┌─────────────────────────────────────────────────────────────────┐
  │  ucn_context "processOrder"                                     │
  │                                                                 │
  │    Callers:                                                     │
  │      handleCheckout    src/api/checkout.ts:45                   │
  │      batchProcess      src/workers/batch.ts:12                  │
  │      runDailyOrders    src/jobs/daily.ts:88                     │
  │                                                                 │
  │    Callees:                                                     │
  │      validateItems     src/orders/validate.ts:20                │
  │      calculateTotal    src/orders/pricing.ts:55                 │
  │      saveOrder         src/db/orders.ts:30                      │
  │                                                                 │
  │  3 callers, 3 callees. Verified from the AST.                   │
  └─────────────────────────────────────────────────────────────────┘

The tradeoff: text search works on any language and any text. UCN only works on 5 languages + HTML, but gives structural understanding within those.


UCN commands in action

Extract a function from a large file without reading it:

$ ucn fn expandGlob

core/discovery.js:135
[ 135- 166] expandGlob(pattern, options = {})
────────────────────────────────────────────────────────────
function expandGlob(pattern, options = {}) {
    const root = path.resolve(options.root || process.cwd());
    const ignores = options.ignores || DEFAULT_IGNORES;
    ...
    return files.sort(compareNames);
}

See who calls it and what it calls:

$ ucn context expandGlob

Context for expandGlob:
════════════════════════════════════════════════════════════

CALLERS (7):
  [1] cli/index.js:1847 [runGlobCommand]
    const files = expandGlob(pattern);
  [2] core/project.js:81
    const files = expandGlob(pattern, {
  [3] core/project.js:3434
    const currentFiles = expandGlob(pattern, { root: this.root });
  ...

CALLEES (2):
  [8] parseGlobPattern [utility] - core/discovery.js:171
  [9] walkDir [utility] - core/discovery.js:227

See what breaks if you change it:

$ ucn impact shouldIgnore

Impact analysis for shouldIgnore
════════════════════════════════════════════════════════════
core/discovery.js:289
shouldIgnore (name, ignores, parentDir)

CALL SITES: 2
  Files affected: 1

BY FILE:

core/discovery.js (2 calls)
  :255 [walkDir]
    if (shouldIgnore(entry.name, options.ignores, dir)) continue;
    args: entry.name, options.ignores, dir
  :373 [detectProjectPattern]
    !shouldIgnore(entry.name, DEFAULT_IGNORES)) {
    args: entry.name, DEFAULT_IGNORES

Get a function with all its dependencies inline:

$ ucn smart shouldIgnore

shouldIgnore (core/discovery.js:289)
════════════════════════════════════════════════════════════
function shouldIgnore(name, ignores, parentDir) {
    for (const pattern of ignores) {
        if (pattern.includes('*')) {
            const regex = globToRegex(pattern);
            ...
        }
    }
    ...
}

─── DEPENDENCIES ───

// globToRegex [utility] (core/discovery.js:208)
function globToRegex(glob) {
    let regex = glob.replace(/[.+^$[\]\\]/g, '\\$&');
    ...
    return new RegExp('^' + regex + '$');
}

Trace the call tree:

$ ucn trace expandGlob --depth=2

Call tree for expandGlob
════════════════════════════════════════════════════════════

expandGlob
├── parseGlobPattern (core/discovery.js:171) [utility] 1x
│   └── globToRegex (core/discovery.js:208) [utility] 1x
└── walkDir (core/discovery.js:227) [utility] 1x
    └── shouldIgnore (core/discovery.js:289) [utility] 1x

See the impact of your recent edits:

$ ucn diff-impact --base=HEAD~1

Diff Impact Analysis (vs HEAD~1)
════════════════════════════════════════════════════════════
3 modified, 1 new, 12 call sites across 4 files

MODIFIED FUNCTIONS:

  processOrder
  src/orders/service.ts:45
  processOrder (items: Item[], user: User): Promise<Order>
  Lines added: 48-52
  Lines deleted: 49
  Callers (3):
    src/api/checkout.ts:89 [handleCheckout]
      await processOrder(cart.items, req.user)
    src/workers/batch.ts:12 [batchProcess]
      processOrder(order.items, systemUser)
    src/jobs/daily.ts:88 [runDailyOrders]
      results.push(await processOrder(items, admin))

  validateItems
  src/orders/validate.ts:20
  validateItems (items: Item[]): ValidationResult
  Lines added: 25-30
  Callers (2):
    src/orders/service.ts:46 [processOrder]
      const valid = validateItems(items)
    src/api/admin.ts:55 [bulkValidate]
      return items.map(i => validateItems([i]))

NEW FUNCTIONS:
  calculateShipping — src/orders/shipping.ts:10
  calculateShipping (items: Item[], region: Region): number

MODULE-LEVEL CHANGES:
  src/orders/service.ts: +5 lines, -1 lines

Scoped to staged changes or a specific file:

$ ucn diff-impact --staged                 # Only what's staged for commit
$ ucn diff-impact --base=main              # Everything since branching from main
$ ucn diff-impact --file=src/orders        # Only changes in this path

Find unused code:

$ ucn deadcode

Dead code: 15 unused symbol(s)

cli/index.js
  [1649-1654] extractFunctionNameFromContent (function)
core/project.js
  [1664-1694] findReExportsOf (method)
  [1998-2020] withCompleteness (method)
...

Install

npm install -g ucn

As an MCP Server

One-line setup for supported clients:

# Claude Code
claude mcp add ucn -- npx -y ucn --mcp

# OpenAI Codex CLI
codex mcp add ucn -- npx -y ucn --mcp

# VS Code Copilot
code --add-mcp '{"name":"ucn","command":"npx","args":["-y","ucn","--mcp"]}'

Or add to your client's MCP config file manually:

{
  "mcpServers": {
    "ucn": {
      "command": "npx",
      "args": ["-y", "ucn", "--mcp"]
    }
  }
}
{
  "servers": {
    "ucn": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "ucn", "--mcp"]
    }
  }
}

As a Claude Code / Codex Skill

When MCP server is not needed, drop it in as a native skill:

# Claude Code
mkdir -p ~/.claude/skills
cp -r "$(npm root -g)/ucn/.claude/skills/ucn" ~/.claude/skills/

# OpenAI Codex CLI
mkdir -p ~/.agents/skills
cp -r "$(npm root -g)/ucn/.claude/skills/ucn" ~/.agents/skills/

As a CLI Tool

Works standalone from the terminal — no agent required:

ucn toc                             # Project overview
ucn about handleRequest             # Understand a function
ucn impact handleRequest            # Before modifying
ucn fn handleRequest --file api     # Extract specific function
ucn --interactive                   # Multiple queries, index stays in memory

UCN workflows

Investigating a bug:

ucn about problematic_function            # Understand it fully
ucn trace problematic_function --depth=2  # See what it calls

Before modifying a function:

ucn impact the_function                   # Who will break?
ucn smart the_function                    # See it + its helpers
# ... make your changes ...
ucn verify the_function                   # Did all call sites survive?

Before committing:

ucn diff-impact                           # What did I change + who calls it?
ucn diff-impact --base=main               # Full branch impact vs main
ucn diff-impact --staged                  # Only staged changes

Periodic cleanup:

ucn deadcode --exclude=test               # What can be deleted?
ucn toc                                   # Project overview

Limitations

  ┌──────────────────────────┬──────────────────────────────────────────┐
  │  Limitation              │  What happens                            │
  ├──────────────────────────┼──────────────────────────────────────────┤
  │                          │                                          │
  │  5 languages + HTML      │  JS/TS, Python, Go, Rust, Java.          │
  │  (no C, Ruby, PHP, etc.) │  Agents fall back to text search for     │
  │                          │  the rest. UCN complements, doesn't      │
  │                          │  replace.                                │
  │                          │                                          │
  ├──────────────────────────┼──────────────────────────────────────────┤
  │                          │                                          │
  │  Dynamic dispatch        │  getattr(), reflection, eval() — UCN     │
  │                          │  does static analysis and can't follow   │
  │                          │  calls that only exist at runtime.       │
  │                          │                                          │
  ├──────────────────────────┼──────────────────────────────────────────┤
  │                          │                                          │
  │  Duck-typed methods      │  obj.method() in JS/TS/Python — when     │
  │                          │  the receiver type is ambiguous, results │
  │                          │  are marked "uncertain" so the agent     │
  │                          │  knows to verify. Go/Rust/Java resolve   │
  │                          │  with high confidence.                   │
  │                          │                                          │
  ├──────────────────────────┼──────────────────────────────────────────┤
  │                          │                                          │
  │  Single project scope    │  UCN follows imports within the project  │
  │                          │  but stops at the boundary — no tracing  │
  │                          │  into node_modules or site-packages.     │
  │                          │                                          │
  ├──────────────────────────┼──────────────────────────────────────────┤
  │                          │                                          │
  │  First-query index time  │  Tree-sitter index is built on first     │
  │                          │  query. A few seconds on large projects. │
  │                          │  Cached and incrementally updated —      │
  │                          │  only changed files are re-indexed.      │
  │                          │                                          │
  └──────────────────────────┴──────────────────────────────────────────┘

All 28 UCN tools

  UNDERSTAND                          MODIFY SAFELY
  ─────────────────────               ─────────────────────
  ucn_about     everything in one     ucn_impact      all call sites
                call: definition,                     with arguments
                callers, callees,
                tests, source         ucn_diff_impact what changed in a
                                                      git diff + who
  ucn_context   callers + callees                     calls it
                (quick overview)
                                      ucn_verify      check all sites
  ucn_smart     function + helpers                    match signature
                expanded inline
                                      ucn_plan        preview a refactor
  ucn_trace     call tree — map                       before doing it
                a whole pipeline


  FIND & NAVIGATE                     ARCHITECTURE
  ─────────────────────               ─────────────────────
  ucn_find      locate definitions    ucn_imports     file dependencies
  ucn_usages    all occurrences       ucn_exporters   who depends on it
  ucn_fn        extract a function    ucn_graph       dependency tree
  ucn_class     extract a class       ucn_related     sibling functions
  ucn_toc       project overview      ucn_tests       find tests
  ucn_deadcode  unused functions      ucn_stacktrace  error trace context
  ucn_search    text search           ucn_api         public API surface
  ucn_example   best usage example    ucn_typedef     type definitions
  ucn_lines     extract line range    ucn_file_exports file's exports
  ucn_expand    drill into context    ucn_stats       project size stats

License

MIT

UCN - Universal Code Navigator