A workplace for coding agents.

aegis serve runs Claude Code and OpenCode sessions on your machine and serves them to browser tabs: a Fleet view, shared tabs, a transcript per session, and an archive. The agents in it get monitors, queues of workers and handoffs over MCP, and an inbox that delivers what those produce.

uv tool install aegis-harness
cd ~/your/project
aegis

The last line serves and opens a browser window. Version 2.3.0 on PyPI, MIT licence, Python 3.13 or newer.

Fleet
Flaky CI: the websocket test…keen-noether
Release 2.4.0amber-hopper
Port the parser…calm-dijkstra
Docs: configurationplain-curie
+
studio2.3.0
studio
2 need you
2 working
1 waiting
1 done
Host
CPU
38%
RAM
41%12.9 / 31.3 GB
Disk
62%88 / 142 GB
Context
31%avg of 4 live
Quotaread 40s ago
Claude
5 hours
22%→ 64%↻ 3h 10m
week
61%↻ 2d 4h
OpenCode Go
month
45%→ 87%↻ 16d 9h

Sessions

Needs you
keen-noetherneeds you
Flaky CI: the websocket test that waits forever
Two fixes pass locally. Cap the wait at 25 s, or mock the socket? I lean to the cap.
reviewerclaude-opus-5-5 · acme/api
nowAsk Alex which fix to land
didRun the test 20 times and read the hung runs
2m ago$4.121 monitorplan 2/523%
amber-hoppererror
Release 2.4.0: build, tag, publish
uv.lock is out of date; the publish gate refused the tag.
opusclaude-opus-5-5 · acme/api
6m ago$1.8018%
Everything else
calm-dijkstraworking
Port the parser to the new tokenizer
opusclaude-opus-5-5 · acme/api
Bash · Run the parser suite against the fixtures
just now$8.522 unread40%
quiet-lovelaceworker · generalworking
Write the migration for the audit table
opusclaude-opus-5-5 · acme/api
Edit · migrations/0042_audit.py
30s ago$0.9412%
brisk-turingwaiting · 1 monitor
Benchmark the cold start on the staging box
opusclaude-opus-5-5 · acme/infra
14m ago$3.071 monitor55%
plain-curiedone
Docs: the configuration page
opusclaude-opus-5-5 · acme/docs
1h 12m ago$5.313 unread67%

What you get

Scroll. The window on the right follows the feature you are reading.

A Fleet that says who needs you

Each tab and Fleet card carries one of six marks: working, needs you, error, review, waiting or done. The Fleet orders cards by that mark and puts the ones that block on you first, oldest wait on top. Alt+J goes to the session that has waited longest.

aegis knows what you have read on every browser. The page title counts the sessions that need you, and a review you already read drops out of the group.

A transcript that reads well

A tool row closes on a one-line verdict, a failure in red. The output and the diff load when you open a row. Agent prose renders as Markdown in a reading face. A prompt sent mid-turn shows as pending until the agent reads it, and Esc interrupts.

The plan, the monitors, the cost

The sidebar carries what the agent reported: its plan with the item it is on, its monitors with their progress and ETA, the context window as a bar, the cost so far, and your Claude quota windows. Hovering a monitor opens its readings chart and each of its checks with the last exit code, so a check that cannot run shows red instead of looking like one still waiting.

One tap to answer

An agent ends each turn by saying how it ended and may offer up to three replies, which you send with one tap. /model, /effort and /permission switch a running session; / opens a menu that completes them, and an unknown command is refused rather than sent as a prompt. Alt+M dictates into the box, transcribed in the browser.

Tools for the agents themselves

Over MCP an agent starts a monitor with a bash done condition and is woken when it holds, hands a self-contained task to a fresh worker on a queue, reads a peer's transcript or hands it an instruction, and gives you a file that shows as a card with a preview. What those produce comes back as an inbox entry in the transcript.

On a phone

Below 760 px the tabs get their own row, the side panel becomes a drawer, and touch targets are 44 px. Chrome installs aegis from its menu as an app named after the server. A return to one of the last eight tabs, or a reconnect after the phone slept, sends only what changed.

The gauges

The Fleet band carries the session counts, the host's CPU, RAM and disk, the average context of the live sessions, and your Claude and OpenCode Go quota windows: the share already spent, where the window is heading at this pace, and when it resets.

Fleet
Flaky CI: the websocket…keen-noether
Port the parser…calm-dijkstra
Benchmark the cold startbrisk-turing
+
studio2.3.0
studio
1 need you
1 working
1 waiting
Host
CPU
38%
RAM
41%12.9 / 31.3 GB
Disk
62%88 / 142 GB
Quotaread 40s ago
Claude
5 hours
22%→ 64%↻ 3h 10m
week
81%→ 100%↻ 2d 4h

Sessions

Needs you
keen-noetherneeds you
Flaky CI: the websocket test that waits forever
Two fixes pass locally. Cap the wait at 25 s, or mock the socket? I lean to the cap.
reviewerclaude-opus-5-5 · acme/api
nowAsk which fix to land
didRun the test 20 times and read the hung runs
2m ago$4.121 monitorplan 2/523%
Everything else
calm-dijkstraworking
Port the parser to the new tokenizer
opusclaude-opus-5-5 · acme/api
Bash · Run the parser suite against the fixtures
just now$8.522 unread40%
brisk-turingwaiting · 1 monitor
Benchmark the cold start on the staging box
opusclaude-opus-5-5 · acme/infra
14m ago$3.071 monitor55%
10:02❯
The websocket test hangs CI for hours sometimes. Find out why and propose a fix.
10:02⌬
BashRun the websocket test 20 times20 runs, 3 hung
10:04📖
Readtests/test_ws.py212 lines
10:05⏺

