coat-of-many-colors

Stitches what your agents left behind into one thing you can read.

Agents leave scraps everywhere — logs, diffs, notes, results — and then you're the one who has to work out what actually happened. coat collects the scraps, records where each one came from at the moment it was made, and stitches them into a single self-contained HTML page.

$ coat install
🪡 wired PreToolUse, PostToolUse, Stop in .claude/settings.json
   agents work, coat collects, coat.html lands when the session stops

Then work. Nothing to prefix, nothing to remember:

$ coat patches
  1  linter       autocorrect
  2  refactorer   harden the parser

$ coat seams
🪡 1 seam, 1 open
   ✗ lib/parser.rb  ←  linter, refactorer

$ coat mend lib/parser.rb --note "kept the refactorer's version"
🪡 mended lib/parser.rb  ←  linter, refactorer

$ coat build --title "Overnight run, 26 August"
🧥 coat.html — 4 patches, 0 of 1 seams open

Install

gem install coat-of-many-colors

The words

  • A scrap is raw agent output. On its own it's noise.
  • A patch is a scrap with its provenance still attached — what ran, where, how it exited, what it touched. That's the unit the coat is sewn from.
  • A seam is where more than one source laid a patch over the same ground. coat finds seams; it does not resolve them.
  • A seam is mended when a person says it's settled. Only a person can: coat can see that two agents disagreed, not which one was right.

Commands

Command What it does
coat install Wire the hooks so you never type the rest of this table
coat add --from CMD Run CMD, keep its output as a patch
coat add --file PATH Take an existing file as a patch
coat pin Mark where the working tree stands, for --since
coat patches List the scraps collected so far
coat seams Where two sources touched the same ground
coat mend PATH Say that seam is settled
coat build Stitch the coat into one HTML file
coat verify Walk the hash chain and report the first break
coat hook Read one Claude Code hook payload on stdin

Options for add: --label TEXT, --agent NAME, --claims A,B, --cwd DIR, --cmd CMD, --exit N, --since [KEY]. Options for mend: --by NAME, --note TEXT. Options for install: --settings PATH, --tools LIST. Options for build: -o PATH, --title TEXT.

Let the harness do the typing

coat install writes three hooks into .claude/settings.json, all of them the same command:

Hook What it does
PreToolUse Pins the working tree before the tool runs
PostToolUse Adds what the tool produced, and asks the pin what moved
Stop Stitches the coat

By default it watches Task, so you get one patch per subagent — coarse enough to read, fine enough for seams to mean something. --tools 'Task|Bash' gets you a patch per shell command too, and a much longer coat.

Everything already in your settings file is left alone, and installing twice does nothing the second time.

A hook never fails the work it is watching. If coat can't make sense of a payload it says so on stderr and exits zero.

Provenance the harness hands over

coat add --from runs the command, so it knows everything first-hand. A hook fires after the tool has run, so it can only be handed the result. Those are different, and the ledger says which: a captured patch is recorded as "kind":"captured", never as something coat watched happen.

Captured patches claim nothing by default — text can't know what it touched. That's what coat pin is for: pin the working tree before, ask --since after.

coat pin
# ... something else does the work ...
coat add --file /tmp/agent.log --cmd "claude -p 'harden the parser'" --exit 0 --since

Provenance is captured, not reconstructed

coat add --from runs the command itself. That's the whole point — the command, the working directory, the exit status, the duration, the output, and its SHA-256 are all recorded at the moment the scrap is made. Nothing is inferred afterward from a file lying around, because after the fact you can only record what you can guess.

Everything lands in .coat/ledger.jsonl, append-only, one JSON object per line, each entry carrying the hash of the entry before it:

{"ts":"2026-08-26T04:12:03Z","event":"patch","label":"autocorrect","agent":"linter","kind":"command","cmd":"bundle exec rubocop -A","exit":0,"duration_s":6,"body":"0001-autocorrect.txt","body_sha256":"9c2…","claims":["lib/parser.rb"],"seq":1,"prev":"000…","hash":"a1f…"}

