agency_demo.mp4
curl -fsSL https://raw.githubusercontent.com/lemonsaurus/agency/main/install.sh | bashThis handles everything — installs tmux 3.5+ (building from source if your distro's version is too old), Go 1.24+, and agency itself. Sudo is only used for system-level installs (apt, /usr/local); everything else runs as your user.
You'll also need at least one agent CLI: claude, codex, gemini, pi, or any command you like.
Manual install
- Go 1.24+
- tmux 3.5+ (most distros ship an older version — Ubuntu 24.04 has 3.2a)
socatorncfor the agent self-spawn script
sudo apt install -y build-essential libevent-dev libncurses-dev \
autoconf automake pkg-config bison
TMUX_VERSION=3.5a
curl -sL "https://github.com/tmux/tmux/releases/download/${TMUX_VERSION}/tmux-${TMUX_VERSION}.tar.gz" \
| tar xz
cd tmux-${TMUX_VERSION}
./configure && make -j$(nproc) && sudo make install
tmux -V # should show 3.5a or newerIf
tmux -Vstill reports the old version, make sure/usr/local/bincomes before/usr/binin your$PATH.
After upgrading, kill any running tmux server so it picks up the new binary: tmux kill-server
git clone https://github.com/lemonsaurus/agency
cd agency
make install # builds and copies to ~/.local/bin/Agency turns your terminal into a Bloomberg-style multi-terminal workstation. Every pane stays on screen in a tiled grid — no tabs, no alt-tabbing, no context switching. Designed for giant ultrawide monitor nerds who are trying to juggle and keep track of 10+ terminal sessions.
Each pane gets a unique color and a bold agent@folder label in its border, so you always know what's running where. Borders dynamically switch color to match the label. Each label has an icon. Hotkeys to start pi, claudejail, codex and gemini sessions.
PS: This is not really appropriate for a small monitor - for that use case, maybe check out agent deck.
- Everything on screen at once — tiled grid layout, auto-rebalances on every spawn
- Per-pane color labels — every pane gets a unique color and a
claudejail@myappstyle border label - Directory-aware spawning —
agency spawn claude ~/projects/api ~/projects/frontendopens one pane per directory - Glob support —
agency spawn claude ~/projects/client-*expands via your shell - Bounded delegation: controllers create managers, managers create workers, workers cannot spawn
- Spawn dialog —
Prefix+2/3/4/5opens a directory picker pre-filled with the current pane's path - Command palette —
Prefix+cfuzzy-searches all configured agent types - Crash recovery — if agency restarts, it re-adopts existing tmux panes automatically
- Isolated tmux config — agency manages its own
tmux.conf, never touches your~/.tmux.conf - Catppuccin Mocha theme — inline, no plugin dependencies
agency # launch (creates a new tmux session, or reattaches)Inside the session, use Prefix+c (Ctrl+Space, c) to open the command palette and pick an agent type. Or use the number keys:
| Shortcut | Action |
|---|---|
Prefix+1 |
New plain terminal (in current pane's directory) |
Prefix+2 |
Spawn pi (opens directory picker) |
Prefix+3 |
Spawn claudejail |
Prefix+4 |
Spawn codex |
Prefix+5 |
Spawn gemini |
Prefix+c |
Command palette (all agent types) |
agency Launch session (or reattach if one exists)
agency spawn <agent> [dir...] Spawn one pane per directory
agency spawn --cmd "htop" [dir] Spawn an arbitrary command
agency spawn --role <role> ... Programmatic manager or worker spawn
agency whoami [--role] Print current pane authority
agency replace [--cmd "..." dir] Start a role-preserving successor
agency request-promotion <reason> Request worker promotion
agency approve-promotion <pane> Approve promotion (human tmux authority only)
agency kill <pane-id> Kill a specific pane
agency kill-all Kill all managed panes
agency list List all panes
agency layout <name> Switch layout (tiled, columns, rows, main-vertical)
agency attach Reattach to a running session
agency config Print resolved config
agency logs Print path to the log file (tail -f it)
agency help Show help
You can also spawn multiple agents across many directories in one shot:
# One claude pane per client directory
agency spawn claude ~/projects/client-*/
# Three codex panes, explicit paths
agency spawn codex ~/api ~/frontend ~/infraThe tmux prefix is Ctrl+Space.
| Shortcut | Action |
|---|---|
Prefix+c |
Command palette |
Prefix+1 |
New terminal |
Prefix+2–5 |
Spawn agent (opens directory picker) |
| Shortcut | Action |
|---|---|
Prefix+Arrow |
Move focus between panes |
Prefix+Shift+Arrow |
Resize pane |
| Click | Focus pane (mouse enabled) |
| Scroll | Scroll pane history |
| Shortcut | Action |
|---|---|
Prefix+= |
Tiled grid (even distribution) |
Prefix+| |
All columns (ultrawide mode) |
Prefix+- |
All rows stacked |
Prefix+m |
Main pane left, stacked right |
Prefix+Space |
Cycle through layouts |
| Shortcut | Action |
|---|---|
Prefix+x |
Kill focused pane (with confirmation) |
Prefix+q |
Kill session (Enter or y to confirm) |
Prefix+f |
Zoom/unzoom focused pane |
Prefix+b |
Broadcast — type in all panes at once |
Prefix+P |
Approve the focused worker's pending promotion |
Prefix+r |
Respawn dead pane |
Prefix+d |
Detach (session keeps running) |
Agency assigns three pane roles:
controller: human-created, creates managersmanager: creates workersworker: cannot create panes
Tmux keybindings and popups carry human authority rather than focused-pane authority. New sessions name the first window control; default human spawns create controllers there. Agent spawns require an explicit child role. agency-spawn derives that role from the caller's live authority.
Role, parent, root, and pending promotion data live in tmux pane options for restart adoption. agency replace starts a successor in the same window and directory, with optional command and directory overrides for context handoff. It transfers children and returns the successor pane ID. The old pane stays alive until the caller checks the successor and retires itself.
Workers can run agency request-promotion <reason>. Agency notifies the root controller. A human approves the focused pending worker with Prefix+P; approval promotes it to manager, reparents it under the root controller, moves it to its former manager's window, and runs /handoff.
When agency launches it starts a unix socket server at /tmp/agency-{session}.sock and exports AGENCY_SOCKET into every pane's environment.
The agency-spawn script (installed to ~/.local/bin/) is a tiny wrapper agents can call:
agency-spawn claude # spawn a claude pane in the current directory
agency-spawn claude --dir ~/projects/api # spawn in a specific directory
agency-spawn --cmd "aider --yes" # spawn an arbitrary command
agency-spawn --replace # start a role-preserving successor
agency-spawn --request-promotion "reason" # ask the root controller for promotionControllers request managers, managers request workers, and workers receive an error. Worker-to-manager delegation policy belongs in the agent instructions, not Agency.
The protocol is plain text over the unix socket:
spawn-role:{"agent":"pi","role":"worker"} → explicit programmatic spawn
replace:{"command":"handoff-pi","dir":"/tmp"} → role-preserving successor
promotion-request:{"reason":"need fanout"} → worker promotion request
promotion-approve:%3 → human promotion approval
kill:%3 → kill pane %3
layout:tiled → switch layout
Agency looks for ~/.config/agency/config.toml. If it doesn't exist, built-in defaults are used. Copy configs/default.toml as a starting point:
mkdir -p ~/.config/agency
cp configs/default.toml ~/.config/agency/config.toml[session]
name = "agency"
default_layout = "tiled" # tiled | columns | rows | main-vertical
max_panes = 32
max_managers = 12
max_workers_per_manager = 8
[theme]
active_border = "#89b4fa"
inactive_border = "#45475a"
status_bg = "#181825"
status_fg = "#cdd6f4"
[agents.claudejail]
command = "claudejail"
icon = "🔒"
border_color = "#f38ba8"
[agents.claude]
command = "claude"
icon = "🤖"
border_color = "#cba6f7"
# Add your own agent types:
# [agents.aider]
# command = "aider --model ollama_chat/gemma3"
# icon = "🔧"
# border_color = "#a6e3a1"Agents are assigned to the number keys (Prefix+2 through Prefix+5) in the order they appear in the config file.
Agency ships two sandbox wrappers — one for Linux, one for macOS.
Runs Claude Code inside a bubblewrap sandbox. Restricts Claude's filesystem access to only the current working directory. Bubblewrap uses unprivileged user namespaces — no SUID root, no kernel modules. Works reliably on WSL2.
What the sandbox does:
- Starts with an empty
$HOME, then bind-mounts only$PWD(read-write),~/.claude(read-write), and theclaudebinary (read-only) - Drops all Linux capabilities
- Isolates PID, IPC, and UTS namespaces
- Private
/tmpand/dev - Read-only system directories (
/usr,/bin,/lib,/etc) - Bind-mounts
~/.nvm,~/.gitconfig,~/.sshread-only (if they exist) - Allows network access (Claude needs the Anthropic API)
- Allows subprocess execution (Claude needs git, npm, bash, etc.)
- Dies with parent — sandbox is cleaned up if agency exits
# Install bubblewrap if you don't have it
sudo apt install bubblewrap
# Install the claudejail script
make install-claudejailThis copies one file:
~/.local/bin/claudejail— the wrapper script (sandbox config is inline)
Runs Claude Code inside a Docker container. Bubblewrap is Linux-only, so this is the macOS equivalent. Requires Docker Desktop.
What the sandbox does:
- Mounts only
$PWDinto the container — Claude cannot see the rest of your home directory - Mounts
~/.claudeso Claude retains its config, memory, and auth across sessions - Allows network access (Claude needs the Anthropic API)
- Allows subprocess execution (Claude needs git, npm, bash, etc.)
- Uses permissive Claude settings so long unattended sessions don't stall waiting for permission prompts
The Docker image is built automatically on first run (~1 min).
make install-claudejail-macThis copies one file:
~/.local/bin/claudejail-mac— the wrapper script
The one-liner installer (curl ... | bash) handles this automatically on macOS.
Then just use either wrapper anywhere you'd use claude:
cd ~/projects/myapp
claudejail # Linux
claudejail-mac # macOSInside agency, claudejail is the default Prefix+3 agent (Linux) and claudejail-mac is available on macOS. The source files live in scripts/claudejail and scripts/claudejail-mac.
Each pane gets a top-border label in the format agent@folder:
🔒 claudejail@api 🤖 claude@frontend 🧠 codex@infra
- The label background color is unique per pane, cycling through a 12-color palette
- Plain terminal panes (spawned with
Prefix+1) showzsh@currentfolderand update live as youcd - Labels are stored as tmux pane options (
@agency_label) so they survive application title changes
Pane borders are all the same color
You need tmux 3.4+ for per-pane pane-border-style. On older versions the colored badge in the top border status bar still shows per-pane colors; only the border lines themselves won't differ. See Installing tmux 3.5+ above.
agency spawn types into the current pane instead of opening a new one
This means agency isn't running (AGENCY_SOCKET isn't set or the socket server isn't listening). Start a session first with agency, then spawn from a pane inside it.
Command palette / spawn dialog doesn't appear
display-popup requires tmux 3.2+. Also verify agency is in your $PATH — the keybindings call it by name.
Check the logs
tail -f $(agency logs)Work directly on main. Don't create feature branches, worktrees, or pull requests. Start with a clean checkout; if it isn't clean, finish or resolve that work first. Commit every finished change and push main. Don't leave dirty files behind.
make build # compile
make install # build + install to ~/.local/bin/
make uninstall # remove all installed binaries
go test ./... # run tests
go vet ./... # static analysisTo test the installer against your local checkout instead of cloning from GitHub:
REPO_DIR=$(pwd) bash install.shSee CLAUDE.md for the full architecture spec and development guidelines.
