Operator
A telephone operator connecting calls at a switchboard
Generated image

Operator · a macOS app for Claude Code

You run the agents.

Every tool call, diff, and delegation on one board. Every task in its own git worktree. Nothing leaves your machine.

A personal project, built for the way I run Claude Code all day. Public in case that resembles your setup.

Download for macOS GitHub Free · MIT · ~10 MB

Navigating

01

Pick up any project, mid-flight

the gallery

Every repo you work in, with the ones running agents right now saying so. Active projects are cards, shelved ones are rows, and shelving writes archivedAt the moment you decide it. Nothing files itself away on a timer.

02

Keep every agent in peripheral view

the left list
scoped to operator v0.15.1
Projects
operator2 running
Coderunning
Designyour turn
Researchidle
el-encanto1 needs you
mantel
Plan usageAgents
homeBacklog 1 · Running 1 · Waiting 1 · Done 2
Refactor the auth modulerunning code · in its own worktree
Implement the reply sentinelheld · needs you a dispatch from Research, waiting on approval
Fix the tray icon in dark modedone · green design · +14 −3, check passed
Collapsed and expanded are the same list. An agent never appears twice.

Every active project stays on screen, and the one you are in unfolds its agents beneath it. An agent appears exactly once, so there are never two lists to reconcile. Collapse it to 60px and the same list becomes tiles.

Watching

03

Watch the call tree as it happens

nothing to install
orchestration · session 7c1f live
refactor auth module orchestratoropus running
Read src/auth/session.ts0.4s
Grep 'refreshToken'0.2s
delegate › extract-types haiku2.1s
Read types/auth.d.ts0.3s
delegate › write-tests sonnet3.2s
Edit auth/session.test.ts3.2s
Bash npm testqueued
3 tools 2 subagents worktree auth-refactor

Nested tool calls, subagent delegations, durations ticking as they run, and what is queued behind them. Rebuilt from Claude Code's own transcript files, so there is nothing to instrument. The tailer polls once a second: you watch phases, not keystrokes.

04

Read what the agent did, not just what it said

transcript and plan
transcript · refactor auth live
Refactor auth so the token is passed explicitly, then update the tests.
I'll thread the token through refresh(), then adjust the suite.
Read 7 files
Searched 3 times
Delegated to a subagentwrite-tests
Edited auth/session.test.ts
Editing Stop
plan mode 3/5
Map the token flow through session.ts
Thread the token into refresh()
Extract the shared AuthError type
Update auth/session.test.ts
Run the suite and note coverage
The agent's own TodoWrite, rendered live.

Tool runs are first-class blocks, and consecutive ones of a kind coalesce, so a two-hundred-turn session stays readable. The status line says what is happening rather than which tool is running, send becomes Stop while it works, and the agent's own plan ticks off beside it.

05

Take the keyboard back mid-task

a real pty
terminal · auth-refactor zsh
~/operator claude
Refactoring the auth module…
Read src/auth/session.ts · Grep 'refreshToken'
Dev server is running: http://localhost:5273/
✓ 24 passed
~/operator
pid 48213 OPERATOR_DEV_PORT 5273
sessions 4 open
refactor auth module ⤷ 2 running
port the theme system your turn
sweep flaky tests idle
compact session log compacting…
Each session tinted by what it is doing right now.

Every session is a real pty you can type into, not a re-render of one. Run a command yourself, then hand it back. Sessions run concurrently, each with its own reserved dev port, and the preview tab probes that port and the usual defaults to render whichever server answers.

Directing

06

Staff the project once, then work the board

project home
team · operator 2 running
orchestrator fable running
code opus running
design sonnet your turn
Ready · 3
research sonnet idle
review opus idle
qa haiku idle
The coordinator carries the only filled badge.
board · operator project home
Backlog · 1
Write release notes for 0.16 unassigned
Running · 1
Refactor the auth module coderunning
Waiting · 1
Implement the reply sentinel held · needs you
Done · 2
Fix the tray icon in dark mode design+14 −3 · pass
Port the theme system abandoned
The card is the task. The agent is a chip on it.

Each lane pins a model, an effort level, and permissions, so launching a correctly configured session is one click instead of a setup ritual. Work moves on the board: the card is the task, the agent is a chip on it, and Waiting is the column that needs you. Finishing runs the project's check command, so done can read done and green. A task whose lane vanished reads abandoned, because nobody saw the work finish.

07

Hand work between agents, on the record