A coat is evidence of what your agents did. Its provenance should be at least as hard to quietly rewrite as the work it describes. coat verify walks the chain and tells you the first entry that doesn't hold.

Seams, and mending them

If two different agents touch the same file, that's a seam. coat shows both patches, marks them, and lists the seam at the top of the document.

It does not pick a winner. Surfacing the disagreement is the value; deciding who was right is a judgment call a tool has no business making.

Which is why a seam stays open until you say otherwise:

coat mend lib/parser.rb --note "kept the refactorer's version"

That lands in the same chained ledger as everything else — {"event":"mend"}, with your name and the time on it. It's the one entry in a coat a person makes rather than a tool, and the document draws the difference: an open seam is double-stitched in red thread, a mended one is stitched shut and goes quiet. The contested path stays marked either way. The disagreement still happened.

Mending the same path twice is a correction, not a second seam — the latest word wins.

Claims come from git — coat digests the contents of everything git reports as changed, before and after the command. Content, not git status codes: a file an earlier agent already dirtied stays M no matter how many more agents rewrite it, so status codes can't see the second edit, which is the exact case this feature exists for. Outside a git checkout, pass --claims.

The PATCHWORK style

The output has its own look, and the metaphor does real work in it:

  • Every patch is bordered with a running stitch — a dashed seam in thread color.
  • Every source keeps its own color, derived from a hash of its name, so the same agent is the same color in every build on every machine. Color is provenance; the header strip doubles as the legend.
  • An open seam is double-stitched in red thread, with the contested path underlined wavy in the metadata. A mended one is stitched shut in plain thread and says who settled it.
  • A command that exited non-zero is torn, not hidden. A failed step is still evidence.
  • Warm linen background, woven texture drawn in CSS, serif body, mono for anything a machine wrote. Light and dark, honoring both prefers-color-scheme and an explicit data-theme override.
  • Every coat opens with a line from Dolly — a saying or a single lyric, picked at random per build.

One file, no build step, no external requests. See example.html.

Development

bundle install
rake test

In memoriam: Dolly Parton

Named for Coat of Many Colors, which she wrote in 1971 on the back of a dry-cleaning receipt from Porter Wagoner's suit, on the tour bus. She has called it her favorite of everything she wrote.

It's about a coat her mother sewed out of rags people had given the family, telling her the story of Joseph while she stitched. Dolly wore it to school proudly and the other children laughed at her for being poor.

The scraps were never the point. The stitching and the story are what made them worth something. That's the whole thesis of this tool: a fragment of agent output on its own is noise, and a fragment with its origin still attached is evidence.

It's written in Ruby because Dolly was a gem.

She wrote thousands of songs, and that's the part everyone knows. The rest of it deserves saying too:

  • The Imagination Library, founded in 1995 in honor of her father, who never learned to read. It mails a free book every month to any enrolled child from birth to age five. It has given away well over 200 million books and now runs across the US, Canada, the UK, Ireland, and Australia.
  • A million dollars to Vanderbilt University Medical Center in April 2020, which helped fund the research behind Moderna's COVID-19 vaccine. Her name is in the acknowledgments of the paper.
  • The My People Fund. After the 2016 wildfires tore through Sevier County, she paid $1,000 a month for six months to every family that lost a home — roughly 900 households — and closed it out with a larger final check.
  • Dollywood and the Dollywood Foundation, which turned her hometown corner of the Smokies into one of its largest employers, and whose Buddy Program cut the local high school dropout rate by paying students to keep each other in school.
  • She turned down the Presidential Medal of Freedom. Twice. She said she didn't feel she'd earned it.

She also acted — 9 to 5, Steel Magnolias, The Best Little Whorehouse in Texas — and kept the publishing rights to her own catalog at a time when almost nobody in Nashville let a woman do that.

Keep the scraps. Keep the story with them.

License

MIT. See LICENSE.txt.