Putting your repos on it
Run the wall, wire it to the agents on your machine once, and every repo you work in is on it the first time something renders.
Run the wall
macOS. Homebrew is the way in, and it brings its own Node:
brew install orochi235/tap/transom
transom install # starts the wall under launchd
launchd keeps it running across logins and restarts; transom stat
says whether it answers, and transom cycle restarts it.
To hack on it, run it from a clone instead. That needs Node 22.18 or newer:
git clone https://github.com/orochi235/transom
cd transom
npm install
npm run dev
The client is at localhost:7750 and the daemon at
localhost:8787, watching ~/transom/inbox/. Put it on the monitor
you do not type on.
Wire it to your agents
Once per machine, and again after you change anything here — it is idempotent.
From a clone it is bin/transom wire.
transom wire # --dry says what it would change
# --off takes it all back out
It puts three things where an agent will meet them:
-
The skill, symlinked into every
~/.claude*/skills/. It tells an agent how to send, how to diagnose a render that never arrived, and how to except a repo. -
The wall-nudge hook, a
PostToolUseentry in eachsettings.json. It fires when an agent reads or creates an image that never reached the wall and hands the model a one-line correction, which is what stops renders dying in a scratch directory. -
transomon PATH, symlinked into~/.local/bin. Without it an agent that half-remembers the rule typestransom post chart.png, getscommand not found, and goes back to reporting a file path.
A session that was already running keeps the hooks it started with, so a live one is not
evidence that wiring failed. transom wire also prints a rule for your
CLAUDE.md and leaves you to paste it: that file is hand-written prose, and a
tool that rewrites preferences fights their author.
A repo needs no setup
A zone is one pile on the wall, and the zone is the directory name of the repository you
ran in. Nothing has to register a project: the first send creates its zone, and
bin/transom records which directory the renders came from so the daemon can
read that project’s .hued file and paint the pile in its color.
transom post render.png # the zone is this repo
transom post --zone icons sheet.png # or say where it goes
some-generator | transom post # a pipe is a send too
What a send can carry
Every flag is optional, and the file alone is the whole protocol. These are the ones worth knowing on the first day:
transom post --ttl 5m draft.png # how long it lives
transom post --caption "after the fix" a.png
transom post --attention soon broken.png # or look, urgent, problem
transom ask "which crop reads better?" \
--choice left --choice right crop.png
transom ask puts the question on the card, waits, and prints the answer, so an
agent can stop and ask you something about a picture instead of guessing. Groups of
pictures share one card with --group; video, self-contained HTML pages and
.glb/.stl meshes land as cards whose lightbox plays, runs or
orbits the real thing.
Settings for one repo
A .transom.yaml at the repo root changes what a send from that repo does. It
is committed with the repo, and every key is optional; a flag on
transom post still beats it. Inside the repo:
# write a starter, or check the file
transom wire --repo
# remove a starter nobody edited
transom wire --repo --off
zone: icons # not the directory name
show: preview # open locally, skip the wall
defaults:
ttl: 30m
apps: [LDView] # “Open in LDView”
attention:
loudest: soon # louder sends are lowered
sound: false
The file’s first line points your editor at
the schema, which completes the keys and flags a
wrong one. transom post checks it too: a file with a mistake in it stops
the send and names each problem rather than being quietly ignored.