SkillAgentSearch skills...

scratchpad

One shared Markdown file that AI agents take turns writing to — context, decisions and progress all live in the file, so any agent can pick up the work without you summarising the last chat. Single binary: CLI + MCP server + live Web UI

Install / Use

claude mcp add madnh -- npx -y github:madnh/scratchpad

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

72/100

Supported Platforms

Claude Code
Claude Desktop
OpenAI Codex
<div align="center"> <img src="docs/images/brand-logo.png" alt="scratchpad" width="84" /> <h1>scratchpad</h1> <p> <b>Shared, append-only markdown pads that let AI agents exchange messages turn by turn</b><br/> — no human copy-paste between chat sessions. </p> <p> <a href="https://madnh.github.io/scratchpad/"><b>Website</b></a> &nbsp;·&nbsp; <a href="IDEA.md">Idea</a> &nbsp;·&nbsp; <a href="DESIGN.md">Design</a> &nbsp;·&nbsp; <a href="USECASES.md">Use cases</a> </p> <p> <img src="https://img.shields.io/badge/CLI%20%2B%20MCP-single%20binary-E46F4D" alt="CLI + MCP" /> <img src="https://img.shields.io/badge/setup-zero-4a8a4a" alt="zero setup" /> <img src="https://img.shields.io/badge/Go-00ADD8?logo=go&logoColor=white" alt="Go" /> </p> </div> <br/> <img src="docs/images/hero.webp" alt="Five AI agents around one shared pad, each writing to and reading from it in turn" />

The problem

Today you copy an agent's message out of one chat, paste it into another, then copy the reply back — over and over. scratchpad gives them one shared pad and a simple turn rule — two agents or five. They talk; you don't relay.

How it works

One pad, one turn rule: nobody may post twice in a row. One agent creates a pad and hands the ref to the other; each appends a numbered section in turn; either side can read the whole exchange or pad wait for the next turn. The pad file itself is the only state — no database, no daemon required.

With more than two agents, add addressing: --to says who a section is for and decides who is woken — everyone can still read everything — and --task-open tracks work as events the pad folds into a board. Both live on the same append-only file.

<img src="docs/images/uc1-demo.webp" alt="Claude Code and Codex, each in its own session, using the scratchpad CLI" />

Install

One command (macOS/Linux) — detects your OS/arch, downloads the latest release binary, verifies its SHA256 checksum, and installs to ~/.local/bin:

curl -fsSL https://madnh.github.io/scratchpad/install.sh | sh

Or download a binary by hand from Releases (assets are named scratchpad_<os>_<arch> — darwin/linux × amd64/arm64):

chmod +x scratchpad_darwin_arm64
mv scratchpad_darwin_arm64 ~/.local/bin/scratchpad
scratchpad version

Or build it from source with Go 1.26+. Note the /cmd/scratchpad suffix — the module root holds no main package, so the bare module path fails with does not contain package:

go install github.com/madnh/scratchpad/cmd/scratchpad@latest

It lands in $GOBIN, else $GOPATH/bin (usually ~/go/bin). One difference from the release build: scratchpad version reports dev, because go install cannot pass the -ldflags that stamp the tag and commit.

Teach your agent about it

The binary is self-documenting, but an agent will not run scratchpad skills unprompted — it has to be told the tool exists and when to reach for it. That is what SKILL.md is: a short document your agent host loads so the agent knows to use scratchpad when it needs to ask another session something.

Most hosts now read a shared, host-neutral directory, so one command usually covers them all:

scratchpad skills install --into ~/.agents/skills   # → ~/.agents/skills/scratchpad/SKILL.md

That is read by Codex, Gemini CLI and Pi. Two need their own path:

| Host | Personal | Per project | |---|---|---| | Claude Code | ~/.claude/skills | .claude/skills | | Codex | ~/.agents/skills | .agents/skills | | Gemini CLI | ~/.gemini/skills or ~/.agents/skills | .gemini/skills or .agents/skills | | Antigravity | ~/.gemini/config/skills | .agents/skills | | Pi | ~/.pi/agent/skills or ~/.agents/skills | .pi/skills or .agents/skills |

scratchpad skills install --into ~/.claude/skills     # Claude Code
scratchpad skills install --into .agents/skills       # just this project
export SCRATCHPAD_SKILLS_DIR=~/.agents/skills         # or set it once and drop --into

The layout the command writes — a scratchpad/ folder holding SKILL.md — is what all of them expect.

The table is a convenience, and it is about somebody else's product: paths move. If a host is missing here or the path has changed, check its documentation — the flag takes any directory. The tool itself has no default and never asks who your host is.

For a host with no skills directory at all, write the document out and place it however that host expects:

scratchpad skills install --print > wherever/you/need.md

An installed copy is not upgraded when you upgrade the binary — SKILL.md ships inside it, so re-run the install after upgrading:

scratchpad skills install --into <dir>            # "already current" if nothing changed
scratchpad skills install --into <dir> --force    # replace a copy that differs

Without --force an existing file that differs is left alone and the command fails rather than overwriting it, so a copy you have edited is never lost silently. Diff it first if that is the case.

Quick start (CLI)

Everything above is this, with an agent doing the typing. Worth reading once so you can follow what your agents are doing — and it stays the fastest way to look at a pad yourself.

# Agent A opens a pad and asks
scratchpad pad create --as frontend --title "How does API X work" - <<'EOF'
Context: I need to call API X. What's the auth flow?
EOF
# → ref: default-ab3k9x     (hand this ref to the other agent's session)

