New
Apps 1,067Makers 1,065This week 1,067
Promote your app−30%
CoalWash screenshot 1
2views in
the last 30 days

CoalWash

Fidelity-first cleanup and defragment engine for AI agent memory files.

Built with Claude Code

by thecolliery · added Oct 29, 2026
no ratings0 comments

🧼 CoalWash

Coal washing is the real mining process that cleans raw coal — separating the waste without damaging the coal. This one is a memory washer/defragmenter for your agent: it cleans the fat, never the meat.

A fidelity-first memory-defragment/cleanup engine for agent memory — two lanes, different contracts: class-B (the memory and governance files your platform loads into context every session) gets the semantic wash — a free mechanical Quick pass plus a code-enforced fidelity gate that blocks any structured-token drop by diff (links, dates, versions, URLs, quotes, numbers, code-spans, frontmatter — presence proven, not hope; a swap among survivors, like prose fidelity, is the paid semantic layer's job), a separate-consent Full pass, every cut snapshot-backed and revertible. class-A (transcripts — the estate) gets byte-identity archiving instead — copy-verify-then-delete, never semantic-edited.

Compatibility ·

Antigravity: works with Cursor: works with Codex: works with Gemini CLI: works with Cline: works with Copilot: works with

The auto layer — the session-start gauge and the enforce/airbag hooks — runs on Claude Code only today; every other platform sits at the manual rung of the capability-keyed activation ladder (hooks → best-effort agent-driven offer → manual): /coalwash by hand after a file-copy install. validated = ran end-to-end on that platform · works with = the documented file-copy install — designed-degrade-safe, not yet run there.

Changelog · Security · Privacy · Releases

Docs: docs.thecolliery.org/tools/coalwash

Part of TheColliery — siblings: CoalMine (quality canaries) · CoalTipple (model/effort routing) · CoalBoard (consensus board) · CoalHearth (warm-resume) · CoalFace (fan-out discipline) · CoalLedger (docs health) · CoalGob (OS-trash delete guard, PUBLIC BETA v0.1.0-beta.1).


🧼 What it is

Agent memory grows additively, unmanaged — the always-loaded set (memory index + governance files) is paid every session, forever, and the market's cleanup tools are lossy summarize-and-hope. Cutting the wrong line from a memory your agent trusts is silent breakage that never surfaces.

CoalWash is the SSD cleanup + defragment discipline ported to that store, fidelity-first:

  • What the gate proves — and what it cannot see. A mechanical fidelity gate diffs every rewrite's structured-token inventory — [[wikilinks]], dates, versions, link/URL destinations, quoted spans, numerals, code-spans, frontmatter keys — and proves every token that went in came out: any drop blocks the apply, code-caught, not hoped. What it cannot see is surviving values trading places — a rewrite that turns pass 878 / fail 0 into pass 0 / fail 878 drops nothing, so it passes. So don't skip your own read: when a wash rewrites a file whose numbers, URLs, or labels bind to specific subjects, read the diff yourself before trusting it — that check, like a load-bearing prose fact (e.g. "the rate limit is 5000/hr"), rests on the paid semantic reviewers and you.
  • Deletes are UNDO-backed, not pre-approved. A delete/merge is authorized by its presence in the adjudicated plan — no separate approval flag. Safety lives in UNDO instead: every apply snapshots (verified at creation) before the first mutation, any failure triggers a whole-run rollback, a pinned: true file is refused outright — the gates don't depend on agent diligence.
  • The apply is transactional. Exclusive lock, marked snapshot before the first mutation, fsync'd WAL, atomic writes, deletes last, wholesale rollback on any failure. Worst realistic crash outcome: "the run did not happen" — never "memory is corrupted."
  • A foreign mid-run write aborts everything. Anything else touching your files mid-run — a cloud-sync client, an editor, another agent — CoalWash detects at the moment of writing, stops, rolls back rather than guessing; every snapshot is also read back and verified before the destructive phase begins.
  • Plain in, plain out. CoalWash never transforms your files into a tool-specific format — plain markdown in, plain markdown out; every artifact it writes (snapshots, WAL journal, keeps.json) is a plain file you can read without CoalWash.

Honest frame: CoalWash slows how fast your memory-overhead grows — a rate intervention, not a level reset. It doesn't eliminate memory cost, reach zero, or stop legitimate growth (the floor of real facts rises with your project; that's meat, not fat).

