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.

That tmux clipboard tip lets servers read your last copy
---
title: "That tmux clipboard tip lets servers read your last copy"
published: true
description: "Turned on tmux's set-clipboard to copy over SSH? The servers you log into can read your last copy back too, and your terminal never gets asked."
tags: "security, privacy, tmux, ssh"
canonical_url: "blog.peng.ly"
cover_image: "blog.peng.ly"
ai_assisted: true
---
I SSH'd into a box from a tmux pane and got the banner and a prompt, same as always. By the time the prompt came up, the box had already read the last thing I'd copied:
box-b:~$ cat /tmp/loot
hunter2
box-b is a throwaway Alpine container. Its ~/.profile asks the terminal for the clipboard at login and saves whatever comes back. It worked because my tmux had set-clipboard on, the setting most copy-over-SSH guides tell you to turn on. On tmux's default, /tmp/loot stayed empty.
It doesn't have to be something you copied on that box, either. A token I copied on a different server came out of box-b just the same.
To check yours, copy something in tmux and paste this into a pane (bash or zsh). It asks for the clipboard the same way and prints the answer:
stty -echo; printf '\033]52;c;?\a'; read -r -t 1 -d $'\a' r; stty echo; echo "${r##*;}" | base64 -d; echo
If it prints what you copied, anything running on a server you SSH into from that pane can get it too, without you pressing a key.
What just happened?
That \033]52;c;?\a is OSC 52, the escape code programs print to set your clipboard. Swap the copied text for a ? and it asks what's on the clipboard instead. Here's where that question goes:
1. Something on the server prints the question. SSH carries it back to your laptop like any other output.
2. tmux reads everything a pane prints before your terminal does. With set-clipboard on, it answers the question itself, with its newest paste buffer.
3. The answer goes into the pane's input, the same place your typing goes, so ssh sends it up to the server as if you'd typed it.
4. Whatever asked reads it back off the terminal. Nothing shows on your screen.
Your terminal never sees the question at all.
The tip everyone gives
Copying over SSH is a pain, and this is the usual fix. Neovim's clipboard support and a few vim plugins copy on a server by sending OSC 52 to set your clipboard. tmux throws that away unless set-clipboard is on. vim-oscyank's README tells you to set it, and so did seven of the nine copy-over-SSH guides I read. On GitHub, 3,796 .tmux.conf files have it.
None of them warn about reads. Neither does the tmux man page under set-clipboard. The tmux wiki has a security section on it, and it's all about apps setting your clipboard, not reading it.
It's not only your copies
What tmux hands over is its newest paste buffer. That's anything you've copied in tmux's copy mode, and with on, anything a program in any pane has copied, because that's the whole point of the setting. Programs on other servers included.
So I had something on a second container, box-a, copy a token over OSC 52, like a yank in vim would. tmux made it a buffer, as asked:
buffer0: 17 bytes: "ghp_tokenFromBoxA"
Then I opened a second pane and SSH'd into box-b. Its /tmp/loot said ghp_tokenFromBoxA. One server read what I'd copied on another one.
What's not in there is anything you copied outside tmux, in your browser or a password manager. tmux only knows its own buffers.
Doesn't my terminal ask first?
It would, if it got asked. Terminals worked out a while ago that OSC 52 reads are risky. Ghostty and kitty ask you before handing anything over, Alacritty only does copying unless you change it, and Warp got CVE-2026-48725 this year for answering without asking. But tmux sits in front of all of them and answers first.
Zellij, the other popular multiplexer, went the other way. It blocks reads, and when you turn them on it asks your terminal rather than answering itself. The setting for that, added in August, is called dangerously_enable_paste_buffer_read.
mosh, and tmux on the server
mosh doesn't help. I half expected it to drop the question, since it redraws the screen rather than passing bytes along. Instead mosh 1.4.0 copies the ? across as if it were clipboard text, its client prints it out again on your laptop, tmux answers, and mosh sends the answer back up as keystrokes.
A tmux on the server usually shields you. On its default, external, it ignores the question, and with on it answers from the server's own buffers. The catch is get-clipboard, added in tmux 3.7. Set it to request or both on the server's tmux and it passes the question up to your laptop's tmux, which answers. box-b read hunter2 with either.
Who'd actually do this?
Something that can read your terminal on the server. On your own box, that's you, so this is more about the boxes you don't fully trust. A shared server where somebody else has root. A server that's been broken into, where whoever's in there would love a token you copied somewhere else. A container you docker exec -it into, which I tried as well, and which read hunter2 exactly the same way.
On your own laptop it's not much of a hole. Anything running in a pane there could just run tmux show-buffer.
Keeping the copying
If tmux -V says 3.7 or newer, keep on and add one line:
set -s set-clipboard on
set -s get-clipboard off
Here's what each setting did, copying from box-a and then logging into box-b:
!Copying over SSH, and what the server gets back
Copying over SSH, and what the server gets back (the data)
_All three with tmux 3.7c on the laptop, 30 October._
On 3.6 or older there's no clean answer. external stops the reads, and stops copying from servers too, which was the point of turning it on. So it's that, or a newer tmux than your distro gives you. Ubuntu 24.04 ships 3.4 and 26.04 3.6a, Debian 13 ships 3.5a (its backports have 3.7c). Homebrew and Arch are on 3.8, so on a Mac it's a brew upgrade tmux away.
And don't set get-clipboard to request or both on a server, for the reason above.
The option somebody asked for in 2018
tmux has answered these questions since 2.9, from a 2018 commit that never made it into the changelog. The person who asked for it saw this coming:
> I am aware that many people consider such a feature as a potential security risk when connecting to other machines. In my opinion, clipboard reading is ok if one only connects to trusted machines. OSC52 reading could be activated with an extra option.
>
> - IngoMeyer441, tmux issue 1477
It went in behind set-clipboard on instead, the switch for writes. The extra option turned up in tmux 3.7 this June, as get-clipboard, and the changelog says it's off by default. Ask 3.7c with tmux show -s get-clipboard and it says buffer, the setting that hands out your newest copy.
1 reaction · 1 comment
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. 
That tmux clipboard tip lets servers read your last copy --- title: "That tmux clipboard tip lets servers read your last copy" published: true description: "Turned on tmux's set-clipboard to copy over SSH? The servers you log into can read your last copy back too, and your terminal never gets asked." tags: "security, privacy, tmux, ssh" canonical_url: "blog.peng.ly" cover_image: "blog.peng.ly" ai_assisted: true --- I SSH'd into a box from a tmux pane and got the banner and a prompt, same as always. By the time the prompt came up, the box had already read the last thing I'd copied: box-b:~$ cat /tmp/loot hunter2 box-b is a throwaway Alpine container. Its ~/.profile asks the terminal for the clipboard at login and saves whatever comes back. It worked because my tmux had set-clipboard on, the setting most copy-over-SSH guides tell you to turn on. On tmux's default, /tmp/loot stayed empty. It doesn't have to be something you copied on that box, either. A token I copied on a different server came out of box-b just the same. To check yours, copy something in tmux and paste this into a pane (bash or zsh). It asks for the clipboard the same way and prints the answer: stty -echo; printf '\033]52;c;?\a'; read -r -t 1 -d $'\a' r; stty echo; echo "${r##*;}" | base64 -d; echo If it prints what you copied, anything running on a server you SSH into from that pane can get it too, without you pressing a key. What just happened? That \033]52;c;?\a is OSC 52, the escape code programs print to set your clipboard. Swap the copied text for a ? and it asks what's on the clipboard instead. Here's where that question goes: 1. Something on the server prints the question. SSH carries it back to your laptop like any other output. 2. tmux reads everything a pane prints before your terminal does. With set-clipboard on, it answers the question itself, with its newest paste buffer. 3. The answer goes into the pane's input, the same place your typing goes, so ssh sends it up to the server as if you'd typed it. 4. Whatever asked reads it back off the terminal. Nothing shows on your screen. Your terminal never sees the question at all. The tip everyone gives Copying over SSH is a pain, and this is the usual fix. Neovim's clipboard support and a few vim plugins copy on a server by sending OSC 52 to set your clipboard. tmux throws that away unless set-clipboard is on. vim-oscyank's README tells you to set it, and so did seven of the nine copy-over-SSH guides I read. On GitHub, 3,796 .tmux.conf files have it. None of them warn about reads. Neither does the tmux man page under set-clipboard. The tmux wiki has a security section on it, and it's all about apps setting your clipboard, not reading it. It's not only your copies What tmux hands over is its newest paste buffer. That's anything you've copied in tmux's copy mode, and with on, anything a program in any pane has copied, because that's the whole point of the setting. Programs on other servers included. So I had something on a second container, box-a, copy a token over OSC 52, like a yank in vim would. tmux made it a buffer, as asked: buffer0: 17 bytes: "ghp_tokenFromBoxA" Then I opened a second pane and SSH'd into box-b. Its /tmp/loot said ghp_tokenFromBoxA. One server read what I'd copied on another one. What's not in there is anything you copied outside tmux, in your browser or a password manager. tmux only knows its own buffers. Doesn't my terminal ask first? It would, if it got asked. Terminals worked out a while ago that OSC 52 reads are risky. Ghostty and kitty ask you before handing anything over, Alacritty only does copying unless you change it, and Warp got CVE-2026-48725 this year for answering without asking. But tmux sits in front of all of them and answers first. Zellij, the other popular multiplexer, went the other way. It blocks reads, and when you turn them on it asks your terminal rather than answering itself. The setting for that, added in August, is called dangerously_enable_paste_buffer_read. mosh, and tmux on the server mosh doesn't help. I half expected it to drop the question, since it redraws the screen rather than passing bytes along. Instead mosh 1.4.0 copies the ? across as if it were clipboard text, its client prints it out again on your laptop, tmux answers, and mosh sends the answer back up as keystrokes. A tmux on the server usually shields you. On its default, external, it ignores the question, and with on it answers from the server's own buffers. The catch is get-clipboard, added in tmux 3.7. Set it to request or both on the server's tmux and it passes the question up to your laptop's tmux, which answers. box-b read hunter2 with either. Who'd actually do this? Something that can read your terminal on the server. On your own box, that's you, so this is more about the boxes you don't fully trust. A shared server where somebody else has root. A server that's been broken into, where whoever's in there would love a token you copied somewhere else. A container you docker exec -it into, which I tried as well, and which read hunter2 exactly the same way. On your own laptop it's not much of a hole. Anything running in a pane there could just run tmux show-buffer. Keeping the copying If tmux -V says 3.7 or newer, keep on and add one line: set -s set-clipboard on set -s get-clipboard off Here's what each setting did, copying from box-a and then logging into box-b: !Copying over SSH, and what the server gets back Copying over SSH, and what the server gets back (the data) _All three with tmux 3.7c on the laptop, 30 October._ On 3.6 or older there's no clean answer. external stops the reads, and stops copying from servers too, which was the point of turning it on. So it's that, or a newer tmux than your distro gives you. Ubuntu 24.04 ships 3.4 and 26.04 3.6a, Debian 13 ships 3.5a (its backports have 3.7c). Homebrew and Arch are on 3.8, so on a Mac it's a brew upgrade tmux away. And don't set get-clipboard to request or both on a server, for the reason above. The option somebody asked for in 2018 tmux has answered these questions since 2.9, from a 2018 commit that never made it into the changelog. The person who asked for it saw this coming: > I am aware that many people consider such a feature as a potential security risk when connecting to other machines. In my opinion, clipboard reading is ok if one only connects to trusted machines. OSC52 reading could be activated with an extra option. > > - IngoMeyer441, tmux issue 1477 It went in behind set-clipboard on instead, the switch for writes. The extra option turned up in tmux 3.7 this June, as get-clipboard, and the changelog says it's off by default. Ask 3.7c with tmux show -s get-clipboard and it says buffer, the setting that hands out your newest copy.
Free GitHub tool: organise terminal work with Zellij Ever lost your place while juggling Terminal windows? Zellij is a free, open-source terminal workspace. It lets you keep several panes and tabs in one session, so a running command and your notes can stay side by side. On macOS with Homebrew installed: 1. `brew install zellij` 2. Run `zellij` in Terminal. Try opening a second pane to keep logs visible while you work in the first. The interface shows available keyboard actions, and the official guide has a beginner tutorial. Local use needs no account or payment. Zellij also offers an optional paid hosted session-sharing service; this example does not use it. Project: zellij-org/zellij Install guide: zellij.dev
If tmux never stuck for you, try zellij. Same idea (panes, tabs, sessions you can detach from), but the keybindings sit on screen, so you never need a cheat sheet to split a pane. zellij-org/zellij
SSH 开了太多窗口,任务切来切去?🖥️ Zellij 在一个终端里分屏、开标签,还能保存布局。看日志和跑脚本更有条理。🧩 zellij-org/zellij #Terminal #DevTools #浇朋友 #蓝朋友 #互关 #fo
Helix transparent bg does not work in zellij Since starting to use zellij 0.45.1, helix with a transparent theme does not work and defaults to a black bg. Has anyone been able to fix it, i've found this issue in zellij zellij#5175 but when i tested with neovim and a transparent bg, the bg does not change. So i dont know if its a helix or zellij error