Borrowed from runtime garbage collection: periodically scan for objects that are no longer referenced, redundant, expired, or low-value, and reclaim the space. The critical difference: here, collection requires a human in the loop. Never delete autonomously.
Do NOT activate for: cleaning project source code (that's refactoring), clearing chat history, or uninstalling Claude Code itself.
.disabled > move to ~/.claude/_gc_trash/ > real deletion. Always keep an undo path.[y/n/skip] confirmation. No "yes to all" shortcut.~/.claude/gc_log.md: what was touched, why, and how to undo it.| # | Channel | Path | Staleness / redundancy signals |
|---|---|---|---|
| 1 | Skills | ~/.claude/skills/*/ |
Heavily overlapping names; never triggered in recent transcripts; domain mismatch with the user's actual work; broken or empty SKILL.md |
| 2 | Memory | ~/.claude/**/memory/*.md + its index |
Multiple index entries for one topic; contents contradicting newer entries; dates that have passed; orphan files missing from the index; sub-100-word fragments that should merge |
| 3 | Hooks | ~/.claude/hooks/ + settings |
Scripts present on disk but referenced by no hook config; old versions superseded by rewrites |
| 4 | Permissions | permissions.allow in settings.json / settings.local.json |
Duplicate entries; specific entries already covered by a wildcard (e.g. Bash(git push) when Bash(*) is allowed); one-off grants from past experiments |
| 5 | MCP servers | ~/.claude.json or project .mcp.json |
Servers that fail to connect; functional duplicates; long-unused |
| 6 | Scheduled reminders / jobs | wherever the user keeps them | Fired one-shots older than 30 days; jobs whose target scripts no longer exist |
| 7 | Project history | ~/.claude/projects/*/ |
Stale handoff snapshots; session records superseded by newer state |
| 8 | Runtime caches | cache/, file-history/, logs/, shell-snapshots/ |
Sort by size and mtime; propose items >30 days old and large |
[y/n/skip]. The user can stop at any point..disabled rename for skills/hooks and _gc_trash/<date>/ move for files. Permission entries live in JSON (no comments possible): back up the settings file, record each removed entry verbatim in gc_log.md, then remove it from the allow array with jq. Only hard-delete when the user explicitly asks.~/.claude/gc_log.md: timestamp, items actioned, undo instructions.Orphaned hook scripts (channel 3) — scripts on disk that no hook config references:
for f in ~/.claude/hooks/*; do
name=$(basename "$f")
grep -rq "$name" ~/.claude/settings.json ~/.claude/settings.local.json 2>/dev/null \
|| echo "ORPHAN: $f"
done
Redundant permission entries (channel 4) — duplicates, and specific grants shadowed by a wildcard:
jq -r '.permissions.allow[]' ~/.claude/settings.local.json | sort | uniq -d
if jq -e '.permissions.allow | index("Bash(*)")' ~/.claude/settings.local.json >/dev/null; then
jq -r '.permissions.allow[]' ~/.claude/settings.local.json \
| grep '^Bash(' | grep -vF 'Bash(*)'
fi
Largest stale caches (channel 8) — du -k instead of GNU-only find -printf, so it works on macOS/BSD too:
find ~/.claude/file-history ~/.claude/shell-snapshots -type f -mtime +30 \
-exec du -k {} + 2>/dev/null | sort -rn | head -20
Soft-delete with undo path (capture the date once so the log can't disagree with the directory):
gc_date=$(date +%Y-%m-%d)
mkdir -p ~/.claude/_gc_trash/$gc_date
mv ~/.claude/skills/dead-skill ~/.claude/_gc_trash/$gc_date/
echo "$(date -Iseconds) moved skills/dead-skill -> _gc_trash/$gc_date/ (undo: mv back)" >> ~/.claude/gc_log.md
Removing a confirmed-redundant permission entry (JSON has no comments — back up, log, then edit):
cp ~/.claude/settings.local.json ~/.claude/settings.local.json.bak
echo "$(date -Iseconds) removed permission entry: Bash(git push) (undo: restore from .bak or re-add)" >> ~/.claude/gc_log.md
jq '.permissions.allow -= ["Bash(git push)"]' ~/.claude/settings.local.json.bak \
> ~/.claude/settings.local.json
_gc_trash/ copy or .disabled rename, you did it wrong.~/.claude (or the project's .claude/). Config GC never wanders into source trees.gc_log.md forever. It's tiny, and "when did I disable that hook and why" comes up more often than you'd think.skill-stocktake — audits skill quality; config-gc audits skill existence. Run stocktake on what survives GC.workspace-surface-audit — the additive counterpart: recommends what to install. config-gc is the subtractive half of the same lifecycle.configure-ecc — after installing skills with it, run config-gc to reconcile overlaps with your pre-existing setup.continuous-learning — produces the memory files this skill later audits.security-review — pairs well with the permissions channel.