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

projscan

v1.9.0

Published

Agent-first code intelligence. MCP server (2025-03-26) with AST parsing for JavaScript, TypeScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, Swift, and C++; code graph, file + per-function AST cyclomatic complexity, per-function fan-in + fan-out, co

Readme

projscan

npm version license node projscan health

Agent-first code intelligence. An MCP server that lets AI coding agents (Claude Code, Codex, Cursor, Gemini, Windsurf, Cline, Continue, Zed — any MCP-aware client) query your codebase — with a CLI for humans on the side.

AI Agent Quick Start · CLI Quick Start · Commands · Full Guide · Roadmap


Why?

AI coding agents are becoming the primary interface to code. Today, when you ask your agent "which files implement auth?" or "what breaks if I bump React from 18 to 19?" - it either guesses from names, or it shells out to grep and reads raw output not built for it.

projscan is the first code-intelligence tool built for agents, not for humans. Your agent gets a fast, AST-accurate, context-budget-aware view of your codebase through 27 structured MCP tools. It can query the import graph, find symbol definitions, preview upgrades, rank hotspots, diff structural changes between refs, surface coupling/cycle hotspots, get an intent-grounded one-call PR review (now with new-taint-flow detection that blocks unsafe merges, plus an optional natural-language intent arg that labels each finding expected / unexpected / out-of-scope), request structured fix-action prompts for any open issue and mechanically apply the safe ones with rollback, ask "what breaks if I change this?" via transitive blast-radius analysis (across registered sibling repos too), surface source-to-sink taint flows, share a durable session across multiple agent invocations, and learn from how you use it — quieting accumulated noise on this specific repo over time without ever phoning home.

Humans get the same thing through the CLI.

Everything is offline-first. Zero network calls. No API keys.

npx projscan

Run projscan doctor for a focused health check:

npx projscan doctor

Install

npm install -g projscan

Or run directly without installing:

npx projscan

Quick Start

Run inside any repository:

projscan                            # Full project analysis
projscan doctor                     # Health check
projscan hotspots                   # Rank files by risk (churn × complexity × issues × ownership)
projscan search <query>             # BM25-ranked search (content + symbols + path)
projscan file <path>                # Drill into a file - purpose, risk, ownership, issues
projscan fix                        # Auto-fix detected issues
projscan ci                         # CI health gate (exits 1 on low score)
projscan ci --changed-only          # Gate only on this PR's diff
projscan ci --format sarif          # SARIF 2.1.0 for GitHub Code Scanning
projscan outdated                   # Declared-vs-installed drift (offline)
projscan audit                      # npm audit, normalized + SARIF-ready
projscan upgrade <pkg>              # Preview upgrade impact (local CHANGELOG + importers)
projscan coverage                   # Coverage × hotspots - scariest untested files
projscan diff                       # Compare health + hotspot trends against a baseline
projscan diagram                    # Architecture visualization
projscan structure                  # Directory tree
projscan mcp                        # Run as an MCP server for AI coding agents

For a comprehensive walkthrough, see the Full Guide.

Commands

| Command | Description | |---------|-------------| | projscan analyze | Full analysis - languages, frameworks, dependencies, issues | | projscan doctor | Health check - missing tooling, architecture smells, security risks | | projscan hotspots | Rank files by risk - churn × complexity × issues × ownership | | projscan search <query> | BM25-ranked search - content + symbols + path, with excerpts | | projscan file <path> | Drill into a file - purpose, risk, ownership, related issues | | projscan fix | Auto-fix issues (ESLint, Prettier, Vitest, .editorconfig) | | projscan ci | CI health gate - SARIF output, --changed-only PR-diff mode, exits 1 if score below threshold | | projscan diff | Compare current health and hotspot trends against a baseline | | projscan explain <file> | Explain a file's purpose, imports, exports, and issues | | projscan diagram | ASCII architecture diagram of your project | | projscan structure | Directory tree with file counts | | projscan dependencies | Dependency analysis - counts, risks, recommendations | | projscan outdated | Declared-vs-installed drift check (offline) | | projscan audit | npm audit-powered vulnerability report - SARIF-ready for Code Scanning | | projscan upgrade <pkg> | Preview upgrade impact - local CHANGELOG + importer list, offline | | projscan coverage | Coverage × hotspots - rank the scariest untested files (--changed-only for diff mode) | | projscan badge | Generate a health score badge for your README | | projscan init | (1.6) Scaffold .projscanrc.json with sensible defaults | | projscan install-hook | (1.6) Install a pre-commit hook running projscan ci --changed-only | | projscan workspace | (1.6) Register sibling repos for cross-repo intelligence (add / list / remove) | | projscan apply-fix <id> | (1.6) Mechanically execute the safe fix templates with rollback (default dry-run) | | projscan taint | (1.6) Source-to-sink reachability over the call graph | | projscan mcp | Run as an MCP server for AI coding agents (Claude Code, Codex, Cursor, Gemini, Windsurf, …) |

