Skip to content

CLI

Terminal window
madr-lint [OPTIONS] [PATHS...]

One or more files or directories to lint. Directories are searched recursively for .md files.

When omitted, madr-lint lints the configured adrDir (default: docs/adr).

Terminal window
# lint the configured adrDir
madr-lint
# lint explicit paths
madr-lint docs/adr docs/decisions/0007-use-x.md
FlagDefaultDescription
--format <format>textReporter: text, json, or sarif.
--quietoffReport errors only; suppress warnings from output.
--max-warnings <n>(none)Exit 1 when warning count exceeds n. 0 means any warning fails CI. Negative = no limit.
--config <path>(auto)Load exactly this config file (TS or JSON), bypassing discovery.
--cache / --no-cache--cacheUse the per-file content-hash cache.
--cache-dir <dir>.madr-lint/cacheCache directory.
--baseline / --no-baseline--baselineSubtract .madr-lint/baseline.json when present.
--update-baselineRewrite .madr-lint/baseline.json from a full lint, then exit 0.
--helpShow help.
--versionPrint the version.

CLI flags win over the config file — e.g. --no-cache overrides cache: true.

--quiet filters warnings from output but the original warning count is still used for the --max-warnings threshold — mirroring ESLint’s documented semantics. This lets you run --quiet --max-warnings 0 to keep CI logs free of warning noise while still failing the build when warnings exist.

When the threshold is exceeded, the reason is printed to stderr for every --format, so stdout payloads stay clean for machine consumers:

madr-lint: 3 warning(s) found, exceeds --max-warnings 0
Terminal window
# CI: fail on any warning, but keep output clean
madr-lint --quiet --max-warnings 0

Warnings absorbed by the baseline do not count toward --max-warnings — the baseline is subtracted before the threshold is checked, so inherited debt never fails CI. Only fresh warnings count. --update-baseline always exits 0, regardless of --quiet or --max-warnings.

Human-readable, grouped by file:

docs/adr/0003-use-postgres.md
error madr/status-enum Status "decided" is not one of: ...
error madr/required-sections Missing required section: "Consequences"
2 errors

Structured output for tooling:

Terminal window
madr-lint --format json
{
"version": 1,
"summary": { "total": 2, "errors": 2, "warnings": 0, "baselineHidden": 0 },
"results": [
{
"path": "docs/adr/0003-use-postgres.md",
"ruleName": "madr/status-enum",
"messageId": "invalidStatus",
"severity": "error",
"message": "Status \"decided\" is not one of: ...",
"data": { "status": "decided" }
}
]
}

SARIF for code-scanning integrations (e.g. GitHub code scanning):

Terminal window
madr-lint --format sarif > madr-lint.sarif
Exit codeMeaning
0No errors; warning count within --max-warnings limit (if set)
1One or more error-severity diagnostics, or warning count exceeds --max-warnings
2Usage or configuration error (invalid --max-warnings value, missing --config file, invalid rule options, unknown --format)

The cache stores per-file diagnostics keyed by content hash and is invalidated when the package version or resolved config changes. Cross-file rules always re-run.

Terminal window
# force a clean run
madr-lint --no-cache
# use a custom cache directory
madr-lint --cache-dir .cache/madr-lint

Adopting madr-lint on a repo that already has violations? Snapshot them into .madr-lint/baseline.json so only new violations fail the build:

Terminal window
# snapshot today's violations and commit the file
madr-lint --update-baseline
# subsequent runs subtract the baseline automatically
madr-lint
# audit everything, ignoring the baseline
madr-lint --no-baseline

Subtraction runs after the cache and after inline suppression, and never touches the cache — so editing or deleting the baseline takes effect immediately. See the Adopting on an existing repo guide for the full workflow.