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

code-visualizer

v0.1.4

Published

Your codebase companion for JavaScript/TypeScript, in the browser, the terminal and your AI agent: a live dependency map, impact and call sites, affected tests and patch coverage, review order, new-only CI gates (SARIF, GitLab), git hooks, a status line a

Readme

◆ code-visualizer

Your codebase companion — in the browser, in your terminal, and inside your AI agent. See, search and understand any JavaScript / TypeScript codebase, and every change you (or your agent) make to it.

npm version license node

npx code-visualizer serve

The Today view: your work, its impact and the health of the codebase


Table of contents

Why?

Most of a developer's day is not typing code. It is understanding code:

AI coding assistants make these questions more frequent, not less:

  • Review is the new bottleneck. On teams with high AI adoption, merged PRs went up 98%, but review time went up 91% and PR size went up 154% — Faros AI, 10,000+ developers, 2025. 96% of developers don't fully trust AI-written code, and 38% say it takes more effort to review — Sonar State of Code 2026.
  • Reading order matters. Across 219,476 PRs, files shown earlier got more comments. In a controlled experiment, a defect in the last file shown had 64% lower odds of being found — Fregnan et al., ESEC/FSE 2022.
  • Copy-paste is growing. In 211M changed lines, duplicated blocks of 5+ lines rose about 8× in 2024, and copy/pasted lines outnumbered moved (refactored) lines for the first time — GitClear 2025.
  • Agents lack structure. The top AI frustration is code that is “almost right, but not quite” (66%) — Stack Overflow 2025. Giving an agent a map from code to its dependents and tests cut test regressions by 70% — TDAD, arXiv 2603.17973. Agents that walk an import/call graph localize the right file 92.7% of the time at about 86% lower cost — LocAgent, ACL 2025.

code-visualizer answers these questions from one static analysis of your project. Nothing is executed and nothing leaves your machine. The same answers reach you wherever you work:

| Where | What you get | | --- | --- | | Browser | A live, interactive map of the codebase, your current work, your team and its health. It updates on every save. | | Terminal | One-line answers to who, uses, impact, path, route, tests-for and similar, plus a status line, git hooks and a sync forecast. | | AI agent | An MCP server and guardrail hooks for Claude Code, Cursor, VS Code, Codex and Gemini, so the agent knows what it is about to break. | | CI | Gates that fail only on new problems, with SARIF, GitLab Code Quality, GitHub annotations, a job summary and a sticky PR comment. |

Quick start

No installation needed. In the root of any JS/TS project (or any folder inside it):

# Live companion: updates by itself while you edit, stage, commit or switch branches
npx code-visualizer serve
# One-off report: a single offline HTML file you can share
npx code-visualizer
# What would changing this break? Exact call sites, routes, tests and owners
npx code-visualizer impact src/lib/format.ts
# Give your AI agent the project map (preview first, then --write)
npx code-visualizer agents init
# In CI: fail only on problems your change introduces
npx code-visualizer check --changed

For daily use, install it once. You get a faster start, git hooks and status lines that work offline, and the short cviz alias:

npm i -D code-visualizer      # per project (hooks and agents use it automatically)
npm i -g code-visualizer      # or globally: code-visualizer … / cviz …

It also works with npm create (options go after --):

npm create code-visualizer@latest -- serve

Requirements: Node.js 20+. macOS, Linux and Windows. git is optional but unlocks history, changes, people, risk, review and sync. git ≥ 2.38 gives sync a real trial merge.

A day with code-visualizer

☕ Morning: catch up without opening anything. Your prompt already shows where you stand: health, what you changed and what it affects, tests to run, new problems and what is waiting on main.

◆ 82▼3 · 5Δ→23 · 3 tests · ✖1 new cycle · ↓7 main (1 conflict) · cov 72%

Before you rebase, sync runs a real trial merge and tells you what main and your teammates bring:

$ cviz sync
origin/main is 7 commits ahead (alice 4, bob 3) · fetched 2 h ago
✖ conflict if you rebase now: src/cart/price.ts
! formatPrice(value) → formatPrice(value, currency) in 3f2a1c9 (bob); you call it at src/cart/Total.tsx:12
→ git rebase --autostash origin/main, then update 1 call site

Open Today in the browser for commits since your last visit, an Incoming card, the health trend with quick wins and the files you pinned yesterday.

⌨️ While you code: the live guard. Keep serve running. On every save, yours or your agent's, it prints what got worse (or better), about 150–250 ms later:

10:21:03 ↻ 1 change · re-analyzed 132 files in 240ms
         ✖ new cycle: src/cart/a.ts → src/cart/b.ts → src/cart/a.ts
         ▲ checkout() complexity 12 → 19 · src/cart/checkout.ts:40
         ✖ formatPrice() signature changed (14 importers, 3 call sites not updated)
         ✔ cycle fixed: src/cart/a.ts → src/cart/b.ts → src/cart/a.ts

The browser shows the same Live feed, a toast with a Show button and the open problem count in the tab title.

My changes: impact, tests to run, reviewers and risk

🔍 Before you touch something: ask. cviz impact formatDate lists the exact call sites, dependents by depth, routes, tests (with the command) and owners. cviz uses, cviz who and cviz path answer the rest. cviz similar slugify tells you whether the helper you are about to write already exists.

🧪 Before you commit: run only what matters. cviz test runs exactly the tests your change affects: unit tests through imports, e2e and API tests through the routes they visit. cviz coverage shows which of your added lines no test ran.

🔒 On commit and push: git hooks. cviz hooks install --yes runs check --staged before every commit (new problems, plus stray it.only, debugger and conflict markers) and check --changed --committed plus test --push before every push.

🤖 With your agent: the same map. After cviz agents init --write, your agent can call impact, tests_for, check_architecture or find_similar instead of grepping. Hooks refuse an edit that breaks an architecture rule, and tell the agent which call sites its change left behind.

🚀 Before the pull request. cviz pr --copy writes a complete description: changed functions and who uses them, architecture changes (breaking APIs with call sites not updated), tests, patch coverage, risk, reviewers and a review path. Reviewing a teammate's (or an agent's) branch? cviz review feature/refunds gives you a reading order, where to start and the effort, without checking it out.

✅ In CI. check --changed fails only on what the PR makes worse, and writes SARIF, GitLab Code Quality, annotations, a job summary and a sticky PR comment from one analysis.

