Skip to content

Anti-Slop Writing Skills: Unslop, miodkuj, and What the Evals Say

Unslop (theclaymethod/unslop) is an Agent Skill that finds and removes the patterns that make prose read as machine-written, backed by three standard-library Python scanners that also run in CI without an agent. Its own core benchmark has not yet shown that it beats a plain editorial pass (the project records a no-ship). For Polish, bartekpucek/miodkuj covers officialese and calques that English catalogues miss.

This page is for developers and tech leads who publish documentation, release notes, or READMEs drafted with Claude Code, Codex, or Cursor. The situation: a reviewer writes “this reads like ChatGPT” on your pull request, and nobody can point at the sentence that caused it. Asking the agent to “sound more natural” fails, because the model rewriting the text has the same defaults as the model that wrote it.

What an anti-slop skill gives your docs pipeline

Section titled “What an anti-slop skill gives your docs pipeline”
  • A named finding instead of a vague complaint: “negative parallelism on line 12, false agency on line 30” rather than “this feels off.”
  • A hard gate you can run in CI without an agent: unslop’s phrase scanner exits non-zero on a flag and emits JSON with line numbers.
  • An audit-only mode that reports and changes nothing, which is the mode to use until you trust the rules.
  • A preservation check that fails a rewrite which drops a number, name, or hedge, so you verify the rewrite without rereading it line by line.
  • For Polish text, a rule set built for Polish officialese rather than a translated English word list.

Unslop splits the job in two. Detection is deterministic and runs as Python. Repair and voice are generative and run in the agent, under gates the scanners enforce. The README states the product boundary plainly: “Scanners suggest candidates; the agent checks each use in context.”

  1. Phrase layer (scripts/banned_phrase_scan.py). The compact runtime pack holds 16 literal triggers, each with contextual false-positive protection. Quoted spans, blockquotes, and code fences are masked first, so a tutorial that quotes bad writing does not flag its own examples. Every hit carries a severity of hard or soft.

  2. Structure layer (scripts/structure_scan.py). 36 structural patterns plus document-level metrics such as sentence_burstiness, triad_density, connective_paragraph_openers, and conclusion_coda. This layer catches rhythm: uniform sentence length, staccato runs, and every paragraph opening on “However,”. --genre docs allows the bold-label lists that reference documentation uses.

  3. Silhouette layer (scripts/silhouette_scan.py). This layer scores how ideas are arranged: previews that the body then fulfils point by point, headings that restate the introduction’s outline (heading_preview), and opening vocabulary that returns as a recap at the end (callback_content, which the README calls the strongest single tell). On the corpus in the repository it flags 12 of 12 AI documents and 0 of 8 human ones. The README also notes that deleting discourse cues defeats the scaffold metric, so treat silhouette as one signal next to the structure scanner.

The agent-facing surface is four commands. A bare /unslop <text> defaults to rewrite.

CommandWhat it does
cleanupReviewable suggestions with span, severity, and rationale. Its report-only variant (“flag it, change nothing”) edits nothing.
rewriteDiagnoses the draft, rebuilds it under the guards, and validates the result.
teachBuilds a voice profile from your own writing samples.
mimicDrafts in a taught voice, then passes the full removal-gate battery.

cleanup enforces four gates that make an “accept all” button safe: each edit changes only its own span, each replacement passes the scanners on its own, applying every suggestion still preserves every constraint, and no two suggestions overlap.

The scripts need Python 3.8 or later and no third-party packages. Clone the repository once, then run the scanners from your terminal:

Terminal window
git clone https://github.com/theclaymethod/unslop.git ~/dev/unslop
cd ~/dev/unslop
python3 scripts/banned_phrase_scan.py ~/work/docs/launch-post.md
python3 scripts/structure_scan.py --genre docs ~/work/docs/launch-post.md
python3 scripts/silhouette_scan.py --genre docs ~/work/docs/launch-post.md
python3 scripts/validate_preservation.py original.md rewritten.md

On a four-line test draft, the phrase scanner returned this summary and exited with status 1:

{
"total_violations": 4,
"by_severity": { "hard": 4, "soft": 0 },
"by_category": {
"throat_clearing": 1,
"negative_parallelism": 1,
"false_agency": 1,
"copula_avoidance": 1
}
}

