Agentic orchestrator for parallel coding agents — plans tasks, spawns agents, and autonomously handles CI fixes, merge conflicts, and code reviews.
Go to file
prateek c3eeecb686
merge fork, 25 May - 2 June (#2086)
* feat(core): add prs[] array to Session for multi-PR support — Phase 1 metadata layer

* feat(core): update lifecycle-manager for multi-PR per session — Phase 2

* feat(web): add prs[] to DashboardSession and wire up multi-PR display — Phase 3

* feat(plugins): append to prs metadata field on gh pr create — Phase 4

* fix: address all code review issues — PR number, enrichment pipeline, claimPR append, stale PRs, V1 compat, SCM calls, dead code, isDraft, session validation

* fix: address Greptile review — state machine aggregation, URL dedup, React keys, review comments, typecheck

* fix: remove useless assignment in lifecycle-manager — lint error

* fix: add missing prs field to Session objects in cli and plugin test files

* fix: add prs field to integration-tests helpers and fix V1 flat-file fallback in agent-claude-code

* fix: use stack approach for claimPR prs field — claimed PR becomes primary

* feat(core,web): multi-PR per session — enrichment, status dots, bug fixes (#1821)

- Session metadata now stores a comma-separated prs list; all PR URLs
  parsed into session.prs[] on load, backwards-compatible with single-PR
- Enrichment loop hydrates every PR in the list each poll cycle via the
  existing batch GraphQL call
- Fixed closed-PR filter reading from session lifecycle state instead of
  per-PR enrichment cache, which misclassified secondary PRs
- Fixed isDraft never propagating from enrichment cache to dashboard.pr
  and dashboard.prs[i]
- Fixed prs[0] and dashboard.pr being separate objects — enrichment on
  one now syncs to the other
- SessionCard PR badges now show a colored status dot per PR: green (CI
  passing/merged), yellow (CI pending), red (CI failing/changes
  requested), grey (unenriched/draft/closed)
- Corrected color token mapping: passing uses --color-status-merge
  (green), pending uses --color-status-pending (yellow)

* fix(core): add missing prs field to code-review-manager test fixture

* feat(web): per-PR rows with colored chips, titles, and click-to-switch on session card

- Replace single-PR badges with one row per PR when session has multiple PRs
- Each row shows: status-colored chip, PR title (truncated), diff size
- Chip colors: green (CI passing/merged), yellow (CI pending), red (CI
  failing/changes requested), grey (closed/draft/unenriched)
- Repo initials badge (e.g. AO, CM) shown per row when PRs span multiple repos
- Clicking a row selects it — description, alerts, and action buttons in the
  card body all switch to that PR's context
- Clicking the chip opens GitHub; clicking title/diff area selects without
  navigating away
- Single-PR sessions are completely unchanged

* fix(web): address multi-PR card review — effectivePR for merge button, color-mix chips, left-border selection

* fix(web): derive prs from pr in makeSession test helper

* fix(core): fall back to raw[pr] when prs absent in claimPR

* feat(web): PR switcher in session detail header for multi-PR sessions

* fix(core): treat ciStatus/reviewDecision 'none' as passing in multi-PR aggregation

* fix(core): stale-session cleanup checks all prs before killing multi-PR session

* fix(core): all-none reviewDecision aggregates to none, not approved

* fix(core): prs accumulation in Node hook, bump WRAPPER_VERSION, clear stale enrichment on claimPR

* fix(core,web): webhook matching for secondary PRs, restore lifecycle PR number fallback

* fix(web): merge endpoint resolves target PR from session.prs for secondary PRs

* fix(core,web): clamp selectedPRIndex, guard multi-PR partial cache miss, clear prs on takeover

* fix(core,web): scope webhook secondary PR match by owner/repo, handle JSON metadata in Node hook

* fix(web): guard merge route PR lookup by owner/repo to prevent number collision

* fix(web): forward owner/repo from merge button to activate PR disambiguation guard

* fix(web): propagate owner/repo through BottomSheet and AttentionZone merge triggers

* test(web): update onMerge assertion to expect owner/repo arguments

* fix(core,web): resolve 5 multi-PR logical gaps — conflict detection, partial cache miss, isDraft aggregation, event context prs, AttentionZone labels

* fix(core,cli,plugins): add prs field to NotificationEventContext fixtures across all packages

* fix(web): add owner/repo guard to primary PR branch in webhook session match

* fix: handle unknown update versions and flat interactive config

* ci: pin GitHub Actions to SHAs

* fix: support new orchestrator from flat config

* ci: skip dependency review on unsupported forks

* revert: run dependency review on all PRs

* docs(design): add dashboard design-language exploration + mockups

Capture the design-language direction explored for the AO dashboard as
live HTML mockups plus rationale, under docs/design/.

- dashboard-language.md: the language — blue=orchestrator / orange=agents
  identity, rationed semantic color, Schibsted Grotesk + JetBrains Mono,
  unified status system, layout patterns, and how it diverges from DESIGN.md.
- mockups/kanban.html: canonical fleet board (frameless lifecycle columns).
- mockups/session.html: canonical session detail (framed xterm + pluggable
  inspector rail: Summary / Changes / Browser; review-comment "Address").
- mockups/{concepts,refined,*-icons}.html: exploration / icon comparisons.
- mockups/mascot.png: the blue conductor mascot.

Reference mockups only (CDN fonts + inline styles); production must use the
Tailwind tokens in globals.css per C-02/C-07.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(web): migrate dashboard to mission-control design language (supersedes DESIGN.md)

Replace the "Warm Terminal" system with the "Mission Control" language from
the merged design exploration (docs/design/dashboard-language.md + the kanban
& session mockups). One coherent system, dark control-room aesthetic, rationed
color (blue = orchestrator/you, orange = working agent, amber = needs-input,
red = failing/stuck, green = mergeable, else grayscale).

Tokens & fonts
- globals.css @theme/.dark: add literal palette (--bg #0a0b0d, --bg-side,
  --card #15171b = only bordered surface, --term #0c0d10, --line/--line-2,
  text ramp --t1..--t4, --blue/--orange/--amber/--red/--green) and re-point the
  existing --color-* semantic tokens to it (no token renames — alias + migrate).
  Flat surfaces, no warm gradients/glows. Dark theme preserved.
- Self-host Schibsted Grotesk (UI) + JetBrains Mono (machine) via
  next/font/local — no external font CDN. Geist Sans removed.

Status system (one spectrum, used everywhere)
- lib/status-spec.ts (getStatusSpec) + <StatusBadge> render the kanban card
  badge, sidebar dot, and session topbar pill from a single source; working dot
  breathes (CSS-only @keyframes breathe).

Fleet board (kanban.html)
- Frameless tinted columns Working -> Needs you -> In review -> Ready to merge
  with per-column semantic top-glow; the card is the only bordered surface
  (hairline ring, no status left-rail). Sidebar-shows-all-projects + SSE 5s
  unchanged.

Session detail (session.html)
- Framed xterm terminal: theme object tied to tokens (orange cursor, blue
  selection, token-mapped ANSI) — terminal content unstyled.
- New pluggable inspector rail <SessionInspector>: Summary (PR -> review
  comments -> Activity -> Overview) / Changes / Browser. Review comments keep
  the soft-blue Address action (askAgentToFix passing comment + file:line).
- Topbar: shared status pill, Kill, solid-blue Orchestrator primary; the PR
  popover is now mobile-only (desktop has the inspector). Blue mascot mark.

Tests: add status-spec / StatusBadge / SessionInspector / AppMark tests; update
column-label, theme, layout-metadata and PR-location assertions; mock
next/font/local in vitest. typecheck / test / lint / build all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* wip(web): compact card footer + cleanup before mockup-fidelity pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(web): mockup-faithful redesign pass — sidebar brand, resizable panels, cleaner chrome

Addresses review feedback to follow docs/design/mockups/{kanban,session}.html closely.

Sidebar (ProjectSidebar + mc-sidebar.css)
- Brand + blue mascot mark moved to the TOP of the sidebar (was in the topbar).
- Cool sidebar background (var(--color-bg-sidebar) #08090b) — removed the warm tint.
- Removed the yellow session-count chip (plain mono count) and the Review button.
- Per-project action icons now reveal on hover only.
- Consolidated the footer's four buttons into a single Settings gear + popover
  (show killed / show done / show session id / theme).
- Right edge is drag-resizable.

Board (Dashboard + AttentionZone + SessionCard + mc-board.css)
- Topbar brand removed; "Board" header + mockup subtitle; blue primary CTA.
- Frameless tinted columns with per-column glow; compact informational cards
  (status badge · id · hover terminal, 2-line title, branch w/ git icon, thin
  PR/CI footer). Removed inline quick-reply/alerts/CI-chips/merge+review buttons
  from cards (actions live on the session page); kept hover kill + terminal link.
- Split Done card into SessionCard.parts.tsx (≤400 lines).

Session detail (SessionDetail* + SessionInspector + TerminalControls + mc-session.css)
- Topbar: ‹ Kanban back button, title with branch to its RIGHT (git icon, no odd
  truncation), shared status pill, Kill, blue Orchestrator. Brand removed from the
  session shell header too.
- Terminal header: removed the "Connected" status text; matches the mockup
  (Terminal label · id · zoom · fullscreen). Terminal flush (no stray left margin).
- Terminal head and inspector tab bar are both 47px so their rules align.
- Inspector: PR → review comments → Activity timeline → Overview; left edge
  drag-resizable. Split header helpers into SessionDetailHeader.parts.tsx.

Shared infra
- useResizable hook (pointer drag → CSS var on :root, localStorage-persisted,
  no inline style); .resize-handle styles; per-screen mc-*.css loaded after
  globals.css in layout.tsx; sidebar/inspector widths read --ao-sidebar-w /
  --ao-inspector-w with sensible min/max + double-click reset.

typecheck / web tests (1005) / lint (0 errors) / build all green; resize verified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): sidebar/topbar polish from review feedback

- Notification bell icon 13→17px (was tiny inside its 34px button).
- Sidebar project rows: count shows at rest in the right slot; per-project
  action icons are now an absolutely-positioned hover-reveal group (out of
  flow) so the project name keeps full width and the row stays single-height
  (fixes the inflated rows / vertically-stacked icons).
- Session status dot nudged 1px to vertically center against the mono label.
- Orchestrator session page no longer renders the inspector rail (full-width
  terminal — nothing to inspect).

typecheck / web tests (1005) / lint (0 errors) green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): notification icon size + sidebar/topbar review fixes

- Notification bell on the session topbar was squeezed to a 6px sliver: the
  text-button padding rule applied to the icon-only button inside its fixed
  34px width. Give the bell its own 34px square / zero-padding rule → 17px icon.
- Remove the redundant sidebar toggle from the session topbar on desktop
  (mobile keeps the drawer hamburger); the sidebar owns collapse/expand.
- Collapsed sidebar now shows an expand button so it can be reopened.
- Trim sidebar padding + session-list indent so project/agent rows get more
  width.

typecheck / web tests (1005) / lint (0 errors) green; collapse↔expand + icon
size verified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): sidebar session names truncate with ellipsis; rename pencil no longer overlays

