@umxr/spec-lint
v0.1.0
Published
A linter for spec-driven development markdown files
Maintainers
Readme
spec-lint
A linter for spec-driven development. Checks that specification markdown files are complete, well-structured, and ready for implementation — by humans or AI agents.
Install
npm install -g @umxr/spec-lintUsage
# 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/ --verboseExit codes
| 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) |
Rules
Structural rules (always run, fast, free)
| 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], ... |
Semantic rules (behind --ai flag, requires API key)
| 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.
Configuration
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".
AI-powered rules
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).
Output
Text (default)
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 warningJSON (--json)
{
"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 }
}License
MIT
