A linter for spec-driven development. Checks that specification markdown files are complete, well-structured, and ready for implementation — by humans or AI agents.
npm install -g @umxr/spec-lint# Lint a single spec
spec-lint docs/specs/auth.md
# Lint all specs in a directory (recursive)
spec-lint docs/specs/
# JSON output for CI/agent consumption
spec-lint docs/specs/ --json
# Read from stdin
cat my-spec.md | spec-lint --stdin
# AI-powered semantic rules (requires ANTHROPIC_API_KEY)
spec-lint docs/specs/auth.md --ai
# Fail on warnings (default: fail on errors only)
spec-lint docs/specs/ --fail-on warning
# Custom config file
spec-lint docs/specs/ --config .speclintrc.json
# Verbose output
spec-lint docs/specs/ --verbose| Code | Meaning |
|---|---|
| 0 | All specs pass (or only info-level findings) |
| 1 | Errors found (or warnings, if --fail-on warning) |
| 2 | Usage error (bad arguments, missing files) |
| Rule | Default | Description |
|---|---|---|
has-required-sections |
error | Spec must contain all required sections |
sections-not-empty |
error | Every section must have content |
has-acceptance-criteria |
error | At least one acceptance criterion must exist |
acceptance-criteria-are-checkboxes |
warning | Criteria should use - [ ] checkbox format |
has-problem-statement |
error | Problem section must be more than one sentence |
no-todo-placeholders |
warning | Flags TODO, TBD, FIXME, XXX, [placeholder], ... |
| Rule | Default | Description |
|---|---|---|
detect-vague-language |
warning | Flags weasel words, vague quantifiers, and ambiguity |
criteria-are-testable |
warning | Checks if acceptance criteria can be objectively tested |
suggest-missing-edge-cases |
info | Suggests edge cases not covered in the spec |
The detect-vague-language rule also includes a fast heuristic pass that works without an API key.
Create a .speclintrc.json in your project root:
{
"requiredSections": ["Problem", "Approach", "Acceptance Criteria"],
"recommendedSections": ["Edge Cases", "Boundaries"],
"rules": {
"has-required-sections": "error",
"sections-not-empty": "error",
"has-acceptance-criteria": "error",
"acceptance-criteria-are-checkboxes": "warning",
"has-problem-statement": "error",
"no-todo-placeholders": "warning",
"detect-vague-language": "warning",
"criteria-are-testable": "warning",
"suggest-missing-edge-cases": "info"
},
"ai": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514"
}
}Each rule can be set to "error", "warning", "info", or "off".
To use semantic rules, set the ANTHROPIC_API_KEY environment variable and pass the --ai flag:
export ANTHROPIC_API_KEY=your-key-here
spec-lint docs/specs/ --aiIf --ai is passed without a key, semantic rules are skipped gracefully (structural rules still run).
docs/specs/auth.md
✗ error has-required-sections Missing required section: "Edge Cases"
✗ error sections-not-empty Section "Approach" is empty
⚠ warning no-todo-placeholders Found "TODO" on line 23
✓ 3 rules passed
Summary: 1 file, 2 errors, 1 warning
{
"files": [{
"path": "docs/specs/auth.md",
"results": [{
"rule": "has-required-sections",
"severity": "error",
"message": "Missing required section: \"Edge Cases\"",
"suggestion": "Add a ## Edge Cases section"
}],
"summary": { "errors": 2, "warnings": 1, "info": 0, "passed": 3 }
}],
"summary": { "files": 1, "errors": 2, "warnings": 1, "info": 0 }
}MIT