The same run shows the limit of a phrase list: “Let that sink in.” appears in the README’s catalogue but did not fire in the compact runtime pack. The scanner finds candidates. It does not certify a clean draft.

Install unslop in Claude Code, Codex, or Cursor

Section titled “Install unslop in Claude Code, Codex, or Cursor”

Unslop follows the Agent Skills open standard, so the skills CLI installs it for all three agents. The install commands differ only in the -a target.

Terminal window
npx skills add theclaymethod/unslop -g -a claude-code

This writes ~/.claude/skills/unslop/. The skill sets user-invocable: true, so it appears as /unslop, with /unslop cleanup, /unslop rewrite, /unslop teach, and /unslop mimic.

Context cost. Until the skill triggers, only its name and description sit in context. The SKILL.md body is about 6.8 KB. The 50 KB phrase catalogue in references/taboo-phrases.md and the 2.7 MB evals/ directory load only when a step reads them, and scanner scripts contribute their JSON output, not their source. Check the real cost in your session with /context in Claude Code before and after a first /unslop cleanup run.

How to gate AI tells in CI and verify rewrites

Section titled “How to gate AI tells in CI and verify rewrites”

The workflow that works is scan, triage, repair, prove, gate. Nobody rereads the whole document; the scanners and the preservation check carry the proof, and the author signs off only on the findings list.

  1. Scan in audit mode. Run the report-only prompt above on the draft. Hard phrase hits are the only findings you act on without discussion.

  2. Triage the soft flags. Structure and silhouette flags are advisory. On a well-edited page from this site, structure_scan.py --genre docs raised one soft conclusion_coda flag and silhouette_scan.py raised two soft flags, and both scripts still exited with status 1. That is why those two scanners belong in a report, not in a blocking check.

  3. Repair with a preservation contract. Ask for a rewrite of the flagged spans only, then run validate_preservation.py. It compares the constraints of the original and the rewrite. In a test, changing $47.3M to $47.3 billion produced "passed": false and exit status 1. For legal, medical, or security text, run python3 scripts/validate_preservation.py --strict original.md rewritten.md; the flag must come before the file names. In strict mode, dropping a hedge like “does not establish causation” becomes a hard failure.

  4. Gate the merge. In CI, block only on hard phrase findings in changed files, and publish the other scanners’ output for the reviewer.

  5. Sign-off. The author approves the findings list and the preservation result; the reviewer reads the diff of flagged spans. Neither has to reread unchanged paragraphs.

This GitHub Actions job implements step 4. It runs on pull_request with a read-only token and no secrets, treats the contributor’s files as data only, and pins the scanners to a known commit:

.github/workflows/prose-lint.yml
name: prose-lint
on:
pull_request:
paths: ["docs/**/*.md", "docs/**/*.mdx"]
permissions:
contents: read
jobs:
unslop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Fetch unslop scanners at a pinned commit
run: |
git clone --quiet https://github.com/theclaymethod/unslop.git "$RUNNER_TEMP/unslop"
git -C "$RUNNER_TEMP/unslop" checkout --quiet 17ed39c9d0b522f44190ff0c6233867eadee192a
- name: Block hard AI tells in changed prose
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
git diff -z --name-only --diff-filter=AM "$BASE_SHA" HEAD -- ':(glob)docs/**/*.md' ':(glob)docs/**/*.mdx' > changed.txt
python3 - <<'PY'
import json, os, subprocess, sys
scan = os.path.join(os.environ["RUNNER_TEMP"], "unslop/scripts/banned_phrase_scan.py")
failed = False
for path in filter(None, open("changed.txt", encoding="utf-8").read().split("\0")):
out = subprocess.run([sys.executable, scan, path], capture_output=True, text=True).stdout
for v in json.loads(out)["violations"]:
if v["severity"] == "hard":
failed = True
print(f"::error file={path},line={v['line_number']}::{v['category']}: {v['phrase']}")
sys.exit(1 if failed else 0)
PY

The :(glob) pathspec makes ** match any depth, including docs/a.md at the top level, and -z keeps paths with spaces or non-ASCII characters intact. The inline Python ignores the scanner’s exit code on purpose and reads the JSON instead, so a soft hit never blocks a merge. To update the scanners, change the pinned SHA in a reviewed pull request.

