Skip to content

What's New

  • Three ways a queued message could be silently lost are fixed. The queue — the chip holding what you type while a turn runs — deduped on a timestamp from your browser, so one fast clock destroyed every later queued message on that chat. It also drained from only one of the eight places a turn can end, so anything queued behind a /compact, a trigger or a background sub-agent sat stranded until a later message flushed it.
  • A second tab merges instead of overwriting. The queue is one shared slot per chat. Previously a second window replaced the first one’s message, and that client then watched someone else’s text appear as though they had typed it.
  • Stop returns your queued message to the composer rather than sending it.

0.66.0 — Config screen, and a new default port

Section titled “0.66.0 — Config screen, and a new default port”
  • The instance Config screen is now navigable. Forty-seven settings that rendered as one 5,508-pixel column get a section rail with counts and scroll-spy, a live filter, and a Modified only lens. It follows VS Code’s settings screen rather than tabs, and that is the argument: tabs partition, which is exactly what defeats a search. The filter matches labels, keys, help text and environment variable names. Env-overridden settings carry a chip, explained once in a legend rather than beside twenty fields.

The redesigned instance Config screen: a section rail with per-group counts down the left, a live filter and Modified-only toggle across the top, an env-override legend, and a dirty dot marking the one group holding an unsaved edit

One document, filtered and jumped. Searching by environment-variable name is the case tabs would have made impossible.
  • Breaking: the default port moves from 4000 to 7233. Setting PORT, port: or --port changes nothing. If you rely on the default, update your reverse proxy, docker run -p, Kubernetes targetPort and SSH tunnels — or pin PORT=4000.
  • Both on-disk formats declare a schemaVersion. An older build used to drop keys it didn’t recognise and write the file back without them. A config file from the future now refuses to start; a project file is skipped loudly. Nothing on disk changes — the current shape is version 1.
  • Deleting or reverting a chat stops the turn first. claude writes the transcript itself, so unlinking it mid-turn didn’t delete the chat — the live process wrote itself back, stripped of history. Promote lost it from both projects.
  • The UI says “adopt” rather than “import” — where the transcripts are your own ~/.claude, the sessions offered are already there and the action only registers them. Your originals are never moved or deleted.
  • A running sub-agent keeps its place in the bar. Backgrounded sub-agents pair within milliseconds, so one was stamped with a final duration that kept climbing.
  • On driveMode: batch only, deleting the chat you just finished no longer misfiles your next message into a new session.
  • An agent can convert its own notebook project to a repo-backed one. Without an MCP verb it had to stop and ask, or create a second project and abandon the first — losing every chat in it. promote_project clones, re-points the working directory and re-registers against the existing chat store. A failed clone rolls back.

0.64 — Linked directories, managed and unmanaged

Section titled “0.64 — Linked directories, managed and unmanaged”
  • path: links a directory that already exists, used in place. No copy, no clone: your checkout keeps its history, branches and remotes. Paddock writes nothing into it, and deleting the project never touches it.
  • Two axes replace one flag. Managed means Paddock curates the project’s own files; unmanaged means you version-control the content yourself. Whether a git repo sits behind it is a separate question. repoBacked is removed from the API response.
  • The Changes tab reports on the code, not the notes — it had been reading the metadata directory.

0.63 — Host plugins and MCP server fidelity

Section titled “0.63 — Host plugins and MCP server fidelity”
  • A plugin installed in Claude Code now works here. Sharing instructions brings its commands, agents and skills; sharing MCP servers brings its servers too, each allow-listed automatically — without that they connect and have every call denied with no prompt.
  • headers and type on an inherited MCP server are carried through rather than stripped, which matters because a stored OAuth token is keyed on a hash including both.
  • On driveMode: batch, a credential declared in mcpServers: is readable in process arguments by any local user while a turn runs. Paddock can’t fix this from its side, so it warns at startup. The default session mode is unaffected.

0.62 — Granular host Claude inheritance options

Section titled “0.62 — Granular host Claude inheritance options”

