Prompt Queue
experimentalStack of follow-up prompts queued while an agent works: reorder, edit inline, remove, or Send now to steer. Renders nothing when empty.
Two queued prompts
Queued2
Sends when the agent finishes this turn- When tests pass, update the auth section of the README
- Don't touch src/legacy/ — it's deleted next sprint
Alt plus arrow keys or Space then arrows to reorder. Enter to edit, Delete to remove, Control or Command plus Enter to send now.
Controlled, with steering
Attachments, a prompt that arrives after mount, and Send now reported below.
Queued3
Sends when Kura finishes running pnpm test- Use the refreshSession() helper instead of calling fetch('/api/session') directlysession-flow.png
- Don't touch src/legacy/ — it's being deleted next sprint
- When tests pass, update the auth section of the README and link the migration guideMIGRATION.md+1
Alt plus arrow keys or Space then arrows to reorder. Enter to edit, Delete to remove, Control or Command plus Enter to send now.
Hover a prompt, or focus it and use Alt+↑/↓, Enter, Delete and ⌘↵.
Tray
Rounded on top only, tucked onto the input below.
Queued2
Sends when the agent finishes this turn- Use the refreshSession() helper instead of calling fetch('/api/session') directlysession-flow.png
- Don't touch src/legacy/ — it's being deleted next sprint
Alt plus arrow keys or Space then arrows to reorder. Enter to edit, Delete to remove, Control or Command plus Enter to send now.
Above a composer
Messages sent while the agent works are queued; Send now steers.
Run pnpm test --filter web
Running- Steps
- 5/7
- Cost
- $1.52
- Elapsed
- –:––
Queued2
Sends after this turn- Use the refreshSession() helper instead of calling fetch('/api/session') directlysession-flow.png
- Don't touch src/legacy/ — it's being deleted next sprint
Alt plus arrow keys or Space then arrows to reorder. Enter to edit, Delete to remove, Control or Command plus Enter to send now.
Installation
npx shadcn@latest add https://kuro.abstergo.fyi/r/prompt-queue.jsonCopies the source into components/kura/prompt-queue with its dependencies (kura-theme, button, icon-button, kura-motion, use-controllable-state, use-reduced-motion, utils). Tokens come from the kura-theme item.
When to use it
Use it for
- The user types follow-ups while an agent is mid-turn (Claude Code / Codex queued messages) and they should send in order when it finishes.
- Letting the user steer: interrupt the agent and send one queued prompt immediately.
- Directly above a composer (variant='tray') so queued prompts read as part of the input.
Reach for something else when
- Suggested prompts the user has not written — use prompt-suggestions.
- The prompt input itself — use composer (and put PromptQueue above it).
- Work the agent plans to do — use task-list.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items | QueuedPrompt[] | — | Queued prompts in send order (controlled): { id, text, attachments?: { name, type?: 'image' | 'file' }[] }. |
| defaultItems | QueuedPrompt[] | — | Initial prompts when uncontrolled. |
| onItemsChange | (items: QueuedPrompt[]) => void | — | Called with the whole new list after a reorder, edit, remove or Send now. Fires on every step while dragging. |
| onSendNow | (item: QueuedPrompt) => void | — | Steer: interrupt the agent and send this prompt now. The prompt is removed from the queue first. Without it no Send now button renders. |
| title | React.ReactNode | "Queued" | Header title; the count follows it. |
| hint | React.ReactNode | "Sends when the agent finishes this turn" | Secondary header text, e.g. 'Sends when Kura finishes running pnpm test'. null hides it. |
| variant | "panel" | "tray" | "panel" | panel = standalone card; tray = sunken, rounded on top only, meant to sit flush on top of a Composer (inset it with className='mx-3'). |
All native attributes of the root element, className and ref pass through.
Anatomy
- PromptQueueRoot with `data-variant`.
data-slot="prompt-queue" - HeaderTitle, count and prompt-queue-hint.
data-slot="prompt-queue-header" - ItemFocusable <li> (`data-state` = editing | dragging): index (grip on hover), text, attachments, actions.
data-slot="prompt-queue-item" - HandleDrag grip shown in place of the index on hover (pointer only; keyboard uses Alt+arrows or Space).
data-slot="prompt-queue-handle" - TextOne truncated line; the full text is the title tooltip.
data-slot="prompt-queue-text" - AttachmentsFirst attachment's icon and name in mono, then '+N'.
data-slot="prompt-queue-attachments" - ActionsMove up, Move down, Edit, Remove and prompt-queue-send ('Send now'); shown on hover/focus, always on touch.
data-slot="prompt-queue-actions" - EditorAuto-growing textarea replacing the row while editing, with Cancel/Save.
data-slot="prompt-queue-editor"
Accessibility
- Role:
list (ol) of focusable items - The list is labelled by the title and described by visually hidden keyboard help. Items use a roving tabindex (one Tab stop) and are named '2 of 3: <text>'.
- A polite status region announces moves ('Moved to position 1 of 3'), removals and Send now. Actions are icon buttons with tooltips.
- Escape in the editor cancels without reaching the composer's own Escape (stop) handler.
- Reduced motion: Reorders jump into place instead of sliding; the drag still follows the pointer.
| Keys | Action |
|---|---|
| ArrowUp / ArrowDown | Move focus between prompts |
| Alt+ArrowUp / Alt+ArrowDown | Move the focused prompt up / down |
| Space, then arrows, then Space | Grab, move and drop (Escape restores) |
| Enter / F2 | Edit inline (Enter saves, Shift+Enter newline, Escape cancels) |
| Delete / Backspace | Remove |
| Mod+Enter | Send now |
Notes for agents
- When the agent finishes a turn, shift the first item off `items` and send it yourself — the component never sends on its own.
- onSendNow means 'interrupt and send': stop the current turn in your harness before sending.
- Keep ids stable across edits; reordering and focus rely on them.
- Empty queue renders only a visually hidden status region, so you can leave it mounted above the composer.