{"slug": "agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode", "title": "Agent-Manager: A Tmux TUI for Running Claude Code, Codex and OpenCode", "summary": "Agent-Manager, a terminal user interface that runs multiple AI coding agents side by side in tmux sessions, has been released by developer YoanWai. The tool supports Claude Code, Codex, OpenCode, and Grok Build out of the box, letting users monitor, interact with, and revive sessions from a single list with live status and project tree organization. It is available via Homebrew, Go install, or GitHub Releases for macOS and Linux.", "body_md": "Run every AI coding agent from one terminal. Claude Code, Codex, OpenCode, and Grok run side by side, each in its own tmux session, so they keep working after you quit the manager.\n\nInstead of hunting through terminal tabs to see which agent is done and which is stuck, every session shows up in one list with live status, grouped into a project tree you can fold and reorder. You answer any of them without attaching: `space`\n\nsends a prompt straight into a session's pane, or spawns a new agent in the selected group. A dead session revives where it left off with `v`\n\n. And `ctrl+r`\n\nopens a full-file diff of what an agent changed, syntax-highlighted, where a comment you leave on a line goes straight back to the agent's pane.\n\nStatus detection currently supports **Claude Code**, **OpenCode**, **Codex**, and **Grok Build** out of the box. Any other CLI tool can run as a session; add a `[tools.<name>]`\n\nblock with status rules to get live status for it (see [Configuration](#configuration)).\n\n```\nbrew install yoanwai/tap/agent-manager\n```\n\nInstalls tmux with it if missing.\n\n```\ngo install github.com/YoanWai/agent-manager@latest\n```\n\nRequires Go 1.26+ and tmux; installs to `$(go env GOPATH)/bin`\n\n.\n\nDownload from [Releases](https://github.com/YoanWai/agent-manager/releases) (macOS and Linux, amd64/arm64).\n\nRun inside [WSL2](https://learn.microsoft.com/windows/wsl/install): agent-manager lives on tmux, which is a Linux/macOS tool. In a WSL shell, install with Homebrew or grab the Linux binary from Releases.\n\nThe manager checks GitHub Releases once a day and shows a `↑ vX.Y.Z available`\n\nbadge in the header when a newer version is out. Pull it in the way you installed:\n\n```\nbrew upgrade yoanwai/tap/agent-manager   # Homebrew\ngo install github.com/YoanWai/agent-manager@latest   # Go\nagent-manager\n```\n\nSessions run inside tmux (`am_*`\n\nnamespace), so they survive the manager quitting. Inside a session, **Ctrl+Q** detaches back to the manager. `agent-manager --version`\n\nprints the version.\n\n| Key | Action |\n|---|---|\n`n` |\nNew session (name, tool, directory, optional starting prompt, group picker) |\n`g` |\nNew group (name, parent, default path) |\n`enter` |\nAttach session / fold group |\n`ctrl+q` |\nInside a session: back to the manager |\n`K` / `J` (or `shift+↑` / `shift+↓` ) |\nReorder session or group among its visible siblings |\n`m` |\nMove session to another group |\n`r` |\nRename session / edit tool; edit group name and default path |\n`v` |\nRevive a dead session (`revive_command` , e.g. `claude --continue` , resumes the conversation) |\n`a` / `u` |\nArchive / restore a session, or a group and its entire subtree |\n`d` |\nDelete session, or a group + its entire subtree |\n`space` |\nQuick prompt: answer the selected session, or spawn an agent in the selected group |\n`ctrl+r` |\nReview the selected session's changes: full-screen whole-file diffs, line comments sent to the agent |\n`f` |\nFold / unfold group |\n`s` |\nSettings (quick-spawn tool, theme, review layout) |\n`t` |\nToggle archived view |\n`e` |\nHide / show empty groups |\n`/` |\nSearch |\n`?` |\nHelp |\n`q` |\nQuit (sessions keep running) |\n\nPress `space`\n\nto dock a prompt bar at the bottom of the sidebar. The target follows the cursor while the bar is open (`↑↓`\n\nstill navigate):\n\n- On a\n**session** row,`enter`\n\nsends the typed text straight into the session's pane, so the agent gets it as a user message without you attaching. The bar stays open and clears, ready for the next answer. - On a\n**group** row,`enter`\n\nspawns a new agent in that group with the prompt embedded, using the group's default path. The spawn tool starts at the Settings (`s`\n\n) default and`tab`\n\ncycles it (claude ↔ opencode ↔ any configured tool); the footer shows the current pick. The agent starts working on the prompt immediately.\n\n`esc`\n\ncloses the bar. The new-session form's optional `prompt`\n\nfield launches an agent the same way; tools whose CLI takes the prompt behind a flag declare it with `prompt_flag`\n\n(see [Configuration](#configuration)).\n\nSessions spawned without a custom name (every quick spawn, and the form with the name left blank) get a placeholder like `claude-a1b2`\n\n, and their first prompt opens by asking the agent to run `agent-manager rename \"<name>\"`\n\nonce with a short name for the broad feature of the session (not a single subtask). The directive also tells the agent not to rename again unless you ask. When the first prompt cannot carry the directive (a `/slash`\n\ncommand, or no prompt at all), the manager sends it as its own message once the tool's input box appears in the pane. The subcommand drops the name into a per-session file; the manager picks it up on the next poll and updates the sidebar row and the tmux status bar. This works with any tool, since it only needs the agent to read its prompt and run one shell command.\n\nSessions you name yourself keep that name: the first prompt only notes that `agent-manager rename`\n\nis available later if you ask, and does not instruct the agent to rename now. You can still ask an agent to rename its session later, or run `agent-manager rename`\n\nyourself from a shell inside the session.\n\nA session's working directory is often an umbrella folder holding many repos, so review can only guess which one the agent means. An agent that knows which repo it is working in can say so by running `agent-manager review-repo <path>`\n\nfrom a shell inside its session. The subcommand checks that the path is (or sits inside) a git repo, resolves it to the repo root, and drops it into a per-session file; the manager picks it up on the next poll and review opens on that repo the next time you open it. A path that is not inside a git repo is rejected, so a declaration is always a fact rather than a guess.\n\nAn agent can also declare what its branch diffs against by running `agent-manager review-base <ref>`\n\nfrom inside its worktree: the ref is validated in that repo, stored per session and repo, and the \"vs target\" scope uses it from then on. `agent-manager review-base --clear`\n\nreturns to automatic detection. A stored ref that stops resolving surfaces as an error in review, and `B`\n\nopens a target picker (the repo's branches plus an `auto`\n\nentry) to set or clear it by hand.\n\nAgents usually work in git worktrees, one branch per worktree, and those worktrees can live anywhere on disk. A declared path that is a worktree root is accepted wherever it lives, so one `review-repo`\n\ncall names both the repo and the branch under review. Review resolves its target in a fixed order: a repo you picked by hand with `r`\n\nor `b`\n\nwins for as long as the manager is running, then the agent's declared repo, then the ranking (dirty working trees first, then most recent commit). When the picked or declared path stops being a git repo, review says so in the status line and `r`\n\nis there to pick the right one.\n\nEvery session the manager spawns or revives carries the agent-manager MCP server, so MCP-capable agents see `rename`\n\n, `review_repo`\n\nand `review_base`\n\nas native tools with descriptions telling them when to call each: no prompt injection, no per-project setup. The server lives in the same binary (`agent-manager mcp`\n\n, stdio) and identifies the calling session through its environment.\n\nRegistration is per tool. The built-in claude, codex, opencode and grok tools register automatically: claude gets a generated `--mcp-config`\n\nfile, codex gets `-c mcp_servers...`\n\noverrides, opencode gets an `OPENCODE_CONFIG`\n\nmerge file, and grok gets a one-time `grok mcp add --scope user`\n\nentry on its first launch. A custom tool opts in with `mcp = \"<style>\"`\n\nin its config section, or out with `mcp = \"none\"`\n\n. The CLI subcommands keep working everywhere, MCP or not.\n\nPress `ctrl+r`\n\non a session to open a full-screen review of its repo: changed files with +/− counts on the left, the whole file on the right with syntax highlighting and changed lines tinted, so every edit reads in full context. Arrow keys and `ctrl+d`\n\n/`ctrl+u`\n\nscroll the file, `g`\n\n/`G`\n\njump to top and bottom, `J`\n\n/`K`\n\n(or `tab`\n\n/`shift+tab`\n\n) switch files, `n`\n\n/`N`\n\njump between changes, `u`\n\ntoggles unified and side-by-side, `s`\n\ncycles the scope (uncommitted, vs target, last commit, staged), and `space`\n\nmarks a file reviewed. When the working directory holds several repos, `r`\n\nopens a picker you type to filter, and `b`\n\nlists the current repo's worktrees by branch name so you can review another branch with one keypress. `B`\n\npicks the target (the merge-into branch) the \"vs target\" scope compares against. Each changeable value in the header wears its own key, so the scope, layout, repo, and target pills read as `s`\n\n, `u`\n\n, `r`\n\n, `B`\n\nlegends at a glance. The diff refreshes as the agent keeps editing.\n\nPress `c`\n\non a line to write a comment; `C`\n\nflattens every comment into one review prompt and sends it straight into the agent's pane, so the agent starts addressing your notes while you watch the diff update. `esc`\n\ncloses the review.\n\nGroups are paths (`backend/api/auth`\n\n) forming a tree of unlimited depth. Sessions can live at any node, including the root. Create subgroups inline with `g`\n\n, reorder both groups and sessions with `K`\n\n/ `J`\n\n(or `shift+↑↓`\n\n; the order persists), fold a subtree with `f`\n\n, hide or restore empty groups visually with `e`\n\n, and edit a group's name and default path with `r`\n\n. On a session, `r`\n\nrenames it and `tab`\n\ncycles the tool (status rules and revive follow the new tool; useful when you quit one agent in the pane and start another).\n\nEach session's tmux pane is polled (default every 2s) to derive a status:\n\n| Status | Meaning |\n|---|---|\n`working` |\nThe agent is busy on a turn |\n`waiting` |\nBlocked on you: a dialog, a permission ask, or a plain-text question |\n`finished` |\nTurn ended — an alert that clears to `idle` once you enter the session |\n`errored` |\nThe tool reported an error |\n`idle` |\nNothing running |\n`dead` |\nThe tmux session is gone |\n\nEach row carries its status and tool inline, and a folded group keeps a count per status so a collapsed subtree still tells you whether anything needs you. Selecting a session shows the tail of its pane on the right, which is how a `waiting`\n\nagent's actual question reaches you without attaching.\n\nDetection matches per-tool regex rules against the visible pane, analyzes the newest turn to tell `finished`\n\nfrom `waiting`\n\n, and treats streaming output (content changing between polls) as `working`\n\n. A turn that ends without any turn-summary line still resolves: when a `working`\n\npane goes quiet, the turn counts as `finished`\n\n, or `waiting`\n\nwhen it ends on a question. Polling keeps running while you are inside a session, so statuses stay live. The selected session's pane tail renders in the preview panel, and moving the cursor fetches the preview immediately.\n\nFor Claude Code, status comes first-hand from [hook events](https://docs.anthropic.com/en/docs/claude-code/hooks) instead of pane guessing: sessions launch with a generated `--settings`\n\nfile whose hooks write the lifecycle state (`working`\n\n, `waiting`\n\n, `finished`\n\n, `idle`\n\n) to a per-session status file that the poller reads first. Pane rules still refine it — hooks cannot see a plain-text question, an Esc interrupt, or an error line, so a matching pane verdict upgrades the hook status — and they take over fully as fallback when the hook file is missing or stale. Enabled per tool with `status_source = \"claude-hooks\"`\n\n.\n\nThe header shows a fleet summary: per-status session counts, plus `agents total usage: cpu N% · ram M% · X GB`\n\nfor every live agent's full process tree (shell, agent, and children). CPU is that tree's CPU time over the last poll as a share of total machine capacity (same 0–100% unit as the computer gauge). RAM is resident set as a share of installed memory, with absolute size beside it. The selected session's detail line uses the same scale for that session alone.\n\nThe Computer block in the sessions panel shows machine gauges:\n\n**CPU**: whole-machine utilization (0-100%)** Memory**: used/total. On macOS this matches Activity Monitor's Memory Used (resident RAM minus free, speculative, and reclaimable file cache). On Linux it is`Total - MemAvailable`\n\n, so file cache is not counted as used.**Swap**: used/total of the current swap allocation (`used/total * 100`\n\n). On macOS the swap file grows under pressure, so the denominator is the live size from`vm.swapusage`\n\n, not a fixed partition.**Disk**: fill of the root filesystem (used / (used + available)), with free space from the kernel's available figure** Network**: up/down rates on real NICs only (loopback, utun, bridges, and similar virtual interfaces are excluded)\n\n`s`\n\nopens Settings, where `↑↓`\n\nmove between fields and `←→`\n\nchange the focused one.\n\nNine palettes ship: `classic`\n\n, `solarized dark`\n\n, `catppuccin mocha`\n\n, `tokyo night`\n\n, `gruvbox dark`\n\n, `nord`\n\n, `dracula`\n\n, `rosé pine`\n\n, and `monochrome`\n\n. The swatch strip beside the name previews the palette, and the theme applies as you step through it, so the picker is a live preview of the whole UI. The manager also matches the terminal's own background to the palette, so the window has no seam against it, and restores the terminal's background on exit. Your pick is saved with the rest of the state and restored on the next run.\n\nConfig lives in your OS user config dir (`~/Library/Application Support/agent-manager/config.toml`\n\non macOS, `~/.config/agent-manager/config.toml`\n\non Linux) and is created on first run with working defaults for Claude Code, OpenCode, Codex, and Grok Build.\n\nTop-level: `poll_interval`\n\n(default `\"2s\"`\n\n) sets how often panes are polled for status, preview, and stats.\n\nAdd any CLI tool as a `[tools.<name>]`\n\nblock:\n\n```\n[tools.mytool]\ncommand = \"mytool\"\ndefault_status = \"idle\"\nrules = [\n  { state = \"working\", pattern = \"esc to interrupt\" },\n  { state = \"errored\", pattern = \"(?im)^\\\\s*error:\" },\n]\n```\n\nRules match top-down against the visible pane text; first match wins, and `default_status`\n\napplies when nothing matches. Optional per-tool fields refine detection: `activity_cutoff`\n\n(regex locating the tool's input box, everything above it is turn content), `turn_end`\n\n(a turn-summary line marking the turn as over), `chrome_line`\n\n, `blocked_line`\n\n, and `trailing_note`\n\n. The generated config's `claude`\n\nand `opencode`\n\nblocks show all of them in use.\n\nOther per-tool fields: `revive_command`\n\nis what `v`\n\nruns to revive a dead session (e.g. `claude --continue`\n\nresumes the conversation in place); `status_source = \"claude-hooks\"`\n\nswitches status to Claude Code hook events (see [Status](#status)).\n\n`prompt_flag`\n\ncontrols how the new-session form's optional prompt is embedded into the launch command. Tools that take the prompt as a positional argument (Claude Code: `claude 'the prompt'`\n\n) leave it empty; tools whose positional argument means something else declare the flag (OpenCode: `prompt_flag = \"--prompt\"`\n\n, since its positional argument is the project path). The prompt only shapes the launch command; revive (`v`\n\n) uses `revive_command`\n\nuntouched.\n\nState is stored next to the config in `state.db`\n\n(SQLite).\n\n```\ngo test ./...   # includes end-to-end tests against a real tmux server\ngo run .\n```\n\n", "url": "https://wpnews.pro/news/agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode", "canonical_source": "https://github.com/YoanWai/agent-manager", "published_at": "2026-07-30 09:34:27+00:00", "updated_at": "2026-07-30 09:52:09.210972+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "large-language-models"], "entities": ["Agent-Manager", "YoanWai", "Claude Code", "Codex", "OpenCode", "Grok Build", "tmux", "Homebrew"], "alternates": {"html": "https://wpnews.pro/news/agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode", "markdown": "https://wpnews.pro/news/agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode.md", "text": "https://wpnews.pro/news/agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode.txt", "jsonld": "https://wpnews.pro/news/agent-manager-a-tmux-tui-for-running-claude-code-codex-and-opencode.jsonld"}}