Repository context. Gather first
Collect these with individual Bash calls, one command per call, never combined into a single
invocation:
- Current branch,
git branch --show-current
Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as
separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute
block as one shell invocation, and a worktree-isolated session refuses a compound command that
contains git.
Pre-computed context
Effective config: !"${CLAUDE_SKILL_DIR}/scripts/detect.sh" --show-config >/dev/null 2>&1 && { "${CLAUDE_SKILL_DIR}/scripts/detect.sh" --show-config 2>/dev/null | head -8; :; } || echo "detector unavailable"
Purpose
Detect and remove AI-writing tells in checked-in markdown prose. Two detection layers over one
rule inventory (reference/catalog.md, distilled from Wikipedia's
"Signs of AI writing", revision-pinned, plus the catalog's "Cursor unslop additions" section
and its repo-owned, evidence-graded "Model-era additions" section of current-generation model
vocabulary):
- Deterministic:
${CLAUDE_SKILL_DIR}/scripts/detect.sh runs the catalog's v1: script
rules. Its findings carry argued severity tiers (the detector-findings convention's crosswalk)
and persist as a conforming findings file, which is how a consumer sees them and how they
reach a surface that can rewrite them. Audit step 6 names which surface, and when.
- Judgment rubric: the catalog's
v1: rubric tells, applied by reading the prose. Rubric
findings reach the human report only, never the findings file.
Both layers sit behind the catalog's policy-level quotation exemption: wording rules never
scan blockquotes, double-quoted spans, or inline code spans (typography rules still do), so a
document that quotes a tell to document it, and a changelog that backticks the phrase a fix
removed, stay marker-free by construction.
Action router
| Argument |
Action |
(empty) or audit [target] |
Read-only audit (default). Empty target = repo-wide |
fix [target] |
Explicit fix pass over the target's findings (guarded; below). "Detect and rewrite" or audit fix chains audit then fix in one invocation |
Audit flow
- Scope. A path argument narrows to that file or directory. Empty target = the repo's
tracked markdown minus config
excluded_paths. Order repo-wide work by impact class first
(instruction surfaces: CLAUDE.md, AGENTS.md, .claude/rules/**, **/SKILL.md,
README.md), then by change frequency (git log --since=90.days --name-only counts over
tracked .md); ordering affects report and chunk order only, never inclusion.
- Run the detector. Chunk large corpora: write the ordered list to a temp file and invoke
detect.sh --paths-file <list> --offset N --limit M per chunk (one process per chunk, no
per-file shell loop; roughly 200 files per chunk keeps each call under a minute).
- Apply the rubric to the highest-priority files (instruction surfaces always; further files
as budget allows, saying which were rubric-covered). The rubric pass is independent of the
detector: a file with zero script findings still gets its rubric read when it is in the
priority set — a fix pass that only revisits detector hits has not covered the rubric. The
rubric tells and their boundaries are the catalog entries marked
v1: rubric; cite the
entry when reporting. Counter-signs (the catalog's "Signs of human writing") temper a
verdict, never generate findings.
- Report. Group findings by file in priority order: for script findings quote the rule id,
line, and fired condition; for rubric findings quote the offending text and name the catalog
entry. State the declined counts (marker/config/code-fence exemptions) and any disabled rules
from the detector's
Summary rows. State what was scanned and what the rubric did not cover.
- Persist the findings file per
context/persist-findings.md
whenever the audit examined tracked files: fetch the producer contract first and refuse to
write when unreachable (report-only is then the outcome, and say so). Script findings only.
- Recommend, never auto-run: the
fix action for the findings, or /ai-slop:setup when the
run tripped over deliberate house style (heavy declined counts or a flooded rule).
review:fanout fix routes the whole file: it hands every row but rule-utm-params to this
skill's own fix action, which the crosswalk declares as their remediation owner. rule-utm-params is the one row the relay is capable of applying
meaning-preservingly — do not promise that it will. It takes its ordinary cleanup class and
reaches the relay's cleanup route, which prefers /simplify, a code-simplification skill that
reads no findings file, and applies rows itself only when /simplify is absent. Neither the
relay's own applier nor /simplify loads this skill's rewrite guide. Recommend the relay when
the operator is already running a fix pass; recommend this skill's fix directly
when they are not, since it is the shorter path to the same rewrites. Name the condition that
changes the answer — the relay can only hand the rows over when /ai-slop:audit is available
in that session, and surfaces them otherwise.
Fix flow (explicit invocation only)
Never runs on bare invocation. Requires the user's explicit fix (or a chained
"detect and rewrite" request). Per file, worst-first:
- Apply the file's findings per
reference/rewrite-guide.md
(read it first; it owns the replacement forms, the plain-speech target, the legitimate-hit
taxonomy, the risky-class disambiguation rules, and the voice guidance): rewrite each
flagged line (em dashes to commas, periods, or restructured sentences — never parentheses
or en dashes, which swap one tell for another; deflate stock phrases; collapse
parallelisms; delete filler and chat residue; strip utm_* params; delete or source
residue artifacts) and the rubric rewrites for tells the audit reported. Preserve meaning
over style: when a rewrite would change what a sentence asserts, skip it and record why.
Triads collapse toward one: for a rule-of-three rubric finding, prefer the single
strongest item and cut the rest — keep all three only when each is load-bearing (a complete
set the reader needs, not rhetorical rhythm; enumerating three actual things is not a
tell), and never collapse when the survivors would not entail the deleted items. Fewer
parallel items is also less to maintain. Then run the guide's voice pass (its "Adding
voice" section) on the file's authored-register prose — README narrative, changelog
rationale, design tradeoffs; never operative instructions or reference tables — and close
each file with the guide's self-audit pass ("what still makes this read machine-written?")
before handing it to verification.
- Verify with a fresh-context semantic-diff subagent: hand it the before/after pair,
blind to the rewrite rationale; it flags SEMANTIC LOSS (a qualifier, threshold, or claim
dropped), AMBIGUITY (a reading the original excluded), and QUOTE CORRUPTION (any changed
byte inside quoted text), with the guide's risky classes called out for adversarial
attention: a negative-parallelism restatement must preserve which reading the original
meant, and a collapsed triad must still entail its deleted items. Revert every flagged
hunk before moving on.
- Close the file: findings fixed, explicitly suppressed (in-file marker with a reason), or
reverted-with-reason. Report per file as you go on long runs.
After the last file: re-run the detector over the fixed set and re-emit the findings file per
context/persist-findings.md "Re-running", so no stale findings
file survives its own remediation. Then report totals: fixed, suppressed, reverted, remaining.
Configuration
.claude/ai-slop.json per the config-cascade convention; keys, layers, and the in-file marker
forms are documented in the plugin README and managed by /ai-slop:setup. The detector's
--show-config names the layer supplying each effective value. When a whole document
legitimately needs em dashes, the remedy is em_dash_allowed_paths or the file marker, never a
threshold. The em-dash rule is zero-tolerance by design; the catalog's rule-em-dash entry
carries the reason.
What this skill does NOT do
- Does not fix on bare invocation.
audit and scan verbs are read-only in this
marketplace; mutation rides only the explicit fix argument.
- Does not put rubric findings in the findings file. No crosswalk row, no relay: judgment
verdicts reach the human report only (V1 boundary, revisit with field history).
- Does not scan code comments (
code-tidying:audit-comment-residue owns them), commit
messages, PR bodies, or non-repo text; structural markdown (heading hierarchy, multiple H1,
title case) belongs to the markdown linter lane. Reshaping those commit messages, PR bodies
and non-repo text so they lead with the point and carry fewer words is /writing:be-concise,
which owns that doctrine when the writing plugin is installed; without it, say the text
sits outside this skill's regime rather than auditing it anyway.
- Does not weaken rules to pass its own corpus: a deliberate house style is config in the
consuming repo, never a shipped-default change.
1---2name: audit-23description: Audit markdown prose for AI-writing tells (slop): em dashes (zero-tolerance by default), emoji formatting, AI vocabulary, negative parallelisms, chatbot phrases, filler, stacked hedging, citation artifacts, model-era phrases ('that's the unlock', 'the part most people skip'), and the rest of the catalog (distilled from Wikipedia's Signs of AI writing plus an evolving model-era inventory), plus a judgment rubric for superficial analysis, vague attribution, promotional tone, metaphor jargon ('load-bearing', 'seam'), and mechanism-free claims. Use when: 'check for AI slop', 'de-slop this doc', 'unslop this', 'find AI tells', 'does this read AI-written', 'remove em dashes', or before publishing agent-written prose. Read-only by default; 'fix' as an explicit argument applies rewrites behind a semantic-diff guard and may be chained ('detect and rewrite'). Empty target audits the repo's tracked markdown, high-impact and high-velocity files first.4---56## Repository context. Gather first78Collect these with **individual** Bash calls, one command per call, never combined into a single9invocation:1011- Current branch, `git branch --show-current`1213Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as14separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute15block as one shell invocation, and a worktree-isolated session refuses a compound command that16contains git.1718## Pre-computed context1920Effective config: !`"${CLAUDE_SKILL_DIR}/scripts/detect.sh" --show-config >/dev/null 2>&1 && { "${CLAUDE_SKILL_DIR}/scripts/detect.sh" --show-config 2>/dev/null | head -8; :; } || echo "detector unavailable"`2122## Purpose2324Detect and remove AI-writing tells in checked-in markdown prose. Two detection layers over one25rule inventory ([`reference/catalog.md`](reference/catalog.md), distilled from Wikipedia's26"Signs of AI writing", revision-pinned, plus the catalog's "Cursor unslop additions" section27and its repo-owned, evidence-graded "Model-era additions" section of current-generation model28vocabulary):29301. **Deterministic**: `${CLAUDE_SKILL_DIR}/scripts/detect.sh` runs the catalog's `v1: script`31 rules. Its findings carry argued severity tiers (the detector-findings convention's crosswalk)32 and persist as a conforming findings file, which is how a consumer sees them and how they33 reach a surface that can rewrite them. Audit step 6 names which surface, and when.342. **Judgment rubric**: the catalog's `v1: rubric` tells, applied by reading the prose. Rubric35 findings reach the human report only, never the findings file.3637Both layers sit behind the catalog's policy-level **quotation exemption**: wording rules never38scan blockquotes, double-quoted spans, or inline code spans (typography rules still do), so a39document that quotes a tell to document it, and a changelog that backticks the phrase a fix40removed, stay marker-free by construction.4142## Action router4344| Argument | Action |45|---|---|46| *(empty)* or `audit [target]` | Read-only audit (default). Empty target = repo-wide |47| `fix [target]` | Explicit fix pass over the target's findings (guarded; below). "Detect and rewrite" or `audit fix` chains audit then fix in one invocation |4849## Audit flow50511. **Scope.** A path argument narrows to that file or directory. Empty target = the repo's52 tracked markdown minus config `excluded_paths`. Order repo-wide work by impact class first53 (instruction surfaces: `CLAUDE.md`, `AGENTS.md`, `.claude/rules/**`, `**/SKILL.md`,54 `README.md`), then by change frequency (`git log --since=90.days --name-only` counts over55 tracked `.md`); ordering affects report and chunk order only, never inclusion.562. **Run the detector.** Chunk large corpora: write the ordered list to a temp file and invoke57 `detect.sh --paths-file <list> --offset N --limit M` per chunk (one process per chunk, no58 per-file shell loop; roughly 200 files per chunk keeps each call under a minute).593. **Apply the rubric** to the highest-priority files (instruction surfaces always; further files60 as budget allows, saying which were rubric-covered). The rubric pass is independent of the61 detector: a file with zero script findings still gets its rubric read when it is in the62 priority set — a fix pass that only revisits detector hits has not covered the rubric. The63 rubric tells and their boundaries are the catalog entries marked `v1: rubric`; cite the64 entry when reporting. Counter-signs (the catalog's "Signs of human writing") temper a65 verdict, never generate findings.664. **Report.** Group findings by file in priority order: for script findings quote the rule id,67 line, and fired condition; for rubric findings quote the offending text and name the catalog68 entry. State the declined counts (marker/config/code-fence exemptions) and any disabled rules69 from the detector's `Summary` rows. State what was scanned and what the rubric did not cover.705. **Persist the findings file** per [`context/persist-findings.md`](context/persist-findings.md)71 whenever the audit examined tracked files: fetch the producer contract first and refuse to72 write when unreachable (report-only is then the outcome, and say so). Script findings only.736. **Recommend**, never auto-run: the `fix` action for the findings, or `/ai-slop:setup` when the74 run tripped over deliberate house style (heavy declined counts or a flooded rule).75 `review:fanout fix` routes the whole file: it hands every row but `rule-utm-params` to this76 skill's own `fix` action, which the crosswalk declares as their remediation owner. `rule-utm-params` is the one row the relay is *capable* of applying77 meaning-preservingly — do not promise that it will. It takes its ordinary cleanup class and78 reaches the relay's cleanup route, which prefers `/simplify`, a code-simplification skill that79 reads no findings file, and applies rows itself only when `/simplify` is absent. Neither the80 relay's own applier nor `/simplify` loads this skill's rewrite guide. Recommend the relay when81 the operator is already running a fix pass; recommend this skill's `fix` directly82 when they are not, since it is the shorter path to the same rewrites. Name the condition that83 changes the answer — the relay can only hand the rows over when `/ai-slop:audit` is available84 in that session, and surfaces them otherwise.8586## Fix flow (explicit invocation only)8788Never runs on bare invocation. Requires the user's explicit `fix` (or a chained89"detect and rewrite" request). Per file, worst-first:90911. **Apply** the file's findings per [`reference/rewrite-guide.md`](reference/rewrite-guide.md)92 (read it first; it owns the replacement forms, the plain-speech target, the legitimate-hit93 taxonomy, the risky-class disambiguation rules, and the voice guidance): rewrite each94 flagged line (em dashes to commas, periods, or restructured sentences — never parentheses95 or en dashes, which swap one tell for another; deflate stock phrases; collapse96 parallelisms; delete filler and chat residue; strip `utm_*` params; delete or source97 residue artifacts) and the rubric rewrites for tells the audit reported. Preserve meaning98 over style: when a rewrite would change what a sentence asserts, skip it and record why.99 **Triads collapse toward one**: for a rule-of-three rubric finding, prefer the single100 strongest item and cut the rest — keep all three only when each is load-bearing (a complete101 set the reader needs, not rhetorical rhythm; enumerating three actual things is not a102 tell), and never collapse when the survivors would not entail the deleted items. Fewer103 parallel items is also less to maintain. Then run the guide's **voice pass** (its "Adding104 voice" section) on the file's authored-register prose — README narrative, changelog105 rationale, design tradeoffs; never operative instructions or reference tables — and close106 each file with the guide's self-audit pass ("what still makes this read machine-written?")107 before handing it to verification.1082. **Verify** with a fresh-context semantic-diff subagent: hand it the before/after pair,109 blind to the rewrite rationale; it flags SEMANTIC LOSS (a qualifier, threshold, or claim110 dropped), AMBIGUITY (a reading the original excluded), and QUOTE CORRUPTION (any changed111 byte inside quoted text), with the guide's risky classes called out for adversarial112 attention: a negative-parallelism restatement must preserve which reading the original113 meant, and a collapsed triad must still entail its deleted items. Revert every flagged114 hunk before moving on.1153. **Close** the file: findings fixed, explicitly suppressed (in-file marker with a reason), or116 reverted-with-reason. Report per file as you go on long runs.117118After the last file: re-run the detector over the fixed set and re-emit the findings file per119[`context/persist-findings.md`](context/persist-findings.md) "Re-running", so no stale findings120file survives its own remediation. Then report totals: fixed, suppressed, reverted, remaining.121122## Configuration123124`.claude/ai-slop.json` per the config-cascade convention; keys, layers, and the in-file marker125forms are documented in the plugin README and managed by `/ai-slop:setup`. The detector's126`--show-config` names the layer supplying each effective value. When a whole document127legitimately needs em dashes, the remedy is `em_dash_allowed_paths` or the file marker, never a128threshold. The em-dash rule is zero-tolerance by design; the catalog's `rule-em-dash` entry129carries the reason.130131## What this skill does NOT do132133- **Does not fix on bare invocation.** `audit` and `scan` verbs are read-only in this134 marketplace; mutation rides only the explicit `fix` argument.135- **Does not put rubric findings in the findings file.** No crosswalk row, no relay: judgment136 verdicts reach the human report only (V1 boundary, revisit with field history).137- **Does not scan code comments** (`code-tidying:audit-comment-residue` owns them), commit138 messages, PR bodies, or non-repo text; structural markdown (heading hierarchy, multiple H1,139 title case) belongs to the markdown linter lane. Reshaping those commit messages, PR bodies140 and non-repo text so they lead with the point and carry fewer words is `/writing:be-concise`,141 which owns that doctrine when the `writing` plugin is installed; without it, say the text142 sits outside this skill's regime rather than auditing it anyway.143- **Does not weaken rules to pass its own corpus**: a deliberate house style is config in the144 consuming repo, never a shipped-default change.