the dispatch log
dispatches · operator 1 needs approval
Today
Operator → Code18:54 delivered
Fix the tray icon in dark mode. Brief in dev/briefs/tray.md.
Research → Code19:14 held · needs your approval
Implement the reply sentinel per dev/briefs/reply-impl.md.
Approve & sendDecline
Review → Design19:22 held · pair sending too fast
Same finding, third message in a minute. The brake suspends the pair, not the lanes.
Code → Research19:26 not delivered · lane wasn't running
Where does the dispatch parser live now?
Nothing here retries on its own. Every chip says why.

One agent can route a task to another, and every hop lands here with its outcome on a chip. A dispatch from a lane that is not the coordinator is held until you approve it, chains brake themselves, and nothing retries. Results come back through operator__report and arrive on the board as a diff, not as chat.

08

Pick the model where you define the agent

your .claude/agents
agents 5 defined
extract-types haikuproject
write-tests sonnetproject
security-review opususer
plan-architect opusplanproject
docs-writer haikuuser
opusplan plans with Opus, then builds with Sonnet.

Haiku for extraction, Sonnet for the everyday, Opus where it earns its keep, chosen at the point where you say what the agent is for. It edits the .claude/agents files you already have and writes back to the same markdown, so your agents keep working in the terminal with Operator closed.

Landing

09

Run agents in parallel without collisions

one worktree per task
worktrees 3 active
auth-refactor opus running +142 −38
docs-pass haiku ready +9 −2
flaky-tests sonnet merged → main
Branches never collide with main.
fan-out · fix the flaky test 4 agents
retry-fix-1 1/4 running +21 −9
retry-fix-2 2/4 your turn +14 −3
retry-fix-3 3/4 running +47 −18
retry-fix-4 4/4 queued +0 −0
One prompt, four attempts. Keep the best diff.

One git worktree per task, so parallel agents never share a checkout and nothing touches your working tree until you say so. Fan-out sends the same prompt to N of them at once; you read the diffs side by side and keep one.

10

Review the diff and land it in place

local only
review · auth/session.ts +3 −1
@@ -18,7 +18,9 @@ export async function refresh(token)
export async function refresh(token: string) {
- const res = await fetch('/api/refresh')
+ const res = await fetch('/api/refresh', {
+ headers: { authorization: `Bearer ${token}` },
+ })
if (!res.ok) throw new AuthError(res.status)
return res.json()
}
2 of 5 files reviewed commit, merge, or discard
usage · last 7 days 25.6M tokens
sonnet12.7M
in 2.8Mout 610Kcache 9.3M
haiku7.2M
in 5.1Mout 120Kcache 2.0M
opus5.6M
in 1.2Mout 340Kcache 4.1M
API time14m 02s
Wall time1h 38m
Parsed from your own local transcripts. Nothing sent anywhere.

Work comes back as a diff you read in place, then commit, merge, or discard without leaving the window. Usage is tokens per model, split into input, output, and cache reads. No dollar figures anywhere: what a token costs depends on your plan.

Scope

Operator hosts Claude Code's own CLI over a pty and reads the transcripts it writes. Everything above follows from that, including the parts it will not do.

BehaviourStatusWhy
Stop an agent mid-rundoes Send becomes Stop. That is Claude Code's own interrupt, not a kill: the session survives and hands the turn back.
Push a message into a busy laneleaves alone One submit queue per terminal. A mid-turn message rides the lane's own queue and is read at the turn boundary.
Let two agents talk foreverleaves alone A reply chain with no human in it hits a hop limit, and a pair sending too fast is suspended.
Host or proxy the modelleaves alone It runs the CLI you already have. Your Claude Code auth, your account, your session.
Send anything to a serverleaves alone Transcripts are read from disk and rendered locally. No upload, no telemetry, no account. The code is public, so this row is checkable.
Estimate what a session costleaves alone Tokens are measurable. Dollars depend on your plan.

Why it exists

I run several Claude Code sessions at once, across a few repos. I wanted one window where I could see what each was doing, stop the one that had gone wrong, and read the diff before it reached my working tree. Operator is that window. Every panel above exists because I needed it, in the order I needed it.

It is not a product. No roadmap, no support queue, no telemetry, no account. I use it every day, which is the only guarantee it comes with. The source is MIT, so if it is close but not quite right for you, it is yours to change.

Operator, standing by.

Free, about 10 MB. It reads the Claude Code sessions you already run.