- The session label was an inline <span>, so text-overflow:ellipsis never
  applied — long names hard-clipped. Make it display:block so it ellipsizes.
- The rename pencil now absolutely positions at the row's right edge; at rest
  the label gets the full row width, and on hover the link gains right-padding
  so the text re-truncates and the pencil sits in the reserved space instead of
  covering the name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): project name reserves space for hover action icons (no overlap)

On hover the per-project action icons reveal over the right slot; the toggle now
gains right-padding so the project name re-truncates with ellipsis instead of
running underneath the icons — same pattern as the session rows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): remove kanban topbar toggle + redesign empty state to mission-control

- The board (kanban) topbar still rendered a desktop sidebar toggle; make it
  mobile-only (the sidebar owns collapse/expand), matching the session topbar.
- Empty state (Skeleton EmptyState): ghost columns now use the live board's
  labels (Working / Needs you / In review / Ready to merge), 4 columns, and the
  frameless tinted-trough look — removing the old dashed/warm-tinted columns and
  the stale 5-category set. Orchestrator glyph recolored to the blue accent via
  tokens (was hardcoded orange).

typecheck / web tests (1005) / lint (0 errors) green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(web): show project name in titlebar, not the raw project id hash

The board topbar special-cased projects named 'Agent Orchestrator' to display
the project id (e.g. agent-orchestrator_649ba24578) — unreadable gibberish.
Always show the human-readable project name instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(core,web): detectPR branch guard, multi-PR prLabel aggregation, reset selectedPRIndex on session change

