-
Notifications
You must be signed in to change notification settings - Fork 0
CLI Reference
Complete reference for the ste100 command. Everything here also works as
python ste_lint.py from a source checkout, or python -m ste100 -- see
Installation.
ste100 [PATH ...] [--format {text,json}] [--profile PROFILE]
[--config CONFIG] [--preset PRESET] [--root ROOT] [--version]
[--fix] [--explain RULE_ID] [--baseline PATH] [--stats]
[--today YYYY-MM-DD]
With no arguments, ste100 lints every .md and .csv file under the
current directory (minus never_lint paths -- see
Configuration), using the resolved config's default
preset.
ste100 # whole project tree
ste100 docs/ # everything under docs/
ste100 docs/ README.md # a directory plus one specific fileA file named explicitly on the command line gets linted even when it
matches a never_lint entry. Only automatic directory discovery honors
never_lint.
Default: text. Reach for --format json when a script, CI dashboard, or
another tool needs to consume findings as data, not as text for a person to
read in a terminal.
ste100 --format json docs/ > report.jsonThe JSON object shape, verified by running the tool:
{
"schema_version": 1,
"run_at": "2026-08-25T14:02:32Z",
"summary": {
"files": 1,
"errors": 12,
"warnings": 3,
"review": 9,
"smell_density": 5.0,
"ari_grade": 10.96,
"passive_ratio": 0.6667,
"budget_violations": 1
},
"findings": [
{
"file": "sample.md",
"line": 3,
"column": 21,
"rule": "STE-T1-SUB-0104",
"test": "T1",
"severity": "error",
"message": "Replaceable: 'utilize' -> 'use'.",
"excerpt": "...perator should utilize the correct pr...",
"suggestion": "use",
"source": "vale_redhat.simple_words"
}
]
}suggestion is present only on findings that carry a concrete replacement,
which today means T1 findings. The four summary metrics are documented
under Reading the output below.
Overrides profile detection and forces every targeted file to use the named
profile, regardless of path glob or a first-line
<!-- lint-profile: NAME --> comment. Use this for a one-off check against
a stricter or looser rule set than the file's detected profile applies by
default.
# Check a design doc as if it were formal requirements text
ste100 --profile spec docs/design/notes.mdSee Configuration for the full profile-detection order and what each shipped profile does.
Path to a specific JSON config file. This is the highest-priority way to
choose configuration -- it overrides --preset and any project-local
ste100.json found by directory walk.
ste100 --config path/to/my-config.json docs/Reach for this when you keep a config that does not live at the project root, or run the same config against unrelated repositories from one script.
Selects one of the presets that ship inside the package:
ste100 --preset default or ste100 --preset veistra. See
Configuration for what each preset is for.
ste100 --preset default docs/Reach for this to use a shipped preset without writing a config file, or to
pin CI to a known preset even if a project-local ste100.json later gets
added by mistake.
Sets the project root used to compute each finding's reported path.
Default: the current working directory. path_globs in profile detection
are also matched against paths measured from this root.
ste100 --root /repo docs/guide.mdVerified: running from a different directory with --root run pointed at
the directory containing sample.md reports the finding as sample.md,
not run/sample.md. Use this when invoking the linter from outside the
tree being linted -- for example, a build script that runs from a shared
tools directory.
Prints the installed version and exits.
$ ste100 --version
ste100 0.1.0Rewrites Markdown files in place, applying only unambiguous T1
substitutions. See The --fix safety envelope below for what
"unambiguous" means here. --fix does not change the exit-code rule --
findings left after fixing still decide the exit code.
ste100 --fix docs/Reach for this after a T1 review pass, to apply the easy replacements in
bulk, then re-run without --fix to review what is left.
Prints what a rule ID means and the rule's source, then exits -- no files are linted. Useful when a finding's message alone is not enough context, or when deciding whether to override a rule's severity.
$ ste100 --explain STE-T1-SUB-0104
STE-T1-SUB-0104: {
"pattern": "utilize",
"suggestion": "use",
"alts": [
"use"
],
"source": "vale_redhat.simple_words",
"id": "STE-T1-SUB-0104"
}$ ste100 --explain STE-T3-HDG-0106
STE-T3-HDG-0106: {
"id": "STE-T3-HDG-0106",
"pattern": "should"
}$ ste100 --explain STE-BUD-0001
STE-BUD-0001: Budget: sentence exceeds the profile's word budget (spec §9).An unrecognized rule ID prints Unknown rule id: <RULE_ID> and exits 2,
the same "tool failure" exit code as a bad config path -- an unresolvable
rule ID is an input error, not a normal empty result.
Points at a JSON report from an earlier --format json run whose findings
are suppressed on this run. This is how an existing codebase adopts the
linter without fixing years of prose first. See Baselines in
Configuration for the full adoption workflow and the exact
suppression semantics (occurrence-count matching, not presence matching;
line numbers excluded from the match key).
ste100 --format json docs/ > .ste100-baseline.json
ste100 --baseline .ste100-baseline.json docs/Also reports review-tier findings, hidden by default because they are
advisory, not defects. Does not affect the exit code -- review findings
never fail a run.
ste100 --stats docs/guide.mdReach for this while developing a config or profile, or when doing a deeper editorial pass beyond what CI enforces.
Overrides "today" for CSV review-date staleness checks (csv_integrity
tests that compare a review_by column against the current date). Useful
for reproducible test fixtures and CI runs that need deterministic output
regardless of when they execute.
ste100 --today 2026-01-01 registry/decisions.csv| Code | Meaning |
|---|---|
0 |
Lint ran cleanly; no error-tier findings. |
1 |
Lint ran cleanly; one or more error-tier findings exist. |
2 |
The tool itself failed -- bad config, missing preset, unreadable file, an internal crash, or nothing matched the given paths. |
Distinguishing 1 from 2 matters in CI. Both codes are nonzero, but they
signal two opposite problems:
-
Exit
1-- the documentation needs work; a failing pipeline is correct here. -
Exit
2-- the linter did not run: a misconfigured--configpath, a typo in--preset, or a permissions problem. The pipeline failure has no bearing on the docs.
A CI script that treats both exit codes the same way hides a tool failure inside what reads as an ordinary lint failure. A person then spends time editing prose the linter never checked.
Verified failure modes, each confirmed to exit 2:
$ ste100 --preset nope docs/
tool failure loading config/data: unknown preset 'nope'; available: default, veistra
$ ste100 --config missing.json docs/
tool failure loading config/data: config file not found: missing.json
$ ste100 empty-directory/
No files to lint.A single text-format finding line:
sample.md:3:21 ERROR T1 STE-T1-SUB-0104 -- Replaceable: 'utilize' -> 'use'.
...perator should utilize the correct pr...
| Field | Value here | Meaning |
|---|---|---|
file |
sample.md |
Path measured from --root (or cwd); uses /. |
line:column |
3:21 |
1-indexed position of the finding in the source file. |
| Severity | ERROR |
One of ERROR, WARNING, REVIEW -- see Configuration's severity precedence for how a rule lands in a tier. |
| Test | T1 |
Which of the six tests (or structural) produced the finding. |
| Rule ID | STE-T1-SUB-0104 |
Stable identifier; look it up with --explain. |
| Message | Replaceable: 'utilize' -> 'use'. |
Human-readable description, including the fix text where one exists. |
| Excerpt | (second line, indented) | Surrounding text, truncated with ...; makes the finding legible without opening the file. |
The run summary line above the findings:
ste100: 1 files, 12 errors, 3 warnings, 9 review
smell_density=5.0 ari_grade=10.96 passive_ratio=0.6667 budget_violations=1
-
smell_density-- findings per 100 words across the run. A single scale-independent number for comparing writing quality across files or runs of differing length. -
ari_grade-- the Automated Readability Index for the linted corpus, a US grade-level estimate computed from characters-per-word and words-per-sentence. Lower is simpler prose. -
passive_ratio-- the fraction of sentences flagged as passive voice (0.6667above means two of three sentences). -
budget_violations-- count of sentence/paragraph/whole-file length budgets exceeded.
review-tier findings are counted in the summary (9 review above) even
when --stats is not passed to print them. The summary reflects the full
run.
--fix is conservative by design. Verified against src/ste100/fixer.py
and by running --fix against test fixtures:
- Only T1 (Replaceable) findings are ever auto-fixed. No other test applies a substitution.
-
Only when the rule has a single candidate replacement. 146 of the 424
substitution rules list more than one
altsentry, for exampleabsent→none/not here. When a rule has more than one,--fixreports the finding and leaves the text unchanged -- picking between choices needs human judgement. -
Never deletes text. 14 rules carry an empty suggestion, meaning:
remove this phrase (
be advised,in the process of,inter alia, and 11 others). Deleting words changes the grammar of the surrounding sentence -- the fixer's source comment gives a worked example of the corruption this used to cause ("the operator selects the type of report"→"the operator selects the of report"). These 14 are reported and never auto-applied. -
Never touches a line containing inline code, a link, or other
masked spans, and skips fenced code blocks. Verified: a file containing
`utilize`inside a code span was linted (the finding was still reported), but the backtick-quoted text stayed byte-for-byte unchanged after--fix. -
Preserves the file's line endings. The fixer writes back with
newline="\n"set explicitly, not Python's newline-translation default.--fixcannot change a file's line endings when it substitutes a word.
A verified before/after, run against a fixture with an ordinary case, a code span, and a curly-quote substitution:
# before
The operator will utilize the tool.
Run `utilize` in code, which must not change.
The operator didn't utilize the manual and/or the guide.
# after --fix
The operator will use the tool.
Run `utilize` in code, which must not change.
The operator didn't use the manual … or … or both the guide.
The code-span utilize is untouched; the two plain-text instances are
fixed, including the non-ASCII curly apostrophe and ellipsis characters
(see the UTF-8 note in Installation).
-
Installation -- getting
ste100on your machine. - Configuration -- presets, profiles, severity precedence, and baselines in depth.
- Simplified Technical English -- the writing standard the six tests are derived from.
- How the Linter Works -- the engine internals behind these checks.
- Agent Skill -- driving the linter from an AI coding agent.
- Contributing -- the test suite and how to add a rule.
STE-Linter — Apache-2.0, Firelight Innovations. Not a licensed or certified implementation of ASD-STE100. See Simplified Technical English.
Start here
The standard
Using it
Contributing