npm.io
0.1.0 • Published yesterdayCLI

madr-lint

Licence
MIT
Version
0.1.0
Deps
9
Size
283 kB
Vulns
0
Weekly
0

A fast, configurable linter for MADR (Markdown Architectural Decision Records). It validates the things a plain Markdown linter can't: required sections, a valid status, ISO-8601 dates, filename convention, and cross-file integrity like unique numbering and non-broken links — across MADR v2, v3, and v4.

madr-lint terminal output: two errors in an ADR, one clean file

Why madr-lint

MADR ships no official linter, and the general-purpose tools each cover only part of what an ADR collection needs:

Tool Markdown style Inter-doc links ADR numbering Status enum Date format Supersedes graph v2 bold-list
markdownlint-cli2 n/a
lychee n/a
adrs (rust)  (init) ~
madr-lint —¹

¹ Deliberately not Markdown style — pair it with markdownlint-cli2 if you want both. madr-lint owns the ADR-specific semantics.

  • MADR v2 / v3 / v4 aware — reads YAML frontmatter and v2 body-list metadata (both - **Status**: and canonical * Status:), or auto-detects per file.
  • ESLint-style rules — named madr/* rules with error / warn / off and per-rule options validated by a JSON Schema.
  • Per-file & cross-file — fast single-pass checks plus project rules for unique numbering, the supersedes graph, and link rot.
  • CLI, library & CItext / json / sarif reporters, a programmatic API, and a drop-in GitHub Actions step.

Install

npm install --save-dev madr-lint   # or: pnpm add -D madr-lint / yarn add -D madr-lint

Node.js 22+. ESM-only. Ships TypeScript types.

Quick start

# Lint the configured adrDir (default: docs/adr)
npx madr-lint

# Explicit paths (files or directories; directories are searched recursively)
npx madr-lint docs/adr libs/x/adr

# Machine-readable output for CI
npx madr-lint --format sarif > madr-lint.sarif

Exit code: 0 clean · 1 on error-level diagnostics · 2 on a config problem.

Configure

A madr-lint.config.ts (or .madrlintrc.json) at your project root:

import { defineConfig } from 'madr-lint';

export default defineConfig({
  extends: ['madr-lint:recommended'],
  madrVersion: 'auto',
  adrDir: 'docs/adr',
  ignorePatterns: ['**/template.md', '9999-*'],
  rules: {
    'madr/filename-format': ['error', { pattern: '^[0-9]{4}-.+\\.md

Rule values are a severity ('error' | 'warn' | 'off') or a [severity, options] tuple. Options are validated — an invalid option fails fast with exit code 2. Full reference: Configuration.

Rules

8 rules — 7 enabled by recommended, 1 opt-in. Each page documents its options, examples, and MADR-version compatibility.

Rule Type Default Checks
madr/required-sections per-file error Required heading sections are present
madr/status-enum per-file error status is one of the allowed values
madr/date-iso8601 per-file error date is a valid ISO-8601 calendar date
madr/filename-format per-file error Filename matches the ADR convention
madr/no-broken-links project error Relative links resolve to existing files
madr/no-duplicate-numbering project error ADR numbers are unique
madr/supersedes-bidirectional project error supersedes / superseded-by agree
madr/no-numbering-gap project off ADR numbers are contiguous (opt-in)

Use in CI

# .github/workflows/adr-lint.yml
jobs:
  madr-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npx madr-lint

The sarif reporter integrates with GitHub code scanning — see GitHub Action.

Programmatic API

import { runRulesOnFile, buildProjectFile, rules } from 'madr-lint';

const diagnostics = runRulesOnFile(
  [rules.requiredSections, rules.statusEnum],
  { path: '0001-x.md', content },
  { severity: 'error' },
);

Full surface: Programmatic API.

Pairs well with

madr-lint intentionally skips Markdown style — compose it:

markdownlint-cli2 'docs/adr/**/*.md'   # Markdown style
lychee 'docs/adr/**/*.md'              # external link rot
madr-lint docs/adr                     # ADR structure + inter-ADR links

Status

Alpha. Self-dogfooded (this repo lints its own ADRs) and validated against an external repository. Until 1.0, treat each minor bump as potentially breaking; the 1.0 gate is adoption feedback.

Contributing

Issues and PRs welcome. See CONTRIBUTING.md for the dev setup, rule-shape guide, and TDD/changeset workflow. The project dogfoods its own linter against its own ADRs in docs/adr/.

License

MIT t.kaneko

}], 'madr/no-numbering-gap': 'off', }, });

Rule values are a severity (__INLINE_CODE_17__) or a __INLINE_CODE_18__ tuple. Options are validated — an invalid option fails fast with exit code __INLINE_CODE_19__. Full reference: Configuration.

Rules

8 rules — 7 enabled by __INLINE_CODE_20__, 1 opt-in. Each page documents its options, examples, and MADR-version compatibility.

Rule Type Default Checks
__INLINE_CODE_21__ per-file __INLINE_CODE_22__ Required heading sections are present
__INLINE_CODE_23__ per-file __INLINE_CODE_24__ __INLINE_CODE_25__ is one of the allowed values
__INLINE_CODE_26__ per-file __INLINE_CODE_27__ __INLINE_CODE_28__ is a valid ISO-8601 calendar date
__INLINE_CODE_29__ per-file __INLINE_CODE_30__ Filename matches the ADR convention
__INLINE_CODE_31__ project __INLINE_CODE_32__ Relative links resolve to existing files
__INLINE_CODE_33__ project __INLINE_CODE_34__ ADR numbers are unique
__INLINE_CODE_35__ project __INLINE_CODE_36__ __INLINE_CODE_37__ / __INLINE_CODE_38__ agree
__INLINE_CODE_39__ project __INLINE_CODE_40__ ADR numbers are contiguous (opt-in)

Use in CI

__CODE_BLOCK_3__

The __INLINE_CODE_41__ reporter integrates with GitHub code scanning — see GitHub Action.

Programmatic API

__CODE_BLOCK_4__

Full surface: Programmatic API.

Pairs well with

__INLINE_CODE_42__ intentionally skips Markdown style — compose it:

__CODE_BLOCK_5__

Status

Alpha. Self-dogfooded (this repo lints its own ADRs) and validated against an external repository. Until 1.0, treat each minor bump as potentially breaking; the 1.0 gate is adoption feedback.

Contributing

Issues and PRs welcome. See CONTRIBUTING.md for the dev setup, rule-shape guide, and TDD/changeset workflow. The project dogfoods its own linter against its own ADRs in __INLINE_CODE_43__.

License

MIT t.kaneko

Keywords