Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claudeq

a queue for claude code that lives beside it.

type your next instructions into a small pane next to claude. they wait in a list you can see, reorder, edit and park, and each one is handed to claude when the turn ends. the list survives a crash and comes back with --continue.

it does not patch claude code. everything runs through claude code's public hooks api. no network, no telemetry, nothing leaves your machine.

claudeq demo

left: claude. right: cq. two follow-ups queued mid-task, then a paragraph plus a screenshot, then a crash and --continue.

why

stock claude code has two ways to send while it works: Enter steers into the running turn, Ctrl+X Enter waits for it to end. neither gives you a list. claudeq adds editing a queued message, reordering, parking, waiting for background tasks, and a queue that survives a restart.

install

bun install && bun run build:bin
ln -s $PWD/dist/cq ~/.local/bin/cq
cq install

macOS and linux, no windows build. cq install shows the four hook entries it will add to ~/.claude/settings.json, backs the file up, and asks first. it also registers an mcp server (cq mcp) that serves image attachments.

run cq install with no other claude sessions open: a running session keeps its own copy of ~/.claude.json and can write it back without the cq entry. cq doctor checks everything, cq uninstall removes exactly what was added.

use

open a split next to claude (cmd+d in ghostty, iterm, kitty, wezterm) and run cq in it.

the pane has two halves: the draft you type into, and the list of queued messages. from the first line of the draft moves to the list, past the last row comes back. ? shows every key.

typing

key does
enter queues the draft (or saves the item you are editing)
tab cycles the mode: wait -> background -> parked
ctrl+j newline
ctrl+v attaches a clipboard image, or pastes clipboard text
esc esc clears the draft
ctrl+c clears the draft; quits when it is already empty
backspace at the start removes the last attached image

the draft is a real text editor: readline keys (ctrl+a/e/k/w/u, alt+←/→), undo with ctrl+z, home/end/pgup/pgdn through a long paste, and a pasted paragraph goes in as one message with its newlines intact. the keys match claude code's own where they overlap.

the list

key does
move the highlight
change that item's mode
shift+↑ shift+↓ move the item up / down the queue
e edit it in the draft
d / u delete / undo the delete
r re-queue a sent message
h hold or release the queue
q quit

modes: [waits] runs when the turn ends. [waits for background] also waits for background agents and shells to finish. [parked] never runs until you change it.

rows are numbered as cq ls numbers them, so cq rm 2 in another shell acts on the row you are looking at. quitting the pane changes nothing; the queue lives in files.

images. ctrl+v attaches whatever image is on the clipboard (macOS only for now - linux would need wl-paste or xclip; the pane says so instead of pretending the clipboard is empty). cmd+v cannot work for this: with image data on the clipboard the terminal has no text to send, so nothing reaches cq at all. an image copied from a web page also drops its source url into the draft.

the header tells you when nothing is moving: held after a resume (press h, or send a prompt in claude), the 8-in-a-row limit claude code enforces, and idle: 2 waiting - send a prompt in claude. that last one matters: nothing here can start a turn, so a queue with nothing running in front of it waits until you type something yourself.

optional: make enter wait in claude's own box

cq install --keybindings rebinds enter to chat:queueSubmit and shift+enter to chat:submit in claude's own input box, so enter waits for the turn to end instead of steering into it. cq uninstall --keybindings reverts it, touching only the bindings still set to what cq wrote. it has nothing to do with claudeq's pane, where enter always means "queue this".

how it works

four hooks in ~/.claude/settings.json, each with a 10 second timeout so a stuck hook can never stall your turn.

  • SessionStart registers the session so the pane knows which ones are live. on a resume it holds the queue and marks anything delivered-but-unconfirmed as restored, so a crash never drops or double-runs a message.
  • SessionEnd removes that registration. the queue file survives.
  • UserPromptSubmit releases a hold, resets the continuation count, and confirms the last delivery into history.
  • Stop delivers. it picks the first runnable item and returns it as additionalContext, which claude code feeds back as the next thing to act on. delivery is at-least-once: an item moves into history only once a later hook proves a turn actually ran after it.

state lives under ~/.cq (queues/, sessions/, log), never inside a project. CQ_HOME overrides the location; whichever directory it points at is chmod'd to 0700.

guarantees

  • no network calls, no telemetry, no update check. a test greps src/ for network apis, and another spawns the built binary with DEV=true to prove ink's bundled devtools probe never connects.
  • claude code's binary is never modified.
  • hooks fail open: a bug in cq logs a line, it never stalls a turn.
  • cq uninstall removes exactly the hooks, mcp registration and keybindings cq install added, and nothing else.
  • queued text is never deleted by cq, except by cq uninstall --purge, which needs its own confirmation.
  • nothing is written inside your project.

cli

the pane is a convenience over a plain cli that works the same way:

cq add [--mode wait|background|parked] <text...>   # text from args or stdin
cq ls [--json]
cq rm <n|id>
cq edit <n|id> <text...>
cq mv <n|id> <up|down|top|bottom|position>
cq mode <n|id> <wait|background|parked>
cq hold | cq release
cq sessions

n is the row number cq ls prints, id is the item's ulid. every mutation goes through the same versioned write as the hooks.

development

bun install, bun test, bun run typecheck, bun run lint. bun run build:bin for the binary, bun run build:node for the npm entry.

four scripts under test/live/ run against your logged-in claude and cost a few small model calls each: drain.sh, payload-shape.sh, resume-hold.sh, cap.sh. test/live/CHECKLIST.md is the manual pass for what no script can reach.

demo/record.sh re-records the demo above with vhs (use 0.11.0; 0.12.0 captures frames but never encodes them).

licence

mit. not affiliated with anthropic. inspired by the problem statement in nuuxcode/claude-queue; no code is shared with it.

About

a queue for claude code

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages