Semlint is a deterministic semantic lint CLI that:
- reads a git diff,
- runs enabled semantic rules in parallel,
- executes an external backend command per rule,
- prints text or JSON diagnostics,
- returns CI-friendly exit codes.
pnpm install
pnpm buildsemlint checkScaffold a project config with automatic coding agent CLI detection:
semlint initIf running from source:
pnpm check--backend <name>: override backend name--model <name>: override model name--config <path>: config file path--format <text|json>: output format--base <ref>: base git ref for explicit ref-to-ref diff--head <ref>: head git ref for explicit ref-to-ref diff--fail-on <error|warn|never>: failure threshold (defaulterror)--batch: run all selected rules in one backend call--debug: enable debug logs to stderrinit --force: overwrite an existingsemlint.json
Default diff behavior (without --base/--head) uses your local branch state:
- tracked changes across commits since merge-base,
- staged changes,
- unstaged changes,
- untracked files.
If you pass --base or --head, Semlint uses explicit git diff <base> <head> mode.
0: no blocking diagnostics1: blocking diagnostics found2: backend/runtime failure
--config <path>./semlint.json./.semlint.json- defaults
Unknown fields are ignored.
{
"backend": "cursor-cli",
"model": "auto",
"budgets": {
"timeout_ms": 120000
},
"output": {
"format": "text"
},
"execution": {
"batch": false
},
"rules": {
"disable": ["SEMLINT_EXAMPLE_001"],
"severity_overrides": {
"SEMLINT_API_001": "error"
}
},
"backends": {
"cursor-cli": {
"executable": "agent"
}
}
}Run:
semlint initThis creates ./semlint.json and auto-detects installed coding agent CLIs in this priority order:
cursor-> backendcursor-cliclaude-> backendclaude-codecodex-> backendcodex-cli
If no known CLI is detected, Semlint falls back to cursor-cli + executable cursor.
Use semlint init --force to overwrite an existing config file. Init also creates .semlint/rules/ and a starter rule SEMLINT_EXAMPLE_001.json (with a placeholder title and prompt) if they do not exist.
Rule JSON files are loaded from .semlint/rules/. Run semlint init to create this folder and an example rule you can edit.
Required fields:
id(string, unique)title(string)severity_default(error|warn|info)prompt(non-empty string)
Optional fields:
include_globs: string[]exclude_globs: string[]diff_regex: string[]
Invalid rules cause runtime failure with exit code 2.
For backend cursor-cli, Semlint executes:
cursor agent "<prompt>" --model <model> --print --output-format textFor cursor-cli, Semlint always uses cursor agent directly.
Other backend names still resolve executables from config:
backends.<backend>.executableif provided
Backend stdout must be valid JSON with shape:
{
"diagnostics": [
{
"rule_id": "SEMLINT_API_001",
"severity": "warn",
"message": "text",
"file": "src/file.ts",
"line": 42
}
]
}If parsing fails, Semlint retries once with appended instruction:
Return valid JSON only.
Use batch mode to reduce cost by evaluating all runnable rules in a single backend call:
semlint check --batchOr configure it in semlint.json:
{
"execution": {
"batch": true
}
}