Claude produces more than a person can keep up with. Questions get buried in long replies, things it's waiting on you for scroll away, and you miss stuff. Docket keeps every open thread between you and Claude in numbered lists in a pane beside the chat, so you can answer by label (q10 yes, c3-c5 confirmed, accept all other leans) or with one click.
At the prompt of a Claude Code session, add docket's marketplace, then install it from there:
/plugin marketplace add StoneCypher/docket
/plugin install docket@docket
docket needs node on the PATH: Claude Code runs it to serve docket's tool (see How it works).
Pick a scope when asked. From a shell instead, claude plugin marketplace add StoneCypher/docket then claude plugin install docket@docket.
docket is also listed in StoneCypher/claude-plugins, alongside StoneCypher's other plugins: /plugin marketplace add StoneCypher/claude-plugins, then /plugin install docket@stonecypher.
In the pane, the most important list comes first:
| Letter | List | What's in it |
|---|---|---|
| R | Requests | Things Claude wants to do on its own initiative. It waits for your ✔ or ✗. |
| Q | Questions | Decisions only you can make. Each has a lean: the answer Claude would pick. |
| C | Confirm | Claude checking that it read you right, or making sure you know something risky is coming. |
| N | Needs you | Things only you can do: consoles, accounts, hardware. |
| V | Verify | Things for you to check: that a change works, reads right or looks right. |
| U | Underway | Claude's work in progress. |
| L | Later | Claude's work that's decided but not started, in order. |
| W | Waiting | Things stalled on something other than you. |
| P | Pinned | Parked for later, drawn on one line. |
Numbers only ever go up, so Q12 always means the same question. Unchanged items are dimmed and new ones are marked.
- ✔ / ✗ on a lean, a request or a confirm item answers it. The row dims at once and leaves about 20 seconds later.
- 🗑️ on an item clears just that item. ✕ on a heading clears the whole list. Clearing only empties the display: it never cancels work, answers a question or approves a request.
- Accept all leans, Confirm all and Approve all answer a whole list.
- ⚙ at the bottom of the pane opens the settings.
/docket reopens the pane if you close it.
Claude can do all of this for you too: ask it to clear a list, press a button or close the pane.
Buttons work only in Claude Code's fullscreen terminal layout. The regular (main-screen) layout reports no mouse clicks, and it draws the pane inline above the prompt rather than docked beside the transcript; a pane docks only in fullscreen, from 110 columns. So on a main-screen terminal, docket shows a short notice in place of its pane and band: type /tui fullscreen to switch. That saves the setting and relaunches with the conversation intact, and /tui default switches back. Claude Code refuses the switch while background work is running ("Cannot switch renderers while work is running in the background"), so wait for that work to finish, or stop it in /tasks, first. /docket says the same there.
The desktop app, VS Code, the phone, and fullscreen terminals are unchanged, as is a remote surface that hasn't yet said which layout it's in. The notice's words are in the language files with the rest of docket's; they show in English until each language translates them.
Claude keeps the docket with one tool, mcp__plugin_docket_docket__update. Everything in one call:
| Field | What it does |
|---|---|
add |
Adds items to a list, by letter. The tool assigns the labels and returns them. |
change |
Corrects an item, by label. A changed item gets its buttons back. |
close |
Closes items, by label; unasked marks one Claude closed on its own judgment. |
clear |
Clears lists, by letter, or "all": what a heading's ✕ does. It runs before add, so a clear and an add start the docket afresh. |
press |
Presses an item's button, by label and button: yes (✔), no (✗), an option's own label, start (🏗️), open (👁️) or clear (🗑️). Only the buttons the item shows now can be pressed. |
pane |
open opens the pane; close closes it the way your close does, so it stays closed, the band with it, until /docket or Claude opens it again. |
language |
The language Claude hears you write in, when docket asks for it. |
A press goes through the same code as your click. The row is answered at once, and a press on docket's own items acts at once: ✔ on the offer to create docket's config writes the config, as your ✔ does. A press on one of Claude's own items sends the same message your click sends, as you, but only once Claude's turn ends, as a prompt can't start while the tool call holds the turn. Several presses in one turn go as one prompt. Claude is told to press its own items' buttons only when you ask.
A pane Claude opens without your asking is placed only on a terminal at least 144 columns wide; /docket places it at any width.
docket's own stdio server lists the tool (see How it works), and docket asks for it to be listed up front (isDeferred: false), not behind ToolSearch. Two things follow:
- ToolSearch never finds it. ToolSearch looks only through deferred tools, so a search for "docket" comes back empty whether the tool is there or not. That alone doesn't mean it's missing.
- It needs its server. Claude Code starts the server from
.mcp.jsonwithnode, so the tool is missing whennodeisn't on the PATH or the server didn't start./mcpshows whether docket's server is connected.
docket's own start (/docket, its version and its config) is tried again at the next prompt when it didn't finish, so one failure there doesn't leave the whole session without the docket.
If the tool is still missing, run /reload-plugins and send one more prompt, or start a new session. Subagents are a separate case: one Claude starts may be given a tool list without docket's, even while the main conversation has it.
Settings live in ~/.claude/docket/config.json, a versioned JSON file with every setting written out. A project can have its own .claude/docket/config.json, whose settings win. The first time docket runs without one, the pane offers to create yours with the defaults; when docket adds settings, it updates the file in place and tells you in Verify. Edit the file directly, or use ⚙ at the bottom of the pane:
language:auto(the default) follows Claude Code's language setting, then VS Code's display language, then the terminal's locale, then the language Claude hears you write in; or a language code with a file inlocales/, such ases,jaordeturnReview: whether the Deep dive switch, at the pane's bottom left, starts each session on (it does by default); the switch decides from then on. With it on, each prompt quietly asks Claude, before it ends the turn, to go back over it once for decisions it made on your behalf and threads it left open, and to add them to the docket. You never see that request. Only if a turn you started ends with a reply that speaks of pending work while the docket stayed as it was does Claude get sent back, visibly, once. Turns started by a task notification, a wakeup or another background event are never sent back.updateCheck: on by default. Once a day docket reads itsplugin.jsonon GitHub, its only outside request, and says in Verify when a newer version is out. Off stops the request too.display:panebeside the chat (the default), orbandabove the prompt- a cap for each list (7 by default) before "+N more"
itemColor,itemDimColor,leanColor,leanDimColor: hex colors or theme keysemoji,headingEmoji,noItemEmojiLists: emoji on or off, overall or per liststakesDisplay:emoji,textornoneinlineLists,targetWords: which lists draw on one line, and soft word limits per listansweredLingerSeconds,strikeLingerMinutes: how long answered and auto-closed items stay up
docket speaks English, Spanish, Japanese and German: the headings, buttons, settings, and the messages its buttons send. Each language names its lists so each starts with its own letter, and items are labeled with those letters, so a Spanish question is P12 under Preguntas, and a Japanese one is 質12 under 質問. Claude is told to write items in the same language. The config file keeps docket's internal English letters, whatever the language.
Every language but English is one JSON file in locales/, mapping each English string to its translation, so translating docket needs no code. Each translation, and the file as a whole, says how ready it is: false (not translated, so English shows), "ai translated", or true (checked by a person):
{
"ready": "ai translated",
"version": 1,
"Questions": { "text": "Preguntas", "ready": true },
"Accept the lean on {id}.": { "text": "Acepto la propuesta de {id}.", "ready": "ai translated" }
}docket uses any file not marked false. A list's letter is the first character of its translated name, so name the lists to start with different letters, and keep anything in {braces} as it is. A regional file, such as es-MX.json, holds only what differs from es.json.
Every language docket recognizes already has a file, so helping means editing one: open it on GitHub, press the pencil, fill in or fix each text, set its ready, and commit. GitHub copies docket to your account and offers to open a pull request. When Claude Code is set to a language whose file isn't ready, machine-translated, or behind English, docket asks once, in Requests, whether you'd like to help, and its ✔ opens that file in GitHub's editor.
A language can also end in a dialect, as BCP 47 tags end in a variant (en-US-something): a file in locales/dialects/ with its own "name" and "tag", laying its words over English and listed below the real Englishes in the picker. docket ships none; the novelty lives in voices.
Voices are their own setting, in any language: a character Claude writes the docket's items as. The casts live in locales/voices/ (Star Trek, Samurai Jack, Yinzer, Hackerman), each a "voice" for every item and "voices" per list by English name, and each may bring its own ✔ and ✗, as text or a picture: Star Trek has Uhura on Verify, Chekov on Underway and Sulu on Questions, with 👉 and 🤦; Samurai Jack has Aku gloating over Waiting, with a katana and Aku. Pick one in ⚙, or write a character into the config's "voice", such as "drunk Optimus Prime". When the language or voice changes, Claude rewrites the open items to match.
When English changes, STRINGS_VERSION in hooks/i18n.ts goes up and npm run locales brings every file in line: new strings arrive blank, and strings English no longer says are dropped. npm test checks that each file is in line, keeps every placeholder, is no readier than its strings, and gives each list its own letter.
npm testruns the unit tests for the pure logic (hooks/lists.ts,hooks/config.ts,hooks/i18n.ts,hooks/languages.ts,hooks/buttons.ts,hooks/screen.ts), the tool server (server/tools.mjs) and the language files under Node's own test runner, with coverage: it fails below 80% of lines, branches or functions. Needs Node 23.6 or later, which runs TypeScript directly.npm run test:modruns the hooks and pane tests (tests/*.test.tsx) inside Claude Code's engine, on every surface.npm run validatechecks the manifest, the marketplace file and the hooks module the way Claude Code loads them.
Docket is a Claude Code mod. It adds its rules to Claude's system prompt, gives Claude one tool for adding, changing and closing items (and for clearing lists, pressing buttons and opening or closing the pane), sends Claude the current docket with each of your prompts (with any labels you mention expanded), and draws the lists in a pane. If Claude's reply talks about pending work without updating the docket, your next prompt reminds it to reconcile.
The tool is mcp__plugin_docket_docket__update. A small stdio MCP server in server/ (started by .mcp.json, plain JavaScript with no dependencies) lists it, and docket's tool.call hook answers every call, so the server never handles one itself. A mod's own $.tool.register would be simpler, but Claude Code's server for those tools answers its client's tools/list with a response the client can't read (InvalidHTTPResponse in claude --debug), so a tool registered that way never reaches Claude.