Command-line interface
Scratch ships a small headless companion called scratch. It reads and writes the same Markdown buffers the app uses, from a shell, a script, or an agent. No daemon, no API — just files on disk, opened atomically, with frontmatter preserved. The app does not need to be running, and if it is, changes flow back in through the live file watcher.
Install
The CLI lives in this repo at packages/scratch-cli. Link it once and the scratch command is on your PATH:
pnpm --filter @repo/scratch-cli link --global
Run scratch help to confirm the install.
Where buffers live
The CLI resolves the buffers directory in this order:
SCRATCH_BUFFERS_DIR— environment override. Highest precedence, useful for scripts and tests.general.buffersDirfrom Scratch’ssettings.json— if you relocated the folder in Settings → General → Buffer location, the CLI follows.- The default —
~/Library/Application Support/Scratch/bufferson macOS.
scratch path with no arguments prints the resolved directory.
Commands
| Command | What it does |
|---|---|
scratch new [--title <t>] [--stdin] | Create a new buffer. With --stdin, seed the body from standard input. |
scratch list [--json] | List buffers, newest first. |
scratch read <id|latest> [--raw] | Print the buffer body. --raw includes frontmatter. |
scratch write <id|latest> [--stdin] | Replace the buffer body from standard input. |
scratch append <id|latest> [--stdin] | Append standard input to the buffer body. |
scratch title <id|latest> <title> | Set a manual title. |
scratch search <query> [--json] | Substring search across titles and bodies. |
scratch path [<id>] | Print the absolute path to the buffer file, or the buffers directory if no id. |
scratch help | Show usage. |
Identifiers
Buffer IDs are a 13-digit millisecond timestamp plus a 6-character hex suffix — for example, 1717272000000-a1b2c3. They sort lexicographically by creation time. The literal latest resolves to the most recently modified buffer, which is usually what you want from a shell.
Piping and stdin
The --stdin flag opts a command into reading from standard input. Without it, new creates an empty buffer and write empties the body.
echo "meeting notes" | scratch new --stdin
pbpaste | scratch append latest --stdin
scratch read latest | grep -i todo
Frontmatter and atomic writes
Every write goes through a temporary file and is renamed into place, so a running Scratch app sees a single consistent change rather than a partial file. Existing frontmatter — title, title source, and any unknown keys — is preserved by append and write. Only the body changes.
Use with agents
The CLI exists partly so a coding agent can leave you a note without taking over your editor. A common pattern:
echo "summary of what I just did" | scratch new --title "agent log" --stdin
The buffer shows up in your list the next time you summon Scratch.
See also
- The buffer — how buffers work in the app.
- General settings — where to relocate the buffers folder.