From Tabs to tmux (and Why It's Not Snobbery)

I work in Windows Terminal on top of WSL2 (Ubuntu 26.04). My editor is Zed; in the terminal I only reach for nano/vim/neovim for tiny edits. My main CLI agent is OpenCode.

tmux looks scary. In practice it's about a dozen shortcuts and one short config. I'd recommend learning it once, as a separate practice. Then you can calmly move on to herdr: same model with the ctrl+b prefix, just different bindings.


How it started

I lived in Windows Terminal tabs for a long time. The problem isn't tabs, it's the routine. Every day before work it's the same thing: open the project, start the dev server, launch an agent, run scripts. And in the background, the fear that something will crash, close, and you'll lose everything.

tmux fixed both problems at once:

For me tmux isn't about the editor. It's about not reassembling your workspace from scratch.


Basics: shortcuts and scenarios

Everything hinges on one prefix: Ctrl + b. Press it and release. Then comes the command. There's almost nothing else to learn. And when you move to herdr, it's the same model with the ctrl+b prefix.

Sessions: the main thing

tmux new -s myproject   # create a named session
tmux a -t myproject     # reattach to it
tmux ls                 # list live sessions

Scenario: you start a dev server in a session, hit Ctrl + b → d (detach), close the terminal. The server keeps running. You come back and reattach: tmux a -t myproject.

Windows (tabs)

ActionHotkey
New windowCtrl + b → c
Switch by numberCtrl + b → 0 (or 1, 2…)
RenameCtrl + b → , (comma)

Scenario: one window for the dev server, another for the CLI agent.

Panes (splits)

ActionHotkey
Vertical splitCtrl + b → %
Horizontal splitCtrl + b → "
NavigationCtrl + b → arrows
Closeexit / Ctrl + d

Scenario: server on the left, console on the right.


A config for OpenCode in Windows Terminal

Vanilla tmux just works. But when OpenCode (a TUI) runs inside it under Windows Terminal, small things break. Below is the config that fixes them.

File: ~/.tmux.conf

# 1. Terminal environment
set -g default-terminal "tmux-256color"

# 2. Everything Windows Terminal needs, in one line:
#    RGB (TrueColor): fixes backgrounds in OpenCode
#    extkeys: Shift+Enter (soft wrap)
#    clipboard: clipboard
#    cstyle: cursor shape
set -as terminal-features ",xterm-256color:RGB:extkeys:clipboard:cstyle"

# 3. Mouse and extended keys
set -g mouse on
set -s extended-keys on

# 4. Clipboard for OpenCode
set -g set-clipboard on
set -g allow-passthrough on

# 5. Guard against garbage on status-bar clicks
#    (OpenCode enables mouse tracking, and Windows Terminal echoes)
set -g focus-events off
bind-key -n MouseDown1Status select-window -t= \; send-keys -M

What are the problems?

Problem 1: copy doesn't work. OpenCode says "Copied", but the Windows clipboard is empty. Reason: tmux doesn't pass through OSC 52 ANSI codes by default. Fix: allow-passthrough on.

Problem 2: garbage in the input line on status-bar clicks. You click on 0:bash*, and junk like 7070b8b/a8a8e3e3... flies into the console. Reason: OpenCode keeps the terminal in mouse/focus tracking mode; a click on the status bar produces an echo reply from Windows Terminal that sails straight through tmux. Fix: focus-events off and intercept status-bar clicks to switch windows.

After the edits, restart the server:

tmux kill-server

On the next launch everything is clean.


Coordinating agents

This, to me, is the whole point of the exercise: tmux as a layer between AI agents. Right now I run OpenCode (the orchestrator) and Pi Agent. Each in its own pane; the orchestrator sends requests to the executor and reads the reply straight through tmux.

An idea for later: Claude Code and locked-in pricing

Anthropic has two billing modes for Claude Code, and the difference is large:

My simple thesis here: for any locked-in pricing, a proper automation workaround eventually shows up. For Claude Code the potential loophole is this: run orchestration not through the API/Agent SDK, but through the interactive TUI. Open Claude Code in a neighboring tmux pane and drive it directly — send keystrokes, read the reply. Then usage formally stays "interactive" and stays in the cheap subscription tier instead of slipping into expensive automation.

Honestly: this is a hypothesis I haven't yet tested in practice, not a ready recipe. I'm keeping it for later. So far, the ollama cloud + opencode / pi combo fully covers my orchestration needs. I don't need a separate Claude Code. If the hypothesis pans out, I'll write a separate note with proof.


Next: herdr

If agents become your main scenario, the next step is herdr. It's not tmux, it's a separate multiplexer built for agents: same model with the ctrl+b prefix, but its own bindings. The upside is that the mouse just works out of the box and a sound fires when an agent is waiting for you. And the sidebar shows which agent needs attention. You learn tmux precisely so you don't have to retrain onto a different approach later — you step straight into herdr.


Cheatsheet

# Sessions
tmux new -s <name>       # create
tmux a -t <name>         # attach
tmux ls                  # list
tmux kill-server         # restart everything
# Inside tmux (Prefix = Ctrl + b)
Prefix + d               # detach
Prefix + c               # new window
Prefix + ,               # rename window
Prefix + %               # vertical split
Prefix + "               # horizontal split
Prefix + arrows          # navigation
Prefix + 0-9             # window by number

This note was assembled from a real setup. The basics and the config are tested on myself. The idea about Claude Code via tmux remains a hypothesis for later.

← Prev.
Half a year of porting now fits in one Saturday?