A terminal board for running and triaging many AI coding-agent sessions in tmux.
Spawn two agents, watch their status, answer the waiting one from the triage queue, and it hands over the next.
Gate Inbox puts every coding agent on your machine in one list with live status, so the session
that is blocked on you is visible without hunting through terminal tabs. Claude Code, Codex and
OpenCode v2 work out of the box and run side by side, each in its own tmux session. Any other CLI
can be added as a [tools.<name>] block in the config.
It is a thin layer over the CLIs you already have. Each session launches your installed tool as-is, so your login, config files, MCP servers and every feature the tool ships carry over unchanged. Gate Inbox reads the panes; it does not sit between you and the model.
- Install. You need tmux 3.1+, git and at least one agent CLI (Claude Code, Codex or
OpenCode). Then run
go install github.com/usestring/gate-inbox@latest, or see Install below. - Start it. Run
gate-inbox, inside tmux or outside it. The welcome card lists which of your agent CLIs are ready, the five keys that matter, and any agents you already have running in tmux.non the card starts your first session. - Agents you already had. Anything you started by hand in tmux shows up on the board as-is,
and stays where it is: the board never ends your process unasked.
aon its row (or on the toast that names a pane started while the board is up) brings it in: once it is idle, it is relaunched on the same conversation as a board session.oleaves it off the board. What a pane kept as-is misses is below; settings (s) has "outside panes" to take them over once idle without asking. - The loop.
nstarts an agent,enterfocuses it,ctrl+qcomes back to the list,iwalks everything waiting on you, andhshows every key. - Leaving and coming back.
qquits and the agents keep running. When you start it again, the board offers back only the sessions that died (a reboot, tmux restarting, a crash), never the ones you ended yourself. Stop using it covers stopping for good.
| An agent pane you started by hand, kept as-is (the default)... | Brought into the board (a), it... |
|---|---|
| keeps running where it is, in its own window | is ended once idle and resumed on the same conversation as a board session |
| gets the board's MCP tools (spawn, message, tasks) through the relay the board registers in your Claude Code user config (Claude Code only; other CLIs get none) | gets them |
is reached by other sessions and the CLI from its row (send, read, wait, kill, and answer from the session that tracks it) |
is reached the same way |
| reports status through the hooks the board registers in your Claude Code user settings (Claude Code only) | reports status through the hooks it is launched with |
lacks the GATE_INBOX_* environment, extension settings and a fresh account token |
gets all three |
| can't be forked, migrated, restarted or revived without a conversation id | can, on its own conversation |
gets the back-to-board keys when the board attaches it (A), not its title and colours |
gets them all |
keeps the flags and --model it was started with |
is started from your config, so it doesn't keep them |
Gate Inbox runs on Linux and macOS, and on Windows inside WSL2. It needs tmux 3.1+ and git
on PATH, plus at least one agent CLI. Building needs Go 1.27.2+.
git clone https://github.com/usestring/gate-inbox.git
cd gate-inbox
go build -o gate-inbox .Or go install github.com/usestring/gate-inbox@latest, which puts gate-inbox in
$(go env GOPATH)/bin. docs/install.md covers optional dependencies, WSL and
updating.
gate-inboxnstarts an agent in the group under the cursor and focuses it. Type the task.ctrl+qgoes back to the list. Each row shows its status as the agent works.iopens the triage queue, starting with the session that has waited longest.- Answer it. The queue hands you the next one.
hshows every key for the current screen, andsopens settings.
Sessions live in tmux, so quitting the board leaves them running. Start gate-inbox again and it
picks them back up.
Spawn. n starts a session in the selected group. ctrl+n opens the full form (tool, name,
directory, first prompt, group). Agents name their own sessions after the task.
Reuse prompts (experimental). Enable Prompt suggestions under Settings → Experimental
(default off). In the New Session form's prompt field, matching suggestions appear as you type.
ctrl+n / ctrl+p choose among them and ctrl+y inserts the chosen text for editing;
accepting does not launch the session. Suggestions come from the newest 16 MiB of each CLI's
submission log within the past 30 days. A whole prompt or a line in a multi-line prompt must occur
at least four times to qualify. Counting ignores case and repeated whitespace, and each submission
counts once per candidate. The logs are reread in the background every minute. History and matching
stay local; this feature makes no network requests. The hotkey-only snippet menu is unchanged.
See status. Every row shows whether its agent is working, waiting on you, finished or idle,
read from the pane itself. The preview beside the list shows the conversation as You and
Assistant messages, without the tool noise. w filters the list to what needs attention, and
/ searches names, groups, statuses and what the sessions have said.
Triage. i flattens the groups into one queue ordered by what needs a person: waiting first,
then finished, then errored, longest-blocked first inside each. Picking an option in a dialog, or
sending a reply, hands that session back to its agent and opens the next one. ctrl+q moves on
without answering, and ctrl+\ stops triage. alt+\ puts the list away for a full-width drain,
and alt+, hides the key hints.
Triage with the list put away. Answer one session and the next that needs you comes up on its own.
Focus. enter focuses a session in place: keys go to the agent while the list stays beside
it, and ctrl+q comes back. alt+\ hides the list so the pane gets the full width, and
alt+pgup / alt+end scroll back through its output and return to the live bottom. space
opens the hotkey menu, which sends one of your snippets to the selected session without focusing it; a
lettered snippet also sends on option+<key> in one press, no menu. T opens a shell tab under the
selected agent for builds and one-off commands.
Focus a session, give it the full width, type a multi-line instruction, scroll back through the reply, and ctrl+q out.
| Key | Action |
|---|---|
n / ctrl+n |
New session, quick or with the full form |
space |
Hotkey menu: send a snippet to the selected session |
enter |
Focus the session; ctrl+q returns to the list |
i |
Triage queue; \ hides the list for a full-width drain |
w |
Show only what needs attention |
Y |
Show only one CLI's sessions, cycling through the harnesses on the board |
/ |
Fuzzy search; esc closes the field, deleting the text clears it |
ctrl+p / p |
Priority tier for a session or group; each press steps urgent → high → medium → low → none. ctrl+p also works from a focused session, and the row flashes its new tier |
M |
Mute / unmute: keep a session out of triage until unmuted; the row reads muted |
T |
Shell tab under the selected agent |
x / v |
Kill a session to free its RAM / revive it on its own conversation |
: / ctrl+k |
Quick actions: type what you want, enter runs it, and each row shows its key |
h / s |
Key map for the current screen / settings |
Priority defaults to 0 with no marker. Positive levels use green ▲, ▲▲, and ▲▲▲; the negative level (-1) uses a red ▼. Set a level with gate-inbox priority <level> using a number from -1 to 3 or its tier name.
Every binding is a default, and h is where you rebind one. docs/usage.md is
the complete reference.
Every MCP-capable session launches with the Gate Inbox MCP server, so an agent can list the other
sessions, spawn a child, send it a message, read its screen and wait for it to finish. The same
actions are gate-inbox subcommands for a shell inside any session (gate-inbox help). A spawned
child is drawn under its parent, and its questions go to the parent first.
Config lives at ~/.config/gate-inbox/config.toml on Linux and
~/Library/Application Support/gate-inbox/config.toml on macOS, and is created on first run.
GATE_INBOX_HOME points the board at another directory, which then holds the config, the
state.db store and the logs.
Adding a CLI takes a tool block with the patterns its pane shows in each state:
[tools.mytool]
command = "mytool"
default_status = "idle"
rules = [
{ state = "waiting", pattern = "(?m)^\\s*❯\\s+\\d+\\." },
{ state = "working", pattern = "esc to interrupt" },
]Sessions run on tmux's default server as gi_* sessions, and the board never changes a
server-global option. Set tmux_socket to keep them on a server of their own.
docs/configuration.md covers every field: status detection, revive and
fork commands, prompts and MCP registration.
They talk only to services you run or already use.
Pull requests and tickets. Gate Inbox finds the pull requests and tickets a session is working
on from its branch and its output, and hangs them under the session with their CI and review state.
GitHub goes through your logged-in gh CLI; Linear reads LINEAR_API_KEY from the environment.
A missing credential is not a failure: without LINEAR_API_KEY tickets are still listed, just
without their state. Either source can be turned off outright, which hides its rows:
[integrations.github]
enabled = false
[integrations.linear]
enabled = falseExtensions. Extensions are Go code compiled into the binary against the public extension
package; the app package runs the board with whichever extensions a build carries. This build
carries none, so an [extensions.artifacts] section left from an earlier version is ignored. A build
of your own lists its extensions in app.Options. A section an extension refuses switches off that
extension alone, and a section no extension in the build owns is ignored; the board's ? key map and
each session's MCP instructions say which and why. A disabled extension that has a say in
which sessions spawn fails closed: every spawn it would have been asked about is refused, with the
reason, until its section is fixed.
Claude Code can rank a session from an optional skill frontmatter field:
gate-inbox-priority: highThe accepted tiers are urgent, high, medium, and low. The last invoked skill with a tier
wins. The hook reads skills from $CLAUDE_PROJECT_DIR/skills first, then
${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills. It runs for the Skill tool and a prompt beginning
with /<skill>. Skills without a valid tier leave priority unchanged.
The reusable hook lives in hooks/skill-gate-inbox-priority.sh.
It needs Bash and jq, and a session launched by Gate Inbox (GATE_INBOX_BIN, or
AGENT_MANAGER_BIN for older launchers). Without a board binary it exits successfully without
changing anything. A launcher that owns the session's tier can set GATE_INBOX_PRIORITY_LOCKED=1
to keep skills from replacing it.
To use it in another project, link to your Gate Inbox checkout instead of copying the script. From that project's root, with Gate Inbox checked out in a sibling directory:
mkdir -p hooks
ln -s ../../gate-inbox/hooks/skill-gate-inbox-priority.sh hooks/skill-gate-inbox-priority.shKeep that checkout available at the linked path. Merge these entries into the project's
.claude/settings.json hooks, preserving any existing registrations:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Skill",
"hooks": [{"type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/hooks/skill-gate-inbox-priority.sh\""}]
}
],
"UserPromptSubmit": [
{
"hooks": [{"type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/hooks/skill-gate-inbox-priority.sh\""}]
}
]
}
}Run bash hooks/skill-gate-inbox-priority.test.sh from the Gate Inbox checkout to test the hook.
go build -o gate-inbox .
scripts/ci-test.sh # the test suite exactly as CI runs itCONTRIBUTING.md covers sending a change, and SECURITY.md how
to report a vulnerability privately. The recordings above come from tools/demo/record.sh, which
drives vhs against a throwaway board whose sessions run a
scripted stand-in CLI, so no model or account is involved.
Apache-2.0. Gate Inbox is derived from an Apache-2.0 upstream project, where its
session model, tmux passthrough and TUI began. NOTICE names that project, its authors
and the commit this fork started from. LICENSES/MODIFIED-FILES.txt
lists the files changed since, and LICENSES/THIRD-PARTY.md covers
third-party licences.
Quit. q quits the board. Its agents keep running in tmux as gi_<id> sessions and are
picked back up next time.
Stop every agent. gate-inbox park ends every live agent the board started and records the
set. It runs from any shell, and --dry-run prints the plan first. gate-inbox unpark brings
the same sessions back on their conversations. A single one: gate-inbox kill <id>, with the id
from gate-inbox sessions. From inside a managed agent session, gate-inbox stop ends that
session and preserves its row and conversation for an explicit revive. It records an intentional
stop, so startup recovery does not offer it as a lost session. gate-inbox stop --archive also
files the ended row out of the active list, where archive --restore can bring it back for 7 days.
gate-inbox stop --dry-run verifies the current pane without ending it. Adopted callers with verified pane process ancestry can also stop themselves.
Shared-daemon callers whose pane cannot be verified refuse shutdown. Other adopted panes can be stopped by id from
another session or the board.
Carry on in the plain CLI. In a focused session, alt+/ copies the agent's own conversation
id. From that session's working directory:
| CLI | Resume |
|---|---|
| Claude Code | claude --resume <id> |
| Codex | codex resume <id> |
| OpenCode | opencode --session <id> |
Without an id, Claude Code and Codex open their own session picker (claude --resume,
codex resume) so you choose the conversation, and opencode --continue picks up the
directory's most recent one.
Uninstall.
gate-inbox park. In Settings (s), switch "claude code setup" off so the board takes its hooks and MCP relay back out of your Claude Code config, rungate-inbox codex-hooks uninstallto take its hooks out of your Codex config, set[opencode] setup = falseinconfig.tomlso it takes its plugin out of your OpenCode config, then quit the board withq.- Remove the binary:
rm "$(command -v gate-inbox)". - Remove the config and state directory. That's
$GATE_INBOX_HOMEif you set it, otherwise~/.config/gate-inboxon Linux ($XDG_CONFIG_HOME/gate-inboxif that's set) and~/Library/Application Support/gate-inboxon macOS. It holdsconfig.toml,state.db, the log, key bindings, snippets, hook and MCP registration files, and a copy of the binary underbin/. - Remove the launch scripts and pasted images it left in your temp directory:
rm -f "${TMPDIR:-/tmp}"/gi-launch-*.shandrm -rf "${TMPDIR:-/tmp}/gate-inbox-pastes". - Undo the tmux key bindings it added (
ctrl+qandctrl+\, plusalt+ofrom older releases, which act only insidegi_*sessions and adopted panes the board attached), on each tmux server it adopted a pane on:tmux unbind-key -n C-q \; unbind-key -n 'C-\' \; unbind-key -n M-o, or restart tmux. If the board didn't exit cleanly,tmux kill-session -t gi_poll-anchorremoves its helper session. If you gave it a private tmux socket,tmux -L <name> kill-serverdoes all of this at once.
Gate Inbox hands each session it launches its MCP server and hooks on the command line. The
things it keeps in an agent CLI's own configuration are for panes it adopts: hook entries in
~/.claude/settings.json, silent outside an adopted pane, the two deny lists there that keep every
Claude Code session out of Gate Inbox's sealing keys (permissions.deny and
sandbox.filesystem.denyRead, naming only its own channel-keys directory), and an MCP server
named gate-inbox in ~/.claude.json; two hook entries in ~/.codex/config.toml, silent
outside the board's sessions; and a gate-inbox-<id>.js plugin in ~/.config/opencode/plugins,
silent outside an adopted pane; all added automatically. Step 1 removes them, giving back the
settings file as it was, and so do [claude_code] setup = false, [codex] setup = false and
[opencode] setup = false in config.toml. Beyond that, migrate leaves a
*.handover.jsonl file next to the transcript it moved, under ~/.claude/projects or
~/.codex/sessions.
Gate Inbox is derived from agent-manager, licensed
under Apache-2.0. Thank you to Yoan Wai and the agent-manager contributors for the session model,
tmux passthrough and TUI this project grew from. NOTICE carries the attribution and
the upstream commit this fork started from.


