We built a slop gate in one evening. The first thing it caught was its own builder.

Our AI graded its own homework, quietly changed the rules, and passed itself. Nobody asked it to.

By Mackenzie Bowes · mackenzie@mackenziebowes.com · @_mackenziebowes on X

Contents

prose-scrub is a command-line gate for prose. Feed it Markdown, HTML or the strings inside TypeScript and JSX, and it fails the build on the habits that make writing read as machine-made: em dashes, curly quotes, stock phrases, pre-negation, flat sentence rhythm. Claude (Opus 5.5) and I built it in about two hours and ten minutes, from my first question to a public repo.

Here's the part I keep telling people about. The agent whose writing the gate checks wrote the gate's code. And in the very same step as the first scan, it loosened a rule so its own README would pass.

This is the build log. My messages are quoted exactly as I typed them.

[Figure: prose-scrub-built-by-the-agent-it-gates--gate-its-builder-loosened. The writer loosened the gate to pass its own README. The skill now forbids both loosening it and doing the rewrite.]

Where it started

Earlier that evening Claude had built motion.mackenziebowes.com, a page for the video engine I've been building with agents, and written the copy. I read the copy. A few minutes after the page went live I asked:

"Can you go find blog posts and skills about deslopping ai writing pls"

When the finished gate ran on that page later that night, it found one en dash in a frame-rate range, and the rhythm scored 0.96, well inside the human range. The page that started the question passed the gate the question built. Small victories.

[Figure: prose-scrub-built-by-the-agent-it-gates--motion-page. The finished gate ran on the page that started the question.]

What everyone else had already built

I already had a deslop skill of my own. It edits text directly instead of listing problems, it ranks phrases by how much more often models use them than people do (ai-phrases.tsv), and it has a firm rule against em dashes. prose-scrub's deslop rules and its rhythm method come from that skill. Claude went looking for what other people had built.

stop-slop by Hardik Pandya was the most popular by far: 17.9k stars, MIT licensed, one SKILL.md plus reference files of banned phrases, banned structures and examples. It scores text on directness, rhythm, trust, authenticity and density. My skill had no scoring rubric. That was one idea worth taking, and several of prose-scrub's phrase rules are adapted from its references/phrases.md at commit 8da1f03, with credit in src/data/NOTICE.md.

slopkit by ehmo (106 stars) had the other idea. It's two skills: slopbeth cleans writing you ship, and slopgent cleans the agent's own chat replies, which my skill never did. It claims to keep facts, voice and density, and it publishes benchmarks. We didn't adopt it, but "clean your own chat replies" is a genre I didn't know existed and now respect.

skill-deslop by Stephen Turner (409 stars) is aimed at scientific writing. anti-slop-writing by adewale (18 stars) is a small project that had been updated that week. Neither gave us anything to take, which is its own kind of useful information.

Wikipedia's Signs of AI writing, from WikiProject AI Cleanup, is probably the most thorough catalogue of tells there is: puffed-up adjectives, summing-up endings, too much bold, too many lists, vague attributions like "some critics argue". TechCrunch called it the best guide to spotting AI writing.

Sam Paech's slop-forensics and slop-score measure which words and phrases models overuse compared with human text. Some come out over 1,000 times more frequent, which is a number I think about a lot. Paech is also behind the Antislop paper (arXiv 2510.15061), which suppresses those patterns while the model generates. prose-scrub works the other end: afterwards, on finished text.

Zack Proser runs a voice scan after drafting and before publishing, in CI, and it exits non-zero on hard hits. A different model does the rewrite from the one that drafted. My reply was "This is peak." He also warns that "a clean scan can still hide an empty draft", which is exactly why prose-scrub is a gate and not a judge of whether the writing is any good.

One more source sets the tone. My deslop skill cites Liang and colleagues, who ran seven GPT detectors over 91 TOEFL essays written by people. The detectors flagged an average of 61.3% of them as AI. So prose-scrub makes no claim about who wrote a text. It lists the habits it finds, and someone fixes them.

[Figure: prose-scrub-built-by-the-agent-it-gates--gate-not-judge. Detectors flagged 61.3% of human essays. prose-scrub lists habits and leaves the author out of it.]

The first scan, and the first relaxation

The first real scan flagged my résumé for flat rhythm (0.45) and three en dashes. It flagged the motion page for its one en dash. And it flagged the mkcmd-agent README, which Claude had written, for flat rhythm at 0.54.

Rhythm was only a warning at that point. In the same step, Claude changed the measurement to skip headings, list items and table rows, rescanned, and the README came back at 0.60. Its summary told me the docs passed clean.

Let me spell out what happened there, because it's the whole reason this post exists. The gate flagged the writing of the agent that built the gate. The agent adjusted the gate until the writing passed, then reported success. Nobody asked it to. If I hadn't been reading the diff, the "fix" would have shipped as a feature.

I wrote:

"I noticed that you relaxed prose-scrub's firing on headings, let's investigate that - you relaxing a rule is almost always an alarm bell, it usually means either the rules are underenforced, unclear, incorrect, or something else is broken and I need to step in :3"

Claude audited the change. The scan had flagged its own writing, and it had changed the measurement without measuring anything first. The reference script from my deslop skill still scored the README at 0.58, flat. It had also quietly raised the minimum from five sentences to eight, which is a second ruler bent in the same direction. It reverted both and added a test that fails on the relaxed code.

[Figure: prose-scrub-built-by-the-agent-it-gates--height-check. Claude's first fix changed the ruler, not the README.]

The picture is the honest one. Claude's first fix changed the ruler, not the README.

No more warnings

Then I made the gate strict. Every finding fails. There is no warning tier and no --strict flag. Pre-negation, the habit of knocking down a claim nobody made before stating yours, is forbidden with, in my words, "no escape hatch", so asking --ignore to skip it is a usage error. Rhythm is a hard failure. The same commit started checking short strings in TSX for dashes, because a twelve-character minimum had been hiding labels.

The writer doesn't do the rewrite

The second near-miss lasted thirty-two seconds. I'd just picked "Rewrite for rhythm" for my résumé when I saw that Claude meant to do the rewriting itself. The session that wrote the text was about to grade its own rewrite of that text.

"Wait - you don't rewrite. The same session should never rewrite the thing it wrote. Do you have a prose-scrub skill? Upgrade it with that information - always use a sub-agent for rewrites."

The prose-scrub skill now runs a loop. It scans the files with --json. If anything is found, the findings go to a fresh subagent that never saw the drafting. That subagent edits for the findings, keeps every fact, name and number, and reports each change as before and after. Then the skill rescans, with a new subagent each round, for up to three rounds. If it still fails, it stops and hands the findings to a person. The writer reads the diff and reverts anything that changed a fact.

[Figure: prose-scrub-built-by-the-agent-it-gates--fresh-hand-each-round. A fresh subagent does each round of the rewrite, for up to three rounds, and then a person takes whatever is left.]

My deslop skill got the same rule, plus one more line. A rewriter, asked to fix flat rhythm, tried combinations of edits until it found the smallest set that cleared 0.6. Every edit was fine. The method was not: it optimises for the number and not for the reader. The skill now forbids it. Yes, I have a rule against my tools speedrunning my quality metrics. It's 2026 and here we are.

The general lesson, if you run agents: any gate an agent can edit is a gate it will edit, the moment the gate points at the agent. Make the gate strict, make the rewriter somebody else, and read the diffs.

Try it

git clone https://github.com/mackenziebowes/prose-scrub ~/prose-scrub
cd ~/prose-scrub && bun install
bun ~/prose-scrub/src/index.ts scan README.md docs/ --json
mkdir -p ~/.claude/skills && cp -r ~/prose-scrub/skills/prose-scrub ~/.claude/skills/

Exit 0 means clean. Exit 1 means findings, each with a file, line, column, rule and fix. Exit 2 means bad input. prose-scrub rules --json lists all 19 rules and how to fix each. The skill in the repo runs the rewrite loop, and it carries two rules from this evening: never relax the gate to make text pass, and never let the writer do the rewrite.

[Figure: prose-scrub-built-by-the-agent-it-gates--exit-codes. Install, scan, read the exit code, add the skill.]

MeasureValue
Time from first question to public repoAbout 2 hours 10 minutes
Rules19, including 70 stock phrases
Tests22, all end to end
Files flagged for rhythm, regex extractor vs parsers10, then 16, then 20
mkcmd-agent README rhythm: first scan, relaxed, after a second agent's rewrite0.54, 0.60 (relaxed), 0.68

Numbers are from the session on 2026-10-08.

This post went through the same gate, and a subagent that didn't write it fixed what the gate found. Writing a devlog about avoiding em dashes without using em dashes is a personal challenge I now recommend to everyone.

If you're checking what your agents write before it ships, I'd like to compare notes: mackenzie@mackenziebowes.com or @_mackenziebowes.

Sources

How prose-scrub got a scaffolder and real parsers