* fix(web): render terminal with xterm WebGL renderer (fixes broken box-drawing)

The dashboard terminal used xterm's default DOM renderer, which draws each
row as a separate DOM line and cannot tile box-drawing / block glyphs across
cells. Agent TUIs (Claude Code's bordered panels, the "N shell command"
expansion) rendered with broken/gappy frames and a grey blob — independent of
font or lineHeight (verified: even a complete font at lineHeight 1.0 breaks in
the DOM renderer).

Load xterm's WebGL renderer (@xterm/addon-webgl), which GPU-draws box/block
glyphs into each cell so frames connect and shaded regions stay solid. Loaded
rAF-deferred after open() with a DOM fallback on context-loss / when WebGL is
unavailable (headless, blocklisted GPU). This matches how superset renders
the same agent TUIs.

The WebGL addon only ships for the xterm 6.1.0-beta train, so bump
@xterm/xterm 6.0.0 -> 6.1.0-beta.256 and the addons to the matched beta set
(the same pair superset runs in production).

Also drops the earlier no-op fontWeight/fontWeightBold/letterSpacing change —
those values equalled xterm's defaults and had no visible effect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(web): enforce dark-mode contrast floor so agent blocks aren't grey blobs

Claude Code's expanded "Ran N shell command" block is painted on an ANSI
white background (ESC[47m). The terminal theme sets `white` ≈ `foreground`
(#c5ccd3), and dark mode used `minimumContrastRatio: 1` (no floor), so the
block's text was the same colour as its background — rendering as an
unreadable grey blob (only independently-coloured links/emoji showed through).

Raise the dark-mode floor to 4.5 (WCAG AA), matching the rationale already
used for light mode (7). xterm then auto-adjusts only the foregrounds that
fail the floor, leaving all other agent colours untouched. Verified in an
isolated harness with the real theme: white-on-white block goes from
invisible to legible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(web): load Unicode 11 addon so emoji/wide-char widths match tmux

Agent TUIs and tmux lay out tables treating emoji like / as 2 cells
wide (modern Unicode). xterm defaults to Unicode 6 width tables, where
those are 1 cell — so the grid shifts a column after every emoji, breaking
table borders and leaving stray text fragments (visible only in the web
terminal; a direct tmux attach via a modern terminal renders it fine).

Load @xterm/addon-unicode11 and set unicode.activeVersion = "11" so xterm's
width tables agree with tmux/the agent. Same beta train as the other addons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(web): rescale overlapping glyphs so out-of-font chars don't overlap text

JetBrains Mono is subset to Latin glyphs, so characters it lacks (arrows
→ ← ↔, CJK, emoji, powerline) are drawn from a fallback font whose advance
can exceed our monospace cell — the glyph then bleeds into the next cell and
overlaps the following character. Set rescaleOverlappingGlyphs so xterm shrinks
any glyph wider than its cell back to fit. Fixes the whole class of out-of-font
overflow, not just arrows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(web): ship full-coverage JetBrains Mono (restore arrows/box/blocks)

The self-hosted JetBrains Mono was subset to ~229 Latin glyphs, dropping
arrows (→ ← ↔), box-drawing, block elements and other symbols agents emit.
Those fell back to a system font at the wrong cell width — overlapping
(pre-rescale) or shrunk/blurry (post-rescale). Replace it with the full
JetBrains Mono variable face (OFL-1.1, wght 100–800, ~111 KB woff2, same
metrics) so those glyphs render in-font, full-size and crisp at the correct
monospace width. rescaleOverlappingGlyphs stays as a safety net for the few
glyphs even the full face lacks (CJK, emoji, powerline PUA).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Laraib-1629 <laraibahmed73@gmail.com>
Co-authored-by: suraj-markup <sk9261712674@gmail.com>
Co-authored-by: itrytoohard <ayetrytoohard@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Priyanshu Choudhary <57816400+Priyanchew@users.noreply.github.com>
2026-06-02 05:10:55 +05:30
.changeset chore: version packages 2026-05-24 00:16:44 +05:30
.cursor feat(windows): complete Windows support (#1025) 2026-05-09 00:10:53 +05:30
.github merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
.husky feat: implement comprehensive security audit and secret leak prevention (#67) 2026-02-16 10:33:50 +05:30
.issue-assets feat(notifier): make notifier system robust with manual harness and desktop setup (#1736) 2026-05-19 14:48:40 +05:30
artifacts docs: clarify one-orchestrator-per-project model + prune superseded docs (closes #2005) (#2012) 2026-05-22 16:36:31 +05:30
changelog chore: rename @composio scope to @aoagents across all packages 2026-04-09 15:59:33 +00:00
completions add zsh completion support for ao (#1374) 2026-04-24 03:48:25 +05:30
docs merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
examples feat: add $schema support to agent-orchestrator.yaml (#1373) 2026-04-26 19:42:45 +05:30
handoff/pr-1466 refactor(core): storage redesign — projectId-based paths, JSON metadata (#1466) 2026-04-28 17:55:53 +05:30
openclaw-plugin refactor: remove --decompose feature entirely 2026-04-10 13:02:52 +05:30
packages merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
schema feat(notifier): make notifier system robust with manual harness and desktop setup (#1736) 2026-05-19 14:48:40 +05:30
scripts merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
skills chore: add bug-triage skill for agent-driven issue triage (#1725) 2026-05-12 20:51:00 +05:30
tests/integration chore(cli): remove deprecated 'ao init' command (#1438) 2026-05-05 18:43:55 +05:30
website feat(notifier): make notifier system robust with manual harness and desktop setup (#1736) 2026-05-19 14:48:40 +05:30
.eslintignore fix: added GraphQL batch PRfeat: add GraphQL batch PR enrichment for orchestrator polling enrichment for orchestrator polling (fixes #608) (#637) 2026-03-30 00:31:04 +05:30
.gitignore feat(windows): complete Windows support (#1025) 2026-05-09 00:10:53 +05:30
.gitleaks.toml refactor(core): storage redesign — projectId-based paths, JSON metadata (#1466) 2026-04-28 17:55:53 +05:30
.npmrc feat: publish to npm under @composio scope (#32) 2026-02-15 04:28:57 +05:30
.prettierignore chore: add ESLint, Prettier, CI workflow, and comprehensive CLAUDE.md conventions 2026-02-13 18:01:52 +05:30
.prettierrc chore: add ESLint, Prettier, CI workflow, and comprehensive CLAUDE.md conventions 2026-02-13 18:01:52 +05:30
AGENTS.md chore: add bug-triage skill for agent-driven issue triage (#1725) 2026-05-12 20:51:00 +05:30
ARCHITECTURE.md feat(windows): complete Windows support (#1025) 2026-05-09 00:10:53 +05:30
CLAUDE.md fix(cli): orchestrate ao update lifecycle + drop misleading ao stop picker (closes #1970, closes #1972) (#1973) 2026-05-21 04:22:22 +05:30
CONTRIBUTING.md refactor(release): split publish into two-repo model — GitHub release public, npm publish private (#1815) 2026-05-13 03:29:04 +05:30
DESIGN.md merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
LICENSE feat: publish to npm under @composio scope (#32) 2026-02-15 04:28:57 +05:30
README.md fix(agent-grok): use json import for manifest metadata (#2040) 2026-05-23 16:22:44 +05:30
SECURITY.md fix: migrate to hash-based project isolation architecture 2026-02-18 00:19:55 +05:30
SETUP.md feat(cli): support AO_PUBLIC_URL for reverse-proxied dashboards (#1757) 2026-05-20 23:09:04 +05:30
TROUBLESHOOTING.md fix: migrate to hash-based project isolation architecture 2026-02-18 00:19:55 +05:30
agent-orchestrator.yaml.example feat(windows): complete Windows support (#1025) 2026-05-09 00:10:53 +05:30
eslint.config.js fix(agent-codex): close codex JSONL streams on abort (#1977) 2026-05-21 07:29:42 +05:30
package.json fix(agent-grok): use json import for manifest metadata (#2040) 2026-05-23 16:22:44 +05:30
pnpm-lock.yaml merge fork, 25 May - 2 June (#2086) 2026-06-02 05:10:55 +05:30
pnpm-workspace.yaml chore: remove React Native/Expo mobile app 2026-03-25 12:00:59 +05:30
tsconfig.base.json fix: scope node types to node packages 2026-04-13 18:25:21 +05:30
tsconfig.node.json fix: scope node types to node packages 2026-04-13 18:25:21 +05:30

README.md

Agent Orchestrator — The Orchestration Layer for Parallel AI Agents

Agent Orchestrator banner

Spawn parallel AI coding agents, each in its own git worktree. Agents autonomously fix CI failures, address review comments, and open PRs — you supervise from one dashboard.

GitHub stars
npm version
License: MIT
PRs merged
Tests
Discord


Agent Orchestrator manages fleets of AI coding agents working in parallel on your codebase. Each agent gets its own git worktree, its own branch, and its own PR. When CI fails, the agent fixes it. When reviewers leave comments, the agent addresses them. You only get pulled in when human judgment is needed.

Agent-agnostic (Claude Code, Codex, Aider) · Runtime-agnostic (tmux, ConPTY/process, Docker) · Tracker-agnostic (GitHub, Linear)

See it in action

Agent Orchestrator demo — AI agents building their own orchestrator

Watch the Demo on X


The Self-Improving AI System That Built Itself

Read the Full Article on X

Quick Start

Prerequisites: Node.js 20.18.3+, Git 2.25+, gh CLI, and:

  • macOS / Linux: tmux — install via brew install tmux or sudo apt install tmux.
  • Windows: PowerShell 7+ recommended. tmux is not required — AO uses native ConPTY via the runtime-process plugin (the default on Windows). Set AO_SHELL=bash if you have Git Bash and prefer it.

Install

npm install -g @aoagents/ao

Nightly builds (latest main, daily FriTue): npm install -g @aoagents/ao@nightly
Back to stable: npm install -g @aoagents/ao@latest

Permission denied? Install from source?

If npm install -g fails with EACCES, prefix with sudo or fix your npm permissions.

To install from source (for contributors):

git clone https://github.com/ComposioHQ/agent-orchestrator.git
cd agent-orchestrator && bash scripts/setup.sh

Zsh Completion

Generate the completion file from the installed CLI:

mkdir -p ~/.zsh/completions
ao completion zsh > ~/.zsh/completions/_ao

Then make sure the directory is on your fpath before compinit runs:

fpath=(~/.zsh/completions $fpath)
autoload -Uz compinit
compinit

For Oh My Zsh, install the same generated file into a custom plugin directory and add ao to your plugin list:

mkdir -p "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/ao"
ao completion zsh > "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/ao/_ao"

If you are contributing from a source checkout, you can also symlink the repo copy at completions/_ao.

Start

Point it at any repo — it clones, configures, and launches the dashboard in one command:

ao start https://github.com/your-org/your-repo

Or from inside an existing local repo:

cd ~/your-project && ao start

That's it. The dashboard opens at http://localhost:3000 and the orchestrator agent starts managing your project.

Add more projects

ao start ~/path/to/another-repo

How It Works

  1. You startao start launches the dashboard and an orchestrator agent
  2. Orchestrator spawns workers — each issue gets its own agent in an isolated git worktree
  3. Agents work autonomously — they read code, write tests, create PRs
  4. Reactions handle feedback — CI failures and review comments are automatically routed back to the agent
  5. You review and merge — you only get pulled in when human judgment is needed

The orchestrator agent uses the AO CLI internally to manage sessions. You don't need to learn or use the CLI — the dashboard and orchestrator handle everything.

Configuration

ao start auto-generates agent-orchestrator.yaml with sensible defaults. You can edit it afterwards to customize behavior:

# agent-orchestrator.yaml
$schema: https://raw.githubusercontent.com/ComposioHQ/agent-orchestrator/main/schema/config.schema.json
# Runtime data is auto-derived under ~/.agent-orchestrator/{hash}-{projectId}/
port: 3000

defaults:
  runtime: tmux       # default on macOS / Linux; on Windows the default is `process` (ConPTY)
  agent: claude-code
  workspace: worktree
  notifiers: [desktop]

projects:
  my-app:
    repo: owner/my-app
    path: ~/my-app
    defaultBranch: main
    sessionPrefix: app

reactions:
  ci-failed:
    auto: true
    action: send-to-agent
    retries: 2
  changes-requested:
    auto: true
    action: send-to-agent
    escalateAfter: 30m
  approved-and-green:
    auto: false # flip to true for auto-merge
    action: notify

CI fails → agent gets the logs and fixes it. Reviewer requests changes → agent addresses them. PR approved with green CI → you get a notification to merge.

Keep the $schema line so editors can autocomplete and validate against schema/config.schema.json.

See agent-orchestrator.yaml.example for the full reference, or run ao config-help for the complete schema.

Remote Access

AO keeps your Mac awake while running, so you can access the dashboard remotely (e.g., via Tailscale from your phone) without the machine going to sleep.

How it works: On macOS, AO automatically holds an idle-sleep prevention assertion using caffeinate. When AO exits, the assertion is released.

# agent-orchestrator.yaml
$schema: https://raw.githubusercontent.com/ComposioHQ/agent-orchestrator/main/schema/config.schema.json
power:
  preventIdleSleep: true  # Default on macOS; no-op on Linux and Windows

Set to false if you want to allow idle sleep while AO runs.

Lid-close limitation: macOS enforces lid-close sleep at the hardware level — no userspace assertion can override it. If you need remote access while traveling with the lid closed, use clamshell mode (external power + display + input device).

Linux / Windows: AO does not currently hold a wake assertion on these platforms. On Linux, idle-sleep behaviour is governed by your desktop environment / systemd-logind; configure that directly. On Windows, set the OS power plan if remote access matters while idle.

Plugin Architecture

Seven plugin slots. Lifecycle stays in core.

Slot Default Alternatives
Runtime tmux (macOS/Linux) / process (Windows) process, docker
Agent claude-code codex, aider, cursor, opencode, kimicode
Workspace worktree clone
Tracker github linear, gitlab
SCM github gitlab
Notifier desktop slack, discord, composio, webhook, openclaw
Terminal iterm2 web

All interfaces defined in packages/core/src/types.ts. A plugin implements one interface and exports a PluginModule. That's it.

Why Agent Orchestrator?

Running one AI agent in a terminal is easy. Running 30 across different issues, branches, and PRs is a coordination problem.

Without orchestration, you manually: create branches, start agents, check if they're stuck, read CI failures, forward review comments, track which PRs are ready to merge, clean up when done.

With Agent Orchestrator, you: ao start and walk away. The system handles isolation, feedback routing, and status tracking. You review PRs and make decisions — the rest is automated.

Documentation

Doc What it covers
Setup Guide Detailed installation, configuration, and troubleshooting
CLI Reference All ao commands (mostly used by the orchestrator agent)
Examples Config templates (GitHub, Linear, multi-project, auto-merge)
Development Guide Architecture, conventions, plugin pattern
Contributing How to contribute, build plugins, PR process

Development

pnpm install && pnpm build    # Install and build all packages
pnpm test                      # Run tests (3,288 test cases)
pnpm dev                       # Start web dashboard dev server

See docs/DEVELOPMENT.md for code conventions and architecture details.

Contributing

Contributions welcome. The plugin system makes it straightforward to add support for new agents, runtimes, trackers, and notification channels. Every plugin is an implementation of a TypeScript interface — see CONTRIBUTING.md and the Development Guide for the pattern.

License

MIT