Unslop keeps three separate scoreboards so supporting machinery cannot inflate the product result: core product (detection, repair, preservation, damage, net improvement), voice (teach and mimic fidelity), and engineering (scanner coverage, schemas, routing, regressions). The README says why: “The engineering suite can show that the implementation behaves as specified. Only the core scoreboard can show that the specification improves writing.”

The core comparison is paired. The same gpt-5.6-luna model gets the same unfamiliar source in both arms; one arm runs the unslop pipeline and the other gets neutral editorial guidance. A blinded gpt-5.6-sol judge compares the results. (Both are OpenAI’s older GPT-5.6 models; the current ones are on the models hub.)

The latest valid public result is a no-ship: unslop “materially improved recall and repair over plain Luna” but missed the precision, damage, and whole-document safety bar. Later development runs recorded seven wins, four ties, and no plain-Luna wins, but they predate scorer fixes, and a fresh preregistered corpus failed its composition floor before either arm ran. The project’s conclusion: the current beta “does not claim a validated comparative lift.”

That result sets the bar for the rest of the category. The most-starred skill in the category, blader/humanizer, had 53,072 stars on 30 September 2026 and ships no eval suite in the repository. Its README (v3.1.0, 27 September 2026) cites one blind test in issue #229, where judges preferred the rewrite over the raw AI text 16 times out of 16. That is a single small comparison against unedited AI output, not against a neutral edit. None of these projects has shown, with a controlled comparison like unslop’s, that automated de-slopping beats a plain editorial pass. Use these tools to find candidates, and let the preservation check, not the rewrite, carry your confidence.

Unslop stops at non-English input: the scanners return non_english: true. Miodkuj (MIT) fills that gap. Its research summary states the design choice: it “nie tłumaczy angielskich list zakazanych słów” (it does not translate English banned-word lists) and adapts anti-slop patterns to Polish instead. The name honours Professor Jan Miodek; the README states that he neither takes part in nor endorses the project.

Some families overlap with English catalogues: chatbot residue, throat-clearing openers, and inflated adjectives. The more useful half comes from Polish officialese, which no English list covers. These pairs come from its plain-polish.md and polish-patterns.md references:

PatternBeforeAfter
Officialesew dniu dzisiejszymdzisiaj
Officialesedokonać zakupukupić
Officialeseposiadać możliwośćmoże
Nominalisationprzeprowadzenie analizy danychprzeanalizowano dane
Impersonal fognależy złożyć wniosekzłóż wniosek
Genitive chainw przypadku braku możliwości uruchomienia pojazdujeśli nie możesz uruchomić pojazdu

Three rules in SKILL.md do most of the work:

  • Minimum effective edit. If the source already passes the quality gate, miodkuj returns it verbatim and does not “replace correct wording merely to show an edit.”
  • Specificity ladder. Ground a generic claim in a fact already in the source, recombine what is there, or make the claim smaller. Never invent a number, example, or source: “A plausible inference is still new information.”
  • Portability test. “If a sentence could move unchanged to another company, ministry, product, project, or person, it is probably filler.” The test does not apply to definitions, legal formulas, or standard warnings.

Miodkuj deliberately ships no prose linter or scanner (its scripts/ only validate the package). Its research summary argues that a list of matches cannot resolve context or protect the author’s voice. So it cannot be a CI gate. What it does have is a bounded behavioural check for v2.1.1 (14 September 2026): a Codex subagent on gpt-5.6-sol ran 13 cases; 12 passed and one was a partial failure, while the previous release failed three of the 12 shared cases. The report states its own limit: with one sample per case, the checks “establish no general reliability rate or cross-model improvement.”

In a Claude Code session:

/plugin marketplace add bartekpucek/miodkuj
/plugin install miodkuj@miodkuj
/reload-plugins

Invoke it as /miodkuj:miodkuj, because Claude Code namespaces plugin skills. Check what the plugin adds to context with claude plugin details miodkuj@miodkuj from your terminal. For a short /miodkuj, copy the skill folder instead:

Terminal window
miodkuj_tmp="$(mktemp -d)"
git clone --depth 1 https://github.com/bartekpucek/miodkuj.git "$miodkuj_tmp"
mkdir -p ~/.claude/skills
cp -R "$miodkuj_tmp/plugins/miodkuj/skills/miodkuj" ~/.claude/skills/miodkuj
rm -rf "$miodkuj_tmp"

This prompt stays in Polish because miodkuj’s triggers and severity names are Polish.

Which anti-slop writing skill should you choose?

Section titled “Which anti-slop writing skill should you choose?”

Stars measure attention, not quality. All counts below come from the GitHub API on 30 September 2026.

SkillStarsWhat it isChoose it when
blader/humanizer53,072One skill of 25 patterns (v3.0.0; v3.1.0 adds a 26th and a Cursor plugin manifest) drawn from Wikipedia’s Signs of AI writing. No scanner; no eval suite (README cites one 16/16 blind test). SKILL.md is about 32 KB, loaded whole when it triggers.You want a one-command rewrite and will review the diff yourself.
hardikpandya/stop-slop17,669A small skill file for removing AI tells.You want a short rule set to adapt into your own house-style skill.
petergyang/no-ai-slop11,579A skill that removes 20+ slop patterns.You want an English counterpart to miodkuj’s edit-first approach.
theclaymethod/unslop493Skill, standard-library Python scanners, and a three-scoreboard eval suite.You need a CI gate and measurable preservation checks.
bartekpucek/miodkuj195One skill, plugin manifests for Claude Code and Codex, no scanner.The text is Polish, especially official, legal, or academic.

Humanizer installs with npx skills add blader/humanizer --global --agent claude-code (or --agent codex), or as a Claude Code plugin with /plugin marketplace add blader/humanizer and /plugin install humanizer@humanizer on Claude Code 2.1.142 or later. Its plugin skill answers to /humanizer:humanizer.

For style-guide review rather than tell-hunting, Vercel’s writing-guidelines skill and Anthropic’s doc-coauthoring are covered on document and writing skills. The official anthropics/skills repository (19 skills at main, checked 30 September 2026) has no dedicated anti-slop writing skill. If you want a linter with no agent in the loop, JMill/deslop is a Vale style package, but it is new and has no adoption yet.

The upstream for most of these catalogues is Wikipedia’s Signs of AI writing. Unslop syncs from it with python3 scripts/wiki_sync.py check, which diffs its catalogue against the live page and proposes eval rows first.

When anti-slop skills get your prose wrong

Section titled “When anti-slop skills get your prose wrong”

The em-dash rule fights your house style. Unslop’s catalogue says “Default to zero em-dashes.” If your style guide uses them deliberately, the rule strips a working part of the register. Recovery: soft findings are overridable by design, so record the decision in your own skill or AGENTS.md (“em dashes are allowed; do not flag them”) and triage those findings as accepted.

Hard bans land on legitimate technical words. load-bearing and wedge are hard flags as metaphors, exempt only in literal construction and mechanics. “This is a load-bearing assumption” in a design document is the targeted sense and also the right phrase. The phrase scanner flags load-bearing only before a noun such as assumption, claim, or decision, so the predicative “This assumption is load-bearing” passes. Recovery: keep the sentence, quote it in a code span if it is a term of art, or accept a documented exception in review. Do not weaken the CI gate for one word.

The rewrite drops a fact. Generative repair can change $47.3M or remove a qualifier. Recovery: always run validate_preservation.py (with --strict before the file names for regulated text) and revert any edit that fails it, as the repair prompt above does.

A clean scan is mistaken for good writing. A draft can pass every scanner and still be an outline with no argument. Wikipedia’s guidance warns against treating the signs as “the problems to be fixed,” because that “could just make detection harder.” Recovery: keep a human judgement on structure and argument in review; the scanners only remove the mechanical noise.

Polish text goes to an English-only skill. Unslop declines non-English input, and humanizer’s patterns are English. Recovery: route Polish files to miodkuj, for example by path (docs/pl/**) in the instructions you give the agent.

The project changes under you. Unslop rebuilt itself around a new core contract on 5 August 2026, changed it again on 7 September, and publishes no tags. Recovery: pin the commit SHA in CI, as the workflow above does, and review upstream changes before bumping it.

Where to go next with anti-slop writing skills

Section titled “Where to go next with anti-slop writing skills”