Custom Rules
Extend the built-in rule set with project-specific checks. Custom rules let you encode domain conventions, enforce team standards, or flag patterns unique to your codebase — anything the built-in rules don't cover.
Setup
- Create a directory for your rules (e.g.
rules/at your project root). - Set
customRulesDirin your config file:
{
"customRulesDir": "./rules"
}
- Add
.tsfiles to that directory — each file should export a rule object.
Only .ts files are loaded. Subdirectories are ignored.
Rule Shape
Every custom rule must export an object with two properties: meta (a descriptor) and check (the inspection function).
import type { RuleContext } from "nestjs-doctor";
export const myRule = {
meta: {
id: "my-rule-id",
category: "correctness",
severity: "warning",
description: "Short explanation of what this rule checks",
help: "Actionable advice on how to fix a violation.",
},
check(context: RuleContext) {
// inspect context.sourceFile, call context.report() for each violation
},
};
meta Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for the rule |
category | string | Yes | One of "security", "performance", "correctness", "architecture" |
severity | string | Yes | One of "error", "warning", "info" |
description | string | Yes | Short summary shown in the report |
help | string | Yes | Fix guidance shown alongside diagnostics |
scope | string | No | "file" (default) or "project" |
check Function
The check function receives a RuleContext object with:
sourceFile— the ts-morphSourceFileAST node for the current filefilePath— the absolute path to the file being inspectedreport(diagnostic)— call this to emit a diagnostic withfilePath,message,help,line, andcolumn
For project-scoped rules (scope: "project"), the context includes the full project information instead of a single file.
Example
A rule that flags unresolved TODO comments:
import type { RuleContext } from "nestjs-doctor";
export const noTodoComments = {
meta: {
id: "no-todo-comments",
category: "correctness",
severity: "warning",
description: "TODO comments should be resolved before merging",
help: "Replace the TODO with an implementation or open an issue.",
},
check(context: RuleContext) {
const text = context.sourceFile.getFullText();
const regex = /\/\/\s*TODO/gi;
let match: RegExpExecArray | null;
while ((match = regex.exec(text)) !== null) {
const pos = context.sourceFile.getLineAndColumnAtPos(match.index);
context.report({
message: "Unresolved TODO comment",
help: "Replace the TODO with an implementation or open an issue.",
filePath: context.filePath,
line: pos.line,
column: pos.column,
});
}
},
};
ID Prefixing
Rule IDs are automatically prefixed with custom/. For example, a rule with id: "no-todo-comments" appears as custom/no-todo-comments in the scan output. This avoids collisions with built-in rules and makes it clear which diagnostics come from your custom checks.
Error Handling
Invalid rules produce warnings but never crash the scan. Common issues are surfaced in CLI output:
- Missing or non-function
checkexport - Invalid
categoryorseverityvalues - Missing required
metafields - Syntax errors in the rule file
Fix the warning and re-run — the rest of the analysis continues unaffected.
Disabling Custom Rules
Custom rules can be toggled just like built-in rules, using the custom/ prefix:
{
"rules": {
"custom/no-todo-comments": false
}
}
You can also suppress them per-file via ignore.rules:
{
"ignore": {
"rules": ["custom/no-todo-comments"]
}
}
Using AI to Create Rules
If you have an AI coding agent set up, /nestjs-doctor-create-rule can write custom rules for you. Install it with npx nestjs-doctor --init, then call /nestjs-doctor-create-rule in your agent's chat. It checks whether the detection is doable with static analysis, picks file or project scope, writes the .ts file, sets customRulesDir in your config, and runs nestjs-doctor to make sure the rule loads.
Rule Lab
The Report includes a Lab tab where you can write and test custom rules in the browser
npx nestjs-doctor . --report
Recommended workflow: use /nestjs-doctor-create-rule to scaffold a rule, test it in the Lab, then save the .ts file to your customRulesDir.