To see all commands and options, run:

projscan --help

Command Screenshots

Output Formats

All commands support --format for different output targets:

projscan analyze --format json       # Machine-readable JSON
projscan doctor --format markdown    # Markdown for docs/PRs
projscan ci --format sarif           # SARIF 2.1.0 for GitHub Code Scanning

Formats: console (default), json, markdown, sarif

Options

| Flag | Description | |------|-------------| | --format <type> | Output format: console, json, markdown, sarif | | --config <path> | Path to a .projscanrc config file | | --changed-only | Scope to files changed vs base ref (ci/analyze/doctor) | | --base-ref <ref> | Git base ref for --changed-only (default: origin/main) | | --verbose | Enable debug output | | --quiet | Suppress non-essential output | | -V, --version | Show version | | -h, --help | Show help |

Health Score

Every projscan doctor run calculates a health score (0–100) and letter grade:

| Grade | Score | Meaning | |-------|-------|---------| | A | 90–100 | Excellent - project follows best practices | | B | 80–89 | Good - minor improvements possible | | C | 70–79 | Fair - several issues to address | | D | 60–69 | Poor - significant issues found | | F | < 60 | Critical - major issues need attention |

Generate a badge for your README:

projscan badge

This outputs a shields.io badge URL and markdown snippet you can paste into your README.

Sample badge: projscan health

What It Detects

Languages: TypeScript, JavaScript, Python, Go, Java, Ruby, Rust, PHP, and C# (full AST analysis for all nine), plus file-level detection for C/C++, Swift, Kotlin, and 20+ more.

Frameworks: React, Next.js, Vue, Nuxt, Svelte, Angular, Express, Fastify, NestJS, Vite, Tailwind CSS, Prisma, and more

Python (0.10)

Python repos now get the same treatment JS/TS has had since 0.6:

  • AST-accurate import graph. from pkg.mod import x, relative imports, __init__.py packages, __all__. Parsed via tree-sitter-python (wasm, offline).
  • Python-aware analyzers. Missing pytest / ruff / black config. Deprecated packages (nose, simplejson, pycrypto). Unused pyproject.toml / requirements.txt deps. Missing lockfile.
  • Code search. BM25 and semantic modes work on .py files out of the box.
  • Hotspots + dead code. Same scoring as JS/TS, with __init__.py and pytest test-file conventions understood.
  • MCP tools work unchanged. projscan_graph, projscan_search, projscan_doctor, projscan_hotspots, etc. all accept Python projects. Agents can ask "which files import pkg.core?" and get an answer in milliseconds.

projscan_upgrade remains Node-only for now - a Python equivalent (reading pip / poetry metadata) is on the roadmap.

Go (0.11)

Go flows through the same pipeline as JS/TS and Python:

  • AST-accurate import graph via tree-sitter-go. Single-line and parenthesized import blocks, aliased imports, dot-imports.
  • Capitalization-rule export visibility - uppercase identifiers are public, lowercase are private. Captures func, method, var, const, type (struct/interface).
  • go.mod module-path resolution - imports prefixed with the module path resolve into the repo; stdlib and third-party are external.
  • Cyclomatic complexity counted from if, for, switch cases, select communication cases, &&/||. Default cases and defer/go don't count.

Coupling and cycles (0.11)

