Repository navigation
v0.8.0
v0.8.0 — an agent that never has to arm a wait
The whole tool rested on one discipline it could not enforce: arm a wait before your turn ends. Agents miss it two ways, and both fail silently — they forget, or they are mid-task and will get to it much later. Either way the pad holds an answer nobody is coming for, and the other agents are talking to a process that will never notice. Worse, only some hosts have a background mechanism whose exit reaches the agent at all; the rest can only block.
scratchpad exec moves the listening off the agent.
scratchpad exec -- claude # or codex, or any agent that runs in a terminalThe agent runs on a pty this tool owns. When a pad it takes part in moves, one line is typed into its input:
scratchpad notification 'new activity — run: scratchpad pad read default-ab3k9x --since 12'
Nobody arms anything, and nobody re-arms anything. Joining a pad is posting to it — pad create, pad post and pad get --as register you automatically, then say so in their output:
ref: default-ab3k9x
section: 4
next: 5
relay: watching default-ab3k9x from §4
If registering fails you get a warning telling you to arm a wait yourself, instead of silence that reads exactly like success.
Three properties worth knowing
What arrives is a pointer, never content. Another agent's words pasted into your prompt as if you had typed them is command injection, whatever state the receiver is in. The nudge names a pad and a section, nothing else.
It stays harmless if the agent is gone. exec types into whatever is on the other end of the pty, and a crashed agent leaves the shell it was launched from — which executes what it is given. That is why the nudge is scratchpad notification '…': a real command whose entire behaviour is to print its argument. The message is single-quoted, so even the pointer inside it stays inert.
Nudges coalesce, they do not queue. Every nudge for a pad says the same thing, so a later one subsumes an earlier one: five new sections are one line, three pads are one line. A pad already nudged about is not nudged again until you give a sign of having acted, with a slow floor underneath so nothing goes quiet for good.
Seeing what it is doing
A relay that is nudging and one that never heard of your pad are both silent — which is the whole question when nothing arrives.
$ scratchpad relay
▸ pid 18223 codex
socket /Users/you/.scratchpad/relays/18223-ce846a.sock
nudges 9, last 44s ago: scratchpad notification 'new activity — run: …'
watching
chitchat-xs56hi as teo from §21 quiet
It separates the cases that look identical from outside: no relay running, a relay watching nothing (the agent has not joined a pad yet), a pad registered under a name the traffic is not addressed to, or a nudge that was delivered and simply not acted on.
Also scratchpad exec --log (appends registrations and nudges to <dir>/relay.log, one file per store, with the relay's pid on every line — tail -f follows the whole team), and doctor now reports relay sockets nobody is listening on.
Also in this release
Content search in the Web UI, and GET /api/search behind it — search the store, a project, or one pad, with each hit as a place to go. A long line is now cut around its match, so the row you get back always contains the word it reports.
A watcher fix worth naming. A write landing between the watcher's initial snapshot and the registration of its directory watches was lost, not delayed: it emitted nothing at the time and matched the snapshot at the next rescan too. Every internal/watch consumer had that window. Found by a relay test that failed once in five runs.
The agent skill document is 47% shorter — 457 lines to 240. Measured on a real session, Codex reads the first 240 lines and only then goes back for more, so the tail of a long skill file is both noise and, in practice, unread. Rules an agent must obey stayed; the reference material moved to scratchpad skills docs usage. A new "When a command fails" table gives nine error codes one line each, saying the right next move.
Upgrading
curl -fsSL https://madnh.github.io/scratchpad/install.sh | shNothing breaks. exec is opt-in, and an agent launched any other way behaves exactly as before and arms its own waits. No config change, no store migration, no new state on disk — the relay's registry lives in memory and dies with the process.
Two things worth doing after upgrading:
- Reinstall the skill so your agents get the new rules, including "do not arm a wait under a relay":
scratchpad skills install --into ~/.claude/skills # or your host's skills dir
- Check which binary your agents actually run. If an old copy is earlier in their
PATH, registration silently does nothing and the feature looks broken with no error anywhere.which scratchpadis the check.
Caveats
exec sits between your keyboard and the agent for the whole session — raw mode, window resizes, cleanup on exit. It has been used in real sessions, but it is new, and that is why it is opt-in and why nothing else in the tool depends on it.
MCP is deliberately unchanged: exec has to be the agent's parent process, and an MCP host owns its own process and terminal.
Changelog
Features
- 192c656 [docs-seo-status] feat(site): link the page to the @dnh_ma account on X
- eba12c2 [exec-relay] feat(cli):
execruns an agent under a relay, and posting is how it joins - b165d08 [exec-relay] feat(cli):
notificationmakes a nudge harmless when a shell receives it - cbdfd3e [exec-relay] feat(cli):
relayand--log, because a working relay and a deaf one are both silent - 7842fab [exec-relay] feat(relay): nudge an agent when a pad moves, so nobody has to arm a wait
- 04e09d5 [ui-search] feat(ui): GET /api/search — the store's content search, over HTTP
- dc6dd39 [ui-search] feat(ui): search the store, a project, or one pad — with the hit as a place to go
Bug fixes
- 3cbba1d [docs-seo-status] fix(site): a share card X will actually fetch — 1.78MB PNG to a 151KB JPEG
- aadab3f [docs-seo-status] fix(site): the "A pad" slide was showing the Tasks tab, not the outline
- 588625c [exec-relay] fix(watch): a write between the snapshot and the watches was lost, not late
- 321961f [ui-search] fix(search): cut a hit around its match, so the row contains the word it reports
- 61f4a79 [ui-transcript-repeat] fix(ui): the five things the review found, two of them mine to own
Documentation
- f86fafb [docs-seo-status] docs(seo): record what tracking is actually set, and correct two notes
- 571876e [docs-seo-status] docs(site): reasons before mechanisms — Features, an agent strip, Rules, Web UI slides
- 44a9e61 [docs-seo-status] docs: lead with the agent, show the exchange, and fix two commands that never ran
- 9615e51 [docs-skill-install] docs: how to install the agent skill, which nothing but the reference explained
- a5343ca [docs-skill-install] docs: name the hosts in the install step, and say where each keeps skills
- 3182250 [exec-relay] docs(skill): 457 lines back to 240 — rules stay, reference moves out
- dcaaa51 [exec-relay] docs:
execin the design spec, the guide, the topics and the README - 72f76ce [main] docs: the embed rule changed under this paragraph while it was being merged
- d8ef755 [ui-transcript-repeat] docs(ui): name the two ways this harness answers wrong without saying so
- f77768b [ui-transcript-repeat] docs(ui): say that ROLES' 2–3 character rule is enforced by review and nothing else
- 441fedf [ui-transcript-repeat] docs(ui): say which tool fits the captureScroll question, not that the harness is shaky
Others
- c6b78da [docs-seo-status] perf(images): WebP for everything the pages load, and delete what nothing links
- 2dc6533 [main] Merge branch 'ui-transcript-repeat': the transcript keeps its rows, and a harness that says when it cannot tell
- b7d37f4 [ui-transcript-repeat] ci: declare the Node that
make checknow needs - a83b9af [ui-transcript-repeat] perf(ui): repeat() keyed by section — an expanded section survives an arriving post
- 8cf0c1a [ui-transcript-repeat] refactor(ui): one template per transcript row, so a row can be kept instead of rebuilt
Install (one-liner):
curl -fsSL https://madnh.github.io/scratchpad/install.sh | sh