tmux vs Zellij vs Hermes IDE: Five CLI Agents, and Which One Is Waiting on You
- Book: Database Playbook
- The series: Pocket Guides for Developers — 8 short books on agents, RAG, prompts, observability, events, databases and system design — the whole series
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
---
Five agents, five panes. Three are still printing. One finished ten minutes ago. One has been sitting on a permission prompt since you went to refill your coffee, and from across the room it looks exactly like the ones that are thinking.
Once you run more than two Claude Code or Codex sessions, most of the work is watching them: which pane is blocked on you, which one is done, and which two are working in the same folder.
This post puts three tools side by side for that job: tmux, Zellij and Hermes IDE. The first two are terminal multiplexers, and you get working configs for both. The third is a desktop app I build, so weigh what I say about it with that in mind. I haven't benchmarked any of them, and nothing below depends on speed.
Five panes, four questions
All three can put five agents on one screen. That part is easy. What you need from the tool is four answers, without clicking through every pane:
1. Which agent is blocked on me right now?
2. Which ones are done?
3. Are they still running if I close the window or my SSH connection drops?
4. Is each agent working in its own checkout?
A multiplexer answers question 3 well and leaves question 4 to you. Questions 1 and 2 depend on what the agent tells the terminal, and that signal is thinner than it looks.
Both big CLIs can ring the terminal bell. Claude Code fires a notification "when Claude finishes a task or pauses for a permission prompt, and you appear to be away from the terminal", and its terminal docs show how to turn that into a bell. Codex has tui.notifications, with a notification_method of auto, osc9 or bel (config reference). With the bell turned on as shown below, the same alert covers "I finished" and "I need you". You can split them with extra work: Codex can limit notifications to specific event types, and a Claude Code Notification hook can match on the notification type, such as permission_prompt or idle_prompt, and run a different command for each. That is per-agent plumbing you write and maintain. A plain bell only means "go look at this one".
!Five terminal windows in a row, each with a small brass bell above it, one bell ringing with burnt-orange sound waves while an engineer's silhouette looks at the wrong window
A bell tells you which window to look at. It doesn't tell you why.
tmux: one window per agent, and let the bell flag it
tmux alerts are per window, not per pane. The man page defines monitor-bell as "Monitor for a bell in the window", and the status line marks that window with !. Put five agents in five panes of one window and a bell only tells you that one of the five rang. So give every agent its own window.
First, make the agents ring. For Claude Code, in ~/.claude/settings.json:
{
"preferredNotifChannel": "terminal_bell"
}
Claude Code only fires this when you "appear to be away from the terminal", and the docs don't say how it judges that inside tmux. If a background window stays quiet, a Notification hook is the next thing to try.
For Codex, in ~/.codex/config.toml:
[tui]
notifications = true
notification_method = "bel"
notification_condition = "always"
notification_condition defaults to unfocused. Setting it to always sidesteps the question of whether a background tmux window counts as unfocused.
Then tmux itself:
# ~/.tmux.conf
setw -g monitor-bell on
set -g bell-action other
set -g visual-bell off
setw -g window-status-bell-style 'fg=black,bg=yellow'
set -g allow-passthrough all
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'
bell-action other reacts to bells in windows other than the one you're in, and the bell style paints the waiting window's name in the status bar. The last three lines follow Claude Code's tmux setup. The docs ask for allow-passthrough on, so desktop notifications and the progress bar reach your outer terminal if you use them instead of the bell, and the two extended-keys lines let Shift+Enter insert a newline instead of submitting. The man page adds a catch on passthrough: with on, it works "only if the pane is visible", and all allows it "even if the pane is invisible". With four of five agents in background windows, all is the setting to pick.
Last, a script that gives each task its own worktree and its own window:
#!/usr/bin/env bash
# agents.sh: one worktree and one tmux window per task
set -euo pipefail
cd ~/code/app
tmux new-session -d -s agents -n shell
for spec in login:claude auth:codex docs:claude \
search:codex billing:claude; do
task=${spec%%:*}; agent=${spec#*:}
git worktree add -b "agent/$task" "../app-$task"
tmux new-window -t agents -n "$task" \
-c "$HOME/code/app-$task" "$agent"
done
tmux attach -t agents
The git worktree add line matters as much as the windows. On its own, tmux gives you five views of one checkout. Without worktrees, five agents edit the same folder.
Where tmux wins is everything around the terminal. The man page says "Each session is persistent and will survive accidental disconnection", so you can start the agents on a dev box over SSH, lose Wi-Fi, and tmux attach -t agents later. The README lists OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris. It is also the host for Claude Code's experimental agent teams, whose split-pane mode "Requires tmux, or iTerm2" (agent teams docs). And every action is a command, so tmux capture-pane -p -t agents:login | tail -5 prints the last lines of one agent without switching to it.
Where it's thin: a reboot ends the server. tmux-resurrect brings back sessions, layouts and working directories, but restores only "a conservative list of programs" by default, and no coding agent is on it. And Claude Code can report working, waiting or done to terminals that implement the OSC 7501 status protocol, but inside tmux it checks tmux for support instead of your terminal. Its docs tell you to start the session outside tmux if you want that status.
Zellij: a layout file you can read
Zellij describes the same setup as a KDL layout. Create the worktrees with the same git worktree add loop, minus the tmux lines, then save this next to them:
// ~/code/agents.kdl
layout {
default_tab_template {
pane size=1 borderless=true {
plugin location="zellij:tab-bar"
}
children
pane size=2 borderless=true {
plugin location="zellij:status-bar"
}
}
tab name="login" cwd="app-login" {
pane command="claude"
}
tab name="auth" cwd="app-auth" {
pane command="codex"
}
tab name="docs" cwd="app-docs" {
pane command="claude"
}
tab name="search" cwd="app-search" {
pane command="codex"
}
tab name="billing" cwd="app-billing" {
pane command="claude"
}
}
Run zellij --layout agents.kdl from ~/code. The layout sets no global cwd, so each tab's relative cwd resolves against the directory you ran the command from. The two agent configs from the tmux section apply here too.
Zellij's best trick for this job is session resurrection, on by default. Exited sessions show up in zellij list-sessions, and the layout and the command in each pane come back. The commands don't start on their own: each waits behind a "Press ENTER to run..." banner. With five agents that might all pick a task back up at once, that's the default you want.
The 0.44 release in March 2026 added "Terminal BEL forwarding from unfocused tabs and panes with visual indication", native Windows support, attaching to a remote session over HTTPS, read-only viewing with zellij watch, and CLI actions such as list-panes and dump-screen (release post). 0.45.0 forwards OSC 9, 99 and 777 desktop notifications only when your host terminal appears to support them. The current release is 0.45.1, from August 28, 2026 (releases).
Zellij has the same gap as tmux. It relays the bell, and a plain bell only says "look at me". Telling done from blocked is hook scripting you add yourself. Worktrees are still your job. And Claude Code's agent teams list only tmux and iTerm2 for split panes.
Hermes IDE: a status per session and an inbox
Hermes is a desktop app for macOS, Windows and Linux. Each agent runs its own interface in a real terminal, with your own sign-ins, so Claude Code is still Claude Code and Codex is still Codex. Around those terminals it adds the parts a multiplexer leaves to you. From the README:
- Status. Every session shows one status: working, needs approval, asked you, done, error or idle. It says when a status is a guess. This is the split a plain bell can't make.
- Inbox. It counts the agents blocked on you, and ⌘I (Ctrl+Shift+I on Windows and Linux) jumps to the one that has waited longest. You answer in that agent's own terminal. Hermes never answers a permission prompt for you and never types into a terminal on its own.
- Notifications. One fires when an agent is blocked on you or done, never for the session you're already looking at.
- Isolation. ⌘N (Ctrl+Shift+N) starts each task on its own hermes/<name> branch in its own worktree, with the task as the agent's first prompt. New worktrees get their dependencies in seconds and their own ports. That replaces the worktree loop above.
- Persistence. On macOS and Linux, agents keep working while Hermes quits, updates or crashes, and you reattach where they left off.
!An engineer's silhouette at a desk facing a single inbox tray, with five small terminal cards filed in it and one card raised with a burnt-orange flag
One place that lists who is blocked on you, oldest first.
The trade-off: it's a GUI app on the machine in front of you. Its SSH docs call SSH sessions alpha, with "no AI agent integration" yet, so status and the inbox are for agents running locally. If your agents live on a remote dev box, tmux or Zellij on that box is the right layer. It also moves fast: 2.3.0 and 2.3.1 both shipped on October 13, 2026, so expect things to change. And a multiplexer you already have costs nothing to try, while Hermes is one more app to install. It is free, source-available under BSL 1.1, and not affiliated with Nous Research, Anthropic, OpenAI or any agent vendor.
Side by side
| | tmux | Zellij | Hermes IDE |
|---|---|---|---|
| Where it runs | Unix-likes, over SSH | macOS, Linux, Windows (0.44+), over SSH | Desktop app on macOS, Windows, Linux |
| Survives closing the UI | Detach and reattach | Detach, plus resurrection after exit | Quit, update, crash (macOS, Linux) |
| "Which one needs me" | ! flag after a bell | Visual BEL indication | Status per session, inbox, ⌘I |
| Done vs blocked | Same bell, unless you script hooks | Same bell, unless you script hooks | Separate statuses |
| One checkout per agent | Your worktree script | Your worktree script | Branch and worktree per task |
| Setup lives in | .tmux.conf and a script | A KDL layout | The ⌘N launcher and presets |
| Scripting | Any tmux command | zellij action, subscribe | Plugin API |
Which one to pick
If your agents run on a remote box you SSH into, use tmux or Zellij on that box. That's what they were built for, and Hermes's SSH support isn't there yet for agents.
If you want Claude Code's agent teams in split panes, use tmux. It's one of the two hosts the docs list.
If you want the whole setup in one readable file, with resurrection that asks before restarting anything, use Zellij.
If every agent you run is Claude Code, check its own agent view first (in research preview). The Claude Code overview points you there "to run several full sessions in parallel and watch them from one screen", with no extra tool.
If you run several agents locally all day and the time goes to finding the one that's blocked, that's the case Hermes is built for. And it isn't either-or: the README notes that Hermes's New Session window also covers tmux sessions.
How many agents do you run at once before the watching becomes the work?
---
If this was useful
I build Hermes IDE, so take the inbox section as the builder's view: download it for macOS, Windows or Linux, run your five agents for a day, and see if you look for the blocked one less. If it earns a place, a star on GitHub helps other developers who juggle agents find it.
A worktree gives each agent its own files, not its own database. Once two of your five agents add migrations or a new index against the same Postgres schema, that's where they collide next, and the Database Playbook is a short read on choosing stores, shaping schemas and changing them without surprises. It's one of 8 short books in Pocket Guides for Developers, covering agents, RAG, prompts, observability, events, databases and system design.

Mentions
tmux vs Zellij vs Hermes IDE: Five CLI Agents, and Which One Is Waiting on You - Book: Database Playbook - The series: Pocket Guides for Developers — 8 short books on agents, RAG, prompts, observability, events, databases and system design — the whole series - My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools - Me: xgabriel.com | GitHub --- Five agents, five panes. Three are still printing. One finished ten minutes ago. One has been sitting on a permission prompt since you went to refill your coffee, and from across the room it looks exactly like the ones that are thinking. Once you run more than two Claude Code or Codex sessions, most of the work is watching them: which pane is blocked on you, which one is done, and which two are working in the same folder. This post puts three tools side by side for that job: tmux, Zellij and Hermes IDE. The first two are terminal multiplexers, and you get working configs for both. The third is a desktop app I build, so weigh what I say about it with that in mind. I haven't benchmarked any of them, and nothing below depends on speed. Five panes, four questions All three can put five agents on one screen. That part is easy. What you need from the tool is four answers, without clicking through every pane: 1. Which agent is blocked on me right now? 2. Which ones are done? 3. Are they still running if I close the window or my SSH connection drops? 4. Is each agent working in its own checkout? A multiplexer answers question 3 well and leaves question 4 to you. Questions 1 and 2 depend on what the agent tells the terminal, and that signal is thinner than it looks. Both big CLIs can ring the terminal bell. Claude Code fires a notification "when Claude finishes a task or pauses for a permission prompt, and you appear to be away from the terminal", and its terminal docs show how to turn that into a bell. Codex has tui.notifications, with a notification_method of auto, osc9 or bel (config reference). With the bell turned on as shown below, the same alert covers "I finished" and "I need you". You can split them with extra work: Codex can limit notifications to specific event types, and a Claude Code Notification hook can match on the notification type, such as permission_prompt or idle_prompt, and run a different command for each. That is per-agent plumbing you write and maintain. A plain bell only means "go look at this one". !Five terminal windows in a row, each with a small brass bell above it, one bell ringing with burnt-orange sound waves while an engineer's silhouette looks at the wrong window A bell tells you which window to look at. It doesn't tell you why. tmux: one window per agent, and let the bell flag it tmux alerts are per window, not per pane. The man page defines monitor-bell as "Monitor for a bell in the window", and the status line marks that window with !. Put five agents in five panes of one window and a bell only tells you that one of the five rang. So give every agent its own window. First, make the agents ring. For Claude Code, in ~/.claude/settings.json: { "preferredNotifChannel": "terminal_bell" } Claude Code only fires this when you "appear to be away from the terminal", and the docs don't say how it judges that inside tmux. If a background window stays quiet, a Notification hook is the next thing to try. For Codex, in ~/.codex/config.toml: [tui] notifications = true notification_method = "bel" notification_condition = "always" notification_condition defaults to unfocused. Setting it to always sidesteps the question of whether a background tmux window counts as unfocused. Then tmux itself: # ~/.tmux.conf setw -g monitor-bell on set -g bell-action other set -g visual-bell off setw -g window-status-bell-style 'fg=black,bg=yellow' set -g allow-passthrough all set -s extended-keys on set -as terminal-features 'xterm*:extkeys' bell-action other reacts to bells in windows other than the one you're in, and the bell style paints the waiting window's name in the status bar. The last three lines follow Claude Code's tmux setup. The docs ask for allow-passthrough on, so desktop notifications and the progress bar reach your outer terminal if you use them instead of the bell, and the two extended-keys lines let Shift+Enter insert a newline instead of submitting. The man page adds a catch on passthrough: with on, it works "only if the pane is visible", and all allows it "even if the pane is invisible". With four of five agents in background windows, all is the setting to pick. Last, a script that gives each task its own worktree and its own window: #!/usr/bin/env bash # agents.sh: one worktree and one tmux window per task set -euo pipefail cd ~/code/app tmux new-session -d -s agents -n shell for spec in login:claude auth:codex docs:claude \ search:codex billing:claude; do task=${spec%%:*}; agent=${spec#*:} git worktree add -b "agent/$task" "../app-$task" tmux new-window -t agents -n "$task" \ -c "$HOME/code/app-$task" "$agent" done tmux attach -t agents The git worktree add line matters as much as the windows. On its own, tmux gives you five views of one checkout. Without worktrees, five agents edit the same folder. Where tmux wins is everything around the terminal. The man page says "Each session is persistent and will survive accidental disconnection", so you can start the agents on a dev box over SSH, lose Wi-Fi, and tmux attach -t agents later. The README lists OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris. It is also the host for Claude Code's experimental agent teams, whose split-pane mode "Requires tmux, or iTerm2" (agent teams docs). And every action is a command, so tmux capture-pane -p -t agents:login | tail -5 prints the last lines of one agent without switching to it. Where it's thin: a reboot ends the server. tmux-resurrect brings back sessions, layouts and working directories, but restores only "a conservative list of programs" by default, and no coding agent is on it. And Claude Code can report working, waiting or done to terminals that implement the OSC 7501 status protocol, but inside tmux it checks tmux for support instead of your terminal. Its docs tell you to start the session outside tmux if you want that status. Zellij: a layout file you can read Zellij describes the same setup as a KDL layout. Create the worktrees with the same git worktree add loop, minus the tmux lines, then save this next to them: // ~/code/agents.kdl layout { default_tab_template { pane size=1 borderless=true { plugin location="zellij:tab-bar" } children pane size=2 borderless=true { plugin location="zellij:status-bar" } } tab name="login" cwd="app-login" { pane command="claude" } tab name="auth" cwd="app-auth" { pane command="codex" } tab name="docs" cwd="app-docs" { pane command="claude" } tab name="search" cwd="app-search" { pane command="codex" } tab name="billing" cwd="app-billing" { pane command="claude" } } Run zellij --layout agents.kdl from ~/code. The layout sets no global cwd, so each tab's relative cwd resolves against the directory you ran the command from. The two agent configs from the tmux section apply here too. Zellij's best trick for this job is session resurrection, on by default. Exited sessions show up in zellij list-sessions, and the layout and the command in each pane come back. The commands don't start on their own: each waits behind a "Press ENTER to run..." banner. With five agents that might all pick a task back up at once, that's the default you want. The 0.44 release in March 2026 added "Terminal BEL forwarding from unfocused tabs and panes with visual indication", native Windows support, attaching to a remote session over HTTPS, read-only viewing with zellij watch, and CLI actions such as list-panes and dump-screen (release post). 0.45.0 forwards OSC 9, 99 and 777 desktop notifications only when your host terminal appears to support them. The current release is 0.45.1, from August 28, 2026 (releases). Zellij has the same gap as tmux. It relays the bell, and a plain bell only says "look at me". Telling done from blocked is hook scripting you add yourself. Worktrees are still your job. And Claude Code's agent teams list only tmux and iTerm2 for split panes. Hermes IDE: a status per session and an inbox Hermes is a desktop app for macOS, Windows and Linux. Each agent runs its own interface in a real terminal, with your own sign-ins, so Claude Code is still Claude Code and Codex is still Codex. Around those terminals it adds the parts a multiplexer leaves to you. From the README: - Status. Every session shows one status: working, needs approval, asked you, done, error or idle. It says when a status is a guess. This is the split a plain bell can't make. - Inbox. It counts the agents blocked on you, and ⌘I (Ctrl+Shift+I on Windows and Linux) jumps to the one that has waited longest. You answer in that agent's own terminal. Hermes never answers a permission prompt for you and never types into a terminal on its own. - Notifications. One fires when an agent is blocked on you or done, never for the session you're already looking at. - Isolation. ⌘N (Ctrl+Shift+N) starts each task on its own hermes/<name> branch in its own worktree, with the task as the agent's first prompt. New worktrees get their dependencies in seconds and their own ports. That replaces the worktree loop above. - Persistence. On macOS and Linux, agents keep working while Hermes quits, updates or crashes, and you reattach where they left off. !An engineer's silhouette at a desk facing a single inbox tray, with five small terminal cards filed in it and one card raised with a burnt-orange flag One place that lists who is blocked on you, oldest first. The trade-off: it's a GUI app on the machine in front of you. Its SSH docs call SSH sessions alpha, with "no AI agent integration" yet, so status and the inbox are for agents running locally. If your agents live on a remote dev box, tmux or Zellij on that box is the right layer. It also moves fast: 2.3.0 and 2.3.1 both shipped on October 13, 2026, so expect things to change. And a multiplexer you already have costs nothing to try, while Hermes is one more app to install. It is free, source-available under BSL 1.1, and not affiliated with Nous Research, Anthropic, OpenAI or any agent vendor. Side by side | | tmux | Zellij | Hermes IDE | |---|---|---|---| | Where it runs | Unix-likes, over SSH | macOS, Linux, Windows (0.44+), over SSH | Desktop app on macOS, Windows, Linux | | Survives closing the UI | Detach and reattach | Detach, plus resurrection after exit | Quit, update, crash (macOS, Linux) | | "Which one needs me" | ! flag after a bell | Visual BEL indication | Status per session, inbox, ⌘I | | Done vs blocked | Same bell, unless you script hooks | Same bell, unless you script hooks | Separate statuses | | One checkout per agent | Your worktree script | Your worktree script | Branch and worktree per task | | Setup lives in | .tmux.conf and a script | A KDL layout | The ⌘N launcher and presets | | Scripting | Any tmux command | zellij action, subscribe | Plugin API | Which one to pick If your agents run on a remote box you SSH into, use tmux or Zellij on that box. That's what they were built for, and Hermes's SSH support isn't there yet for agents. If you want Claude Code's agent teams in split panes, use tmux. It's one of the two hosts the docs list. If you want the whole setup in one readable file, with resurrection that asks before restarting anything, use Zellij. If every agent you run is Claude Code, check its own agent view first (in research preview). The Claude Code overview points you there "to run several full sessions in parallel and watch them from one screen", with no extra tool. If you run several agents locally all day and the time goes to finding the one that's blocked, that's the case Hermes is built for. And it isn't either-or: the README notes that Hermes's New Session window also covers tmux sessions. How many agents do you run at once before the watching becomes the work? --- If this was useful I build Hermes IDE, so take the inbox section as the builder's view: download it for macOS, Windows or Linux, run your five agents for a day, and see if you look for the blocked one less. If it earns a place, a star on GitHub helps other developers who juggle agents find it. A worktree gives each agent its own files, not its own database. Once two of your five agents add migrations or a new index against the same Postgres schema, that's where they collide next, and the Database Playbook is a short read on choosing stores, shaping schemas and changing them without surprises. It's one of 8 short books in Pocket Guides for Developers, covering agents, RAG, prompts, observability, events, databases and system design. 
@alexeeps @cyberglyphic e.g tmux-plugins/tmux-continuum