io.github.abhiyoheswaran1/projscan
Agent-first code intelligence over MCP. AST for 7 languages. 20 tools. Offline.
Ask AI about io.github.abhiyoheswaran1/projscan
Powered by Claude Β· Grounded in docs
I know everything about io.github.abhiyoheswaran1/projscan. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
projscan
Agent-first code intelligence. An MCP server that lets AI coding agents (Claude Code, Cursor, Windsurf) 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 25 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 a one-call PR review (now with new-taint-flow detection that blocks unsafe merges), 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, Cursor, β¦) |
To see all commands and options, run:
projscan --help
Command Screenshots
projscan structure - Directory tree with file counts
projscan diagram - Architecture visualization
projscan dependencies - Dependency analysis
projscan explain - File explanation
projscan badge - Health badge generation
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.
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__.pypackages,__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.txtdeps. Missing lockfile. - Code search. BM25 and semantic modes work on
.pyfiles out of the box. - Hotspots + dead code. Same scoring as JS/TS, with
__init__.pyand 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 importpkg.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.modmodule-path resolution - imports prefixed with the module path resolve into the repo; stdlib and third-party are external.- Cyclomatic complexity counted from
if,for,switchcases, select communication cases,&&/||. Default cases anddefer/godon'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 searchfalls 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" --semanticSee 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.envis forwarded to child processes (git,npm) so they can find theirPATHβ we never inspect.envvalues, API keys, or session tokens. - Execute user input dynamically. No
eval, nonew Function(...), no shell-string composition. The twoawait import('...')sites in our code (core/embeddings.tsandcore/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 fixis 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 atdist/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.envis 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 bynpm run buildat 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. Seedocs/STABILITY.md. - Run it offline:
npm install -g projscanfollowed by anything exceptauditand--mode semanticworks without network. - Drop privilege further: in CI, run projscan in a sandbox that disallows network egress; everything except
auditwill 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- defaultcithreshold (0β100)baseRef- default base ref for--changed-onlyignore- extra glob patterns added to the built-in ignore listdisableRules- silence rules by id; supports wildcardprefix-*severityOverrides- remap a rule's severity (info/warning/error)hotspots.limit/hotspots.since- defaults for thehotspotscommandmonorepo.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- readspackage.jsonandnode_modules/<pkg>/package.jsonto classify drift (major/minor/patch/same/unknown). No network.audit- wrapsnpm audit --json, normalizes the output, and emits SARIF with per-finding rules anchored topackage.json. Graceful fallback message for yarn/pnpm projects.upgrade <pkg>- readsnode_modules/<pkg>/CHANGELOG.md, slices the section between your installed version and the previous one, flagsBREAKING CHANGE/deprecated/removed supportmarkers, 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 .projscanrc β disableRules 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
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
runAuditdefined?" β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 25 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 acrosssymbols(exported names),files(path substring), orcontent(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 bydirection: 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. Composespr_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 viagit 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 reportprojscan_doctor- health score + issues (now includescycle-detected-Nfor 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). Passview: "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, smellsprojscan_structure- directory treeprojscan_coverage- scariest untested files (coverage Γ hotspots)
Dependencies:
projscan_dependencies- declared deps, risks. In a monorepo: aggregated totals +byWorkspacebreakdown;packagearg scopes to one (0.13).projscan_outdated- declared-vs-installed drift (offline). Per-packagebyWorkspace;packagearg.projscan_audit- normalizednpm audit.packagearg 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 thenameas thepackagearg onprojscan_hotspots/projscan_couplingto 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 fromnotifications/file_changedpush events when--watchis 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 disableRulessnippet),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 withprojscan 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; passconfirm: trueto write. Atomic writes, per-apply rollback record at.projscan-cache/rollbacks/<id>.json. Reverse withaction: "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.jsontaint.projscan_reviewautomatically 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 onXenova/all-MiniLM-L6-v2embeddings. 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
cursorandpage_size, getnextCursorback. Works onprojscan_hotspots,projscan_search,projscan_audit,projscan_outdated,projscan_coverage. - Progress notifications: set
_meta.progressTokenon the tool-call request. The server emitsnotifications/progressat coarse milestones (scanning β analyzing β ranking β done) so your agent can display progress or cancel. - Response chunking: set
stream: truein arguments to split large arrays into multiplecontentblocks (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 hotspotsinvestigate_file- senior-engineer brief for a specific filerefactor_hotspot(1.5) - step-by-step refactor plan for one hotspot filetriage_doctor_issues(1.5) - critical / important / backlog ordering of open issuesreview_this_pr(1.5) - PR-comment-ready review primed with the structural diff and verdictsafely_rename_symbol(1.5) - ordered rename + verification checklist viaprojscan_impactblast 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 markdownand paste into PRs - Tech-debt prioritization: Use
projscan hotspotsto decide what deserves refactoring time - AI-assisted development: Mount
projscan mcpin your agent of choice for grounded edits - CI/CD: Use
projscan cito enforce health standards in your pipeline - Security: Catch committed secrets and
.envfiles before they reach production - Consulting: Quickly assess client projects before diving in
- Maintenance: Track health trends with
projscan diffacross releases
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT
