CLI reference

Run a scan without installing anything:

npx nestjs-doctor@latest [directory] [options]

The directory defaults to the current one.

Commands

CommandDoes
ci installWrites .github/workflows/nestjs-doctor.yml at the repository root. Add --force to replace an existing file

Scanning

FlagDoes
--verboseShow the file and line behind every diagnostic
--config <path>Use a specific config file instead of auto-detecting
--list-rulesPrint every built-in rule and exit
-h, --helpPrint usage and exit

Ctrl+C cancels a running scan immediately and exits 130.

Scope

Scoping changes what is reported, never what is analyzed. Cross-file rules need the whole project, so the score always covers all of it.

FlagDoes
--scope fullEverything. The default
--scope filesDiagnostics in the changed files
--scope linesDiagnostics on the changed lines
--scope changedOnly what the change introduced, compared against the merge base
--base <ref>The ref to compare against. Auto-detected when omitted
--stagedScope to staged files, for a pre-commit hook
--changed-files-from <path>Read the changed file list from a file, for CI

changed needs history. Without a reachable base ref it degrades wider and says so: to every diagnostic in the changed files when --changed-files-from is set, and to the whole project when it is not. In CI, check out with fetch-depth: 0.

files and lines keep a finding whose file sits above the scanned directory. The changed-file set describes the scanned tree only, so a package.json one level up is never known to be unchanged. changed still drops it, because it compares against the base revision rather than the file list.

Output

FlagDoes
--format <f>console (default), json, sarif, gitlab, markdown, github
--jsonShorthand for --format json
--json-compactEmit JSON formats without indentation
--output <path>Write to a file instead of stdout. With --report, where the HTML goes
--scorePrint only the number
--reportBuild the interactive HTML report. --graph is an alias
--timings <path>Overlay boot timings on the report's module graph. See Boot trace

--report writes HTML rather than a payload, so it refuses to share a run with --format, --json or --score. Any of those combinations exits 2 and names the flag. Run them as separate commands.

Only the payload goes to stdout, so a machine-readable one stays parseable. Warnings print on stderr.

Two of them are suppressed instead in machine-readable mode, meaning --score and every format except console and github. A custom rule that failed to load is silent, and a run below --min-score exits 1 with no message on either stream.

The menu

A console scan in a terminal ends on a score screen: the nest, the score with its bar, the severity counts, and a short action menu. Review the findings, open the HTML report, hand off to a coding agent, scaffold the GitHub Actions workflow when it is missing, or copy the findings as markdown. Everything comes from the scan that just ran, so nothing is scanned twice.

In a monorepo the breakdown is a two-pane browser. Sub-projects list worst score first. The left pane is the scrollable project list, and the right pane is the action menu.

A side panel shows the selected project's score, error, warning and info counts, file count, and the rules it trips most. ↑↓ moves in the focused pane, ←→ or tab switches panes, enter confirms the menu action, q quits.

An interactive run hands its presentation to that screen and prints nothing else. Pass --verbose to print the full findings list above it instead.

Review issues opens a live browser. The left pane lists the findings grouped by rule under category captions, worst first; the right pane follows the selection with the rule's identity and severity badge, the location, the message, the offending code window, the rule's recommendation with its docs link, and then a bad and a good sample of the pattern. Most samples are tested against the rule they illustrate, so the bad one is what the rule reports and the good one is what it accepts.

Navigation is by key: ↑↓ or j/k moves finding by finding, ←→ jumps a whole rule group, g/G go to the ends, c copies an agent-ready fix prompt for the selected rule, o opens the docs page, b returns to the score screen.

Handing off detects Claude Code, Codex, and Cursor on your PATH and starts the one you pick with the top findings as its first prompt, plainly: no permission-skipping flags are passed. Copy the prompt instead to use any other agent. The prompt never leaves your machine; the scan itself reports only anonymous rule counts.

The menu never appears where it could hang a machine. It is skipped in CI, inside coding agents, in pipes, in dumb terminals, and in every mode other than plain console output. Quitting keeps the run's exit code.

Gates

FlagDoes
--blocking <level>Severity that fails the run: none, warning, error. Only findings on the ciFailure surface can trip it
--min-score <n>Fail when the project's score is below this

--min-score overrides the config file's minScore, which applies on its own when the flag is omitted. --blocking has no single default. It is set by the output mode:

Output modeDefault
The console reporterror
--format githuberror
--score, and the formats that replace the console report: json, sarif, gitlab, markdownnone

Those exit codes predate the flag. Set --blocking explicitly and every mode agrees.

Agents

FlagDoes
--initInstall the skill for your coding agent. See Coding agents

Exit codes

Every run ends in one of four codes:

CodeMeaning
0Passed
1A gate failed
2Bad input: the path does not exist, a flag is invalid, or two flags conflict
130You cancelled the scan with Ctrl+C

The score gate is checked before the severity gate, so a run below --min-score exits 1 whether or not any diagnostic was blocking.