aoaoe
v7.5.0
Published
Autonomous supervisor for agent-of-empires sessions using OpenCode or Claude Code
Maintainers
Readme
An autonomous supervisor for Agent of Empires sessions. Uses OpenCode or Claude Code as the reasoning engine.
This project is a companion to Agent of Empires (AoE) by Nate Brake. AoE is the foundation -- it manages multiple AI coding agents in tmux sessions with git worktrees. aoaoe adds an autonomous supervisor layer on top. You need AoE running first; aoaoe plugs into it.
Self-improvement mode:
make selfstarts aoaoe supervising its own AoE session — reading the roadmap fromaoaoe.tasks.json, implementing features, committing, and pushing. It updates itself in real time.
What is this?
AoE is great at spawning and organizing agents, but someone still needs to watch the tmux panes and intervene when agents get stuck, ask questions, or finish their work.
aoaoe is that someone -- except it is an LLM. It polls your AoE sessions, reads agent output, decides when to act, and executes without you needing to be there.
This is the conductor, not the orchestra. AoE manages the sessions. The agents inside do the coding. aoaoe watches everything and steps in when needed.
Prerequisites
You need these installed first:
| Tool | What it does | Install |
|------|-------------|---------|
| tmux | Terminal multiplexer (AoE uses it) | brew install tmux |
| Agent of Empires | Manages AI agent sessions | See AoE README |
| OpenCode or Claude Code | LLM reasoning backend | npm i -g @anthropic-ai/claude-code or see OpenCode docs |
Verify they're on your PATH:
aoe --version # agent-of-empires
tmux -V # tmux
opencode --version # if using OpenCode backend
claude --version # if using Claude Code backendInstall
Pick one:
# npm (recommended)
npm install -g aoaoe
# Homebrew
brew install Talador12/tap/aoaoe
# curl
curl -fsSL https://raw.githubusercontent.com/Talador12/agent-of-agent-of-empires/main/scripts/install.sh | bash
# from source
git clone https://github.com/Talador12/agent-of-agent-of-empires
cd agent-of-agent-of-empires && npm install && npm run build && npm linkVerify:
aoaoe --versionTry It Alongside Running Sessions
Already have AoE sessions running? aoaoe is designed to run safely alongside them. Start with zero-risk commands and work your way up:
1. See what aoaoe sees (read-only, no LLM)
aoaoe test-contextLists all your AoE sessions, resolves project directories, discovers context files (AGENTS.md, claude.md, etc.), and reports sizes. No LLM calls, no tmux writes, no side effects. This is just a diagnostic scan.
2. Full loop, actions only logged (costs LLM tokens)
aoaoe --dry-runRuns the complete observe-reason-execute pipeline -- polls sessions, captures tmux output, calls the LLM for decisions -- but never executes actions. Instead of typing into your agents' tmux panes, it logs what it would do. Use this to verify the supervisor makes reasonable decisions before letting it act.
3. Full autonomous mode
aoaoeThe real deal. Polls, reasons, and executes -- sending keystrokes to agents, restarting crashed sessions, etc. You can still interrupt at any time with ESC ESC in the chat UI.
| Mode | Reads sessions? | Calls LLM? | Touches agents? |
|------|:-:|:-:|:-:|
| test-context | Yes | No | No |
| --observe | Yes | No | No |
| --dry-run | Yes | Yes | No |
| --confirm | Yes | Yes | You approve each action |
| aoaoe | Yes | Yes | Yes |
Self-improvement
aoaoe can supervise its own development. With an aoaoe AoE session open on this repo:
make setup # install deps, build, create AoE session if missing (one-time)
make self # aoaoe supervises itself: reads roadmap, implements, commits, pushes
make self-dry # watch-only — see what it would do without letting it actThe goal in aoaoe.tasks.json drives the session: pick backlog items, implement with tests, commit atomically, push, tag releases. The daemon watches its own tmux pane and nudges the agent when it stalls or needs direction.
Quick Start
aoaoe has two parts: a daemon (the brain) and a chat UI (your window into it). Here's how to get both running.
Step 1: Have AoE sessions running
You need at least one AoE session for aoaoe to supervise. If you don't have any yet:
aoe add ./my-project -t my-agent -c "opencode" # add an agent
aoe session start my-agent # start it
aoe # enter AoE TUI to verifyStep 2: Register aoaoe as an AoE session (one-time)
This adds aoaoe's chat UI as a session inside AoE, so you can access it alongside your agents:
aoaoe registerThis creates a session called "aoaoe" that runs the interactive chat UI. You only need to do this once.
Step 3: Start the daemon
In a separate terminal (or tmux pane, or backgrounded):
aoaoeThe daemon starts polling your AoE sessions, reasoning about what it sees, and executing actions. It logs to stderr so you can watch it work.
Step 4: Enter the chat UI
aoe session start aoaoe # start the aoaoe session (if not already running)
aoe # enter AoE TUI, then select "aoaoe"You're now in the chat UI. Type messages to the reasoner, run /overview to see what all agents are doing, or press ESC ESC to interrupt the current reasoning cycle.
Minimal example (all steps)
# Terminal 1: start the daemon
aoaoe
# Terminal 2: register + start + enter
aoaoe register
aoe session start aoaoe
aoe # select "aoaoe" in the TUIUsing a different reasoning backend
# Use Claude Code instead of OpenCode
aoaoe --reasoner claude-code
# Use a specific model
aoaoe --reasoner opencode --model anthropic/claude-sonnet-4-20250514
aoaoe --reasoner claude-code --model claude-sonnet-4-20250514Task System
aoaoe can automatically create and manage AoE sessions from a task list. Define repos you want to work on in aoaoe.tasks.json (next to your config file):
[
{
"repo": "github/adventure",
"sessionTitle": "adventure",
"sessionMode": "existing",
"goal": "Process queued TODOs in this existing AoE session"
},
{
"repo": "github/agent-of-agent-of-empires",
"sessionTitle": "aoaoe-roadmap",
"sessionMode": "new",
"tool": "opencode",
"goal": "Ship next roadmap item with tests"
},
{
"repo": "github/cloud-hypervisor",
"sessionMode": "auto",
"goal": "Address PR review feedback"
}
]| Field | Required | Description |
|-------|:--------:|-------------|
| repo | Yes | Path to the project directory (relative to cwd or absolute) |
| sessionTitle | No | AoE session title to target. Default: derived from repo basename |
| sessionMode | No | Session allocation strategy: existing (link only), new (create), auto (link or create). Default: auto |
| tool | No | Agent tool to use (opencode, claude-code, etc.). Default: opencode |
| goal | No | Goal text injected into the supervisor's context for this task |
When the daemon starts, it now auto-imports any currently visible AoE sessions into the task list (mode=existing) so active and inactive sessions are immediately schedulable. Then it reconciles tasks: creates new AoE sessions when needed, links existing sessions by title, and starts linked sessions as needed. Progress is tracked persistently in ~/.aoaoe/task-state.json and survives session cleanup.
Interactive task updates (aoaoe task new/edit/rm or /task ...) also sync back to aoaoe.tasks.json, so your list evolves as you go.
The supervisor can report progress milestones and mark tasks complete via two special actions:
report_progress— logs a milestone summary to persistent statecomplete_task— marks the task done and cleans up the session
View task status:
aoaoe tasks # show task progress tableDaemon TUI Commands
The daemon runs an interactive TUI with a rich command set. These commands are available when the daemon is running (started with aoaoe).
Talking to the AI
| Command | What it does |
|---------|-------------|
| (any text) | Send a message -- queued for the next reasoning cycle |
| !message | Insist -- interrupt + deliver message immediately |
| /insist <msg> | Same as !message |
| /explain | Ask the AI to explain what's happening right now |
Controls
| Command | What it does |
|---------|-------------|
| /pause | Pause the supervisor (stops reasoning) |
| /resume | Resume after pause |
| /mode [name] | Switch mode at runtime: observe, dry-run, confirm, autopilot (no arg = show current) |
| /interrupt | Interrupt the AI mid-thought |
| ESC ESC | Same as /interrupt (shortcut) |
Navigation
| Command | What it does |
|---------|-------------|
| 1-9 | Quick-switch: jump to session N |
| /view [N\|name] | Drill into a session's live output (default: 1) |
| /back | Return to overview from drill-down |
| /sort [mode] | Sort sessions: status, name, activity, health, default (no arg = cycle) |
| /compact | Toggle compact mode (dense session panel) |
| /pin [N\|name] | Pin/unpin a session to the top |
| /bell | Toggle terminal bell on errors/completions |
| /focus | Toggle focus mode (show only pinned sessions) |
| /mute [N\|name] | Mute/unmute a session's activity entries |
| /unmute-all | Unmute all sessions at once |
| /filter [tag] | Filter activity by tag -- presets: errors, actions, system (no arg = clear) |
| /who | Show fleet status: status, uptime, idle-since, context, errors, group, note |
| /uptime | Show session uptimes |
| /top [mode] | Rank sessions by errors (default), burn, or idle |
| /auto-pin | Toggle auto-pin on error |
| /note N\|name text | Attach a note to a session (no text = clear) |
| /notes | List all session notes |
| /group N\|name tag | Assign session to a group (lowercase, max 16 chars; no tag = clear) |
| /groups | List all groups and their members |
| /group-filter [tag] | Show only sessions in a group (no arg = clear) |
| /rename N\|name [display] | Set custom TUI display name (no display = clear); persisted |
| /watchdog [N] | Alert if session stalls N minutes (default 10); /watchdog off to disable |
| /quiet-hours [H-H] | Suppress watchdog+burn alerts during hours (e.g. 22-06); no arg = clear |
| /broadcast <msg> | Send message to all sessions; /broadcast group:<tag> <msg> for group |
| /duplicate N [t] | Clone a session (same tool/path) with optional new title |
| /tag N tag1,tag2 | Set freeform tags on a session (no tags = clear); /tags to list |
| /tag-filter [tag] | Show only sessions with given freeform tag (no arg = clear) |
| /color N [c] | Set accent dot color: lime amber rose teal sky slate (no color = clear) |
| /color-all [c] | Set accent color for all sessions at once |
| /mute-errors | Toggle suppression of error/! action entries in activity log |
| /pin-all-errors | Pin every session currently in error state |
| /pin-draining | Pin all draining sessions to the top |
| /labels | List all active session labels |
| /sort-by-health | Sort sessions by health score (worst first) |
| /icon N [emoji] | Set or clear a single emoji shown in the session row |
| /timeline N [n] | Show last n activity entries for a session (default 30) |
| /find <text> | Search all session pane outputs for text |
| /reset-health N | Clear error counts + context history to reset a session's health score |
| /prev-goal N [n] | Restore nth-most-recent goal for a session (default 1 = latest) |
| g1-g99 | Quick-switch to session 10+ (e.g. g12 jumps to session 12) |
| /clip [N] | Copy last N activity entries to clipboard (default 20) |
| /diff N | Show activity since bookmark N |
| /mark | Bookmark current activity position |
| /jump N | Jump to bookmark N |
| /marks | List all bookmarks |
| /search <pattern> | Filter activity entries by substring (no arg = clear) |
| Click session | Click an agent card to drill down (click again to go back) |
| Mouse wheel | Scroll activity (overview) or session output (drill-down) |
| PgUp / PgDn | Scroll through activity or session output |
| Home / End | Jump to oldest / return to live |
Info
| Command | What it does |
|---------|-------------|
| /status | Show daemon state (mode, reasoner, poll counts, last cycle) |
| /dashboard | Show full dashboard |
| /tasks | Show task progress table |
| /t ... /todo ... /idea ... | Aliases for /task ... |
| /task [sub] [args] | Task management (list, start, stop, edit, new, rm) |
| /task <session> :: <goal> | Fast path: update/create task for an existing session and set its goal |
| :<goal> | Fastest path in drill-down: set goal for that session |
| just type (in drill-down) | Default behavior: update goal for the focused session |
| /burn-rate | Show context token burn rates (tokens/min) for all sessions |
| /ceiling | Show context token usage vs limit for all sessions |
| /stats | Per-session health, errors (+trend), burn rate, context %, cost, uptime |
| /top [mode] | Rank sessions by errors (default), burn, or idle |
| /who | Fleet status: status, uptime, idle-since, cost, errors+trend, group, note |
| /snapshot [md] | Export session state snapshot to ~/.aoaoe/snapshot-<ts>.json (or .md) |
| /export-stats | Export /stats output to ~/.aoaoe/stats-<ts>.json |
| /session-report N | Full markdown report for one session → ~/.aoaoe/report-<name>-<ts>.md |
| /cost-summary | Show total estimated spend across all sessions |
| /recall <kw> [N] | Search 7-day persisted history for keyword |
| /history-stats | Aggregate stats from history: entry counts, top tags, span |
| /clear-history | Truncate ~/.aoaoe/tui-history.jsonl |
| /copy [N] | Copy session's current pane output to clipboard (default: current drill-down) |
| /alias /x /cmd | Create command alias (/x expands to /cmd); no args = list |
| /ctx-budget | Show context budget allocation across sessions (activity-weighted) |
| /profile [name] | Show active AoE profiles; optionally switch focus to a named profile |
| /replay <N\|name> [lps] | Play back a session's stored pane output line by line (default 10 lps; run again to stop) |
| /notify-filter <session> <events...> | Set per-session webhook event filter (session_error, session_done, etc.); no args = list; clear = remove all |
Other
| Command | What it does |
|---------|-------------|
| /verbose | Toggle detailed logging |
| /clear | Clear the screen |
| /help | Show all commands |
TUI Features
- Activity sparkline -- 10-minute activity rate chart in the separator bar (Unicode blocks with color gradient)
- Activity sparkline -- 10-minute activity rate chart in the separator bar (Unicode blocks with color gradient)
- Session cards -- per-session status with pin
▲, mute◌, note✎, group⊹tag, health⬡N, color●, tags[tag1,tag2], and activity rate3/mindicators - Health score -- composite 0–100 badge (errors, burn rate, context ceiling, stall time); LIME ≥80, AMBER ≥60, ROSE <60; also in compact mode
- Error sparklines -- ROSE 5-bucket mini-chart of recent error frequency in each card (last 5 min)
- Error trend -- ↑/→/↓ arrows in
/statsand/whoshowing error direction - Idle-since -- time since last output change in idle/done cards and
/whooutput - Cost tracking --
$N.NN spentparsed from pane output; shown in/stats,/who,/cost-summary - Session grouping --
/group//group-filterfor named group organization;⊹tagbadge in cards - Session tagging --
/tagfor multi-freeform-tag sets;/tag-filterpanel filter;[tag1,tag2]badge - Session rename --
/renamecustom TUI display name (bold + original dim); persisted - Session color --
/coloraccent●dot per card (8 colors);/color-allfor bulk set; persisted - Watchdog --
/watchdog Nfires on stall; suppressed during/quiet-hours;⊛Nmheader badge - Burn-rate alerts -- auto "status" alert > 5k tokens/min; suppressed during quiet hours
- Context ceiling warning -- auto alert at 90% context when "X / Y tokens" format available
- Quiet hours --
/quiet-hours HH-HHsuppresses watchdog + burn-rate alerts during set hours - Session timeline --
/timeline N [n]shows last n activity entries filtered by session - Session report --
/session-report Nwrites full markdown report to~/.aoaoe/ - Snapshot export --
/snapshot [md]exports all session state to~/.aoaoe/ - History search --
/recall <kw>searches 7-day persisted history;/history-statsshows aggregates - Broadcast --
/broadcast [group:<tag>] <msg>sends to all or group-filtered sessions via tmux - Duplicate --
/duplicate N [title]clones a session (same tool + path) with new title - Ranked view --
/top [errors|burn|idle]composite attention ranking;/statsfull per-session table - Sticky preferences -- sort, compact, focus, bell, auto-pin, tag filter, aliases, groups, renames, colors, tags, quiet hours persist across restarts
- Filter pipeline -- mute → suppress (
/mute-errors) → tag → search all compose - Aliases --
/alias /x /cmdshortcuts; up to 50, persisted - Activity heatmap -- 24-hour colored block chart via
aoaoe stats - Bookmarks -- mark positions, jump back, diff since a bookmark
- Clipboard export --
/clipand/copycopy activity or session pane output to clipboard - Automatic context compaction -- when a session hits 80% context usage, daemon sends a compaction nudge via tmux; 10-min cooldown per session
- Multi-profile polling -- daemon polls all configured AoE profiles simultaneously; sessions deduped by ID across profiles
- Session replay --
/replay <N|name> [lps]plays back stored pane output in the activity log at configurable speed
Chat UI Commands
The chat UI (aoaoe-chat) runs inside an AoE tmux pane. Register it with aoaoe register, then access via aoe -> select "aoaoe".
| Command | What it does |
|---------|-------------|
| /overview | Show all AoE sessions with tasks, model, tokens, cost. Works without the daemon. |
| /tasks | Alias for /overview |
| /status | Daemon connection status + countdown to next reasoning cycle |
| /progress [--since --json] | What each session accomplished recently |
| /health | Per-session health scores (0-100) with fleet average |
| /incident [opts] | Incident quick view: response-flow runbook + recent events (--since, --limit, --json, --ndjson, --follow) |
| /runbook [section] [--json] | Print operator playbook slice (quickstart, response-flow/incident, all) |
| /supervisor [opts] | Judge/orchestrator status across tasks/sessions (--all, --since, --limit, --json) |
| /prompt-template [name] | Set/show reasoner strategy (default, hands-off, aggressive, review-focused, shipping) |
| /pin-save <name> | Save current pinned sessions as a named preset |
| /pin-load <name> | Restore a saved pin preset |
| /pin-presets | List saved pin presets |
| /interrupt | Interrupt the current reasoner call |
| /dashboard | Request full dashboard output from daemon |
| /pause | Pause the daemon (stops reasoning) |
| /resume | Resume after pause |
| /sessions | Instant session list from daemon state (no tmux capture needed) |
| /explain | Ask the AI to explain what's happening right now in plain English |
| /verbose | Toggle verbose logging |
| /clear | Clear the screen |
| /help | Show all commands |
| ESC ESC | Interrupt the reasoner (same as /interrupt) |
| (any text) | Send a message to the reasoner -- included in the next reasoning cycle |
How /overview works
/overview captures every AoE pane directly via tmux and parses:
- Tasks: OpenCode TODO items (
[*]done,[.]in progress,[o]pending) - Model: Which LLM the agent is using (e.g. "Claude Opus 4.6")
- Context: Token count and cost
- Last line: Most recent meaningful output
This works standalone -- you don't need the daemon running.
How interrupt works
When the daemon is reasoning, press ESC ESC (or type /interrupt) to stop the current LLM call. The daemon will pause and wait for your input. Type a message and it will be included in the next reasoning cycle. This is useful when you want to redirect the supervisor's attention.
Daemon CLI
aoaoe [command] [options]
commands:
(none) start the supervisor daemon (interactive TUI)
init detect tools + sessions, import history, generate config
status quick daemon health check (is it running? what's it doing?)
runbook print operator quickstart for day-2 supervision
runbook --json machine-readable runbook output for tooling
runbook --section <quickstart|response-flow|incident|all> print only one runbook section
incident one-shot incident quick view (response-flow + recent activity)
incident --since <duration> filter incident event window (30m, 2h, 1d)
incident --limit <N> cap incident events shown (default: 5)
incident --json machine-readable incident output
incident --ndjson emit compact one-line JSON snapshots
incident --watch stream incident snapshots continuously
incident --follow shortcut for --watch --changes-only --heartbeat 30
incident --changes-only emit only when incident state changes (implies --watch)
incident --heartbeat <sec> keepalive interval (implies --changes-only + --watch)
incident --interval <ms> watch refresh interval (default: 5000, min: 500)
supervisor one-shot supervisor/task/session orchestration status
supervisor --all show full recent supervisor event buffer
supervisor --since <duration> filter events to a time window (30m, 2h, 7d)
supervisor --limit <N> cap number of events shown (default: 5)
supervisor --json machine-readable output for automation
supervisor --ndjson emit compact one-line JSON snapshots
supervisor --watch stream supervisor snapshots continuously
supervisor --changes-only emit only when state changes (implies --watch)
supervisor --heartbeat <sec> keepalive interval (implies --changes-only + --watch)
supervisor --interval <ms> watch refresh interval (default: 5000, min: 500)
config show the effective resolved config (defaults + file)
config --validate validate config + check tool availability
config --diff show only fields that differ from defaults
notify-test send a test notification to configured webhooks
doctor comprehensive health check (config, tools, daemon, disk)
logs show recent conversation log entries
logs --actions show action log entries (from ~/.aoaoe/actions.log)
logs --grep <pattern> filter log entries by substring or regex
logs -n <count> number of entries to show (default: 50)
export export session timeline as JSON or Markdown for post-mortems
export --format <json|markdown> output format (default: json)
export --output <file> write to file (default: stdout)
export --last <duration> time window: 1h, 6h, 24h, 7d (default: 24h)
task manage tasks and sessions (list, reconcile, start, stop, new, rm, edit, help)
task templates show available task templates (roadmap, pr-review, bugfix, etc.)
task new <t> <p> --template roadmap create task with template goal
task start-all|stop-all|pause-all|resume-all batch fleet management
tasks show task progress (from aoaoe.tasks.json)
tasks --json machine-readable task state with live session status
progress per-session accomplishment digest (last 24h)
progress --since <dur> --json filter window + machine-readable output
health per-session health scores (0-100, fleet average)
health --json machine-readable health output
adopt import all untracked live AoE sessions as tasks
adopt --template roadmap apply a template goal to adopted sessions
backup [path] backup ~/.aoaoe/ state + config to tarball
restore <path> restore from backup tarball or directory
sync init <url> set up git-based state sharing with remote repo
sync push push local state to sync remote
sync pull pull remote state and restore locally
sync diff show changes since last push
sync status show sync repo status
export --tasks export task history as JSON or markdown
export --tasks --format md markdown format with progress timelines
history review recent actions (from ~/.aoaoe/actions.log)
test-context scan sessions + context files (read-only, no LLM, safe)
test run integration tests (requires aoe, opencode, tmux)
register register aoaoe as an AoE session (one-time setup)
options:
--reasoner <opencode|claude-code> reasoning backend (default: opencode)
--poll-interval <ms> poll interval in ms (default: 10000)
--port <number> opencode server port (default: 4097)
--health-port <number> start HTTP health check server on this port
--model <model> model to use
--profile <name> aoe profile (default: default)
--dry-run run full loop but only log actions (costs
LLM tokens, but never touches sessions)
--observe observe only — no LLM calls, no execution,
zero cost. shows what the daemon sees.
--confirm ask before each action — the AI proposes,
you approve with y/n before it runs.
--verbose, -v verbose logging
--help, -h show help
--version show version
init options:
--force, -f overwrite existing config
register options:
--title, -t <name> session title in AoE (default: aoaoe)Supervisor Streaming Examples
# Human-readable watch output (change-only)
aoaoe supervisor --watch --changes-only --heartbeat 60
# NDJSON stream for pipes/collectors
aoaoe supervisor --watch --ndjson --changes-only --heartbeat 30
# Filter to the last 2 hours and show only 20 events
aoaoe supervisor --since 2h --limit 20JSON/NDJSON payloads include emitReason with one of:
snapshot(one-shot invocation)interval(periodic watch tick)change(watch emission caused by state change)heartbeat(keepalive emission from--heartbeat)
Incident Streaming Examples
# One-shot incident snapshot (human readable)
aoaoe incident --since 30m --limit 10
# Fast follow mode (alias for --watch --changes-only)
aoaoe incident --follow --heartbeat 30 --ndjson
# NDJSON incident stream for monitors (change-only + keepalive)
aoaoe incident --watch --ndjson --changes-only --heartbeat 30
# JSON watch stream (compact one object per tick in watch mode)
aoaoe incident --watch --json --interval 5000Operator Playbook
Use this when running aoaoe as a long-lived judge over many AoE sessions.
# 1) Start low-noise supervision stream in a side pane
aoaoe supervisor --watch --ndjson --changes-only --heartbeat 30
# 2) If sessions/tasks drift, force immediate reconciliation
aoaoe task reconcile
# 3) If a specific session needs new direction, inject a goal quickly
aoaoe-chat
# then type: /task <session> :: <new goal>Recommended response flow:
emitReason=changespikes: inspect/supervisor --since 30m --limit 20- stalled task (pending/paused too long): run
aoaoe task reconcile, then nudge via/task ... :: ... - noisy but unchanged systems: keep
--changes-only --heartbeat 30so monitors still get liveness
Task Templates
Create tasks with built-in goal presets instead of writing JSON by hand:
aoaoe task templates # list available templates
aoaoe task new my-project ./path --template roadmap
aoaoe task new bugfix-auth ./path --template bugfixBuilt-in templates: roadmap, roadmap-strict, pr-review, bugfix, explore, ci-fix
Custom templates: add to ~/.aoaoe/templates.json
Prompt Templates
Switch the reasoner's supervision strategy at runtime:
/prompt-template hands-off # minimal intervention
/prompt-template aggressive # proactive nudging
/prompt-template shipping # focus on commits and pushesOr set in config: "promptTemplate": "hands-off"
Pin Presets
Save and restore named sets of pinned sessions:
/pin-save work # save current pins
/pin-load work # restore later
/pin-presets # list all saved presetsConfiguration
Config lives at ~/.aoaoe/aoaoe.config.json (canonical, written by aoaoe init). A local aoaoe.config.json in cwd overrides for development. Defaults work fine without a config file:
{
"reasoner": "opencode",
"pollIntervalMs": 10000,
"opencode": {
"port": 4097,
"model": "anthropic/claude-sonnet-4-20250514"
},
"claudeCode": {
"model": "claude-sonnet-4-20250514",
"yolo": true,
"resume": true
},
"aoe": {
"profile": "default"
},
"policies": {
"maxIdleBeforeNudgeMs": 120000,
"maxErrorsBeforeRestart": 3,
"autoAnswerPermissions": true
},
"sessionDirs": {
"adventure": "github/adventure",
"cloudchamber": "cc/cloudchamber"
},
"contextFiles": [],
"notifications": {
"webhookUrl": "https://example.com/webhook",
"slackWebhookUrl": "https://hooks.slack.com/services/T.../B.../xxx",
"events": ["session_error", "session_done", "daemon_started", "daemon_stopped"]
}
}| Field | Description | Default |
|-------|-------------|---------|
| reasoner | "opencode" or "claude-code" | "opencode" |
| pollIntervalMs | How often to check AoE sessions (ms) | 10000 |
| opencode.port | Port for opencode serve | 4097 |
| opencode.model | Model in provider/model format | (OpenCode default) |
| claudeCode.model | Anthropic model name | (Claude Code default) |
| claudeCode.yolo | Skip permissions in Claude Code | true |
| claudeCode.resume | Maintain session across calls | true |
| aoe.profile | AoE profile to monitor | "default" |
| policies.maxIdleBeforeNudgeMs | Nudge idle agents after this long | 120000 |
| policies.maxErrorsBeforeRestart | Restart after N consecutive errors | 3 |
| policies.autoAnswerPermissions | Auto-approve permission prompts | true |
| policies.allowDestructive | Allow remove_agent and stop_session actions | false |
| policies.maxStuckNudgesBeforePause | Auto-pause task after N nudges with no progress (0 = disabled) | 0 |
| policies.quietHours | Skip reasoning during these hours, e.g. "01:00-06:00" (polling continues) | (none) |
| promptTemplate | Reasoner prompt strategy: default, hands-off, aggressive, review-focused, shipping | "default" |
| policies.userActivityThresholdMs | Ignore sessions with recent human keystrokes | 30000 |
| policies.actionCooldownMs | Minimum ms between actions on the same session | 30000 |
| protectedSessions | Session titles that are observe-only (no actions) | [] |
| sessionDirs | Map session titles to project directories (relative to cwd or absolute). Bypasses heuristic directory search. | {} |
| contextFiles | Extra AI instruction file paths to load from each project root | [] |
| captureLinesCount | Number of tmux lines to capture per session (-S flag) | 100 |
| healthPort | Start HTTP health check server on this port (e.g. 4098). GET /health returns JSON status. | (none) |
| notifications.webhookUrl | Generic webhook URL (POST JSON) | (none) |
| notifications.slackWebhookUrl | Slack incoming webhook URL (block kit format) | (none) |
| notifications.events | Filter which events fire (omit to send all). Valid: session_error, session_done, action_executed, action_failed, daemon_started, daemon_stopped | (all) |
| notifications.maxRetries | Retry failed webhook deliveries with exponential backoff (1s, 2s, 4s, ...) | 0 (no retry) |
| tuiHistoryRetentionDays | How many days of TUI history to replay on startup (1-365) | 7 |
Also reads .aoaoe.json as an alternative config filename.
sessionDirs — explicit project directory mapping
By default, aoaoe resolves project directories by searching subdirectories (up to 2 levels deep) for a folder name matching each session title. This works great for standard layouts like repos/github/adventure/.
For non-standard layouts or when the session title doesn't match the directory name, use sessionDirs to provide explicit mappings:
{
"sessionDirs": {
"adventure": "github/adventure",
"cloudchamber": "cc/cloudchamber",
"my-agent": "/absolute/path/to/project"
}
}Paths can be relative (resolved from the directory where you run aoaoe) or absolute. Case-insensitive matching is used for session title lookup. If a mapped path doesn't exist on disk, aoaoe falls back to heuristic search.
Use aoaoe test-context to verify resolution.
notifications — webhook alerts for daemon events
aoaoe can send webhook notifications when significant events occur (session errors, task completions, daemon start/stop). Supports generic JSON webhooks and Slack incoming webhooks with block kit formatting.
{
"notifications": {
"webhookUrl": "https://example.com/webhook",
"slackWebhookUrl": "https://hooks.slack.com/services/T.../B.../xxx",
"events": ["session_error", "session_done", "daemon_started", "daemon_stopped"]
}
}Both webhook URLs are optional — configure one or both. The events array filters which event types fire (omit it to receive all events). Notifications are fire-and-forget with a 5s timeout and 60s rate limiting per event+session combo to prevent spam.
Run aoaoe notify-test to verify your webhook configuration.
How It Works
┌──────────────────────────────────────────────────────┐
│ aoaoe daemon │
│ │
│ ┌───────────┐ ┌─────��────────┐ ┌───────────┐ │
│ │ Poller │──▶│ Reasoner │──▶│ Executor │ │
│ │ │ │ ┌──────────┐ │ │ │ │
│ │ aoe CLI + │ │ │ OpenCode │ │ │ tmux send │ │
│ │ tmux cap │ │ │ server │ │ │ keys, aoe │ │
│ │ │ │ ├──────────┤ │ │ CLI cmds │ │
│ │ │ │ │ Claude │ │ │ │ │
│ │ │ │ │ Code │ │ │ │ │
│ │ │ │ └──────────┘ │ │ │ │
│ └───────────�� └──────────────┘ └───────────┘ │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ Chat UI (aoaoe-chat) │ │
│ │ runs inside AoE tmux pane, reads state │ │
│ │ from ~/.aoaoe/ via file-based IPC │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
│ │
▼ ▼
AoE sessions LLM Provider
(tmux panes) (local or remote)Three loops
Poller (every N seconds, configurable):
- Calls
aoe list --jsonto get all session IDs, statuses, and tools - For each active session:
tmux capture-pane -t <session> -p -S -100 - Diffs against previous capture to detect new output
- Builds an observation payload
Reasoner (on new observations):
- Sends observation to the configured LLM backend
- System prompt defines the supervisor role, policies, and available actions
- Receives back a structured JSON action decision
Executor (on decisions):
tmux send-keys-- inject a prompt into an agentaoe session start/stop/restart-- lifecycle managementaoe add/aoe remove-- spawn or tear down agents
Supervisor behavior
The LLM supervisor follows these policies:
- If an agent is stuck or idle too long, nudge it with context or a rephrased task
- If an agent asks a question and is waiting for input, answer it
- If an agent finishes its task, acknowledge and optionally assign follow-up work
- If a session crashes, restart it
- Do NOT micromanage -- only intervene when there is a clear problem or decision needed
Available actions
The reasoner returns structured JSON decisions:
{ "action": "send_input", "session": "<id>", "text": "<prompt>" }
{ "action": "start_session", "session": "<id>" }
{ "action": "stop_session", "session": "<id>" }
{ "action": "create_agent", "path": "<dir>", "title": "<name>", "tool": "<agent>" }
{ "action": "remove_agent", "session": "<id>" }
{ "action": "report_progress", "session": "<id>", "summary": "<milestone>" }
{ "action": "complete_task", "session": "<id>", "summary": "<final status>" }
{ "action": "wait" }Reasoning Backends
| Backend | Interface | Stateful | Model Flexibility |
|---------|-----------|----------|-------------------|
| OpenCode | opencode serve + SDK | Yes (long-running session) | Any provider via OpenCode config |
| Claude Code | claude --print subprocess | Via --resume | Anthropic models |
OpenCode backend
Runs opencode serve as a headless HTTP server. Uses the OpenCode JS SDK to maintain a long-running session with full context. Works with any model provider configured in OpenCode (Anthropic, OpenAI, Ollama, etc.).
Claude Code backend
Calls claude --print --output-format json as a subprocess. System prompt injected via --append-system-prompt. Session continuity via --resume <session_id>.
IPC and State Files
The daemon and chat UI communicate via files in ~/.aoaoe/:
| File | Written by | Read by | Purpose |
|------|-----------|---------|---------|
| daemon-state.json | daemon | chat UI | Current phase, countdown, per-session state |
| conversation.log | daemon | chat UI | Observations, reasoning, actions log |
| pending-input.txt | chat UI | daemon | User messages queued for next reasoning cycle |
| interrupt | chat UI | daemon | Flag file -- presence triggers interrupt |
| chat.pid | chat UI | daemon | Chat process PID for detection |
| actions.log | daemon | -- | Persistent action history (JSONL) |
Intelligence Modules
aoaoe includes 196 intelligence modules that run every daemon tick without LLM calls — pure computation, zero runtime dependencies. They cover fleet observability, cost management, goal tracking, scheduling, health monitoring, and operator tooling.
Reasoning Pipeline (8 gates, runs before every LLM call):
- Token quota → fleet rate limiter → observation cache → priority filter → context compressor → LLM call → approval workflow → cost tracker
Core Per-Tick Autonomous Systems:
- Session summarizer, conflict detector + auto-resolver, goal completion detector, cost budget enforcer
- Adaptive poll controller, fleet SLA monitor, progress velocity tracker, recovery playbook
- Dependency scheduler, session graduation (trust ladder), workflow engine
Fleet Intelligence (on-demand via 197 TUI /commands):
- Cost tracking: budgets, forecasts, trends, anomalies, chargebacks, optimization recommendations
- Goal management: auto-priority, cascading, decomposition, NL parsing, confidence estimation, burndown charts
- Observability: incident timeline, event bus, health scoring, diagnostics, structured logs, pattern evolution
- Operations: shift handoff, compliance, runbooks, auto-scaler, canary mode, graceful shutdown
- API: REST server with OpenAPI spec, SSE events, webhooks, bearer auth, rate limiting, pagination
See AGENTS.md for the full module list with descriptions.
Project Structure
src/
# ── core daemon (the 15 files that make it go) ──
index.ts # daemon entry point, main loop, subcommands
loop.ts # extracted tick logic (poll->reason->execute), testable with mocks
config.ts # config loader, CLI arg parser, validation
types.ts # shared types (SessionSnapshot, Action, DaemonState, etc.)
poller.ts # aoe CLI + tmux capture-pane wrapper
executor.ts # maps action decisions to shell commands
tui.ts # in-place terminal UI (alternate screen, scroll, sparklines)
input.ts # stdin readline + keypress handlers (/commands)
init.ts # `aoaoe init`: auto-discover tools, generate config
context.ts # discoverContextFiles, resolveProjectDir, loadSessionContext
health.ts # HTTP health check endpoint
daemon-state.ts # IPC state file + interrupt flag
task-manager.ts # task orchestration: definitions, persistent state
# ── reasoner backends ──
reasoner/
index.ts # common Reasoner interface + factory
prompt.ts # system prompt + observation formatting
parse.ts # response parsing, JSON extraction, action validation
opencode.ts # OpenCode HTTP backend (native fetch to opencode serve)
claude-code.ts # Claude Code subprocess backend (claude --print)
# ── CLI tools ──
chat.ts # interactive chat UI (aoaoe-chat binary)
tail.ts # live-stream daemon activity to another terminal
stats.ts # aggregate statistics + activity heatmap
replay.ts # play back tui-history.jsonl with timing
export.ts # timeline export (JSON/Markdown)
# ── 196 intelligence modules (*.ts + *.test.ts pairs) ──
# fleet observability, cost management, goal tracking, scheduling,
# health monitoring, operator tooling — see AGENTS.md for full listRelated Projects
- Agent of Empires -- the session manager this project controls
- OpenCode -- AI coding agent, used as a reasoning backend
- Claude Code -- Anthropic's CLI agent, used as a reasoning backend
License
MIT License -- see LICENSE for details.
