| name | purge-hallucinations |
| description | Audit a target for hallucinations — concrete, checkable references that don't actually resolve (a missing file path, an undefined R function/object, a non-existent `uses:` action ref or version, a dead URL, a `[[memory-link]]` with no target, a fabricated skill name, citation, package, flag, config key, or SDK method) — then interactively propose a fix for each one. Conservative: only flags references PROVEN absent; unverifiable ≠ hallucination. Scope is any of the memory/instruction corpus (ai-config memories/, skills/, CLAUDE.md), the current repo's code & docs, or an explicit file / PR diff / pasted AI output. Use when asked to 'purge hallucinations', 'ph', 'check for hallucinations', 'verify the references', 'find made-up / fabricated references', 'fact-check this AI output', 'does everything in this file actually exist', 'audit my memories for stale references', or 'what did you make up'. |
| user-invocable | true |
| allowed-tools | ["Bash","Read","Edit","Write"] |
purge-hallucinations — verify references resolve, then purge the fakes
LLM-written content (memories, skills, CLAUDE.md, code, docs, PR
descriptions) drifts into hallucinations: concrete references that read as
authoritative but don't resolve to anything real. This skill checks each
checkable reference against ground truth and, for every one proven fabricated,
proposes a fix interactively.
The prime directive: only purge what you can prove is fake. A reference you
can't verify (network down, ambiguous symbol, private resource) is
unverifiable, not a hallucination — report it, never silently delete it.
When this fires
- "purge hallucinations", "ph", "check for hallucinations", "fact-check this"
- "verify the references", "find made-up / fabricated references"
- "does everything in this file actually exist", "what did you make up"
- "audit my memories/skills for stale references"
- Proactively when reviewing AI-generated text/code that asserts concrete,
checkable facts (file names, function names, versions, links, citations) —
especially memory and instruction files, which compound errors over time.
Step 1 — Resolve the target
Pick the narrowest target the user named, in this precedence order:
- Explicit target — a file, a directory, a PR diff, or pasted AI output
the user pointed at. For a PR:
gh pr diff <n> (local) or
mcp__github__pull_request_read method: get_diff (remote/web — see
memories/github.md); audit only the references the diff introduces.
- The memory/instruction corpus — the ai-config repo's
memories/,
skills/, and CLAUDE.md. Find the repo root with
git -C ~/.claude/skills/purge-hallucinations rev-parse --show-toplevel.
- The current repo's code & docs — when the user says "this repo" or
names no target while inside a project.
If the target is genuinely ambiguous, ask once; otherwise proceed with the
narrowest reasonable reading and state which you chose.
Step 2 — Extract concrete, checkable references
Scan the target for references that have a definite right/wrong answer. Ignore
prose, opinions, and design rationale — those aren't hallucinations, just
claims. Pull out, with file + line for each:
| Reference type | Examples |
|---|
| File / path | src/foo.R, here("data/x.csv"), a relative link in a .qmd |
| Function / object / symbol | pkg::fn(), an R object, a shell command, a Make target |
| Action ref + version | uses: org/action@v3, @<sha>, a tag/release |
| Skill name | ~/.claude/skills/<name>/, a /slash-command |
| Memory cross-link | [[some-memory-name]] in a memory body |
| URL / link | https://…, a docs anchor, a badge target |
| Citation / package | a CRAN/Bioconductor package, a DOI, a DESCRIPTION dep |
| Flag / option / config key | a CLI flag, an env var, a YAML key the schema defines |
| API / SDK method or model id | an SDK method, a model name, an endpoint |
Step 3 — Verify each against ground truth
Use the cheapest check that proves existence or absence. Match the tool to
the reference type:
- File / path —
test -e <path>, git ls-files -- <path>, ls.
- Function / object — grep for the definition, not just a mention
(
grep -rn "fn <- function" R/); for an exported R fn check NAMESPACE /
Rscript -e 'library(pkg); exists("fn")'. Shell command — command -v.
- Action ref + version — confirm the tag/SHA exists
(
gh api repos/<org>/<repo>/git/refs/tags/<tag> or .../commits/<sha>).
- Skill name —
ls skills/<name>/ in the local ai-config directory. If
not found locally, check the session's available-skills list (appears in
system reminders) before classifying as ❌; a globally-available system skill
with no local directory is ❓ Unverifiable, not ❌ Fabricated.
- Memory cross-link —
[[target]] links resolve to skill directories
(ls skills/<target>/); if no matching skill, search memory headings
(grep -rn "^# .*<target>" memories/).
- URL / link —
curl -sSI -o /dev/null -w '%{http_code}' <url> (local) or
WebFetch (remote). A 404/410 is fabricated; a timeout, 403, 429, or
DNS failure is unverifiable — distinguish them.
- Citation / package — CRAN:
https://cran.r-project.org/package=<pkg>;
installed: Rscript -e 'find.package("<pkg>")'; dep: check DESCRIPTION.
- Flag / option / config key — grep the tool's
--help, its schema, or
its source; for a YAML key, the consuming code/schema.
- API / SDK method or model id — check the SDK source/docs. For
Claude/Anthropic specifics (model ids, params), defer to the
claude-api
skill rather than guessing.
Sort every reference into exactly one bucket:
| Bucket | Meaning | Disposition |
|---|
| ✅ Resolves | proven to exist | leave it |
| ❌ Fabricated | proven absent (404, no definition, no such tag/file) | propose a fix (Step 4) |
| ❓ Unverifiable | can't be checked here (network, private, ambiguous) | report, do not edit |
When in doubt, it's ❓ not ❌. False deletions are worse than a flagged
maybe.
Step 4 — Propose a fix for each fabrication (interactive)
Default action is propose, then apply on confirmation — never bulk-edit
silently. For each ❌, present: the reference, where it is, the evidence it's
fake, and a proposed fix — exactly one of:
- Correct it — when a real target is an obvious near-match (typo, moved
path, renamed symbol, bumped version). Show the before→after. Prefer this
over deletion when a true referent clearly exists (
grep/gh for the
nearest real name).
- Remove it — when the reference is wholly invented and removing it leaves
the sentence/code correct.
- Rewrite around it — when removal would leave a dangling clause or broken
code; restate without the fake reference.
Apply each fix only after the user confirms (batch obvious typo-corrections
together if the user prefers). Re-verify after editing. If the target is a
memory or instruction file, the global "verify before recommending" rule is
the reason this matters — a fabricated memory poisons every future session.
Step 5 — Report
Summarize: N references checked → ✅ resolved, ❌ fixed (list before→after),
❓ unverifiable (list, with why each couldn't be checked). The ❓ list is a
feature, not a failure — it tells the user exactly what still needs a human
eyeball.
Custom agent for the detect phase
Steps 1--3 (resolve target, extract references, verify against ground truth)
have no need for Edit/Write access. Delegate them to the
hallucination-detector custom agent (.claude/agents/hallucination-detector.md)
for a hard, harness-enforced guarantee against Edit/Write tool use before the
report in Step 4 is reviewed --- tighter than this skill's own
instruction-only discipline, though the agent retains Bash for read-only
checks, so avoiding a write-capable shell command is still instruction-level.
Run Step 4 (propose/apply fixes) in the main session afterward.
Relationship to other skills
record-learnings, ums, memorize / remember — these write the
memory/skill/instruction corpus; purge-hallucinations audits it. A
natural hand-off: after a big memory/skills write, run this to catch
fabricated cross-links and stale paths.
claude-api — the source of truth for Claude/Anthropic model ids and
params; defer to it instead of guessing when verifying those references.
simplify / tidy — clean structure (dead code, redundancy); this
cleans truth (references that don't resolve). Complementary passes.
reprexes — if verifying a code reference needs actually running it,
isolate it as a reprex first.
check-rendered-refs / crr — the output-side counterpart. This skill
audits source references; crr scans rendered HTML for crossrefs/citations
that broke at render time and leaked into the page as ?@key. Hand a ?@key
hit here to trace the dangling key back to its source line.
check-info-quality / ciq — this skill checks whether a reference
exists; ciq's check C checks whether an existing, real reference
actually supports the claim it's attached to. A citation can pass here
and still fail ciq if it resolves but doesn't say what the text claims.
Anti-patterns
- ❌ Deleting an unverifiable reference as if it were proven fake — the
cardinal sin. Network/permission failures are ❓, not ❌.
- ❌ Flagging prose, opinions, or design rationale — only concrete, checkable
references are in scope.
- ❌ Confirming a symbol exists by finding a mention of it rather than its
definition.
- ❌ Bulk-editing without proposing fixes first (default is interactive).
- ❌ Treating a network 403/429/timeout the same as a 404.
- ❌ Guessing whether a Claude/Anthropic model id or param is real instead of
deferring to
claude-api.