👋 Onboarding someone. The guided tour explains the project from the code itself. Write your own tours while you explore (“Add to tour” on any file or function), save them to .tours/ and commit them. Teammates see them in the report and in VS Code's CodeTour extension.

In the browser

serve (live) and report (a single offline HTML file) show the same interactive views. Cards marked live need serve.

| Area | View | What it shows | | --- | --- | --- | | Workspace | Today | Greeting, branch & upstream status, your work at a glance, health score with trend and quick wins, commits since your last visit, pinned & recently viewed items, your areas (and the ones you haven't touched yet), a Live feed of what got worse or better (live) an Incoming card: what main brings, conflicts and broken call sites (live) and Repository care: the few git chores that matter most today. | | | My changes | Uncommitted work, or your whole branch vs. its base. Changed files in reading order with a role and a reason each, changed functions/components/methods and how widely they're used (symbol-precise), impacted files and routes, tests to run (+ command), a patch-coverage chip and the uncovered lines, an Architecture changes card (new cycles, rule breaks, breaking APIs with call sites not updated, removed routes still called, new area dependencies, new copy-paste clones), Clone drift, reviewers, code owners, risk, diffs and a ready-to-paste PR description. | | | Reviewer mode (live) | An Author / Reviewer toggle in My changes: pick any branch or fetched PR (agent branches such as copilot/, codex/ and claude/ first), then read it in dependency order with viewed checkboxes. Keys: j/k move, v marks viewed, Enter toggles the diff. | | | Search code | Instant full-text / regex search over every file with path filters and matching declarations. Shareable as #/search?q=…. | | Explore | Overview | Frameworks, languages, file & symbol stats, areas of the codebase, most important files, health check, git activity, npm scripts. | | | Guided tour | Auto-generated onboarding tour with a suggested reading order · team tours from .tours/*.tour · your own tour builder (export / save as CodeTour). | | | Dependency graph | Semantic zoom from folders to files; focus, impact (blast radius), import path finder, cycles, an overlay of your changes; color by type, folder, complexity, importance, churn, age or owner; export PNG / Mermaid / DOT / JSON. | | | Architecture | Dependency matrix (layering violations), chord diagram, layered folder graph. | | | Structure | Treemap, sunburst, mind map (folders → files → symbols) and an explorer with metrics. | | Code | Components | React / Vue / Svelte / Angular / Astro component tree with hooks and contexts. | | | Classes & types | UML class diagram: members, visibility, decorators, extends / implements / associations. | | | Routes & APIs | URL map and table for Express, Fastify, Koa, Hono, NestJS, Next.js, Nuxt, SvelteKit, Remix, Astro, React Router, Vue Router and Angular, with full mounted paths, handlers, middleware, who calls each endpoint, and a client calls tab that maps every fetch / axios / useSWR / $fetch / HttpClient request to the route that serves it. | | | Call flow | Callers and callees of any function or method, including HTTP hops from frontend code to backend handlers. | | | Packages | Which npm packages are used where; unused and missing dependencies, devDependencies used in production code, and the license and install scripts of every direct dependency (a License review list for anything that is not permissive). | | | Environment | Every environment variable the code reads (process.env, import.meta.env, Deno.env, Bun.env) with each read site, compared with your .env files: undocumented ones, ones declared but never read, and secrets that reach the browser bundle. Copy a ready-made .env.example. | | Team & health | Activity & team | Commit timeline, calendar heatmap and working-hours chart, people with their areas, a knowledge map of who owns what, who to ask per area with bus factor, knowledge silos. | | | Health & insights | A 0–100 health score (modularity, complexity, size, dead code, dependencies, tests & coverage, knowledge spread, duplication) with history and the best next steps. Hotspots, cycles, complex functions, unused exports, orphans, large files, change coupling, copy-paste clones, duplicate names, TODOs, untested important files, deprecated APIs still in use, architecture rule violations and external services. A New only toggle (live) shows just what your change introduced. Also Security findings (hardcoded secrets, dynamic code execution, unsafe HTML, shell and SQL built from variables, disabled TLS checks), Type-safety escapes per file (any, !, @ts-ignore, @ts-expect-error, eslint-disable) and, for every circular dependency, How to break it: the few imports to cut, cheapest first, and how (import type, move to a shared module, invert, extract). | | | Release | What shipping now would contain: the commits since the last version tag, the changes to the API your package.json publishes, the version number that fits (major / minor / patch, with the reasons), whether you are ready (clean tree, up to date with upstream, no new cycles or rule violations, health) and release notes you can copy. | | Developer tools | Git insights | What to tidy in the repository, with the command for each: branches already merged (delete them in two clicks (live), with the undo commands), branches whose remote is gone, never pushed or untouched for 90+ days; stashes; worktrees; commits no branch has any more (the reflog still has them: one click copies the command that rescues them); commit style (how many commits follow Conventional Commits, the types used, long subjects, wip and fixup! commits); repository hygiene (tracked .env files, node_modules, build output, large files, loose objects) and git settings worth changing (rerere, pull.rebase, merge.conflictstyle…) with a copy-all command. | | | Git toolbox | Forty copy-and-paste recipes for the situations people search for (undo the last commit, recover a deleted branch, move commits to a new branch, find who changed a line…) with your branch and base filled in, a risk label on each (safe, rewrites history, discards work) and the ones that fit right now on top. A commit message helper (writes one from your changes, lints it, sets the type), a standup (your commits of the week as Markdown) and history search (live): text added or removed (-S), regex (-G), message, author, or the history of one file, with each commit's files, the branches that contain it and the commands to show, revert or cherry-pick it. Nothing here runs a command for you except deleting merged branches. | | | GitHub Actions | Every workflow in .github/workflows drawn as a job graph (needs, matrices, environments, reusable workflows, conditions), when each one runs (branch, tag and path filters, cron schedules with the next run) and what would run for your changes; findings from the common rules (script injection through ${{ github.event… }}, unpinned third-party actions, missing permissions, a script package.json does not define, outdated actions, Node.js past end of life, no timeout or concurrency, invalid YAML); every action used with how it is pinned; package.json scripts CI never runs; local actions, Dependabot and the secrets the workflows read (names only). Copy any graph as Mermaid. | | | AI assistants | The Claude Code tools available in this project: CLAUDE.md and the other assistants' instruction files, skills, slash commands, subagents, MCP servers, hooks and plugins, from the project, your .claude/settings.local.json and ~/.claude, each with what it does, how to call it (/review-pr [number], @code-reviewer) and when Claude uses it by itself. Plus a short guide to using Claude Code (slash commands, memory, subagents, hooks, permissions), starter templates for a skill, command, subagent and CLAUDE.md written for this project, a setup check (what is missing and the command that fixes it, what loads at the start of every session) and the code-visualizer tools your agent can call. |

And everywhere: ⌘K / Ctrl+K search across files, symbols, routes, packages and code text · a detail panel with metrics (cyclomatic and cognitive complexity), owners & experts, how tests reach the file, line coverage, Used by with exact call sites, Similar code, history (“why does it look like this?”), git blame (live), diff, outline, source and Copy for AI · a red gutter on changed lines no test ran · pins & notes that survive across sessions · open in VS Code / Cursor / Windsurf / WebStorm / Zed at the exact line (plus IntelliJ IDEA and Sublime Text in live mode) · deep links for every view and selection · dark & light themes · works on phones.

The live companion (serve)

npx code-visualizer serve              # http://127.0.0.1:4747, opens the browser
npx code-visualizer serve --notify     # plus desktop notifications for new errors
  • Incremental. Unchanged files and git history are reused, so an update after a save takes a few hundred milliseconds.
  • One server per project. Running serve again prints Already running at http://127.0.0.1:4747/ (pid 1234) and opens it. --new starts another one. --port 0 binds any free port.
  • Everything else gets faster. While it runs, report, check, pr, context, the terminal answers, status, MCP tools and agent hooks take its live analysis instead of analyzing again (typically 30–150 ms per answer).
  • Live guard events: cycle-added / cycle-fixed, rule-violation / rule-fixed, complexity-up / complexity-down, signature-changed (with call sites not updated), route-removed, missing-dependency, untested-change, unused-export, clone-added, health and config. A problem is announced once and stays open (quietly) until it is fixed; the fix is announced too.
  • Live-only extras: git blame in the code view, open-in-editor without browser prompts (set CODE_VISUALIZER_EDITOR to cursor, windsurf, webstorm, idea, zed or sublime), notes and tours saved into the project, Reviewer mode, the Incoming card and the New-only toggle, history search, commit details and the live standup of the Git toolbox, and deleting merged branches from Git insights. The views refresh when you return to the tab (workflow, skill and branch changes made by other tools are not watched), and each has a Refresh button.

Terminal answers

Ask the codebase from your shell. Every command takes --json, answers from a running serve when there is one (otherwise from the warm cache), and prints file:line links that open your editor.

cviz who src/billing/                    # owners, experts (recent work counts more), last touch, bus factor
cviz uses formatPrice                    # imports + exact call / render / new lines + HTTP callers (alias: refs)
cviz impact formatDate --depth 3         # direct users with lines, dependents by depth, routes, tests + command, owners
cviz path src/pages/Checkout.tsx src/db/client.ts   # the shortest import chain, line by line
cviz route GET /api/users/42             # handler file:line, middleware, callers, tests
cviz tests-for $(git diff --name-only)   # tests to run + the exact command, untested files
cviz similar src/ui/utils.ts:12-30       # does this already exist? similar functions and copies
$ cviz impact displayName

  Impact of displayName  lib/format.ts:4
  2 affected files · symbol-precise

  Direct (1 file)
    components/UserProfile.tsx  displayName
    └─ :16  call in UserProfile (1 arg)
  Depth 2 (1 file)
    app/users/[id]/page.tsx

  Routes and pages (1)
    PAGE /users/[id]  app/users/[id]/page.tsx:3

  Tests (0)
    No test reaches this code or its users.
    no test reaches: displayName (lib/format.ts:4)

  Owners to notify
    @acme/web  2 files
  • Targets can be a file or a unique suffix of one (Cart.tsx), a symbol (useCart, CartService.checkout, src/cart/index.ts#useCart), a folder (src/cart/) or a route ('GET /api/cart/:id', or a concrete URL such as GET /api/cart/42). Paths may be relative to the current folder or to the git root. Typos get “did you mean” suggestions.
  • Symbol-precise. For a symbol, only files that import it by name (through barrels too) or call it count, plus everything that depends on them. When an importer uses import * as or require, the answer widens to file level and says why.
  • “Reached by a test” is one rule everywhere. A file counts as tested when a test imports it, when a test requests or visits a route whose handler reaches it (supertest, page.goto, cy.visit…), or when the coverage report saw its lines run.
  • similar matches renamed variables, changed literals and the other declaration style (function vs arrow). It says which copy to keep: “Keep slugify (exported · used in 6 files): replace toSlug in … with an import of it”. Pipe a snippet with --stdin.
  • Exit codes: 0 answered, 1 nothing matched, 2 usage error.
  • Editor links: CODE_VISUALIZER_EDITOR = vscode (default), cursor, windsurf, vscodium, zed, webstorm, idea, file, none, or a URL template such as subl://open?url=file://{file}&line={line}. NO_HYPERLINKS=1 prints plain text.

Environment, security & releases

Three questions that usually mean a grep, a spreadsheet or a guess. The browser answers all of them (Environment, Health & insights, Packages and Release); env and release answer from the terminal too, with --json and a --check that fails CI.

cviz env                                  # every variable the code reads vs. your .env files
cviz env --missing --example              # a .env.example for the ones nobody documented
cviz env --check                          # exit 1: an undocumented variable, or a secret in the browser bundle
cviz release                              # commits + API changes since the last tag, the version that fits
cviz release --notes --copy               # release notes (Markdown) on the clipboard
cviz release --since v1.4.0 --check       # from a chosen tag; exit 1 when the project is not ready
  • Environment variables. Reads of process.env.X, process.env['X'], destructuring, import.meta.env.X, Deno.env.get('X') and Bun.env.X are matched with the names in your dotenv files. Only names are read, never values, and reads in tests, stories, fixtures and examples are left out (they set up their own environment). A variable is documented when a template declares it (.env.example, .env.sample, .env.template…) or git tracks the dotenv file; variables with a fallback in the code and ones the platform provides (NODE_ENV, CI, GITHUB_*…) are not asked for. A secret-looking name behind a framework's public prefix (VITE_, NEXT_PUBLIC_, REACT_APP_…) is flagged as reaching the browser.
  • Security scan. Hardcoded secrets with a recognisable shape (AWS, GitHub, Slack, Stripe, Google, SendGrid and npm keys, JWTs, private keys, connection strings with a password), literal passwords and tokens, eval / new Function / string timers with a dynamic argument, innerHTML / outerHTML / insertAdjacentHTML / dangerouslySetInnerHTML from a variable, exec built from a variable, SQL built by concatenation, and rejectUnauthorized: false and NODE_TLS_REJECT_UNAUTHORIZED=0. The scan reads JavaScript and TypeScript; Vue and Svelte templates are not scanned. Findings in tests come last. A secret is never shown in full: the report holds AKIA…(20 characters), not the key. It is a code smell scanner, not a replacement for a secret scanner on your git history; rotate anything it finds.
  • Release planner. Commits since the last version tag are read as Conventional Commits (other messages are sorted by their first verb). The suggested version combines them (feat! / BREAKING CHANGE → major, feat → minor, anything else → patch) with the changes to the API your package.json publishes (main, module, exports, bin…), compared with the code at the tag: a commit called fix: that removes an export still asks for a major. Versions below 1.0.0 say so, and a pre-release stays a pre-release. Readiness checks: no uncommitted files, not behind upstream, no new cycles or rule violations since the tag, health not lower. The planner reads the tag from git; a project without one gets a hint on how to start.
  • Cycle plans, licenses and install scripts. Each cycle lists the imports to cut, cheapest first. The Packages view reads node_modules for the license (the looser side of an OR) and the preinstall / install / postinstall scripts (and native binding.gyp builds) of every direct dependency, and puts copyleft, weak-copyleft, proprietary and unknown licenses under License review. That is a prompt to check, not legal advice.

Git, GitHub Actions & AI tools

The browser's Developer tools section (Git insights, Git toolbox, GitHub Actions and AI assistants) works in serve and in a one-off report. Everything is read from plain files and git on your machine: no network, no GitHub token.

cviz actions                               # workflows: when they run, how jobs connect, what is wrong
cviz actions --workflow ci --mermaid --copy # the job graph of one workflow as Mermaid, on the clipboard
cviz actions --check                       # exit 1 when a workflow has an error (script injection, a missing script, invalid YAML)
cviz report --no-personal-ai               # leave your ~/.claude (personal skills, commands, MCP servers) out of a report you share
  • Git insights are computed from git for-each-ref, git stash list, git worktree list --porcelain, the reflog (commits it lists that no branch, remote or tag reaches), git ls-tree, git count-objects and git config --list: a handful of processes, with the part that depends on the commit kept between updates. A branch counts as merged when every commit is in the base (so a squash-merged branch is not offered for deletion; git branch -d would refuse it too). Only a short list of git settings is kept, never your e-mail address or credentials.
  • Deleting merged branches (live) is the only thing the Git views change. It needs a loopback connection, checks each branch again on the server, never touches the current branch, a branch checked out in a worktree, main/master/develop-style names or the base, runs only git branch --delete (which refuses unmerged work, never -D) and shows git branch <name> <hash> for every branch it removed, so nothing is lost.
  • History search (live) runs git log with -S, -G, --grep, --author or --follow: your text is passed as the value of one option, never as a separate argument; at most two searches run at once and each stops after 20 seconds.
  • GitHub Actions rules are the common ones (the ones actionlint and zizmor also find), so they are hints, not a replacement for those tools. The what runs for my changes card applies GitHub's branch, tag and path filter rules to your changed files; only push and pull_request are forecast.
  • AI assistants lists names, descriptions and paths: never the contents of memory files, and never secrets. It covers the project (.claude/, CLAUDE.md, .mcp.json), your own git-ignored *.local files, ~/.claude and installed plugins. A report embeds the personal part too unless you pass --no-personal-ai (to serve as well): do that before sharing one.

AI agents

Your agent sees files. code-visualizer gives it the structure: what imports what, the exact call sites of a function, which tests cover a file, which architecture rules apply and what the current changes break. It gets these from the dependency graph in 10–50 ms instead of grepping again and again.

One-command setup

npx code-visualizer agents init                      # preview: a diff of every change, nothing written
npx code-visualizer agents init --write --agents-md  # register MCP + hooks, write the AGENTS.md block
npx code-visualizer agents init --agents cursor,codex --hooks strict --write
npx code-visualizer agents doctor                    # MCP handshake, one hook round-trip, config, speed
npx code-visualizer agents remove --write            # restore the files exactly as they were

| Agent | Files agents init writes | Hooks | | --- | --- | --- | | Claude Code | .mcp.json, .claude/settings.json | ✔ | | Cursor | .cursor/mcp.json, .cursor/hooks.json | ✔ | | VS Code (Copilot) | .vscode/mcp.json | MCP only | | Codex | .codex/config.toml (a marked [mcp_servers.code-visualizer] table) | MCP only; init prints the hook command line to register by hand | | Gemini CLI | .gemini/settings.json | MCP only |

  • By default it sets up the agents it detects (.claude/, .cursor/, .vscode/, .codex/, .gemini/, the CLIs on your PATH, Claude Code's environment or ~/.claude) and says what it detected. --agents …|all overrides it.
  • --hooks guard (default) installs the session brief, the pre-edit guard and the post-edit radar. strict adds the stop-time test gate. none registers only the MCP server.
  • --skill copies the code-visualizer skill to .claude/skills/. --agents-md writes the managed AGENTS.md block.
  • Only entries named code-visualizer are touched. A second run changes nothing, and remove restores the original bytes. --yes is the same as --write.
  • Agents start the CLI with npx --no-install code-visualizer when it is installed in the project, otherwise npx -y code-visualizer@<major>. npm i -D code-visualizer makes hooks start faster and work offline.

Register the MCP server by hand

mcp --print-config <client> prints the snippet for your project and writes nothing. Add --json to get it as JSON.

claude mcp add --scope project code-visualizer -- npx -y code-visualizer@0 mcp
{
  "mcpServers": {
    "code-visualizer": {
      "command": "npx",
      "args": ["-y", "code-visualizer@0", "mcp", "--root", "${workspaceFolder}"]
    }
  }
}
{
  "servers": {
    "code-visualizer": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "code-visualizer@0", "mcp", "--root", "${workspaceFolder}"]
    }
  }
}
[mcp_servers.code-visualizer]
command = "npx"
args = ["-y", "code-visualizer@0", "mcp"]
startup_timeout_sec = 30
tool_timeout_sec = 120
{
  "mcpServers": {
    "code-visualizer": {
      "command": "npx",
      "args": ["-y", "code-visualizer@0", "mcp"],
      "timeout": 120000
    }
  }
}

With a local install, the printed command is npx --no-install code-visualizer mcp. On Windows it is cmd /c npx …. mcp packages/web --print-config cursor keeps the root you pass.

MCP tools

All tools are read-only. Each takes limit (default 30; find_similar: 5) and response_format: concise (about 10k characters) or detailed (about 40k).

| Tool | What it answers | | --- | --- | | project_overview | Stack, structure, core modules, routes, the test / single-test-file / affected-tests / lint / typecheck commands, architecture rules and layers | | impact {target, depth=2} | Dependents by depth with the exact call sites, routes and pages, tests and the command, untested code, owners, risk | | find_symbol {query, kind?, exported_only?} | Definitions (file:line, signature, doc, deprecation) and use sites | | tests_for {paths[]} | Tests, the command that runs only them, untested files | | review_changes {base?} | Architecture changes first (breaking exports with call sites not yet updated, new cycles and violations), then tests, patch coverage, untested files, clone drift, risk, reviewers, the review path | | check_architecture {from?, to?, paths?} | May A import B? Names the rule, gives up to 2 allowed alternatives and warns about cycles. With paths: the current violations | | route {method?, url} | Handler file:line, middleware, client callers and tests for a URL such as /api/users/42 | | who {target} | Owners, experts, inactive flags, bus factor (no emails) | | find_similar {snippet \| path, start_line?, end_line?, min_similarity=0.8, limit=5} | Existing functions that look like the snippet, which copy to keep, and the clone families the lines belong to |

Resources: cv://project/summary, cv://changes, cv://health, cv://file/{path}. Prompts: review-changes {base?}, plan-change {target}.

| Flag | Meaning | | --- | --- | | [root], --root <dir> | Project root. Default: CLAUDE_PROJECT_DIR, then CURSOR_PROJECT_DIR, then the project around the current folder. | | --tools a,b | Offer only these tools. | | --no-watch | Do not watch files. Each call still checks analyzed files for edits. | | -b, --base <ref> | Base branch for review_changes. | | -e, --exclude <glob> | Exclude files. | | --no-git | Skip git history (no experts, no change review). | | --no-cache | Analyze from scratch: no warm cache and no running serve. | | --print-config <client> | Print the registration for claude, cursor, vscode, codex or gemini. |

  • stdio JSON-RPC, no dependencies. Clients that start with initialize (protocol 2024-11-05 … 2025-11-25) and stateless 2026-07-28 requests (server/discover) are both supported. Progress is reported for _meta.progressToken and cancellation is honoured.
  • It reuses a running serve for the same project, otherwise it keeps its own warm analysis and re-analyzes only what changed.
  • Arguments that do not fit a tool's schema return a tool error that names what to fix; an unknown target gets “did you mean” suggestions.

Guardrail hooks

code-visualizer hook <event> reads the hook's JSON on stdin and answers in the agent's format (--dialect auto|claude|cursor|codex). agents init registers them.

| Event | Claude Code | What it does | | --- | --- | --- | | session-start | SessionStart | A brief of at most 1,500 characters: branch and base, uncommitted files, rules and layers, the most depended-on files with their tests, the MCP tools. | | pre-edit | PreToolUse (Write|Edit|MultiEdit) | Refuses an edit that adds a forbidden import, a layer break, a circular dependency or an undeclared package, and names an allowed alternative (a module that already exports what is needed). Warn-level rules only add context. | | post-edit | PostToolUse (Cursor: afterFileEdit) | Says what the session's edits left behind: call sites still passing the old arguments (file:line), removed exports or routes still used, complexity jumps over 5, new exports no test reaches, new copy-paste clones and clone drift. Silent otherwise; each finding once. | | stop | Stop (--hooks strict; Cursor: stop → followup_message) | Keeps the agent working until a passing test run covers the files it changed: code-visualizer test, or a successful runner command in the transcript after the last edit. Never loops. |

For example, the agent hears:

src/components/Card.tsx must not import src/api/client.ts (rule components-no-api)… src/hooks/useUsers.ts exports useUsers(), which already uses src/api/client.ts.

formatDate(iso, locale) changed its parameters: 1 call site still passes 1 argument: src/components/UserCard.tsx:16.

  • Hooks fail open. Internal errors and malformed input exit 0 with a note on stderr; each hook answers within its client's timeout. CODE_VISUALIZER_HOOKS=off turns them off.
  • Fast. With serve running, hooks ask it (POST /api/whatif) and answer in about 80–150 ms; the no-op path takes about 30–90 ms. Without a server they use the warm disk cache.
  • Codex refusals use exit code 2, and Codex apply_patch edits are understood.

The managed AGENTS.md block

npx code-visualizer context --agents                    # print the block
npx code-visualizer context --agents --write --claude   # update AGENTS.md in place (+ @AGENTS.md in CLAUDE.md)
npx code-visualizer context docs/AGENTS.md --agents --write   # another Markdown file

A short project map between <!-- code-visualizer:start --> and <!-- code-visualizer:end --> (at most 60 lines): script commands and the single-file test command, named rules and layers, generated files, fragile files with their tests, CODEOWNERS boundaries, the MCP tools and CLI commands. Text outside the markers is kept, and an unchanged block is not rewritten, so it is safe to run in pre-commit.

<!-- code-visualizer:start -->
## Project map (code-visualizer)

_Generated by `code-visualizer context --agents --write`; edit outside the markers._

### Commands
- Build: `npm run build`
- All tests: `npm test`
- One test file: `npx vitest run <file>`
- Tests your change affects: `npx code-visualizer test`
- Dev server: `npm run dev`

### Architecture rules (code-visualizer.config.json)
- `components-use-public-lib`: components/** does not import lib/** (except lib/format.ts, lib/types.ts, lib/users-client.ts) — Components may only import the public lib modules
- Layers, top to bottom (a lower layer does not import a higher one): `app/**` → `components/**` → `lib/**`.
- `npx code-visualizer check --changed` judges only what your change adds.

### Fragile files (many dependents: run their tests after changing them)
- `lib/db.ts` — used by 3 files; tests: `npx vitest run test/users.test.ts`

### Code owners (CODEOWNERS)
- `app/users/` → @acme/web
- `components/` → @acme/web
- `test/` → @acme/qa
- `app/layout.tsx` → @acme/web
- `app/page.tsx` → @acme/web
- `app/settings.ts` → @acme/web
- `lib/billing.ts` → @acme/payments, [email protected]
- `next.config.mjs` → @acme/platform
- most files → @acme/backend

### Tools
- MCP server `code-visualizer` (registered by `npx code-visualizer agents init`): project_overview, impact, find_symbol, tests_for, review_changes, check_architecture, route, who, find_similar.
- CLI (add `--json` for machine output): `npx code-visualizer impact <file>`, `uses <symbol>`, `who <file>`, `tests-for <paths>`, `similar <file#Symbol>` (or a snippet on `--stdin`), `test`, `check --changed`, `review <branch>`, `sync`, `status`.
<!-- code-visualizer:end -->

Privacy: MCP tool answers and hook output are sent to your agent's model provider, like any other tool output. Author emails are never included, and text that comes from the repository (commit subjects, TODOs, doc comments) is put in fenced blocks so the model reads it as data. The tools never edit your files.

Tests & coverage

Run only the affected tests

npx code-visualizer test                      # uncommitted work + your branch's commits
npx code-visualizer test --staged             # pre-commit hook
npx code-visualizer test --push               # pre-push hook (what you have not pushed yet)
npx code-visualizer test --since origin/main
npx code-visualizer test --dry-run --verbose  # the plan, with why each test was picked
npx code-visualizer test --list | xargs -r npx vitest run
npx code-visualizer test --coverage -- --reporter=dot

Tests are selected when:

  • they changed (a changed __snapshots__/*.snap selects its test);
  • they import the changed code, directly, through other files or through test helpers;
  • they visit or request an affected route over HTTP: page.goto, cy.visit, cy.request, browser.url, request(app).get(…), Playwright request.post(…);
  • with --with-cochange, they usually change together with your files in git (“likely related”).

Comment-only edits need no tests. A change to a dependency in package.json, a lockfile, a tsconfig*.json, a runner config or a test setup file runs the whole suite of the package that owns it (--no-full turns this off).

Each workspace package runs with its own runner (vitest, jest, mocha, ava, bun, node --test, playwright, cypress) from its own folder, e.g. (cd packages/api && npx jest --runTestsByPath test/users.test.js). Runners are never downloaded: the local binary is used, or the command fails with an install hint. The exit code is the worst runner's. The outcome is recorded for the status line and the agent stop gate.

Patch coverage

npx code-visualizer coverage                 # Patch coverage 72% (18/25 changed lines) · report from 3 min ago
npx code-visualizer coverage --staged --min 80
npx code-visualizer check --changed --min-patch-coverage 80   # CI gate, after npm test -- --coverage
  • It reads the reports your runner already writes: coverage/coverage-final.json (Jest, Vitest) or coverage/lcov.info, at the root and in each workspace package. --coverage <path> (on report, serve, check, pr, coverage) or the coverage config key picks others.
  • Only added code lines count; blank, comment and deleted lines never do. Changed files in a package without a report are listed as not measured.
  • pr adds a line such as “Patch coverage 72% — uncovered src/cart.ts L40-55”. My changes shows a chip and the uncovered lines, and the code view a red gutter. With a report, the health category becomes Tests & coverage.
  • check --min-patch-coverage fails when the change adds code and no report exists. Opt out with "check": { "patchCoverage": { "allowMissingReport": true } }.

Code review

review: any branch or PR, in dependency order

npx code-visualizer review feature/refunds          # a branch, tag or commit (default: your current branch)
npx code-visualizer review copilot/fix-login        # a branch that only exists on origin works too
npx code-visualizer review '#123'                   # a GitHub PR you already fetched (pr/123, refs/pull/123/head…)
npx code-visualizer review '!45'                    # a GitLab MR you already fetched
npx code-visualizer review '#123' --fetch           # fetch it first (the only network access)
npx code-visualizer review --test-first --open      # in the browser, with viewed checkboxes

Nothing is checked out: your working tree and HEAD stay as they are. You get:

  Review  feature/locale → main (since 5031f1545e, 2 commits)
  ~1 min · level 1/5 · 1 file to read (+3 −2)

  ▶ Start here  lib/format.ts
    changes signature of displayName() used in 2 places, 1 call not updated; untested

  Review path
    1. core     lib/format.ts  changes signature of displayName() used in 2 places, 1 call not updated; untested

  API changes
    ✖ displayName(user: Pick<User, 'name' | 'email'>): string → displayName(user: Pick<User, 'name' | 'email'>, locale: string): string  lib/format.ts:4
        1 call not updated: components/UserProfile.tsx:16

  Changed functions without test changes
    displayName() lib/format.ts
  • Start here, with the reason: the file that breaks something, otherwise the largest logic change.
  • A reading order: contracts and types first, then the code others build on, then its users; each test right after the code it covers (--test-first: before it).
  • Skim: lockfiles, snapshots, generated files, pure renames, comment-only edits.
  • Effort (meaningful lines at 400 an hour, level 1–5) and “This is N independent changes” when the PR should be split.
  • API changes with call sites not updated, new cycles and rule violations, code health, clone drift, and changed functions without test changes.
  • --format text|md|json, -o, --copy. --open starts (or reuses) serve and opens Reviewer mode on that ref.

diff: what changed architecturally

npx code-visualizer diff                                   # your branch / uncommitted work vs the merge-base
npx code-visualizer diff --staged                          # what you are about to commit
npx code-visualizer diff origin/main --fail-on new-cycles,breaking-exports,health-drop:2
npx code-visualizer diff v1.2.0..v1.3.0 --format md -o architecture.md

New imports and dependencies between areas, new and fixed cycles and rule violations, API changes (removed exports, changed signatures with the call sites not updated), removed routes that are still called, packages, complexity increases, new unused exports, new clones and the health change. Like a pull request, diff starts from the merge-base (base..head compares the two tips). Renamed or moved files keep their findings. --fail-on accepts new-cycles, new-violations, breaking-exports, removed-routes, new-missing-deps and health-drop:<n>.

pr: the description, written for you

npx code-visualizer pr --copy
npx code-visualizer pr --base origin/develop > pr.md
npx code-visualizer pr --format comment --check -o pr-comment.md   # a sticky PR comment for CI

Summary, files, changed functions and who uses them, impact and routes, Architecture changes (with a mermaid diagram of new area dependencies), tests and patch coverage, risk, suggested reviewers, code owners and a Review path checklist. On main with unpushed commits, those commits are your work. --format comment starts with the marker <!-- code-visualizer:pr-report -->, stays under 60,000 characters and folds long sections. --check adds the quality gates. code-visualizer never posts anything itself.

CI: don't make it worse

New-only semantics

check --changed compares your branch with its merge-base and fails only on findings that are new. Old debt next to your edit is counted, not blamed:

  Only new findings fail (compared with main (5031f1545e)) · 2 changed files

  ✔ Architecture rules 0 new · 2 existing · 0 fixed
  ✔ Declared dependencies 0 new · 0 existing · 0 fixed
  ✔ Circular dependencies 0 new · 0 existing · 0 fixed
  ✖ Hygiene 1 new · 0 existing · 0 fixed
      • lib/billing.ts:14 `debugger` statement: debugger; (new)
      Remove them before you commit — or, for files that need them, set "check": { "hygiene": { "exclude": ["<path>/**"] } }.

  Health 87/100 (B) ▼ 1 vs base · change risk 26/100
  1 gate failed
  • Findings have fingerprints without line numbers, so moving code does not make old findings new. An old function that grew is shown as (worse) with its old value.
  • Count limits (maxCycles, maxUnusedExports) fail when there is a new finding and the total is over the limit. --min-health fails only when your change lowers a score that is already below it.
  • --staged judges the index against HEAD (pre-commit). --committed (with --changed) ignores uncommitted edits (pre-push). --new-since <ref> compares with any ref.
  • In CI the base is the pull request's target branch (GitHub Actions, GitLab, Bitbucket, Azure Pipelines, Jenkins). An unknown or unfetched --base fails with Unknown git ref "mian". Did you mean "main"?, and a hint to fetch it.
  • In a shallow or single-branch checkout where no merge-base can be found, check --changed checks everything instead of passing silently, and warns about it. Use fetch-depth: 0.
  • "check": { "changedMode": "files" } restores the old behaviour: every finding in the files you touched.

| Gate | Flag | Config key | | --- | --- | --- | | Architecture rules & layers | (always on) | rules, layers, check.allowRuleViolations | | Declared dependencies | (always on) | check.allowMissingDependencies, check.allowDevDependenciesInProduction | | Hygiene (it.only, debugger, conflict markers in the lines you add) | (always on) | check.hygiene | | Circular dependencies | --max-cycles <n> | check.maxCycles | | Complexity | --max-complexity <n> | check.maxComplexity | | A changed function got more complex | --no-worse | check.noWorse | | Unused exports | | check.maxUnusedExports | | Health | --min-health <n> · --max-health-drop <n> | check.minHealth · check.maxHealthDrop | | Change risk | --max-risk <n> | check.maxRisk | | Patch coverage | --min-patch-coverage <n> | check.minPatchCoverage | | New copy-paste clones | --max-new-clones <n> | check.maxNewClones |

Adopting on an existing codebase: the baseline ratchet

npx code-visualizer check --update-baseline   # creates code-visualizer.baseline.json — commit it
npx code-visualizer check                     # uses it automatically: only findings not in it fail
npx code-visualizer check --update-baseline   # later: removes fixed findings (prints +a −b)

The baseline stores fingerprints per rule, not line numbers. Updates are a ratchet: new findings are added only with --force. After renaming files, refresh it in the same change with --update-baseline --force.

Outputs

One analysis, several reports: --format text|json|github|sarif|gitlab|markdown, plus --sarif <file>, --gitlab <file> and --json [file].

  • github: workflow annotations, best first (new findings, then findings on changed lines, then errors), at most 10 per level, then +N more.
  • Job summary: in GitHub Actions a gate table, new / existing / fixed counts, the health change, the top 15 new findings with links and the command to reproduce it locally are appended to $GITHUB_STEP_SUMMARY (--no-summary turns it off).
  • SARIF 2.1.0 for GitHub code scanning, with stable rule ids (cv/cycle, cv/architecture-rule, cv/duplicate-code, …) and baselineState.
  • GitLab Code Quality for the merge request widget.

Exit codes: 0 all gates passed (or nothing to check), 1 a gate failed, 2 usage error, invalid configuration or baseline, or an unknown ref.

GitHub Actions

# .github/workflows/code-visualizer.yml
name: code-visualizer
on: pull_request
permissions: { contents: read, security-events: write, pull-requests: write }
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # history: the merge-base, risk and reviewers
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npx code-visualizer check --changed --format github --sarif cv.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: cv.sarif, category: code-visualizer }
      # A sticky PR comment, updated on every push
      - run: npx code-visualizer pr --format comment --check -o pr-comment.md
        if: always()
      - run: gh pr comment ${{ github.event.pull_request.number }} --edit-last --create-if-none --body-file pr-comment.md
        if: always()
        env: { GH_TOKEN: '${{ github.token }}' }
      # The interactive report as an artifact
      - run: npx code-visualizer report --no-open
        if: always()
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: code-map
          path: .code-visualizer/report.html

To gate patch coverage, run your tests with coverage first and add --min-patch-coverage 80 to check.

GitLab CI

code-visualizer:
  image: node:22
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  variables: { GIT_DEPTH: 0 }
  script:
    - npx code-visualizer check --changed --gitlab gl-code-quality.json
  artifacts:
    when: always
    reports: { codequality: gl-code-quality.json }

Status line, git hooks & sync

status: one line for your prompt, tmux or agent

◆ 82▼3 · 5Δ→23 · 3 tests ✔ · ✖1 new cycle · ↓7 main (1 conflict) · patch 64%

Health (and its change on your branch) · changed → affected files · tests to run (✔/✖ from the last test run, only when it covered every test your change needs) · new cycles, rule breaks and copies (⧉) · ✖ check when the last check failed · commits on the base you don't have, with the conflicts (and clean merges that break your call sites) a rebase would bring · patch (patch coverage of your change) or cov (project line coverage).

It never analyzes inline: a running serve answers, otherwise it prints the stored snapshot and refreshes it in the background (marked with ↻; ! when the last refresh failed, and ? after the coverage when the report is older than your code). It takes about 40 ms, exits 0 (2 only for a mistyped option), and prints nothing outside a repository or in one where code-visualizer was never used. Formats: short (default), plain, json, tmux, starship, claude.

status --setup <tool> prints the snippet and edits nothing:

[custom.code_visualizer]
command = "code-visualizer status --format starship"
require_repo = true
when = true
format = "[$output]($style) "
style = "purple"
set -g status-interval 5
set -g status-right-length 160
set -ag status-right ' #(cd "#{pane_current_path}" && code-visualizer status --format tmux)'
# ~/.zshrc
_code_visualizer_status() { CODE_VISUALIZER_STATUS="$(code-visualizer status --format starship 2>/dev/null)"; }
autoload -Uz add-zsh-hook && add-zsh-hook precmd _code_visualizer_status
setopt PROMPT_SUBST
RPROMPT='${CODE_VISUALIZER_STATUS}'
# ~/.bashrc
_code_visualizer_status() { CODE_VISUALIZER_STATUS="$(code-visualizer status --format starship 2>/dev/null)"; }
PROMPT_COMMAND="_code_visualizer_status${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
PS1='${CODE_VISUALIZER_STATUS:+[$CODE_VISUALIZER_STATUS] }'"$PS1"
{
  "statusLine": {
    "type": "command",
    "command": "code-visualizer status --format claude --stdin-json",
    "padding": 0
  }
}

The claude format prints two lines, with a link to the live My changes page when serve runs.

These need code-visualizer on your PATH (npm i -g code-visualizer).

hooks: quality gates on every commit and push

npx code-visualizer hooks install            # preview: a diff, nothing written
npx code-visualizer hooks install --yes      # apply
npx code-visualizer hooks status
npx code-visualizer hooks uninstall --yes    # restore your files exactly

| Hook | Runs | | --- | --- | | pre-commit | check --staged --quiet-pass: new problems in what you commit, plus focused tests, debugger and conflict markers you add | | pre-push | check --changed --committed --quiet-pass (only what you push) and test --push (the affected tests) |

  • Works through the hook manager you already use (husky, lefthook, simple-git-hooks) or plain git hooks; core.hooksPath is respected and an existing hook keeps running first.
  • Only lines between # code-visualizer:start/end markers are touched: a second install changes nothing, and uninstall restores the files byte for byte.
  • A core.hooksPath outside the repository (a global hooks folder) is refused unless you pass --global-hooks.
  • Skip once: CODE_VISUALIZER_SKIP=1 git commit … (or git push).

sync: before you rebase

npx code-visualizer sync                     # what the base branch brings
npx code-visualizer sync --fetch --branches  # fetch first, and check teammates' branches too

Commits on the base you don't have (and who wrote them), files a rebase would conflict in (a real trial merge with git merge-tree; nothing in the repository is touched), your uncommitted edits that would conflict, and changes that merge cleanly but break your code: an export you call got another signature or was removed, a route you request is gone, with your call sites. It ends with the command to run, e.g. git rebase --autostash origin/main. It works from refs you already fetched; only --fetch uses the network.

Configuration reference

Zero config is the default. Add code-visualizer.config.json to the project root (or .code-visualizerrc.json, .code-visualizerrc, or a "codeVisualizer" key in package.json) to narrow, protect or enforce:

{
  "exclude": ["**/*.generated.ts", "src/legacy/**"],
  "base": "origin/main",
  // Forbidden imports: files matching "from" must not import files matching "to".
  "rules": [
    { "name": "ui-not-server", "from": "src/components/**", "to": "src/server/**", "message": "UI must not import server code" },
    { "name": "no-feature-cross-talk", "from": "src/features/a/**", "to": "src/features/b/**", "allow": "src/features/b/public.ts", "severity": "warn" }
  ],
  // Layers from top to bottom: a lower layer must never import a higher one.
  "layers": ["src/app/**", "src/features/**", "src/shared/**"],
  // Thresholds used by `code-visualizer check`.
  "check": { "maxCycles": 0, "maxComplexity": 25, "minHealth": 70, "maxRisk": 70, "maxNewClones": 0, "minPatchCoverage": 80 },
  "serve": { "notify": "errors", "events": { "exclude": ["unused-export"] } },
  "coverage": { "paths": ["packages/web/coverage/lcov.info"] },
  "clones": { "minTokens": 50, "minLines": 6, "ignore": ["src/generated/**"] }
}

Comments and trailing commas are allowed. Violations show up in Health & insights, the Markdown summaries, check, the live guard and the agent hooks. A configuration that can't be parsed is never silently ignored: report and serve print a warning (serve also announces when it is valid again) and check exits with code 2. Unknown check.* keys get a warning with a suggestion.

| Key | Type | Default | Meaning | | --- | --- | --- | --- | | exclude | glob list | [] | Files to leave out (gitignore syntax), in addition to .gitignore. | | base | ref | auto | The branch your work is compared with. Default: the PR target in CI, else origin/HEAD, main, master, develop, trunk. A base that names no commit is reported once and the detected one is used. | | rules[] | object list | | Forbidden imports. Each rule: name, from, to (globs), allow (globs allowed despite to), severity (error | warn, default error), message, includeTypes (also flag type-only imports, default true). | | layers | glob list | | Ordered from top to bottom; a lower layer must not import a higher one. An entry can be a list of globs. | | includeSubprojects | bool | glob(s) | object | false | Packages inside test/, fixtures/, examples/… are left out (with a one-line notice). true analyzes all, globs ("examples/*") analyze the matching ones. | | check.maxCycles | number | off | Fail above this many circular dependencies. | | check.maxComplexity | number | off | Fail when a function is more complex. Also the live guard's limit. | | check.minHealth | 0–100 | off | Fail below this health score (with --changed: only when your change lowers it). | | check.maxHealthDrop | number | off | Fail when health drops by more than n points vs. the base. | | check.maxRisk | 0–100 | off | Fail when the change risk is higher. | | check.maxUnusedExports | number | off | Fail above this many unused exports. | | check.noWorse | bool | false | Fail when a function you changed got more complex. | | check.allowMissingDependencies | bool | false | Don't fail on imports missing from package.json. | | check.allowDevDependenciesInProduction | bool | names | false | Don't fail when production code imports a devDependency (all, or the named packages); reported as warnings. | | check.allowRuleViolations | bool | false | Report rule violations without failing. | | check.baseline | path | bool | code-visualizer.baseline.json when it exists | The committed baseline of known findings; false never uses one. | | check.changedMode | new | files | new | files: --changed judges every finding in the touched files. | | check.minPatchCoverage | 0–100 | off | Fail when less of your added lines are covered. | | check.patchCoverage.allowMissingReport | bool | false | Skip the patch-coverage gate when there is no coverage report. | | check.hygiene | bool | kinds | object | on | Focused tests, debugger, conflict markers in added lines. false, a list ("debugger, conflict-marker"), { "debugger": false } or { "exclude": ["test/fixtures/**"] }. | | check.maxNewClones | number | off | Fail when the change adds more than n copy-paste clone families. | | serve.notify | errors | all | off | off | Desktop notifications for live events ("serve": "errors" is shorthand). | | `serve.events.exclu