Paddock sits next to Claude Code state you already have: transcripts, a login, an MCP server or two, a curated CLAUDE.md. Until this release it reached all of that through one lever — which Claude home it pointed at — so moving it for one reason changed four others. That is how a single week produced data loss, an invisible macOS login, and a delete that destroyed real terminal history.

  • Five independent keys, each answering whose X does this instance use?

    claude:
    transcripts: own # own | host — default own
    credentials: host # own | host — default host
    instructions: own # own | host — default own
    hooks: own # own | host — default own
    mcpServers: own # own | host — default own

    own is Paddock’s, isolated inside the data dir; host is this machine’s Claude Code. Omit the block for full isolation apart from your login. What Paddock touches on your machine states the guarantee in one place.

  • ⚠️ If you keep a curated ~/.claude/CLAUDE.md, read this one. instructions defaults to own, so your user-level CLAUDE.md, agents/, commands/ and plugins/ are not loaded; every release before 0.62 bridged them in unconditionally. Set instructions: host to keep the old behaviour. Each project’s own CLAUDE.md is loaded in every mode and is unaffected. The change bites on the CLI paths — the sweeper, triggers and driveMode: batch — where those files did still apply. (0.64 raised the startup notice to a warning, so you are now told.)

  • Host settings.json hooks no longer run inside Paddock turns. Every hook you had ever configured used to run here with no way to turn it off. hooks: host restores them; the rest of that file still applies either way.

  • Your own MCP servers can reach Paddock two ways. claude.mcpServers: host attaches what is already in your ~/.claude.json. A sibling mcpServers: block declares servers to Paddock itself — the answer for a container with nothing to borrow — where env:VAR_NAME references keep tokens out of a git-tracked file.

  • Deleting a shared chat releases it instead of destroying it. Under transcripts: host a Paddock chat and a claude --resume in the same directory are the same file, so delete no longer means rm — the transcript is your history, not Paddock’s copy.

  • CLAUDE_HOME and --isolated-claude-home are removed, replaced by the block above. CLAUDE_CONFIG_DIR still works as “put Paddock’s home here”, but a value resolving to your ~/.claude is now a startup refusal rather than a silent re-coupling. No migration needed.

Section titled “0.61.1 — CLI login, and symlinks into your Claude home”
  • Paddock no longer plants anything in a Claude home it doesn’t own. It used to redirect a directory’s transcripts by replacing ~/.claude/projects/<encoded-dir> with a symlink to the workspace’s .chats/. It skipped directories you already had history in, but not empty ones — which is exactly what --here is usually pointed at. From then on every claude session in that directory was written into Paddock’s store, so deleting .chats/ took real history with it. One person lost 30 transcripts this way.

  • On a Mac, your existing Claude Code login works again. Claude Code files its Keychain entry under a name derived from whether CLAUDE_CONFIG_DIR is set, so once Paddock pointed at its own Claude home a perfectly good login went invisible and every turn failed with Not logged in. A Keychain entry can’t be bridged the way a .credentials.json can, so with no token in your environment the CLI now runs against your own ~/.claude. (0.62 removed --isolated-claude-home; claude.credentials and claude.transcripts decide this now.)

  • A first run with no credentials prints a message, not a crash. It used to emit several screens of stack trace containing the whole sweeper system prompt, four times, with the useful line forty lines down.

  • Transcripts move out of ~/.claude into Paddock’s data directory. They were the last state living outside it, reached by planting symlinks into your Claude home — and the code doing that would, on every agent registration, copy your transcripts out and delete the originals, inside a bare catch. Paddock now keeps its own home under the data dir and only ever reads ~/.claude.

  • Four turn-level fixes. Appending to a queued message no longer discards the addition; Stop works on a /compact, where slash-command turns had never registered a cancellable id; marking the chat you are reading as unread survives its own turn landing; and the sidebar stops flashing to skeletons twice per turn.

  • Paddock is MIT licensed, and the packaging now says so. There was no licence file and no license field, while the publish script defaulted it to MIT — so every release told npm one thing while the source granted another.

0.59.1–0.60 — npx install, --here, and confirmed adoption

Section titled “0.59.1–0.60 — npx install, --here, and confirmed adoption”
  • npx @edspencer/paddock starts an instance in one command — server, web UI and Claude Code runtime, no Docker and no clone. It starts quiet, says where it put your data, and warns up front rather than failing on the first turn.

  • --here opens the directory you are standing in as the workspace, rather than creating a project somewhere else. It creates .paddock/ for state and .chats/ for transcripts and adds both to your .gitignore; later runs resume with no flag. The model is git init, with .paddock/ as .git.

  • Adoption asks before it takes anything. The old button imported everything on one click and could not be undone. It now opens a dialog listing candidate sessions grouped by source directory — the source path being the detail that makes “these are from a scratch copy, not my checkout” visible before you commit — and a successful adoption offers Undo.

  • It stops offering chats that were never yours. Paddock’s own curation runs were being offered as terminal history, and a same-named directory anywhere on disk counted as your checkout; a repo-backed project now requires the git remotes to match.

  • Published with provenance — releases go to npm from CI through OIDC trusted publishing, with a signed attestation tying each version to the commit.

  • The CLI got quiet and explains its failures. A first run printed about thirty lines of boot logging, scrolling the URL you wanted off the top; it now prints nine, with --verbose to opt back in. --open launches the browser once the server is listening, a port clash is a sentence rather than a stack trace, and --help says where your data lives.

  • Paddock tells the agent what it is rendering into. It injected no system prompt of its own, so Claude ran on its stock preset — written for a terminal. Nothing said that replies render as Markdown in a browser, that a bare #123 is dead text, or that a tool exists to put an image on screen. An audit of the hundred most recent chats on the dogfooding instance found 4,440 bare #123 references against 155 markdown links, and 194 images read with none ever shown to the user.
  • Two rules, and you can replace or silence them. Show, don’t describe, and make clickable things clickable. Set environmentPrompt: to your own text to replace it, or to an empty string to append nothing.
  • npx @edspencer/paddock — no Docker, no clone. The package is synthesised from built output rather than being a workspace package, so no future publish can fire an internal package at the registry. Source maps are stripped, taking it from about 22 MB to 2 MB.
  • The claude CLI was never a prerequisite for chats, whatever CONTRIBUTING.md said — they run through the SDK, which resolves its own bundled binary. Only the sweeper, triggers and driveMode: batch shell out.
  • PADDOCK_SCRATCH_DIR is gone, and an instance still setting it boots and ignores it. Paddock reads config by name rather than validating a schema, so a removed key is never looked at — and a typo’d key is equally silent.
  • Bring the terminal claude history you already have into a project. When a workspace has adoptable sessions, a button appears above its chat list; one click and they arrive, carrying an Adopted badge and their original timestamps, so a conversation from three weeks ago sorts where it belongs rather than collapsing to “today”. Your ~/.claude history is copied, never moved. The count is live rather than a dismissable prompt, and there is a headless equivalent for when the transcripts and the server don’t share a filesystem.
