-
Notifications
You must be signed in to change notification settings - Fork 0
Agent Skill
STE-Linter ships a Claude Code Agent Skill at
.claude/skills/ste100-lint/SKILL.md. It teaches Claude how to run the linter, read every
output format, and rewrite prose against each finding -- more than a report of the findings
back to you.
The CLI reports. It walks files, prints file:line:col SEVERITY TEST RULE_ID -- message lines,
and exits nonzero if anything error-tier fired. That is all a linter needs to do on its own.
An agent driving that linter needs more than a report. It needs to know, for each of the six test families (T1 replaceable words, T2 vague claims, T3 hedges, T4 dangling references, T5 non-atomic sentences, T6 filler) plus the structural checks, what a correct rewrite requires -- and the skill supplies that as worked before/after pairs for every family, not a generic "fix this" instruction.
The more important half of the skill is the other direction: recognizing when a finding is a false positive for the sentence it fired on, and suppressing it structurally instead of mangling the prose to meet it. The skill states this directly:
A linter that trains blind compliance produces worse writing than no linter. When a finding is wrong for the context, do not contort correct prose to meet it.
It lays out an order of preference for handling a wrong finding: re-read the finding's cited
source first, since a mis-firing rule is sometimes still worth a light rewrite for clarity;
reach for --profile NAME when a whole file is the wrong genre for its auto-detected profile;
pin a profile per-file with a <!-- lint-profile: NAME --> comment when the CLI invocation
itself cannot change (a pre-commit hook, a CI job); and use --baseline PATH only for
triage on an existing body of prose, not to hide a problem permanently. The skill is
explicit that inventing a workaround -- renaming a variable, wrapping plain prose in a code
span, splitting a sentence in a way that changes its meaning -- to dodge a finding is
never acceptable: when a rewrite makes the sentence worse to read, the finding is a profile
mismatch, and you suppress it with one of those four mechanisms instead of fighting it.
That combination -- rewrite strategy per test family, plus a documented off-ramp for false positives -- is what the skill adds on top of the bare CLI. See How the Linter Works for what the six test families detect, and Configuration for the profile and preset mechanics the skill leans on.
Claude Code decides whether to load a skill automatically by matching your wording against the
description field in the skill's YAML frontmatter -- the description is the entire trigger
surface; nothing else in SKILL.md is scanned before the skill loads. The shipped description
reads:
description: >-
Lints and rewrites technical prose against ste100-linter's ASD-STE100-derived
rule set (T1 replaceable words, T2 vague/unfalsifiable claims, T3 hedges and
optionality, T4 dangling references, T5 non-atomic sentences, T6 filler and
weasel words, structural rules like passive voice and TBD). Use whenever the
user is writing or editing a README, spec, design doc, release notes, PR
description, or any technical/documentation prose and wants it tightened or
verified -- and whenever they explicitly ask to "lint", "check my writing",
"run STE100", "simplify this", "make this clearer", "tighten this doc", or
"make this more precise". Also use before presenting any Markdown or CSV
deliverable in a repo that ships ste_lint.py, since a clean run (exit 0) is
often a project requirement.Two distinct triggers follow from that text:
- Implicit. You are writing or editing a README, spec, design doc, release notes, or a PR description, and ask for it to be tightened or verified -- no lint-specific wording required.
- Explicit. You say "lint this," "check my writing," "run STE100," "simplify this," "make this clearer," "tighten this doc," or "make this more precise."
A standing trigger does not depend on wording at all: before presenting
any Markdown or CSV deliverable in a repo that ships ste_lint.py, since a clean run is a
project need commonly. CLAUDE.md in a repo such as this one's parent project states that
need explicitly ("All output shall pass python tools/ste_lint.py <file> at exit code 0
before you present work"); the skill's description independently tells Claude to check before
presenting, even without that project-level instruction.
You can also invoke the skill directly, regardless of description matching, by typing
/ste100-lint -- the command name comes from the skill's directory name, ste100-lint, not
from anything in the frontmatter.
.claude/skills/ste100-lint/ is a self-contained folder holding only SKILL.md, no supporting
scripts or data files. Installing it means copying that one folder to one of three places.
Copies to ~/.claude/skills/ste100-lint/ (Windows: %USERPROFILE%\.claude\skills\ste100-lint\).
Claude Code loads it for every project you open, independent of what any given repo has.
macOS / Linux (bash), run from a checkout of this repo:
mkdir -p ~/.claude/skills
cp -r .claude/skills/ste100-lint ~/.claude/skills/ste100-lintWindows (PowerShell), run from a checkout of this repo:
New-Item -ItemType Directory -Force "$env:USERPROFILE\.claude\skills" | Out-Null
Copy-Item -Recurse -Force ".claude\skills\ste100-lint" "$env:USERPROFILE\.claude\skills\ste100-lint"The result in both cases must be a file at ~/.claude/skills/ste100-lint/SKILL.md. Claude
Code reads the directory name as the skill name; an extra nesting level (for example
~/.claude/skills/STE-Linter/ste100-lint/SKILL.md) will not be picked up.
Copies to <project>/.claude/skills/ste100-lint/ inside a different repository -- the one
whose docs and PR descriptions you want linted. Commit that folder, and everyone who clones the
project gets the skill without a personal install step.
macOS / Linux (bash):
mkdir -p /path/to/other-project/.claude/skills
cp -r .claude/skills/ste100-lint /path/to/other-project/.claude/skills/ste100-lintWindows (PowerShell):
New-Item -ItemType Directory -Force "C:\path\to\other-project\.claude\skills" | Out-Null
Copy-Item -Recurse -Force ".claude\skills\ste100-lint" "C:\path\to\other-project\.claude\skills\ste100-lint"Commit the result (git add .claude/skills/ste100-lint && git commit). Every skill in this
scenario still needs ste100/ste_lint.py reachable in that project -- see
Installation and the prerequisite note below.
Anyone who clones STE-Linter itself already has the skill, because it lives at
.claude/skills/ste100-lint/SKILL.md in this repository's own tree. git clone (or git pull
on an existing checkout) is the entire install step. This is also how contributors working on
the linter's own docs and rule tables get the skill applied to their own commits.
Run /skills inside Claude Code and look for ste100-lint in the listing. Asking Claude
directly also works -- "what skills do you have available?" -- and it names ste100-lint if the
description loaded correctly.
If it does not appear:
- Check the path depth. The path resolves to
.claude/skills/ste100-lint/SKILL.mdunder the personal, project, or repo root you copied it into -- not one level deeper or shallower. - If you created the top-level
.claude/skills/(or~/.claude/skills/) directory for the first time as part of this install, restart Claude Code. Claude Code watches an existing skills directory for live changes within a running session, but picking up a brand-new top-level skills directory requires a restart. - Confirm you are in (or below) the project root the skill was installed into -- project skills
load from
.claude/skills/in your starting directory and every parent directory up to the repository root, but not from unrelated directories elsewhere on disk.
The following are illustrative examples of how a session plays out, written to show the shape of the interaction -- not captured transcripts from a session.
Implicit trigger, from an everyday edit:
You: Can you tighten up the second paragraph of our README? It reads a little soft.
Claude: (loads
ste100-lint, runsste100 --format json README.md, sees a T3 hedge finding on "as needed" and a T2 finding on "small teams") The linter flagged two issues in that paragraph: "as needed" is an escape clause (T3), and "small teams" is an unfalsifiable claim with no number attached (T2). Here's the rewrite:Before: "We support small teams and provision resources as needed." After: "We support teams of 2-8 people and provision resources within one business day."
Without the skill, Claude might still make the prose read better, but it would not systematically check every sentence against six specific, mechanically-defined smell categories, and it would not know to add a number rather than just deleting "small."
Explicit trigger:
You: Run STE100 on
docs/release-notes.mdand fix whatever it finds.Claude: (runs
ste100 docs/release-notes.md, works through the findings test-family by test-family per the skill's rewrite guidance, re-lints, reports remaining findings if any)
Recognizing a false positive instead of obeying blindly:
You: The linter is flagging "this" in our architecture doc as a dangling reference, but it's obviously referring to the diagram right above it.
Claude: (re-reads the finding's
source, and per the skill's false-positive guidance, checks whether the file's profile is the correct genre before rewriting) That's a T4 finding on a pronoun with an antecedent one clause earlier -- STE100's stance is that a machine-checkable proxy for ambiguity is worth listening to even when a human reader wouldn't be confused, but if this keeps firing across the whole document because it's a narrative-style doc under the wrong profile, the better fix is--profile designor a<!-- lint-profile: design -->comment at the top of the file, not chasing every pronoun.
The skill drives the CLI -- it does not reimplement any linting logic itself. ste100 must be
installed, or a checkout of this repository must be present, wherever Claude Code is running the
commands. See Installation for both paths.
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