cmdq
Type the next command while one is still running.
cmdq is a small terminal wrapper that hosts your shell in a pseudo-terminal
and gives you a separate "queue input" region below a separator. While a
command is running you can type the next command — review it, edit it,
reorder, cancel, or chain it conditionally — and it dispatches automatically
when the current one finishes.
Works with any shell (zsh, bash, fish, sh).
Why
In a normal terminal, when a command is running:
- You can't see what you're typing for the next command.
- You can't cancel or edit a typed-but-not-yet-executed command.
- You can't queue more than one.
cmdq fixes all three.
Installation
Shell (macOS & Linux) — recommended
|
Detects your OS / CPU, downloads the matching pre-built binary, and drops it
in ~/.cargo/bin (or wherever CARGO_HOME points). No Rust toolchain
required.
Homebrew (macOS & Linux)
From crates.io
Requires Rust 1.88+ (edition 2024).
Manual download
Grab the platform tarball from the
latest release
and put cmdq somewhere on your PATH.
From source
Quick start
The first run auto-installs OSC 133 prompt-marker hooks for your shell into a private rcfile. To make the integration permanent in your normal shell sessions too, run:
Shell setup
Pick the section for your shell. Each one shows how to install the OSC 133
integration and (optionally) auto-start cmdq whenever you open a terminal.
Why the
CMDQ_ACTIVEguard?cmdqitself spawns a child shell which sources your rc. Without the guard, that child would re-launchcmdqand loop forever.execthen replaces (rather than nests inside) your shell.
Install the integration into ~/.zshrc:
Auto-start in every terminal — append to ~/.zshrc:
[ &&
Reload:
macOS users: if you use a custom
ZDOTDIR, install integration manually with--install-integrationrather than relying on the auto-injected shim.
Install the integration into ~/.bashrc (Linux) or ~/.bash_profile (macOS):
Auto-start in every terminal — append to your bash rc:
[ &&
Reload:
Install the integration into ~/.config/fish/config.fish:
cmdq --install-integration
Auto-start in every terminal — append to ~/.config/fish/config.fish:
if not set -q CMDQ_ACTIVE
exec cmdq
end
Reload:
source ~/.config/fish/config.fish
Install the integration into ~/.profile:
Auto-start in every terminal — append to ~/.profile:
[ &&
Reload:
If you'd rather paste the integration snippet yourself (e.g. you manage your dotfiles via a tool that doesn't like generated edits), print it and copy into your rc:
Keybindings
cmdq starts in passthrough mode — keystrokes go directly to your shell. The
queue panel only appears once a command has been running for 1.5 seconds,
so quick commands (ls, cd) don't flash UI. Press F1 or ? any time
the panel is visible for a full help overlay.
Note: while the queue panel is open, ↑ recalls items from the queue, not your shell history. Exit with
Ctrl-\(or double-tapEsc) if you need shell history or want to scroll a pager (git diff,less).
Add to queue
| Key | Action |
|---|---|
| (any printable) | type into the input buffer |
| Enter | add the typed command to the queue |
| Tab | chain — only run if the previous command succeeded |
| Esc | clear the input buffer |
Edit a queued item
| Key | Action |
|---|---|
| ↑ / ↓ | open previous / next queued item for edit |
| Enter | save the edit |
| Esc | cancel the edit (item unchanged) |
| Ctrl-D | delete the item being edited |
| Alt-↑ / Alt-↓ | reorder the item being edited |
Queue control
| Key | Action |
|---|---|
| Ctrl-X | pause / resume auto-dispatch |
| Ctrl-K | clear the entire queue |
Modes
| Key | Action |
|---|---|
| Ctrl-Q | force the panel open even at the shell prompt |
| Ctrl-\ | raw input — keys go straight to the running app |
| Esc Esc | raw input (SSH-safe alternative to Ctrl-\); double-tap again to return |
Misc
| Key | Action |
|---|---|
| Ctrl-C | forward SIGINT to the running command (auto-pauses the queue) |
| Ctrl-D | quit cmdq (twice if the queue is non-empty) |
| Ctrl-A / Ctrl-E | beginning / end of input line |
| Ctrl-U | kill back to start |
| F1 / ? | show / dismiss the help overlay |
Smart behaviors
- Panel only appears for long commands. Anything finishing in under 1.5s
runs without UI getting in the way.
Ctrl-Qforces the panel open at the shell prompt if you want to queue ahead of time. - Auto-passthrough on alt-screen. When the running program enters
alt-screen mode (vim, htop, less, fzf, btop, …),
cmdqautomatically forwards keystrokes verbatim and hides the queue panel. - SIGINT auto-pauses the queue. Ctrl-C on a running command (or exit status 130) pauses the queue instead of dispatching the next item.
- Bracketed paste. Pasting a multi-line snippet collapses newlines into
;so it lands as a single queue item. - Quit-confirm. Ctrl-D with a non-empty queue requires a second press.
- Persistence. The queue lives in
~/.local/share/cmdq/queue.json, so a restart mid-session doesn't lose pending work.
How it works
The shell emits \e]133;A, \e]133;C, \e]133;D[;exitcode] markers around
prompts and command execution. cmdq watches the PTY output stream for these
to decide whether keystrokes should pass through to the shell (at a prompt)
or be captured into the queue (when a command is running).
When the shell finishes a command (\e]133;D), cmdq writes the next queued
command's bytes back into the PTY master — same as if you'd typed it.
Development
Caveats
vt100rendering is solid for normal CLI output, colors, and most TUIs, but may have small fidelity gaps for exotic sequences (sixel, kitty graphics). UseCtrl-\to passthrough to the running program.- The auto-injected ZDOTDIR shim sources your real
~/.zshrcbefore appending the integration. If you have machinery that's strictly ZDOTDIR-aware, install integration manually via--install-integration.