Seven terminal sessions adopted into a project in one click. The dates are the original ones — imported chats sort by when the conversation really happened, not when you imported it.

An imported chat open in Paddock. Every row in the chat list carries a small terminal icon marking it as imported, and the message box below reads "Message Claude…"

  • Detection is forgiving about where your checkout lives. A repo-backed project matches any transcript folder whose recorded working directory has the same checkout name, so history from a clone at a different path still comes over. The working directory is read out of the transcript rather than decoded from the folder name, because that encoding is lossy — /a/b-c, /a-b/c and /a/b/c all collapse to one folder. Empty and slash-command-only transcripts are held back as noise and reported separately, so a lower count always has an explanation.

0.54 — The “keeper” rename, and Home’s attention feeds

Section titled “0.54 — The “keeper” rename, and Home’s attention feeds”
  • The UI says Claude. Paddock is a thin layer over Claude Code, and the “keeper” persona invented a second actor that does not exist — you were messaging Claude the whole time. The composer says Message Claude…, Settings has a Claude section, and where a sentence didn’t need an actor the word is simply gone.

  • Breaking: the keeper names are gone from config, env and the API, with no aliases. If you set either of these, rename them:

    beforeafter
    PADDOCK_KEEPER_DRIVE_MODEPADDOCK_DRIVE_MODE
    PADDOCK_KEEPER_NATIVE_PROMPTPADDOCK_NATIVE_PROMPT

    In paddock.yaml, keeperDriveModedriveMode. An instance still setting the old key falls back to the built-in default quietly, so check yours. On GET /api/models, keeperDefaultdefaultModel.

  • Home leads with what needs you: running chats, then unread. It used to open on a list of recent chats — the same list the sidebar already shows — so the front door duplicated the furniture and buried the signal. The root’s Home is fleet-wide; a project’s is scoped to itself. Running state is read from the live session hub rather than guessed from timestamps, which is also what fixed the in-flight badge: watching the running set is now itself a reason to hold a socket open.

The root workspace's Home, leading with a Running section and then an Unread section listing 88 chats from across every project, each tagged with the project it belongs to and how long ago it replied

  • OVERVIEW.md renders on Home beside CHANGELOG.md, both collapsible. The old Overview card is gone, and the New Project button moved to the sidebar’s Projects header.
  • Foreground sub-agents stopped duplicating themselves into the transcript, and a live bar above the composer now shows each running sub-agent’s latest step — tapping one scrolls its card into view. Liveness comes from the sub-agent’s own transcript, so a parent finishing its turn no longer makes a working sub-agent look idle.
  • A chat can no longer be bound to the curator’s transcript. For a notebook project the sweeper shared a working directory with Claude, and since a sweep is scheduled after every turn the two raced for the same session directory — so curation text could stream back as the reply, and the chat could disappear from the project’s list entirely.
  • The sidebar’s Home link carries the same unread badge as every project row. 0.52 reduced the sidebar to a single Home link, and that link stayed mute — the root is a workspace with chats of its own, yet it was the one row that could never tell you something had come back. It now shows an accent pill counting unread replies, a spinner and count for turns in flight, and nothing at all when quiet, using the same component and accessible labels as a project row. In 0.53 the in-flight half only appeared once you had opened a chat, because nothing held the socket open until then; 0.54 fixed that.
  • Home also costs one request less. The project list used to be followed by a second full fetch of the root workspace, from which everything but a few metadata fields was thrown away.

Everything from 0.52 back to 0.29 lives on What’s New — earlier releases: subtree actions and the one-front-door sidebar, the root becoming a workspace, scratch being retired, driving Paddock from outside over MCP, per-message fork and revert, attachments, streaming, unified triggers, and the rest.


Maintaining this page: add a short, user-facing entry here whenever you cut a release (see RELEASING.md). When this page gets unwieldy, move the oldest entries to the archive page verbatim — the archive is append-only and its entries are never rewritten.