The hang is a race. The test awaits recv() with no timeout, and when the server closes first that await never returns. Three of twenty runs hit it here, so CI hits it about once a day.

10:05✎
Edittests/test_ws.pyold_string not found
String to replace not found in file.
String:     msg = await ws.recv()
10:06✎
Edittests/test_ws.py1 line changed
tests/test_ws.py
- msg = await ws.recv()
+ msg = await asyncio.wait_for(ws.recv(), timeout=25)
10:07⌬
BashRun the suite142 passed in 31.2s
10:08⏺

Two fixes pass locally. Capping the wait at 25 s fails the run loudly instead of hanging it. Mocking the socket removes the race from the test but also the thing it tests. I lean to the cap.

11:20⇄
monitor_startthe full suite in CI, done when the run is no longer in progressmon_7c1e · every 60s · 25m
done: gh run view 4821 --json status -q .status | grep -qv in_progress
progress: gh run view 4821 --json jobs -q '[.jobs[]|select(.status=="completed")]|length*100/6'
11:20⇄
queue_enqueuegeneral · Write the migration for the audit tabletask#12 · quiet-lovelace
11:21⇄
peer_readcalm-dijkstra, last 8 entries8 lines
11:34⇄
from monitor:mon_7c1e · done · 14m

The run finished: 6 of 6 jobs completed, conclusion success.

11:41⇄
from queue:general · task#12 · ok

Migration 0042 adds the audit table with its two indexes. The migration test passes forward and back. Committed on the branch as 3f9c2a1.

11:42▤
The timing of the 20 runs, hung ones in red.
▤ws-runs.png48 KB↗ Open↓ Download
/model<name>Switch this session's modelaegis
/effortlow…maxChange reasoning effortaegis
/permissionread|write|auto|fullChange what the agent may doaegis
/rename<handle>Rename the sessionaegis
/reviewReview the current changesclaude
reply
claude-opus-5-5high effortfull

One file configures it

aegis reads .aegis.yaml at the root of your project. An agent is a preset of harness, model, effort and permission; a queue names the agent its workers run as and how many run at once. The new tab starts from a preset and can change any field for that session. aegis init writes a first file from the harnesses installed on the machine, aegis doctor names every problem by its place in the file, and the server follows the file as it changes.

default_agent: opus
agents:
  opus: {harness: claude-code, model: opus, effort: high, permission: full}
  reviewer:
    harness: claude-code
    model: opus
    effort: max
    permission: read
    priming: |
      You review changes for correctness and report findings by severity.
  local: {harness: opencode, model: ollama/qwen3:32b, effort: medium, permission: write}
queues:
  general: {agent: opus, max_parallel: 5}
recap: {agent: opus}

Permission is read for plan mode, write to accept edits, auto, or full to bypass permissions. The optional recap names the agent that writes a two-sentence recap when you come back to a tab after a while.

What an agent can call

Every session's harness connects to /mcp with its own token, so no tool asks who is calling. The tools are named mcp__aegis__<verb>.

monitor_start
Watch a long process without polling: bash conditions run on an interval and the session is woken when one holds, fails or times out.
monitor_cancel
Stop one of your monitors. No wake is sent.
monitor_list
Your live monitors.
queue_enqueue
Hand a self-contained task to a fresh worker on a queue. Returns at once; the result arrives in your inbox when the worker finishes.
task_status
A task's status, its worker, and its result once finished.
task_cancel
Cancel a task you enqueued: drop it if pending, stop and archive its worker if running.
task_resume
Put a failed or cancelled task's worker back to work, with its conversation intact.
peer_handoff
Give another session context or an instruction; it arrives as a user turn.
peer_read
The last entries of another session's transcript, one line each.
session_list
The open sessions on this server.
session_spawn
Start a session from an agent preset, overriding any of its fields.
session_rename
Rename your session: a handle and a title.
plan_update
Keep your plan where the person can see it: on your tab's card and in its sidebar.
turn_end
Say how the turn ended and offer up to three replies. It sets the mark on your tab and the line on your card.
file_send
Hand a file to the person: a card in the transcript with a preview, Open and Download.
agents_list
The agents you can spawn, each a preset of harness, model, effort and permission.
config_doctor
Check .aegis.yaml, the harnesses it names and the state directory.
quota_read
How much of each subscription window is left, per provider.
meta
How aegis works for you, and its tools.

Three themes

Ink is the warm dark palette of the terminal app aegis used to be. Logbook is a daylight lab notebook with times in the margin. Syalia is the house design system, with tool calls as chips.

Fleet
Flaky CI
10:02❯
Find out why and propose a fix.
10:02⌬
BashRun the test 20 times3 hung
10:05⏺

The hang is a race in recv().

Ink

Fleet
Flaky CI
10:02❯
Find out why and propose a fix.
10:02⌬
BashRun the test 20 times3 hung
10:05⏺

The hang is a race in recv().

Logbook

Fleet
Flaky CI
10:02❯
Find out why and propose a fix.
10:02⌬
BashRun the test 20 times3 hung
10:05⏺

The hang is a race in recv().

Syalia

Where it runs

aegis serve listens on loopback at port 8742 and prints a URL with a token. Opening it once signs that browser in: the token moves into an HttpOnly cookie that lasts a year. aegis serve -d detaches and outlives the terminal or the SSH connection. Behind a reverse proxy, --origin https://dev.example names the public origin, and the proxy terminates TLS. Agents reach /mcp on loopback, so do not proxy it. A restart brings sessions back stopped, and the next prompt resumes each one.