nestjs-doctorGitHub

Setup

Quick Start

Run directly with npx:

npx nestjs-doctor@latest .

For file paths and line numbers:

npx nestjs-doctor@latest . --verbose

No configuration or plugins are required.

Installation

Install as a dev dependency for consistent CI runs:

npm install -D nestjs-doctor

CLI Usage

Usage: nestjs-doctor [directory] [options]

  --verbose             Show file paths and line numbers per diagnostic
  --score               Output only the numeric score (for CI)
  --json                JSON output (for tooling)
  --format <f>          console (default), json, sarif, gitlab, markdown, github
  --output <path>       Write the formatted output to a file instead of stdout
  --json-compact        Emit JSON-based formats without indentation
  --scope <s>           full (default), files, lines, changed
  --base <ref>          Git ref to compare against (auto-detected)
  --staged              Scope to the staged files, for pre-commit hooks
  --changed-files-from  Path to a newline-separated list of changed files
  --blocking <level>    Severity that fails the run: none, warning, error
  --min-score <n>       Minimum passing score (0-100)
  --report              Generate an interactive HTML report (--graph also works)
  --config <p>          Path to config file
  --list-rules          List every built-in rule and exit
  --init                Set up the /nestjs-doctor skill for AI coding agents
  -h, --help            Show help

See CI & Pull Requests for --scope, --blocking, and the official GitHub Action.

CI Integration

Use --min-score to enforce a minimum health score in your CI pipeline:

npx nestjs-doctor . --min-score 75

Or add it as a script in package.json:

{
  "scripts": {
    "health": "nestjs-doctor . --min-score 75"
  }
}

Exit Codes

CodeMeaning
0Both gates passed
1A gate failed — see below
2Invalid input (bad path, invalid flags)

Two independent gates can fail a run. --min-score compares the project's health score against a threshold. --blocking fails on reported findings at or above a severity: error (the default for the console report), warning, or none.

--json and --score default to --blocking none, so they fail only on --min-score — the behaviour they had before --blocking existed. Pass --blocking explicitly to make every output mode behave the same.

Report

npx nestjs-doctor@latest . --report

Self-contained HTML file with five sections: score summary, source-level diagnostics with code viewer, interactive module graph, schema ER diagram, and a custom rule playground. Opens in your browser.

Module Graph

AI Coding Agents

Ships with skills for popular AI coding agents. Run --init to auto-detect installed agents and install the nestjs-doctor skill for each one:

npm install -D nestjs-doctor
npx nestjs-doctor --init
AgentDetectionSkill location
Claude Code~/.claude exists~/.claude/skills/nestjs-doctor/
Amp Code~/.amp exists~/.config/amp/skills/nestjs-doctor/
Cursor~/.cursor exists~/.cursor/skills/nestjs-doctor/
OpenCodeopencode CLI or ~/.config/opencode~/.config/opencode/skills/nestjs-doctor/
Windsurf~/.codeium existsAppends to ~/.codeium/windsurf/memories/global_rules.md
Antigravityagy CLI or ~/.gemini/antigravity~/.gemini/antigravity/skills/nestjs-doctor/
Gemini CLIgemini CLI or ~/.gemini~/.gemini/skills/nestjs-doctor/
Codexcodex CLI or ~/.codex~/.codex/skills/nestjs-doctor/

A project-level fallback is always written to .agents/nestjs-doctor/. Commit it so every contributor gets the skill automatically.

Skills

--init installs two skills per agent:

SkillCommandDescription
nestjs-doctor/nestjs-doctorRuns the scan, shows the report, and fixes what it can
nestjs-doctor-create-rule/nestjs-doctor-create-ruleScaffolds a custom rule: checks feasibility, writes the .ts file, updates config, verifies it loads

See Custom Rules for the rule format.

Node.js API

nestjs-doctor can be used programmatically:

import { diagnose, diagnoseMonorepo } from "nestjs-doctor";

const result = await diagnose("./my-nestjs-app");
result.score; // { value: 82, label: "Good" }
result.diagnostics; // Diagnostic[]
result.summary; // { total, errors, warnings, info, byCategory }

const mono = await diagnoseMonorepo("./my-monorepo");
mono.isMonorepo; // true
mono.subProjects; // [{ name: "api", result }, ...]
mono.combined; // Merged DiagnoseResult

See the pipeline overview for details on the DiagnoseResult structure.

Incremental Scanning API

For tooling that needs fine-grained control — such as editor integrations and language servers — nestjs-doctor exports an incremental scanning API. Instead of running a full diagnose() call, you can prepare a scan context once and then re-scan individual files as they change.

import {
  prepareAnalysis,
  updateFile,
  checkFile,
  checkAllFiles,
  checkProject,
  updateModuleGraphForFile,
  updateProvidersForFile,
  getRules,
} from "nestjs-doctor";

Lifecycle

// 1. Prepare the analysis context (parses all files, builds module graph, resolves providers)
const { context, customRuleWarnings } = await prepareAnalysis("./my-nestjs-app");

// 2. When a file changes, update it in the context
updateFile(context, "/absolute/path/to/changed-file.ts");

// 3. Re-scan just that file (file-scoped rules only)
const { diagnostics, errors } = checkFile(context, "/absolute/path/to/changed-file.ts");

// 4. Or re-run all file-scoped rules across every file
const allFileResults = checkAllFiles(context);

// 5. Or re-run project-scoped rules (module graph, circular deps, etc.)
const projectResults = checkProject(context);

Granular Updates

If you need to update the module graph or providers independently (for example, after editing multiple files before re-scanning):

updateModuleGraphForFile(context.moduleGraph, context.astProject, filePath);
updateProvidersForFile(context.providers, context.astProject, filePath);

Listing Rules

import { getRules } from "nestjs-doctor";

const rules = getRules(); // all built-in rules (AnyRule[])

AnalysisContext

The prepareAnalysis function returns an AnalysisContext that holds:

FieldTypeDescription
astProjectProjectts-morph project with all source files
configNestjsDoctorConfigResolved configuration
filesstring[]Collected file paths
fileRulesRule[]File-scoped rules (filtered by config)
projectRulesProjectRule[]Project-scoped rules (filtered by config)
moduleGraphModuleGraphImport/export graph
providersMap<string, ProviderInfo>Resolved NestJS providers
projectProjectInfoDetected project metadata (name, version, ORM, framework)
schemaGraphSchemaGraph | undefinedExtracted database schema (if ORM detected)
schemaRulesSchemaRule[]Schema-scoped rules (filtered by config)
targetPathstringRoot directory of the scanned project