Terminal multiplexer for coding agents · macOS & Linux
Claude Code left. Codex right. One screen.
yakka has one opinion about layout and gets out of the way after that. Each session runs in its own git worktree, so two agents can work at once without editing the same file — and in a detachable host, so leaving is not killing.
The split
The screen already told you who is waiting
Both sidebars are the same width, so the divider lands on the true centre of the window. Each side keeps its own session list, and every session carries one of three marks.
Working
It said something recently. Leave it alone.
Wants you
It went quiet, or rang the bell, while off screen.
Exited
The process is gone. Its last screen is kept, and Ctrl-a r restarts it.
▲ is the one to watch. It appears when an agent stops, not when it speaks — so it means "this one is waiting on you" rather than "this one is busy". Running several agents is only tolerable if you can tell, at a glance, which of them needs a human. That mark is the whole reason the sidebars exist.
In the list, ▸ is the session in the focused pane and · one that is on screen somewhere else.
Isolation
Two agents cannot edit the same file
Which is the point of running two at once. In the new-session picker, if the directory you have highlighted is inside a git repository, Tab switches to worktree mode.
yakka branches yakka/<agent>-N off the default branch, creates a worktree beside the repository, and starts the agent there. Two sessions on the same repo get two working trees and two branches, so neither can stand on the other's edits.
Killing a session removes its worktree — unless it has uncommitted changes, in which case yakka leaves it alone and says so. Nothing you have not committed is ever thrown away to tidy up.
The picker lists your scan roots and their immediate children, filtered as you type by fuzzy match. Recency only breaks ties between equally good matches, so the ordering never fights your typing.
Detaching
What --continue cannot do
The agents do not run inside the yakka you are looking at. They run in a per-user session host that yakka starts on first use and talks to over a unix socket.
So leaving is a detach rather than a kill. A resumed conversation replays what was said; reattaching finds the same process still running — mid-task, mid-output, with everything it had printed still on screen.
The host keeps the last couple of megabytes of each session's output. Past that the scrollback is dropped and reattaching restores the visible screen only.
If yakka cannot reach the host it says so and runs the agents itself, so a broken socket costs you detaching rather than the session. --no-server asks for that deliberately; either way quitting stops the agents, and yakka asks first.
| Ctrl-a q | Leave. The agents keep working. |
| yakka | Come back to them, screens and scrollback intact. |
| Ctrl-a Q | Stop every agent and close the host. |
| yakka kill | The same, from outside. |
| yakka --fresh | Start empty, ignoring the saved layout. |
Quitting saves the layout to state.json, so the next launch rebuilds the same panes — reattaching to anything the host still has, and otherwise resuming with claude --continue or codex resume --last, both scoped to the session's directory so nothing picks up an unrelated conversation from another repo.
Keys
A leader, not a chord
Press and release Ctrl-a, then press the command key on its own. Everything else goes straight to the focused agent, so the agents keep all of their own bindings.
| Key | Action |
|---|---|
| Ctrl-a h / l | Focus the left / right half |
| Ctrl-a j / k | Focus the pane below / above |
| Ctrl-a Tab / S-Tab | Next / previous session on this side |
| Ctrl-a 1–9 | Show the nth session of this side |
| Ctrl-a n | New session (directory picker) |
| Ctrl-a s | Split this half horizontally |
| Ctrl-a w | Close this pane, leave the session running |
| Ctrl-a x | Kill this session |
| Ctrl-a z | Zoom this pane to the whole window |
| Key | Action |
|---|---|
| Ctrl-a b | Show or hide the sidebars |
| Ctrl-a r | Restart the process in this pane |
| Ctrl-a [ | Scroll back through history |
| Ctrl-a d | Show what this session changed |
| Ctrl-a * | Broadcast keys to every visible pane |
| Ctrl-a m | Move this session to the other side |
| Ctrl-a , | Rename this session |
| Ctrl-a ? | Help |
| Ctrl-a Ctrl-a | Send a literal Ctrl-a to the agent |
In scroll mode: j/k by line, Ctrl-d/Ctrl-u by half page, g/G for the ends, / to search back, q back to live. The prefix is configurable — any ctrl-, alt- or shift- combination, or f1–f20.
Install
One binary, and two agents on your PATH
yakka runs claude and codex — it does not bundle them. Point it at anything else with an [[agents]] entry.
Recommended
Prebuilt binary
The macOS archive is universal — Apple Silicon and Intel. A Linux x86_64 build ships with every tag.
tar xzf yakka-macos-universal.tar.gz
chmod +x yakka
# unsigned, so clear the quarantine flag
xattr -d com.apple.quarantine yakka
mv yakka ~/.local/bin/Verify
Check the archive
Every release ships a .sha256 beside its archive.
shasum -a 256 -c yakka-macos-universal.tar.gz.sha256Rust toolchain
Build it yourself
Then just run yakka.
cargo install --git https://github.com/romankhadka/yakka --root ~/.localOptional
Configure
All of ~/.config/yakka/config.toml is optional. A side has a default agent, not a fixed one.
scan_roots = ["~/code"]
prefix = "ctrl-a"
max_panes = 2
left_agent = "claude"
right_agent = "gemini"
[[agents]]
name = "gemini"
command = "gemini"
resume = ["--continue"]Sidebars hide themselves below 100 columns; below 60×20 yakka says so rather than drawing something unusable. Where the terminal speaks the Kitty keyboard protocol — Ghostty, Kitty, WezTerm — key disambiguation is enabled so Shift-Enter reaches Claude Code as a soft newline. Hold Option on macOS, or Shift elsewhere, for your terminal's own selection while mouse capture is on.