Organizing Coder Terminals: Difference between revisions
Justinaquino (talk | contribs) Created article on organizing coder terminals with tmux (2026-05-02) |
Justinaquino (talk | contribs) Added RCA: tmux send-keys broke launchers, fixed with direct exec; ce-char-gen troubleshooting |
||
| (One intermediate revision by the same user not shown) | |||
| Line 49: | Line 49: | ||
== How to Title Your Session == | == How to Title Your Session == | ||
=== The Default Title Is the Command Itself === | |||
Every new terminal opens with the title: | |||
<pre> | |||
title "project" | |||
</pre> | |||
This is intentional — the '''default title is the command reminder'''. You never forget the syntax because it's staring at you from the tab. | |||
=== Change It === | |||
Inside any terminal, type: | Inside any terminal, type: | ||
| Line 128: | Line 139: | ||
|- | |- | ||
| Tab right-click has no "Set Title" || GNOME Terminal 3.44+ removed it || Use <code>title</code> bash command or <code>Ctrl+b ,</code> | | Tab right-click has no "Set Title" || GNOME Terminal 3.44+ removed it || Use <code>title</code> bash command or <code>Ctrl+b ,</code> | ||
|- | |||
| <code>title</code> command not found || <code>.bashrc</code> not loaded || Start an interactive shell, or run <code>source ~/.bashrc</code> | |||
|- | |||
| Default title shows <code>title "project"</code> || Working as designed — syntax reminder || Type <code>title "your real project"</code> to replace it | |||
|- | |||
| Tmux status bar shows <b>"ce char gen"</b> || Old <code>~/.tmux.conf</code> on host hardcoded the title || Replace host <code>~/.tmux.conf</code> with container's clean version | |||
|- | |- | ||
| AI agent crashed and pane is dead || Process exited || Press <code>Ctrl+b r</code> to respawn | | AI agent crashed and pane is dead || Process exited || Press <code>Ctrl+b r</code> to respawn | ||
| Line 133: | Line 150: | ||
| Session already exists || Previous session still running || <code>tmux attach -t <name></code> or <code>tmux kill-session -t <name></code> | | Session already exists || Previous session still running || <code>tmux attach -t <name></code> or <code>tmux kill-session -t <name></code> | ||
|} | |} | ||
== RCA: Why Tmux Broke the Original Launch Scripts == | |||
=== What Worked Before (No Tmux) === | |||
<pre> | |||
distrobox enter agent260411 -- bash -c 'cd /home/justin/opencode260220 && ./csb.sh; exec bash' | |||
</pre> | |||
<code>./csb.sh</code> does <code>exec claude</code>, which replaces the shell with the interactive AI agent. Claude owns the TTY and runs until the user exits. | |||
=== What Broke (First Tmux Attempt) === | |||
The initial <code>tmux-launcher.sh</code> used <code>tmux send-keys</code> to type commands into a detached session: | |||
<pre> | |||
tmux new-session -s "$SESSION" -n "$WINDOW" -d | |||
tmux send-keys -t "$SESSION:$WINDOW" "./csb.sh" C-m | |||
tmux attach-session -t "$SESSION" | |||
</pre> | |||
=== Why This Failed === | |||
# '''Race condition''': <code>send-keys</code> types faster than the shell initializes. The command often arrived before bash was ready, causing "command not found" or silent failure. | |||
# '''No TTY guarantee''': Interactive apps (Claude, Kimi) need a controlling terminal. <code>send-keys</code> provides a pane but doesn't guarantee the app receives proper TTY initialization before the keystrokes land. | |||
# '''Exit timing''': If the app started before attach, the user attached to a pane that was already dead or mid-execution. | |||
=== The Fix === | |||
Replace <code>send-keys</code> with direct command execution via a wrapper script. This gives tmux the full command upfront, so it initializes the TTY properly before the app starts — exactly like the original scripts, just wrapped in tmux. | |||
== See Also == | == See Also == | ||
Latest revision as of 08:13, 2 May 2026
Problem
When running multiple AI coding agents (Claude, Kimi, Qwen, OpenCode) in separate GNOME Terminal windows, every tab looks identical — usually titled by the running process name (e.g., "Kimi Code"). After opening 3–4 terminals, it becomes impossible to tell at a glance which terminal belongs to which project without clicking into each one.
GNOME Terminal 3.44+ removed the "Set Title" option from the tab right-click menu, eliminating the old manual workaround.
Solution
Use tmux inside every terminal:
- One named tmux session per project (e.g.,
claude,kimi,qwen) - A
titlebash command that renames both the tmux window and the terminal title - Persistent panes — if an AI agent crashes, the pane stays alive and can be respawned
Quick Start
Launch All Agents at Once
Run on the Ubuntu desktop:
~/start_dev_env.sh
This opens 5 GNOME Terminal windows:
| # | Window Title | Tmux Session | Purpose |
|---|---|---|---|
| 1 | Claude Code — tmux | claude | Claude Code AI agent |
| 2 | OpenCode Claude — tmux | opencode-claude | OpenCode (Claude provider) |
| 3 | OpenCode Kimi — tmux | kimi | OpenCode (Kimi provider) |
| 4 | OpenCode Qwen — tmux | qwen | OpenCode (Qwen provider) |
| 5 | Tmux — General | general | Plain bash for git, docker, file ops |
Each session survives even if the GNOME Terminal window is closed.
Launch Individual Agents
Double-click any desktop launcher:
~/Desktop/claude.sh~/Desktop/kimi.sh~/Desktop/opencode.sh~/Desktop/Qwen.sh
Each launcher auto-creates or reattaches to its tmux session.
How to Title Your Session
The Default Title Is the Command Itself
Every new terminal opens with the title:
title "project"
This is intentional — the default title is the command reminder. You never forget the syntax because it's staring at you from the tab.
Change It
Inside any terminal, type:
title "ce char gen"
This does two things:
- Renames the tmux window (visible in the green status bar at the bottom)
- Sets the GNOME Terminal tab/window title
Change it anytime:
title "mneme shipgen" title "IT-knowledge docs" title "$(hostname)" # reset to hostname
The title auto-resets after every shell prompt, so AI agents cannot overwrite it.
Tmux-Only Renaming
tmux rename-window "my project" # rename current window tmux rename-session "newname" # rename entire session
Key Shortcuts
| Key | Action |
|---|---|
| Ctrl+b , | Rename current window (interactive prompt) |
| Ctrl+b r | Respawn pane (restart AI agent if it crashed) |
| Ctrl+b d | Detach session (keeps it running in background) |
| Split pane horizontally | |
| Ctrl+b - | Split pane vertically |
| Alt+Arrow | Switch panes |
| Ctrl+b R | Reload tmux config |
Reattaching to Sessions
If a terminal window is closed, the tmux session keeps running:
tmux list-sessions tmux attach-session -t claude tmux attach-session -t kimi
Aliases added to ~/.bashrc:
tls # list sessions tas claude # attach to claude session
Configuration Files
| File | Purpose |
|---|---|
~/.tmux.conf |
Tmux settings (status bar, mouse, key bindings) |
~/.bashrc |
title() function + auto-reset + tmux aliases
|
~/.config/tmux-launcher.sh |
Helper script for desktop launchers |
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Title shows "Kimi Code" instead of custom | AI resets it via escape sequences | PROMPT_COMMAND auto-resets after every prompt
|
| Tab right-click has no "Set Title" | GNOME Terminal 3.44+ removed it | Use title bash command or Ctrl+b ,
|
title command not found |
.bashrc not loaded |
Start an interactive shell, or run source ~/.bashrc
|
Default title shows title "project" |
Working as designed — syntax reminder | Type title "your real project" to replace it
|
| Tmux status bar shows "ce char gen" | Old ~/.tmux.conf on host hardcoded the title |
Replace host ~/.tmux.conf with container's clean version
|
| AI agent crashed and pane is dead | Process exited | Press Ctrl+b r to respawn
|
| Session already exists | Previous session still running | tmux attach -t <name> or tmux kill-session -t <name>
|
RCA: Why Tmux Broke the Original Launch Scripts
What Worked Before (No Tmux)
distrobox enter agent260411 -- bash -c 'cd /home/justin/opencode260220 && ./csb.sh; exec bash'
./csb.sh does exec claude, which replaces the shell with the interactive AI agent. Claude owns the TTY and runs until the user exits.
What Broke (First Tmux Attempt)
The initial tmux-launcher.sh used tmux send-keys to type commands into a detached session:
tmux new-session -s "$SESSION" -n "$WINDOW" -d tmux send-keys -t "$SESSION:$WINDOW" "./csb.sh" C-m tmux attach-session -t "$SESSION"
Why This Failed
- Race condition:
send-keystypes faster than the shell initializes. The command often arrived before bash was ready, causing "command not found" or silent failure. - No TTY guarantee: Interactive apps (Claude, Kimi) need a controlling terminal.
send-keysprovides a pane but doesn't guarantee the app receives proper TTY initialization before the keystrokes land. - Exit timing: If the app started before attach, the user attached to a pane that was already dead or mid-execution.
The Fix
Replace send-keys with direct command execution via a wrapper script. This gives tmux the full command upfront, so it initializes the TTY properly before the app starts — exactly like the original scripts, just wrapped in tmux.