⚙️ How it works

One standing gauge sits at the chokepoint — memory loads every session, so a session-start caliper sees past, present, and future by construction — then a disciplined pipeline runs per wash:

Stage Who What
Gauge code Discover class-B per platform → measure footprint → break-even math → band verdict
Quick code-gated flags + measurement Empty tables/headings and exact-duplicate/blank-run fat are DETECTED by code and reported with real numbers — the tier flags and measures, it does not cut; clearing what it finds is an agent/human edit or the wizard's semantic tier
Full one outsider sub + the insider Semantic garbage judgment (superseded / duplicate / point-in-time / over-verbose) by a zero-context outsider; session agent adjudicates every flag — always a separate consent
Fidelity gate code Inventory diff, original vs new; any dropped link/date/version/frontmatter key blocks the apply
Apply code Delete/merge authorization is plan-sourced (no separate approval step) — lock → verified snapshot → WAL → atomic writes → deletes last → commit, or whole-run rollback; pinned files refused outright
Receipt code Pushes one line after every run, including one that cuts nothing — [CoalWash] cut ~N tok (−P%); the fuller class B: X KB -> X' KB · removed/trimmed/kept · fidelity gate: PASS block is an on-demand pull (/coalwash:stats or the wizard), never automatic

Why an outsider judges, not you: it's a stranger walking through a house it's never lived in — it can't know what you still use, so it never discards anything itself. Its only power: point and ask, "what is this, can it go?" You answer with a concrete reason, not a feeling — a settled answer sticks (an adjudicated keep isn't re-asked without new evidence).

A keep's own anchor/anchorFile-based structural re-check — verifying the anchor text still sits where it was recorded before honoring an old keep — is lab-only, declared 2026-08-04, and not wired into any shipped write path: nothing in the engine currently produces an anchor-bearing keep record, so every live keep is the plain form above. The file-level pinned: true gate (Apply, above) is a separate, wired, fully-exercised mechanism, unaffected.

Certain fat is measured from CONTENT at every gauge (exact-duplicate substance lines, excess blank-line runs) — never stamped, never a snapshot that can go stale. Muscle = footprint minus that measured fat. A hysteresis-gated ceiling checks the measured fat against two fixed marks — 500 tok arms it, 200 tok disarms it — never a calendar. Armed = OBESE. Memory-BMI survives as an informational ratio (footprint / measured muscle) shown on receipts, no longer what arms anything. Footprint means what this project owns: governance inherited from a parent directory above it — an umbrella repo's own CLAUDE.md and the files it imports — is measured and reported as its own figure but never counted into the band, because a project can neither wash nor externalize a file that isn't its to touch.

FULL is the economic cut-point on that same ceiling, not a separate line: armed + both break-evens proven — cutting the certain fat pays for itself, AND reorganizing the demotable muscle pays for itself too (cost(one run) < cost(carrying it), numbers always shown for both halves) — fires FULL instantly, always a subset of OBESE, latching for the episode (a dip won't un-FULL it; the reset is continuous, the moment Quick's own cut drops the measured fat back under the disarm mark). A capacity wall forces FULL separately, no fat proof needed: the platform's true context capacity, plus the CC index character/line caps (25,000 characters of the trimmed index, 200 lines) — a person-independent machine limit only, with no config knob left to scale it. Capacity-nearing footprint is muscle, not fat: disarmed+wall → the Full-tier consent, UNLESS a Full pass has already genuinely removed something this episode, in which case → externalize/split, never wash-harder; armed+wall → real fat remains, wash first. Fat and muscle are measured from content at every gauge, so there is no install-day wait and no clean-dependent state to get stuck in. Only the fat hysteresis and the wall ever trigger a state change — never time or age. A stat-only Stop-turn recheck (last gauge's known paths, no directory walk or content read) catches a within-session spike before the next SessionStart; full re-measure only re-runs on real drift, never unconditionally.

Band Behavior
LEAN Silent — a run would be a no-op, so none is offered
OBESE Ceiling armed but not yet economical: the Stop hook directs the free mechanical Quick pass and the session agent runs it under standing config (exercisePerBand is read-tolerated and has no runtime effect — changing it changes nothing) — no user ask, a one-line result when something's cut, silent otherwise. Never asks, however long it persists or recurs — the wizard door lives at FULL only
FULL Economic cut-point or capacity wall: hook directs the same free mechanical pass, agent runs it, numbers always shown — no user ask; reaches what OBESE couldn't, sweeps it anyway. Every cut snapshot-backed, revertible. Still over after that pass ran this episode → one run/later ask opens the wizard for semantic judgment — the system's sole ask site, re-asked only once fat grows past the last-flagged level. Firing on the wall with ~no fat found means the Full-tier consent first — externalize/split only once this episode's own clean has landed, never another wash
Mechanism Detail
True bill (0o) Every subagent re-carries its room's parcel — fat cost = footprint × (main + every spawn). Session hooks fire on main only, never inside a sub (named platform constraint); tool-level hooks DO follow sub calls, so PostToolUse on the Agent tool silently counts each spawn there, adding the room's cached parcel figure — write-only, no per-spawn output. Surfaces as one clause where the tool already speaks (/coalwash:stats: "subs this session: N spawns ≈ X tok parcel"; the FULL directive numbers); zero spawns = no clause. A washed room cheapens every future spawn automatically — that, not the meter, is the fix
Write guard (0p) Other hands edit the store daily too (a subagent, a stray edit, another tool), so the fidelity gate gets an advisory twin on the write path: an airbag snapshots a file's first write each session made through the file-edit tools (Edit/Write/MultiEdit) — the undo net for gitignored MEMORY.md/CLAUDE.md on that channel only; a Bash-mediated move (mv, sed, a script) takes no snapshot at all. A seatbelt flags a dropped link/number/quote with one FYI line pointing at the snapshot. Never blocks — a deliberate delete is legitimate, so it informs, not gates; a false alarm costs one ignorable line. In a project whose .claude or .claude/coalwash is itself a link (a symlink or junction) no snapshot is taken and nothing is swept through it, and apply refuses loudly, naming the link; a governance or memory file over 4 MiB is no longer snapshotted or content-measured (its @import closure is flagged instead). Reaches inside subagents (tool hooks do), silent on clean edits; recovery copies the real bytes, never an AI re-typing what it thinks was there. A session folder or an entry under the write-guard folder that is itself a link is neither listed nor restored. Quieter: writeGuard: "snapshot-only" keeps the airbag and silences only the seatbelt's advisory. Off: writeGuard: "off"
Recovery bins Every cut lands in an age-and-size-bounded bin: mechanical Quick/Force cuts → the fat bin (30-day horizon), wizard-tier deletes/shrinks → store.old (60-day horizon) — both sized to the owner's ~monthly cadence. Retention: a Time Machine-style ladder (48h untouched, then one-per-day, then one-per-week), bounded by the horizon above or a size cap (the journald/logrotate model, a multiple of the store's own bytes, never the disk: CoalWash can't know your SSD's capacity) — whichever binds first, except the first 48h, a keep-all floor byte pressure cannot cross: a bin whose young items alone overflow the cap grows past it and reports the conflict by name (receipt + death log) instead of silently eating its freshest restore points — the silent resolution the senior schemes it ports default to. Destruction only inside a real wash — never a clock, never a background sweep — only after a verified delete, logged as a one-line death certificate (NIST SP 800-88 Clear-level: a plain, verified delete, not physical-erasure). Pull-only: never pushed to an agent or reloaded into memory
localOnly (trade-secret mode) Quick-only, the semantic tier skipped — agent-honored, not a code-enforced transmission block (can't be weakened by a project config once set globally; full key detail below). Memory is private data; see PRIVACY.md

⚠️ Read before you run it

Caution

System-level scope. CoalWash washes the files that shape your agent's behavior every session — its kernel, in OS terms. Hence the safety stack (snapshot, drop-blocking fidelity gate, plan-only deletes, whole-run rollback — see above). High stakes, capped blast radius.

1 — No calendar cadence, ever. CoalWash triggers on measured BMI, never a clock — a schedule would clean already-lean memory for nothing and re-pay the semantic cost every round. Back-to-back in one sitting? The ceiling is benchmark-derived: the durability campaign ran 7 consecutive Full rounds before retirement, and the published rule is a protocol — stop at two consecutive damage-dry rounds, then one varied-angle sweep before closing (a dry verdict is angle-relative; a fresh lens finds what one angle never will). See the benchmark records; when in doubt, one Full run per sitting is always safe.

2 — Past fat-exhaustion, a model can throw away something load-bearing — like a person can. While real fat remains, cleaning is safe; once none remains, every further semantic pass pressures the meat. Risk varies by model — the benchmark records hold what's measured so far (a per-tier loss matrix is still being built; numbers are bound to the models/versions each dated record names). Structurally, the campaign proved the safety floor is code-held — gates, snapshot, and keeps caught every engineered trap regardless of model; a stronger model found more fat, never lost more fact. The LEAN band makes post-exhaustion runs a no-op — trust its silence.

🧭 Compatibility

Aspect Detail
Validation Cross-agent by design — zero-dependency Node scripts any agent can run, class-B layout discovered per platform, never hardcoded — but validated end-to-end on Claude Code only; every other platform works with CoalWash — designed-degrade-safe, not yet validated; report what you find at Issues. Unknown platform: the agent proposes files it can see auto-loaded in its context, code certifies each, a human confirms — still never auto-delete
Activation ladder Capability-keyed: lifecycle hooks → the gauge runs automatically (Claude Code today); no hooks → a best-effort agent-driven offer is designed, not shipped on a file-copy install (nothing installs the always-loaded instruction it needs); always → manual /coalwash. Band crossings resolve on the Stop hook (the same blocking channel rot-canary uses), so whatever surfaces is enforced, not suggested — edge-triggered, never a repeating nag. A hookless platform sits at manual today
The list is a mirror, not a list CoalWash keeps no hand-maintained inventory of always-loaded memory — the list mirrors the real load list: whatever the platform delivers into the agent's context is class-B, whether company-wired, user-wired, or a future update adds a surface that doesn't exist today. A new auto-loaded file enters the measurement by definition, no code change. On known platforms this runs as a cheap drift-check at wizard entry (agent-seen vs adapter-listed, flagging adapter rot the day it happens); every candidate is code-certified — exists, contained in the home/project trees, on-disk head matches what the agent actually saw load — so a hallucinated or spoofed entry can never join the measurement. Fail direction: undercount — unseen is unmeasured is uncut
A well-behaved guest on your disk CoalWash keeps its own per-project bookkeeping (the session gauge's state) inside the platform's own project directory — on Claude Code, beside the memory folder it measures — so the platform's lifecycle carries it: remove a project, its state goes too, for free. Every path CoalWash derives is realpath-contained to the config root (~/.claude) and fails closed — never a byte outside it. Validated on Claude Code's layout; other platforms get the same one-namespace discipline, designed-for, not yet validated

🚀 Install

Claude Code — one command pair (also wires the session-start gauge):

claude plugin marketplace add TheColliery/CoalWash
claude plugin install coalwash@coalwash

Other agents (Antigravity · Cursor · Codex · Gemini CLI · Cline · Copilot) — file-copy: copy skills/coalwash/ (skill + references) and scripts/lib/ (the engine) into your platform's skill directory, keeping the relative layout (skills/coalwash/SKILL.md resolves the engine at ../../scripts/lib). On Antigravity that directory is ~/.gemini/config/skills/ (global) or <workspace>/.agents/skills/ (per-project). The gauge hook is Claude-Code-only; elsewhere run /coalwash manually. No API keys, no network, no npm install.

Tip

Install globally — CoalWash is a maintenance utility you want available everywhere, and it still operates per-project, per-session. A project config can tune or shut it off locally.

Commands

On Claude Code the plugin ships the three /coalwash… commands; a file-copy install carries

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#agents · #memory · #dev-tools