Agents
Registers Unterm as an MCP server with every agent it finds, adds a short note to their global context (CLAUDE.md, AGENTS.md, GEMINI.md) and wires the lifecycle hooks that report their state.
unterm-cli setup-ai --dry-run # what would change
unterm-cli setup-ai # register with every agent found
Limit it with --client claude-code (repeatable); undo everything with --remove.
The same inbox as Ctrl Shift A, on the command line. With --json it feeds a status bar, a notifier or a cron job.
unterm-cli agent inbox
# just the ones waiting on you
unterm-cli --json agent inbox \
| jq -r '.items[] | select(.state=="waiting") | "\(.agent): \(.task_hint // .pane_title)"'
What it prints
PANE AGENT STATE FOR TAB TASK
3 ✋ codex waiting 23s 2 Partition the ledger tables
4 ✓ claude done 13s 3 Fix the flaky checkout e2e test
2 ⚡ claude working 27s 1 Add rate limiting to /v1/charge
codex: Partition the ledger tables
States are waiting, done, working and idle, sorted waiting-first.
Unterm reads an agent's state from its title and screen. Its own hooks (Claude Code hooks, Codex notify, Aider's notification command) are more precise: they say “waiting” the moment the agent asks.
unterm-cli agent enable-hooks --dry-run
unterm-cli agent enable-hooks
setup-ai already does this; this is the hooks alone, and --remove takes them out.
Each member gets its own git worktree, branch and tab. Compare the diffs, run your checks in each worktree, merge one and discard the rest.
cd ~/code/payments-api
unterm-cli fleet launch --cwd "$PWD" --agents claude,codex \
-- "add an idempotency key to POST /v1/charge"
unterm-cli review diff --fleet add-an-idempotency-key --member 1 --stat
unterm-cli review verify --fleet add-an-idempotency-key --member 1 --command "cargo test"
unterm-cli review merge --fleet add-an-idempotency-key --member 1
unterm-cli review discard --fleet add-an-idempotency-key --member 2
unterm-cli fleet clean add-an-idempotency-key
What it prints
fleet add-an-idempotency-key launched — 2 member(s)
claude fleet/add-an-idempotency-key-1 ~/code/payments-api.fleet/add-an-idempotency-key-1
codex fleet/add-an-idempotency-key-2 ~/code/payments-api.fleet/add-an-idempotency-key-2
+? -0 idempotency.rs (new)
verification verify-1790326294259-0 queued: cargo test
merged fleet/add-an-idempotency-key-1 — staged in ~/code/payments-api (commit it yourself)
member 2 of add-an-idempotency-key discarded
fleet add-an-idempotency-key cleaned
The merge is a squash left staged in your repo — the commit is yours. A member's uncommitted edits are included. Pass --cwd when you launch from a shell; without it the fleet uses the focused pane's folder.
The command appears as ghost text in the pane. You press Tab to take it or keep typing to ignore it — nothing runs without you.
unterm-cli session suggest post --rationale "tests passed" \
-- "git push origin feat/rate-limit"
unterm-cli session suggest list
What it prints
Suggestion: sg_1790324293038_1
Status: queued
SUGGESTION PANE AGENT TEXT
sg_1790324293038_1 5 anonymous git push origin feat/rate-limit
session suggest list shows what is pending; cancel withdraws one.
Scripting
For a script that needs a real shell with your environment: create a tab in the right folder, run a command and wait for it to finish, then read the screen.
P=$(unterm-cli session create --cwd ~/code/infra | awk '/^Pane:/{print $2}')
unterm-cli exec wait --pane-id $P --timeout-ms 600000 -- "git log --oneline -3 && ls"
unterm-cli session text --pane-id $P | tail -20
What it prints
2f1cf7d (HEAD -> main) init
README.md
exec wait returns the command's output when it exits; exec run fires and forgets.
Put a log tail or a test watcher under the pane you are working in, without touching the mouse.
unterm-cli session split --direction down --size-percent 35 --cwd ~/code/web-dashboard
What it prints
Pane: 6
Title: /bin/zsh
Direction: down
Directions are right, left, down and up.
Each running Unterm has a name — alpha, bravo, … — and every CLI command can be aimed at one.
unterm-cli instance set-title "payments on-call"
unterm-cli instance list
unterm-cli --instance bravo agent inbox
unterm-cli instance set-title --clear
What it prints
Title: payments on-call
ID PID MCP HTTP CWD TITLE
alpha 1383 49173 19877 payments on-call
Without --instance, commands go to the active instance.
Line-delimited JSON-RPC over TCP on 127.0.0.1. The port and a token are in the instance file; log in first, then call any of the 151 methods.
J=~/.unterm/server.json # %USERPROFILE%\.unterm\server.json on Windows
PORT=$(jq .mcp_port $J); TOKEN=$(jq -r .auth_token $J)
{ printf '{"jsonrpc":"2.0","id":1,"method":"auth.login","params":{"token":"%s"}}\n' "$TOKEN"
printf '{"jsonrpc":"2.0","id":2,"method":"agent.status"}\n'
sleep 1; } | nc 127.0.0.1 "$PORT"
What it prints
{"id":1,"jsonrpc":"2.0","result":{"status":"ok"}}
{"id":2,"jsonrpc":"2.0","result":{"agents":[{"agent":"codex","pane_id":3,"state":"waiting",…},…],"enabled":true}}
unterm-cli reference lists every method; MCP clients can use the unterm-cli mcp-stdio bridge instead.
Keep and share
Plain text, no escape codes: the last N lines, or the whole session as Markdown with its project and shell recorded at the top.
unterm-cli scrollback --pane-id 2 --tail 200 > last-run.txt
unterm-cli session export --pane-id 2 -o session.md
What it prints
---
unterm_session_id: e2320821-38dc-4148-b94f-9bd4eef56357
tab_id: 2
project_path: ~/code/payments-api
project_slug: payments-api
Add --escapes to keep colours; --start-line/--end-line pick a range.
One tall PNG of everything a pane printed, rendered off-screen, so it works while the window is covered.
unterm-cli screenshot --scrollback --pane-id 2 -o pane.png
--max-rows caps it; on macOS, --scroll-app Safari does the same for another app's window.
Commands and their output, redacted and kept next to the project in .unterm/sessions — which Unterm tells git to ignore.
unterm-cli session record start
# … work in the pane …
unterm-cli session record stop
unterm-cli sessions list
unterm-cli sessions read <session-id>
What it prints
Session id: next-core-5-1790324289544601
Block count: 4
Markdown: ~/code/infra/.unterm/sessions/1790324289544601/tab-5-1790324289544601.md
Exit reason: recording_stopped
sessions list --project <slug> narrows it to one project.
A named set of tabs and their folders. Restore it after a reboot, or on another day's work.
unterm-cli workspace save morning
unterm-cli workspace restore morning --dry-run
unterm-cli workspace restore morning
What it prints
Workspace: morning
Sessions: 6
Workspace: morning
Planned: 6
--dry-run shows what would open without opening it.
Set it up your way
A profile carries tokens, a git identity and SSH keys. Secrets live in the system keychain and appear as environment variables only in that profile's tabs.
unterm-cli profile create "Work — Acme" --accent "#E8B34B"
unterm-cli profile set-secret "Work — Acme" GITHUB_TOKEN # asks for the value
unterm-cli session create --cwd ~/code/acme --profile work-acme
What it prints
Created profile "Work — Acme"
ID: work-acme
Stored GITHUB_TOKEN in keychain for profile work-acme
macOS asks once for keychain access the first time a profile's secret is read. Pipe from a password manager with --from-stdin.
Open the command palette and choose “New Administrator Window”. Windows asks through UAC, then opens a separate, elevated Unterm.
It shares nothing with your normal window — no Core, no MCP server, no settings page — so nothing running as you can type into an elevated shell. Its title starts with “Administrator:”.
Settings live in ~/.unterm/unterm.conf. A few worth knowing:
font_size = 14
[window]
padding_left = 16
padding_right = 16
backdrop = "mica" # Windows 11
[cockpit]
done_hold_secs = 30 # how long a finished agent stays marked
unterm-cli settings open opens the settings page in your browser instead.
The full list, with anything you have rebound, is unterm-cli show-keys.
| CtrlShiftP | Command palette |
| CtrlShiftA | Agent inbox |
| CtrlShiftAltA | Launch a fleet |
| CtrlShiftS | Quick select: copy a path, hash or URL by its label |
| CtrlShiftJ | Composer: write a long prompt, send it when the pane is idle |
| CtrlShiftG | Git panel |
| CtrlShiftD / E | Split right / down |
| CtrlShiftZ | Zoom the focused pane |