projscan coupling (CLI + MCP tool) reports per-file fan-in / fan-out / instability (Bob Martin's I = Ce / (Ca + Ce)) and detects circular imports via Tarjan SCC. Cross-package edges are flagged when running on a monorepo.

PR-aware structural diff (0.11)

projscan pr-diff returns the structural diff between two refs: exports added/removed/renamed, imports added/removed, call sites added/removed, ΔCC, Δfan-in. Spins up a temporary git worktree at the base ref to build a clean second graph. Renames are detected via similarity scoring (max of normalized Levenshtein and shared-affix fraction, threshold 0.5).

Monorepo support (0.11)

Detects npm/yarn workspaces, pnpm-workspace.yaml, Lerna, modern Nx (nx.json#workspaceLayout + project.json scan), legacy Nx (workspace.json#projects), and a packages/* + apps/* + libs/* fallback. projscan workspaces lists every package; --package <name> (or the package MCP arg) scopes most commands to a single workspace.

Cache version bumped 2 → 3 in 0.11 (CC stored per file). Existing v2 caches are discarded on first run and rebuilt automatically.

Performance

Reference numbers from npm run bench on an Apple M3 Pro running Node 25 (cold / warm cache, milliseconds), refreshed for 1.5.0:

| Repo | Files | analyze | doctor | hotspots | coupling | search | |------|-------|---------|--------|----------|----------|--------| | projscan itself | ~120 | 650 / 576 | 659 / 574 | 794 / 622 | 405 / 186 | 485 / 277 | | Synthetic medium | 500 | 284 / 257 | 277 / 255 | 300 / 278 | 224 / 177 | 239 / 196 |

For real-world numbers against larger codebases, npm run bench:references shallow-clones TypeScript, Django, and kubernetes/client-go into .bench-cache/ (gitignored) and runs the same suite. First run is network-bound; later runs reuse the cache. Restrict to one target with -- --only ts|django|k8s-client-go.

Run npm run bench against your own machine to recalibrate.

  • Zero network requests — everything runs locally
  • 14 runtime dependencies — still minimal
  • ~10.5 MB of vendored tree-sitter grammars, broken down:

| Grammar | Size | Languages | |---|---:|---| | web-tree-sitter | ~190 KB | runtime, all tree-sitter languages | | tree-sitter-python | ~450 KB | Python | | tree-sitter-go | ~210 KB | Go | | tree-sitter-java | ~405 KB | Java | | tree-sitter-ruby | ~2.0 MB | Ruby | | tree-sitter-rust | ~1.1 MB | Rust | | tree-sitter-php | ~785 KB | PHP | | tree-sitter-c-sharp | ~5.2 MB | C# |

JavaScript and TypeScript use the bundled @babel/parser instead of a tree-sitter grammar, so they don't appear in this table.

Optional features

projscan keeps the install slim by default. One feature is gated behind an optional peer dependency:

  • Semantic search uses local embeddings via @xenova/transformers (~25 MB quantized model, downloads on first use, then cached). Without it, projscan search falls back to BM25 lexical search and prints a one-line tip pointing here. Install when you want it:

    npm install @xenova/transformers
    projscan search "cache invalidation" --semantic

    See AI Agent Integration → Semantic search for details.

Security & trust

projscan reads your source code so it can be useful; it does not send your source code anywhere. This section explains exactly what's happening, because supply-chain scanners (Socket, Snyk, npm audit, etc.) will flag a few patterns in any tool that wraps git and npm, and we want you to be able to verify our claims rather than trust them.

What projscan does NOT do

  • Send your source code off-machine. Zero network calls in any code path projscan owns. File contents stay local; AST analysis runs in-process.
  • Read environment variables for secrets. process.env is forwarded to child processes (git, npm) so they can find their PATH — we never inspect .env values, API keys, or session tokens.
  • Execute user input dynamically. No eval, no new Function(...), no shell-string composition. The two await import('...') sites in our code (core/embeddings.ts and core/review.ts) take literal string arguments and exist for lazy-loading optional code paths, not for running user-supplied code.
  • Phone home with telemetry. The opt-in JSONL telemetry shipped in 0.11 was removed entirely in 0.12. Future telemetry, if any, will be remote-sink-with-dashboard and explicitly opt-in.
  • Modify your repo without an explicit command. projscan fix is the only command that writes to source files, and only when invoked. The cache directory .projscan-cache/ is local-only and gitignored.

What projscan DOES do, and what it costs

| Action | When | Network? | Notes | |---|---|---|---| | Read source files | every command | no | parses with tree-sitter / Babel; results cached at .projscan-cache/ | | Spawn git | hotspots, pr-diff, review, diff | git itself may fetch if you run git fetch separately; projscan never invokes git fetch | env: process.env is passed so git can find its config | | Spawn npm audit | audit only | yes — by npm, not by projscan | runs against your local lockfile | | Load wasm grammars | first parse of a non-JS file | no | served from dist/grammars/ inside the package; no fetch | | Build embeddings | semantic search opt-in only | yes — by @xenova/transformers, on first use | model cached locally after first download; remove the peer dep to remove this code path entirely |

Patterns supply-chain scanners flag, and why they're benign here

If you read projscan's Socket report, you'll see four supply-chain alerts. Here's a one-line answer to each:

  • "Network access" — comes from web-tree-sitter's internal API surface; we feed it local wasm files at dist/grammars/. No outbound traffic.
  • "Dynamic require" — two static await import('literal-string') sites for optional code paths. No user-input-driven require.
  • "Environment variable access"env: process.env is forwarded to child processes (git, npm audit). We don't read env contents.
  • "URL strings" — the strings are documentation references (github.com, registry.npmjs.org) shown in error messages and CHANGELOGs, not runtime fetch targets.

Audit it yourself

  • Source is open at github.com/abhiyoheswaran1/projscan. The npm tarball matches the dist/ produced by npm run build at the matching tag.
  • Public API surface is locked by scripts/check-stability.mjs, which runs in CI on every PR and fails on any rename or removal of an MCP tool, CLI command, or exit code. See docs/STABILITY.md.
  • Run it offline: npm install -g projscan followed by anything except audit and --mode semantic works without network.
  • Drop privilege further: in CI, run projscan in a sandbox that disallows network egress; everything except audit will pass.

Dogfooding

projscan runs against itself in CI on every PR. The dogfood loop is the most direct evidence we can offer that the tool works on real code, not just synthetic fixtures.

# .github/workflows/ci.yml — runs after the unit tests
- run: node dist/cli/index.js ci --min-score 90

Current state of the projscan codebase as scored by projscan itself:

| Metric | Value | |---|---| | Health score | A (100 / 100) | | Open issues | 0 errors, 0 warnings, 0 info | | Circular imports | 0 | | Top hotspot | src/reporters/consoleReporter.ts (CC 288, 1108 lines) — known refactor candidate, not a defect | | Dogfood threshold | --min-score 90 (CI fails below this) |

The --min-score 90 threshold is deliberately tight: a regression that drops the score by more than ten points fails the build. The current ten-point margin (90 → 100) is for room to breathe, not slack.

The hotspots projscan finds in itself are real signals — the reporters in particular have grown organically across releases and are candidates for a 2.0-era refactor (tracked in docs/ROADMAP.md "Under consideration"). We choose to ship the signal honestly rather than tune the score to hide it.

CI/CD Integration

Use projscan ci to gate your pipelines:

projscan ci --min-score 70                     # Exits 1 if score < 70
projscan ci --min-score 80 --format json       # JSON output for parsing
projscan ci --changed-only                     # Gate only on this PR's diff
projscan ci --format sarif > projscan.sarif    # SARIF for Code Scanning

GitHub Action (recommended)

projscan ships a first-party GitHub Action that installs, runs, and uploads SARIF to GitHub Code Scanning in one step:

# .github/workflows/projscan.yml
name: ProjScan
on:
  push: { branches: [main] }
  pull_request: { branches: [main] }

permissions:
  contents: read
  security-events: write   # required for SARIF upload

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }  # needed for --changed-only
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - uses: abhiyoheswaran1/projscan@v1
        with:
          min-score: '70'
          changed-only: 'true'

Inputs: min-score, changed-only, base-ref, config, sarif-file, upload-sarif, working-directory, version. Outputs: score, grade.

Findings appear in the Security → Code scanning tab, annotated on files and lines. PRs get inline annotations on changed lines.

Plain workflow (no SARIF upload)

If you'd rather not upload SARIF, .github/projscan-ci.yml is a drop-in workflow that runs projscan and posts a markdown health report as a PR comment.

Configuration (.projscanrc)

Drop a .projscanrc.json at your repo root to set defaults - CLI flags always win over config. A "projscan" key in package.json and plain .projscanrc are also supported.

{
  "minScore": 80,
  "baseRef": "origin/main",
  "ignore": ["**/fixtures/**", "**/generated/**"],
  "disableRules": ["missing-editorconfig", "large-*"],
  "severityOverrides": {
    "missing-prettier": "info"
  },
  "hotspots": {
    "limit": 20,
    "since": "6 months ago"
  }
}

Fields:

  • minScore - default ci threshold (0–100)
  • baseRef - default base ref for --changed-only
  • ignore - extra glob patterns added to the built-in ignore list
  • disableRules - silence rules by id; supports wildcard prefix-*
  • severityOverrides - remap a rule's severity (info / warning / error)
  • hotspots.limit / hotspots.since - defaults for the hotspots command
  • monorepo.importPolicy - cross-package import allow/deny rules in monorepos (0.14+)

See docs/GUIDE.md → Configuration for the full reference (field types, validation behavior, embedding config in package.json, monorepo importPolicy semantics).

Tracking Health Over Time

Save a baseline and compare later:

projscan diff --save-baseline       # Save current score
# ... make changes ...
projscan diff                       # Compare against baseline
projscan diff --format markdown     # Markdown diff for PRs

Hotspots - Where to Fix First

A flat health score doesn't tell you what to do. projscan hotspots combines git log churn, file complexity, open issues, recency, and ownership into a single risk score per file - so you know where refactoring or review will actually pay off.

projscan hotspots                       # Top 10 hotspots
projscan hotspots --limit 20
projscan hotspots --since "6 months ago"
projscan hotspots --format json         # Machine-readable for dashboards
projscan hotspots --format markdown     # Drop into a PR or tech-debt ticket

Hotspot ranking follows the classic Feathers "churn × complexity" heuristic with boosts for files that fail projscan doctor, changed recently, or show bus factor 1 (single-author + high churn). Falls back gracefully outside a git repo.

Drill Into a Hotspot

projscan file src/cli/index.ts

Combines the file's purpose, imports, exports, hotspot risk, ownership, and every open issue that references it - the natural follow-up to projscan hotspots.

Track Trends Over Time

projscan diff --save-baseline           # Snapshots health + hotspots
# ...time passes, commits happen...
projscan diff                           # Shows which hotspots rose / fell

The baseline file now captures top hotspots too, so diff surfaces files that are getting worse (not just new issues).

Dependency Health

projscan ships three focused commands for keeping your dependency graph healthy - all offline by default, no registry calls.

projscan outdated                       # Which declared deps drift from what's installed?
projscan outdated --format json         # Machine-readable drift report
projscan audit                          # Wrap npm audit; normalized, SARIF-ready
projscan audit --format sarif > a.sarif # Upload to GitHub Code Scanning
projscan upgrade chalk                  # What breaks if I bump chalk? Who imports it?
projscan upgrade chalk --format markdown # Paste-ready review comment

What each one tells you

  • outdated - reads package.json and node_modules/<pkg>/package.json to classify drift (major / minor / patch / same / unknown). No network.
  • audit - wraps npm audit --json, normalizes the output, and emits SARIF with per-finding rules anchored to package.json. Graceful fallback message for yarn/pnpm projects.
  • upgrade <pkg> - reads node_modules/<pkg>/CHANGELOG.md, slices the section between your installed version and the previous one, flags BREAKING CHANGE / deprecated / removed support markers, and lists every file in your repo that imports the package. All offline.

Unused dependencies (automatic in doctor)

projscan doctor now flags declared dependencies that are never imported from source. Each finding is anchored to the exact line in package.json so GitHub Code Scanning PR annotations land in the right place.

Implicit-use packages (typescript, eslint/prettier plugins, @types/*, and anything invoked from a package.json script) are allowlisted. Override via .projscanrcdisableRules if projscan flags something that is used but not imported.

Coverage × Hotspots - Scariest Untested Files

projscan coverage joins your test coverage with the hotspot ranking. A file with high churn and low coverage is where a bug is most likely to bite you - so that's where you want tests first.

projscan coverage                       # Top 30 scariest untested files
projscan coverage --format markdown     # Paste into a tech-debt ticket
projscan coverage --format json         # Machine-readable for dashboards

How it decides "scariest": priority = riskScore × (0.3 + 0.7 × uncoveredFraction) - so a file with 50 risk and 10% coverage outranks a file with 50 risk and 95% coverage.

Which coverage files are supported:

  • coverage/lcov.info (lcov - Vitest, Jest, c8)
  • coverage/coverage-final.json (Istanbul per-file detail)
  • coverage/coverage-summary.json (Istanbul summary)

Coverage is also automatically joined into projscan hotspots when one of those files exists - no flag needed. Uncovered churning files get a score bump and a low coverage (X%) reason tag.

Dead-code detection (automatic in doctor)

projscan doctor now flags source files whose exports nothing imports - dead code left over from refactors or utilities that were never wired up. Respects package.json public entry points (main, exports, bin, types), skips test files and barrel (index) files.

AI Agent Integration (MCP)

This is the primary way to use projscan. projscan mcp starts an MCP server over stdio so AI coding agents can query your codebase with real structural accuracy - not regex, not grep.

Two questions an agent asks; structural answers in milliseconds. "What breaks if I rename buildCodeGraph?" → 31 direct callers, 97 files reachable. "Where should I fix first?" → ranked hotspots with AST cyclomatic complexity, churn, and ownership signals.

Claude Code

One-liner — adds projscan as an MCP server in the current project:

claude mcp add projscan -- npx -y projscan mcp

Codex CLI (OpenAI)

Add to ~/.codex/config.toml:

[mcp_servers.projscan]
command = "npx"
args = ["-y", "projscan", "mcp"]

Restart codex and the tool surface (projscan_graph, projscan_review, …) appears alongside Codex's built-ins.

Gemini CLI (Google)

Add to ~/.gemini/settings.json:

{
  "mcpServers": {
    "projscan": {
      "command": "npx",
      "args": ["-y", "projscan", "mcp"]
    }
  }
}

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per-project):

{
  "mcpServers": {
    "projscan": {
      "command": "npx",
      "args": ["-y", "projscan", "mcp"]
    }
  }
}

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "projscan": {
      "command": "npx",
      "args": ["-y", "projscan", "mcp"]
    }
  }
}

Cline (VS Code extension)

In Cline's MCP settings panel (or the underlying cline_mcp_settings.json):

{
  "mcpServers": {
    "projscan": {
      "command": "npx",
      "args": ["-y", "projscan", "mcp"]
    }
  }
}

Continue.dev

Add to ~/.continue/config.yaml:

mcpServers:
  - name: projscan
    command: npx
    args:
      - -y
      - projscan
      - mcp

Zed

Add to ~/.config/zed/settings.json under context_servers:

{
  "context_servers": {
    "projscan": {
      "command": {
        "path": "npx",
        "args": ["-y", "projscan", "mcp"]
      }
    }
  }
}

Any other MCP-aware client

The transport is stdio. Wire your client to invoke npx -y projscan mcp as a subprocess; the server speaks JSON-RPC 2.0 over stdin/stdout. If your client wants notifications/file_changed push notifications when the repo changes, append --watch:

npx -y projscan mcp --watch

Capability is advertised under experimental.fileChanged on initialize so clients can detect support.

What agents can ask

  • "Who imports src/auth/jwt.ts?"projscan_graph { file, direction: "importers" }
  • "Where is runAudit defined?"projscan_search { query: "runAudit", scope: "symbols" }
  • "Which files implement auth?"projscan_search { query: "auth", scope: "content" }
  • "What are the scariest untested files?"projscan_coverage
  • "What breaks if I bump chalk to 6?"projscan_upgrade { package: "chalk" }
  • "Where should I refactor first?"projscan_hotspots

The 27 MCP tools

Structural (0.6.0 / 0.11 / 0.13 / 0.14 / 0.15 - agent-native):

  • projscan_graph - query the AST-based code graph. Directions: imports, exports, importers, symbol_defs, package_importers. Millisecond responses on a warm cache.
  • projscan_search - fast search across symbols (exported names), files (path substring), or content (source substring with line + excerpt). Sub-file mode (sub_file: true) embeds per-function for sharper semantic results (0.15).
  • projscan_coupling (0.11) - per-file fan-in / fan-out / instability + circular-import cycles (Tarjan SCC). Filter by direction: cycles_only | high_fan_in | high_fan_out.
  • projscan_pr_diff (0.11) - structural diff between two git refs. Returns added/removed/modified files with explicit lists of exports, imports, and call sites that changed, plus ΔCC and Δfan-in.
  • projscan_review (0.13) - one-call PR review. Composes pr_diff + per-changed-file risk + new/expanded import cycles + risky function additions + dependency changes + a verdict (ok / review / block).
  • projscan_fix_suggest (0.14) - structured action prompt for any open issue: headline, why it matters, where, one-paragraph instruction, optional suggested test. Closes the diagnose → fix loop.
  • projscan_explain_issue (0.14) - deep dive on one issue: code excerpt, related issues in the same file, similar past commits via git log --grep, plus the structured FixSuggestion.
  • projscan_impact (0.15) - transitive blast-radius for a file or symbol. BFS over reverse imports + symbol callsites. Use BEFORE renaming or deleting to see what breaks.

Analysis:

  • projscan_analyze - full project report
  • projscan_doctor - health score + issues (now includes cycle-detected-N for circular imports as of 0.13)
  • projscan_hotspots - risk-ranked files (churn × AST cyclomatic complexity × issues × ownership × coverage; falls back to LOC for non-AST languages). Pass view: "functions" (0.13) for top-N risky individual functions.
  • projscan_file - per-file risk + ownership + related issues + CC + fan-in/fan-out + per-function CC table (0.13)
  • projscan_explain - per-file purpose, imports, exports, smells
  • projscan_structure - directory tree
  • projscan_coverage - scariest untested files (coverage × hotspots)

Dependencies:

  • projscan_dependencies - declared deps, risks. In a monorepo: aggregated totals + byWorkspace breakdown; package arg scopes to one (0.13).
  • projscan_outdated - declared-vs-installed drift (offline). Per-package byWorkspace; package arg.
  • projscan_audit - normalized npm audit. package arg scopes findings to one workspace's direct deps (0.13).
  • projscan_upgrade - upgrade preview (CHANGELOG + importers, offline)

Workspace (0.11):

  • projscan_workspaces - list monorepo packages (npm/yarn/pnpm/Nx/Turbo/Lerna). Use the name as the package arg on projscan_hotspots / projscan_coupling to scope.

Session (1.4):

  • projscan_session (1.4) - durable cross-invocation session. Subactions: current (id + counts), touched (files touched this session, sorted by recency, filterable by source: tool-result / fs-watch / explicit), events (chronological log), reset (start a fresh session). Auto-populated from every tool result and from notifications/file_changed push events when --watch is on. Lets multiple agents in the same project see "what's been touched here" without re-running git.

Memory (1.5):

  • projscan_memory (1.5) - durable, local-only feedback loop. Records, per analyzer rule id, how many runs surfaced it and how many fixed it. Subactions: current (aggregate counts), stable (rules surfaced across ≥ 3 runs over ≥ 7 days without ever being fixed — paired with a ready-to-paste .projscanrc.json disableRules snippet), runs (every tracked rule with full history), forget (drop a single rule). Stored at .projscan-memory/memory.json; never leaves the machine. Lets an agent ask "what is this project tolerating?" and propose quieting it.

Operator (1.6):

  • projscan_workspace_graph (1.6) - cross-repo intelligence over sibling repos registered with projscan workspace add. Subactions: list (registered repos + parsed-file + export counts), graph (every symbol exported by ≥ 2 repos — the candidate refactor / API contract surface), file_importers (given a file in one repo, every other repo whose graph imports it). Read-only.
  • projscan_apply_fix (1.6) - mechanically execute the safe fix templates. Default is dry-run; pass confirm: true to write. Atomic writes, per-apply rollback record at .projscan-cache/rollbacks/<id>.json. Reverse with action: "rollback", rollback_id: .... Six templates supported at this release: unused-dependency-*, missing-test-framework, missing-eslint, missing-prettier, missing-editorconfig, missing-readme.
  • projscan_taint (1.6) - source-to-sink reachability over the per-function call graph. Built-in defaults cover common JS / Python sources (process.env, req.body, etc.) and sinks (exec, eval, db.query, etc.). Project-specific names go in .projscanrc.json taint. projscan_review automatically diffs taint flows between base and head and blocks any PR that introduces a new flow.

Context-window budgeting

Every MCP tool accepts an optional max_tokens argument. Set it and projscan serializes the result, and - if over budget - truncates the largest array field record-by-record until it fits. Responses include a _budget sidecar when truncated so your agent knows it got a partial view.

{ "name": "projscan_hotspots", "arguments": { "limit": 100, "max_tokens": 800 } }

Semantic search (0.9.0+, opt-in)

projscan ships with BM25-ranked lexical search by default. To unlock true semantic search - embeddings over file content so queries like "which file implements auth" hit files that don't literally contain the word "auth" - install the optional peer:

npm install @xenova/transformers
projscan search "verifying user credentials" --mode semantic

Or via the MCP tool:

{ "name": "projscan_search", "arguments": { "query": "verifying user credentials", "mode": "semantic" } }

Modes on projscan_search:

  • lexical (default) - BM25 over content + symbol + path boosts. No peer needed.
  • semantic - cosine similarity on Xenova/all-MiniLM-L6-v2 embeddings. Requires peer.
  • hybrid - both, fused via Reciprocal Rank Fusion. Requires peer.

Semantic embeddings are cached at .projscan-cache/embeddings.bin keyed by (model, mtime, content hash) - invalidates automatically on file change. All offline after the first-run model download (~25MB).

Pagination, progress, and streaming (0.8.0+)

Large responses can be walked incrementally:

  • Cursor pagination: pass cursor and page_size, get nextCursor back. Works on projscan_hotspots, projscan_search, projscan_audit, projscan_outdated, projscan_coverage.
  • Progress notifications: set _meta.progressToken on the tool-call request. The server emits notifications/progress at coarse milestones (scanning → analyzing → ranking → done) so your agent can display progress or cancel.
  • Response chunking: set stream: true in arguments to split large arrays into multiple content blocks (header + N chunks of ~20 records each).

All opt-in - default behavior is unchanged.

Incremental index cache

projscan caches parsed ASTs at .projscan-cache/graph.json (auto-gitignored). First run populates it; subsequent runs re-parse only files whose mtime changed. Agent queries on a warm cache are milliseconds, not seconds.

Prompts (6, parameterized with live project data)

  • prioritize_refactoring - ranked plan grounded in current hotspots
  • investigate_file - senior-engineer brief for a specific file
  • refactor_hotspot (1.5) - step-by-step refactor plan for one hotspot file
  • triage_doctor_issues (1.5) - critical / important / backlog ordering of open issues
  • review_this_pr (1.5) - PR-comment-ready review primed with the structural diff and verdict
  • safely_rename_symbol (1.5) - ordered rename + verification checklist via projscan_impact blast radius

Resources (3, readable on demand)

  • projscan://health · projscan://hotspots · projscan://structure

Use Cases

  • Onboarding: Understand any codebase in seconds, not hours
  • Code reviews: Run projscan doctor --format markdown and paste into PRs
  • Tech-debt prioritization: Use projscan hotspots to decide what deserves refactoring time
  • AI-assisted development: Mount projscan mcp in your agent of choice for grounded edits
  • CI/CD: Use projscan ci to enforce health standards in your pipeline
  • Security: Catch committed secrets and .env files before they reach production
  • Consulting: Quickly assess client projects before diving in
  • Maintenance: Track health trends with projscan diff across releases

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT