Purpose
The ai-slop detector ships neutral defaults. A consumer repo declares its own exemptions and
tuning in .claude/ai-slop.json, resolved per the config-cascade convention: user-global
(~/.claude/ai-slop.json), team (.claude/ai-slop.json, tracked), local overlay
(.claude/ai-slop.local.json, gitignored). Later layers refine earlier ones per key.
Keys
| Key | Type | Meaning |
|---|---|---|
excluded_paths |
glob list | Files the audit never scans |
em_dash_allowed_paths |
glob list | Documents exempt from the zero-tolerance em-dash rule |
vocab_add |
word list | Additions to the AI-vocabulary list |
vocab_remove |
word list | Removals from the AI-vocabulary list |
phrase_add |
ERE fragment list | Additions to the model-era phrase roster (rule-model-era-phrases); whole fragments, spaces allowed, apostrophes spelled . |
phrase_remove |
ERE fragment list | Removals from the shipped phrase roster, matched verbatim against the shipped fragments |
disabled_rules |
rule slugs | Rules the audit skips entirely (reported as disabled) |
thresholds |
map | Per-rule density thresholds: ai_vocabulary, copulative_avoidance (matches per 1000 words; density rules also need at least 3 matches) |
_comment |
string | Free-text rationale for the choices in this file. Read by nobody; JSON has no comment syntax, and a config that disables a rule without recording why is the drift this skill exists to catch. Not drift — do not flag it as an unknown key |
check (default — read-only)
Report the current state and change nothing:
- Run the detector's
--show-config(it names the layer supplying each value) or read the layers directly; report which layer wins each key and which layers are absent. - Flag drift: unknown keys, an em-dash threshold key (the rule is zero-tolerance by design —
per-document exemption via
em_dash_allowed_pathsis the supported mechanism), globs that match nothing, adisabled_rulesslug that names no shipped rule, aphrase_addfragment that is not a valid ERE (the detector skips it with a stderr note; surface it here as drift), or aphrase_removefragment matching no shipped phrase. - End with what
applywould change, if anything was flagged.
apply
Everything check does, then the confirmed write:
- Interview the user for what they want changed. For em-dash exemptions, ask for the documents that genuinely require em dashes; the default posture is that most work does not.
- Write ONLY the team layer (
.claude/ai-slop.json), showing the diff and getting explicit confirmation before writing. Never write the user-global or overlay layers on the user's behalf; name them as options the user edits themselves. - Re-run
--show-configand report the new effective state. Then run the tracked-file pair on the written team file:git check-ignore -v .claude/ai-slop.jsonreports no match (a match is FAIL with the pattern) ANDgit ls-files --error-unmatch .claude/ai-slop.jsonexits 0 (non-zero right after a fresh write means "written but untracked: commit it to share with the team", never success).