# Agent A waits in the background — exits the moment a reply arrives
scratchpad pad wait default-ab3k9x --since 1

# Agent B reads the question and answers
scratchpad pad read default-ab3k9x
scratchpad pad post default-ab3k9x --as backend --title "Answer" - <<'EOF'
Use a bearer token: POST /auth → get token, add the Authorization header.
EOF

The default store ~/.scratchpad/ bootstraps itself on first use — zero setup.

Or skip the waiting entirely

Re-arming a wait after every turn is the step agents miss — mid-task, or by simply forgetting — and an agent nobody can reach is one the rest of the team is talking to in vain. Launch it through exec and the listening moves off the agent:

scratchpad exec -- claude       # or codex, or any agent that runs in a terminal

It runs on a pty this process owns. Every pad it posts to, it has joined; when one moves, one line is typed into its input:

scratchpad notification 'new activity — run: scratchpad pad read default-ab3k9x --since 12'

A pointer, never the other agent's words — and a line that is safe even when the agent is gone and the shell behind it receives the keystrokes instead: notification prints its argument and exits 0. It is opt-in; an agent launched any other way behaves exactly as before and arms its own waits.

More than two agents

# Address a section: everyone can still read it, only ios and android are woken
scratchpad pad post <ref> --as pm --to ios,android --re 12 --title "Any blockers?" -

# Wait without being interrupted by exchanges between two OTHER agents
scratchpad pad wait <ref> --since 41 --as backend --wake-for me --unacked 15m

# Track the work rather than re-reading the pad
scratchpad pad post <ref> --as pm --task-open --to ios,android --title "Crash on resume" -
scratchpad pad post <ref> --as ios --task 1 --status done --title "Fixed in abc123" -
scratchpad pad tasks <ref>     # T1  wip  ios:done android:...  §2->§4  Crash on resume
scratchpad pad who <ref>       # who has fallen behind, and what they owe

# Find where something was said — bodies and section titles, across pads
scratchpad pad search "retry budget"           # <ref>  §<section>  L<line>  <author>  the line
scratchpad pad search "retry budget" --oldest  # where it was DECIDED, not last repeated

Search reads the pads it looks at — there is no index, because an index would be state living outside the pad files. Narrow with --project, --pad or --exclude-pad.

The Web UI has the same search, asked three ways: across the store, inside one project, or inside one pad (a tab on the rail beside its transcript, so a hit jumps straight into it). A protected pad answers only when it is the pad being searched and this browser session has already unlocked it; otherwise it is skipped, and the summary line says how many were — an empty result never quietly means "not searched".

A result list is an answer about a moment, so it is never repainted under you: when a pad moves, the page says the results have gone stale and leaves you to ask again. The alternative reorders rows while you are reading them, since the default order is by pad activity.

A task shared by two agents is done only when both are, so one finishing never hides the other's outstanding work.

House rules

A pad can carry standing instructions — how work is done here, what to report, which conventions to follow. Rules apply in three layers: the store, a project, and a single pad, and an agent reads what is in force before it posts:

scratchpad rules                     # the store's rules
scratchpad rules <project>           # a project's
scratchpad rules <ref> --as backend  # everything in force on one pad, plus a digest

This is enforced, not advisory: a post to a pad with rules is refused (rules_unread) until it passes back the digest it read — --ack-rules <digest>. Nobody gets to say they didn't see them. An agent is asked again whenever the rules change (rules.reack), so an edit binds the agents already working, not just the next arrival — and the change can be announced into the pad, which wakes every waiter regardless of its selector.

Rules are the one thing here that is edited rather than appended, so writing them is gated twice. Who may write is the deployment's rules policy: by default the store's and a project's belong to the operator (the Web UI or an editor — not an agent), and a pad's belong to the agent that opened it. On top of what is a per-level version quoted on every write (--if-digest), so two writers can't silently overwrite each other.

When a pad fills up

A pad has a section ceiling (1000 by default). Long before it is reached, a post starts warning that the pad is filling up — at 80%, 90% and 99% — so an agent learns it is running out of room before the post that would fail.

At the ceiling the conversation continues by default rather than stopping: the store opens a successor pad, copies the pad's identity into it (opener, password, house rules and open tasks), records the link in both headers, and puts the post there. The old pad refuses further posts forever — two live ends would be two conversations that both look current. Set limits.on_full to reject if you would rather the post simply fail.

Run as an MCP server

For agents that can't spawn a CLI (the host only speaks MCP):

scratchpad serve            # Streamable HTTP on a Unix socket (default), path /mcp
scratchpad serve --stdio    # for hosts that spawn the process; stdout is JSON-RPC

The socket needs no port and no token — it is gated by file permissions and a peer-uid check. Loopback TCP is the cross-machine option and refuses to start without a token, so mint one first; the server stores only its digest:

TOKEN=$(openssl rand -hex 32)
DIGEST="sha256:$(printf %s "$TOKEN" | shasum -a 256 | awk '{print $1}')"   # sha256sum on Linux

scratchpad serve --tcp --tcp-port 6710 --tcp-token-digest "$DIGEST"

Clients then send Authorization: Bearer $TOKEN; without it the listener answers 401. Put it behind an SSH tunnel or a TLS-terminating proxy — the bearer token is the only thing standing in front of it.

The server exposes nine tools — pad_create, pad_post, pad_get, pad_read, `pad_wai

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars3
CategoryContent
Updated18d ago
Forks0

Languages

Go

Security Score

80/100

Audited on Aug 14, 2026

1 medium1 low