lint
Skill13 starsChanged 4 months agoMITView on GitHub
Lint ADRs against schema and four verification gates. Use for ADR lint, validation, status-history checks, or file-and-line findings. Read-only.
80 other projects use a version of this.
Adopted by
Most recently taken up by
- PMDevSolutions/Flaviantheir own version, first seen Nov 8, 2026
- aiagentkit-labs/agentic-dev-kittheir own version, first seen Nov 8, 2026
- levi-qiao/obsidian-llm-wikitheir own version, first seen Nov 8, 2026
- elastic/docs-buildertheir own version, first seen Nov 4, 2026
- DataDog/dd-trace-pytheir own version, first seen Nov 1, 2026
- PMDevSolutions/Aureliustheir own version, first seen Nov 1, 2026
Used with
Projects with it also use query, ingest and 9 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
ArtemXTechSkillquery
Query data from this vault. USE WHEN user asks about projects, clients, tasks, daily notes. Use grep to extract frontmatter - do NOT read full files.
Also in 17 projects that use this
JaimeGBASkillingest
Digest an external source (article, paper, transcript, URL, book chapter) and integrate its content into the knowledge base
Also in 26 projects that use this
PydanticSkillcoverage
Fetch coverage diff from Codecov for the current branch or a specific PR. Shows uncovered lines, patch coverage, and overall coverage change.
Also in 4 projects that use this
seongjaeryuSkillsave
Complete and save your current thinking to Bindly
Also in 5 projects that use this
BugRogerSkillproject
Project lifecycle management. Dispatches to Ada.
Also in 4 projects that use this
AnthropicSkilldigest
Generate a daily or weekly digest of activity across all connected sources. Use when catching up after time away, starting the day and wanting a summary of mentions and action items, or reviewing a week's decisions and document updates grouped by project.
Also in 3 projects that use this
Other versions80 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 80
- ray-project/ray★ 44ksame name
- FalkorDB/FalkorDB★ 10ksame name
- FastLED/FastLED★ 7.5ksame name
- fleetdm/fleet★ 7.2ksame name
- aaddrick/claude-desktop-debian★ 5.5ksame name
- cloudposse/atmos★ 1.4ksame name
- ethereum/execution-specs★ 1.2ksame name
- adobe/S3Mock★ 1.2ksame name
- maxGraph/maxGraph★ 1.2ksame name
- jason-effi-lab/karpathy-llm-wiki-vault★ 718same name
70 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository19 other files it gives its agents.
The file
We split this skill into the rules it gives an agent
10 rules. 0 are common, 5 are distinctive, and 5 are very specific to this project.
0
Common
Most of the 67 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
Use $ARGUMENTS as the ADR file or directory.
- Distinctive: line 48
If the user passed something else (a glob, a non-existent path), explain politely and stop.
- Distinctive: line 116
When evaluating a single (file, gate) pair, apply policies in this order.
- Very specific: line 171
If .adr-kit.json defines template.required_sections, use that custom list.
- Very specific: line 184
When an ADR contains a status_history YAML list, validate that each entry has date, status, changed_by, reason, and changed_via.
- Very specific: line 200
Code references: when a claim is about code, look for file:line or file.ext references.
- Distinctive: line 230
Status conflicts: if this ADR's Status says "Supersedes ADR-XXX" but ADR-XXX's Status is not "Superseded by", flag the inconsistency.
- Distinctive: line 238
If a config file is in effect, prefix the run with a one-line config banner so the user knows which policy is being applied.
- Very specific: line 324
If docs/adr/ is empty or does not exist, say so plainly:
- Distinctive: line 335
If the run produced zero FAILs, say so plainly: "All linted ADRs pass at the configured severity.
“Common” is measured: kept by at least 6 in 10 of the 67 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
adr-kit lint
Reply in the language the user writes in; default to English. Keep command output, identifiers, paths, and ADR file content unchanged.
Use $ARGUMENTS as the ADR file or directory; default to docs/adr/ when it
is empty.
You are running /adr-kit:lint. The user wants to know whether existing ADRs in their project pass the four verification gates that the main adr skill enforces and, for v0.14 ADRs, whether their status histories are intact. You read files; you do not modify them. You report.
Run the deterministic CLI first
The gates below are implemented by bin/adr-lint; run it and report what it
finds, rather than re-deriving every verdict by reading files:
ADR_KIT="${ADR_KIT_ROOT:-${CLAUDE_PLUGIN_ROOT}}"
[ -n "$ADR_KIT" ] || { echo "adr-kit: plugin root not found; set ADR_KIT_ROOT, or update or reinstall the plugin" >&2; exit 1; }
python "$ADR_KIT/bin/adr-lint" --format json docs/adr/Pass the argument path instead of docs/adr/ when one was given. Exit 0 is
clean, 1 means findings, 2 is a configuration or input error: relay its
message and stop. Use the gate descriptions below to explain each finding
and to judge what the CLI leaves to judgment (the heuristic Evidence and
Clarity calls); when the CLI cannot run at all, fall back to reading the
files yourself and say that you did.
The deterministic CLI also returns read-only migration notices. Report them
even when every canonical ADR passes. A notice may contain an exact
adr-migrate --dry-run command for a supported legacy file or a guided
/adr-kit:migrate instruction for Y-Statement, Tyree/Akerman, arc42, hybrid,
or unknown shapes. Never execute the reported write command from this skill.
Inputs
- No argument: lint every
docs/adr/ADR-*.mdfile in the project root. - A directory path: lint every
ADR-*.mdfile under that directory. - A file path: lint that one file.
If the user passed something else (a glob, a non-existent path), explain politely and stop.
Configuration (since v0.9.0)
Established projects often have a long history of ADRs that predate the four canonical gates. Linting them under strict rules produces noise rather than actionable feedback. Two opt-in mechanisms let a project apply the gates surgically: strict on new ADRs, advisory on legacy ones.
Mechanism 1: project-level config file
Before linting, look for docs/adr/.adr-kit.json (relative to the project root, or to the directory passed as argument if the user pointed elsewhere). If it exists, read it and apply it as policy. If it does not exist, fall back to default behaviour (everything strict, exact match to v0.7.x output).
Recognised fields:
strict_from(string, optional): first ADR identifier (inclusive) on which all gates are enforced strictly. ADRs with a numerically lower number are linted in advisory mode for the gates that opt in (seeseverity). Format:ADR-XXXmatching the filename pattern. Example:"ADR-082".ignore(array of strings, optional): list of ADR identifiers (ADR-XXX) or full filenames to skip entirely. Useful for archived or superseded ADRs whose status is final. Skipped ADRs appear in the aggregate as SKIPPED but produce no gate output.severity(object, optional): per-gate severity. Keys arecompleteness,audit,evidence,clarity, andconsistency. Values are one of:always_strict: failures are FAIL regardless ofstrict_from.always_advisory: failures are ADVISORY regardless ofstrict_from.advisory_before_strict_from: failures are ADVISORY for ADRs that predatestrict_from, FAIL otherwise. This is the default forcompleteness,evidence,claritywhenstrict_fromis set.- For
auditandconsistencythe implicit default staysalways_stricteven whenstrict_fromis set, because an invalid status chain, filename / heading mismatch, duplicate number, or broken cross-reference is a real bug regardless of when the ADR was written. Projects can override this in their config but the default is loud-on-purpose.
template.required_sections(array of strings, optional): advanced override for a project-specific section list. Each entry is the exact heading text including the##prefix. Without it, Completeness resolves required headings from each ADR's MADR, Nygard, or canonical profile.template.profile(string, optional): operational creation default and profile contract. Legal values aremadr(default),nygard, andcanonical. Per-fileformatfrontmatter wins; otherwise headings are detected.unknownandhybridfail strict lint.
Example .adr-kit.json:
{
"strict_from": "ADR-082",
"ignore": ["ADR-001", "ADR-007"],
"severity": {
"completeness": "advisory_before_strict_from",
"audit": "always_strict",
"evidence": "advisory_before_strict_from",
"clarity": "always_advisory",
"consistency": "always_strict"
},
"template": {
"profile": "madr"
}
}The file may contain top-level "_comment" keys (any name starting with _); ignore them silently. They are a convention to embed annotations in JSON without breaking parse.
If the file is malformed JSON, report the parse error and stop without linting. Do not silently fall back to defaults: a broken policy file is a bug the user should know about. If a field has an unrecognised value (e.g. "severity.completeness": "lol"), report the unrecognised value, list the legal values, and stop.
Mechanism 2: per-ADR markers
Inside an individual ADR, an HTML comment line of one of these shapes flips the policy for that file only:
<!-- adr-kit-lint: skip -->
<!-- adr-kit-lint: skip completeness, evidence -->
<!-- adr-kit-lint: advisory -->Forms (case-insensitive on the directive, whitespace-tolerant):
skip(no args): the ADR is skipped entirely. Counts as SKIPPED in the aggregate.skip <gate>[, <gate>...]: those gates are skipped on this file only. Other gates still run.advisory: all gates run on this file in advisory mode. Failures are ADVISORY, not FAIL.
The marker may appear anywhere in the file (top, bottom, inside or outside a section). Scan the full file for the first matching marker line and apply it. If multiple marker lines disagree (e.g. one says skip, another says advisory), the first matching marker wins; report the conflict in the file's output.
Severity decision tree
When evaluating a single (file, gate) pair, apply policies in this order. The first matching rule wins.
digraph severity {
"Is the file in config.ignore?" [shape=diamond];
"Skip whole file" [shape=box];
"Per-ADR marker says skip (no args)?" [shape=diamond];
"Per-ADR marker says skip <this gate>?" [shape=diamond];
"Skip this gate only" [shape=box];
"Per-ADR marker says advisory?" [shape=diamond];
"ADVISORY (reason: marker)" [shape=box];
"config.severity[gate] resolved to always_strict?" [shape=diamond];
"FAIL on failure" [shape=box];
"config.severity[gate] resolved to always_advisory?" [shape=diamond];
"ADVISORY (reason: severity=always_advisory)" [shape=box];
"config.severity[gate] = advisory_before_strict_from AND ADR predates strict_from?" [shape=diamond];
"ADVISORY (reason: predates strict_from)" [shape=box];
"Is config absent?" [shape=diamond];
"FAIL on failure (default behaviour)" [shape=box];
"FAIL on failure (post-strict_from)" [shape=box];
"Is the file in config.ignore?" -> "Skip whole file" [label="yes"];
"Is the file in config.ignore?" -> "Per-ADR marker says skip (no args)?" [label="no"];
"Per-ADR marker says skip (no args)?" -> "Skip whole file" [label="yes"];
"Per-ADR marker says skip (no args)?" -> "Per-ADR marker says skip <this gate>?" [label="no"];
"Per-ADR marker says skip <this gate>?" -> "Skip this gate only" [label="yes"];
"Per-ADR marker says skip <this gate>?" -> "Per-ADR marker says advisory?" [label="no"];
"Per-ADR marker says advisory?" -> "ADVISORY (reason: marker)" [label="yes"];
"Per-ADR marker says advisory?" -> "Is config absent?" [label="no"];
"Is config absent?" -> "FAIL on failure (default behaviour)" [label="yes"];
"Is config absent?" -> "config.severity[gate] resolved to always_strict?" [label="no"];
"config.severity[gate] resolved to always_strict?" -> "FAIL on failure" [label="yes"];
"config.severity[gate] resolved to always_strict?" -> "config.severity[gate] resolved to always_advisory?" [label="no"];
"config.severity[gate] resolved to always_advisory?" -> "ADVISORY (reason: severity=always_advisory)" [label="yes"];
"config.severity[gate] resolved to always_advisory?" -> "config.severity[gate] = advisory_before_strict_from AND ADR predates strict_from?" [label="no"];
"config.severity[gate] = advisory_before_strict_from AND ADR predates strict_from?" -> "ADVISORY (reason: predates strict_from)" [label="yes"];
"config.severity[gate] = advisory_before_strict_from AND ADR predates strict_from?" -> "FAIL on failure (post-strict_from)" [label="no"];
}In plain words: ignore beats markers, markers beat config, and within config the precedence is always_strict > always_advisory > advisory_before_strict_from. If the gate would PASS on its own checks, the severity rule does not apply: PASS stays PASS regardless of policy.
What you check, gate by gate
For every ADR you read, evaluate each of the four gates separately. A gate either passes or fails for a given file. Cite line numbers when reporting a failure.
Gate 1: Completeness
A passing ADR has every load-bearing semantic section for its detected or declared profile, with non-empty content.
Required semantic roles are Status, Context/Problem, Decision/Outcome,
Alternatives/Considered Options, Consequences, Related Decisions, and
References. MADR uses Context and Problem Statement, Considered Options,
and Decision Outcome; Nygard/canonical use their shorter equivalents.
If .adr-kit.json defines template.required_sections, use that custom list.
Sub-checks within sections:
- Status line is one of:
Proposed,Accepted,Deprecated,Superseded by ADR-XXX,Amended by ADR-XXX. Date inYYYY-MM-DDformat must be present. - Alternatives/Considered Options has at least 2 alternatives, each with rejection reasoning. A single bullet point of one word does not count as an alternative.
- Consequences has both a positive and a negative direction. Look for
Benefits/Trade-offs/Positive/Negativesubheadings or a clearly mixed list. A one-sided Consequences section fails this gate. - Risks are named with at least one mitigation each (typically inside Consequences as
Risks and mitigationsor similar).
Failure example: Completeness: missing ## Risks and mitigations subsection (line 47); only positive consequences listed.
Audit: Status History (v0.14.0+)
When an ADR contains a status_history YAML list, validate that each entry has
date, status, changed_by, reason, and changed_via; dates are in
chronological order and are not in the future; and the latest history status
matches the ## Status section. ADRs without a history block predate v0.14 and
pass this supplemental gate until deliberately migrated.
Failure example: Audit: latest status_history entry is Proposed but ## Status is Accepted. Append the missing Accepted transition; do not rewrite older entries.
Gate 2: Evidence
A passing ADR replaces challengeable claims with measurements or citations.
Heuristic checks:
- Bare adjectives in critical positions (Decision, Consequences, Alternatives) without an accompanying number or citation. Examples to flag: "fast", "slow", "faster", "slower", "better", "worse", "improves", "reduces", "more reliable", "more performant" when not followed by a measurement or citation.
- Constraint claims ("X has Y RAM", "Y supports up to Z connections") without an anchor (vendor doc, datasheet, measured, internal doc, RFC).
- Code references: when a claim is about code, look for
file:lineorfile.extreferences. A claim about an algorithm that does not cite the implementation is suspicious. - External claims (specs, RFCs, vendor docs): should be linked, not paraphrased.
You will see false positives ("the new system is faster" might be acceptable in a Context paragraph if a measurement appears later in Consequences). Use judgment: if a measurement or citation backs the claim within ~5 lines, count it as supported.
Failure example: Evidence: line 24 says "improves performance" with no measurement in the surrounding paragraphs. Suggest replacing with a measured improvement, e.g. "reduces request latency from 120 ms to 40 ms p99 (load-test on staging, see PERF-103)".
Gate 3: Clarity
A passing ADR is readable to a developer who has never seen the codebase.
Heuristic checks:
- Acronyms: any ALL-CAPS sequence of 2 to 6 letters that appears for the first time without an inline expansion. Example: "TLS" should be "TLS (Transport Layer Security)" on first use.
- Project-specific jargon without explanation: terms like internal service names, internal status codes, or proprietary protocols.
- Decision summary at top: the Decision section should open with a single declarative sentence. If the Decision opens with a multi-paragraph discussion before stating what was chosen, flag it.
- Code examples for technical decisions (algorithm choice, protocol selection): expected to be present in either Decision or Implementation Notes if applicable.
Failure example: Clarity: line 12 uses "WAL" without expansion. Suggest "WAL (write-ahead log)" on first use. Line 31 opens the Decision section with "There are several considerations..." instead of a declarative sentence; suggest leading with the choice and unpacking after.
Gate 4: Consistency
A passing ADR fits the existing record without contradictions.
Heuristic checks:
- Filename matches heading: file
ADR-042-foo.mdshould have a first-line heading# ADR-042 .... Mismatch fails this gate. - Filename pattern:
ADR-XXX-kebab-case-title.mdwith uppercase prefix and 3-digit zero-padded number. Lowercase prefixes (adr-), unpadded numbers (ADR-42-), or non-kebab-case (ADR-042-MyTitle.md) fail. - Cross-references in
## Related Decisionsfollow theADR-XXXformat. References to non-existent files (broken links) fail. - Duplicate ADR numbers in the directory: if two files share an ADR number, both fail the Consistency gate. Recommend a renumbering follow-up.
- Status conflicts: if this ADR's Status says "Supersedes ADR-XXX" but ADR-XXX's Status is not "Superseded by", flag the inconsistency.
Failure example: Consistency: filename ADR-042-foo.md but heading says "# ADR-42 Foo" (missing zero-padding, line 1). Filename and heading must agree.
Output format
For each ADR file, produce a one-line summary plus details for any failing or advisory gate. Three result tiers exist: PASS, ADVISORY (a finding that does not block but is reported), and FAIL.
If a config file is in effect, prefix the run with a one-line config banner so the user knows which policy is being applied.
Single-file output (no config)
ADR-042-foo.md
Completeness: PASS
Evidence: FAIL
line 24: "improves performance" with no measurement.
line 38: "scales better" with no number.
Clarity: PASS
Consistency: PASS
Summary: 3 of 4 gates pass strictly. 1 FAIL. To flip Status to Accepted, fix the Evidence gate.Single-file output (config in effect, gate reduced to advisory)
ADR-042-foo.md
Completeness: PASS
Evidence: ADVISORY
line 24: "improves performance" with no measurement (ADVISORY: ADR predates strict_from=ADR-042)
line 38: "scales better" with no number (ADVISORY: ADR predates strict_from=ADR-042)
Clarity: PASS
Consistency: PASS
Summary: 3 of 4 gates pass strictly. 1 advisory. No FAIL.Directory-tree output (no config)
Linting docs/adr/ (12 ADRs)
PASS (9):
ADR-001-foo.md
ADR-003-bar.md
...
FAIL (3):
ADR-002-baz.md
Evidence: line 24 ("faster"), line 38 ("scales better").
ADR-007-qux.md
Completeness: missing ## Related Decisions section.
ADR-011-quux.md
Consistency: filename has lowercase prefix "adr-011-...", expected "ADR-011-...".
Aggregate:
Most common FAIL gate: Evidence (2 of 3 failures).
Next steps: focus on ADR-002-baz.md, which fails the most gates.Directory-tree output (config in effect)
Linting docs/adr/ (50 ADRs)
Config: .adr-kit.json found (strict_from=ADR-042; severity: completeness=advisory_before_strict_from, evidence=advisory_before_strict_from, consistency=always_strict)
PASS strictly (8):
ADR-042-...
ADR-043-...
...
ADVISORY only (38):
Most common advisory gate: Completeness (38 of 38; legacy template predates canonical seven).
Listed by ADR id; expand on request.
FAIL (4):
ADR-045-foo.md
Evidence: line 24 ("faster") with no measurement.
ADR-046-bar.md
Consistency: filename ADR-046-bar.md but heading "# ADR-46 Bar" (line 1).
...
SKIPPED (0)
Aggregate:
Most common FAIL gate: Evidence (3 of 4 failures).
Next steps: focus on ADR-045-foo.md, which fails 2 of 4 gates.The aggregate's bottom line always names the FAIL count, never the ADVISORY count. ADVISORY is informational; FAIL is what the user is asked to act on.
When you find no ADRs
If docs/adr/ is empty or does not exist, say so plainly:
No ADRs found at docs/adr/. The toolkit is installed but no decisions have been recorded yet.
Create your first ADR with /adr-kit:adr.Reporting
Always end with a single recommended next action that points at a FAIL, not an ADVISORY. ADVISORY findings are background noise the project has explicitly chosen to tolerate; FAIL findings are what the user is being asked to fix. The next-action sentence names which ADR to fix first (the one with the most FAIL gates, or the most-referenced one) and which gate to focus on. Concrete, not abstract.
If the run produced zero FAILs, say so plainly: "All linted ADRs pass at the configured severity. <N> ADVISORY findings remain, treated as informational by the project's policy." Do not invent a FAIL where there is none.
What you do not do
- You do not modify ADRs. Read-only by design.
- You do not invoke the
adr-generatoragent. The lint skill is informational; the user decides whether to fix. - You do not call out style preferences that are not in the four gates. No bikeshedding on heading capitalisation, list-marker style, or whitespace. The gates are the contract.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

