# ReverbCode A Go-backed agent orchestration daemon for supervising parallel coding-agent sessions, with an `ao` CLI today and an Electron supervisor planned. The Go module and packages remain `agent-orchestrator`; "ReverbCode" is the public name. See [`docs/architecture.md`](docs/architecture.md) for the backend mental model and [`AGENTS.md`](AGENTS.md) for the contributor / worker contract. ## What's shipped today - Loopback-only HTTP daemon (`backend/internal/httpd`) controlling projects, sessions, orchestrators, and hook callbacks over `127.0.0.1`. - `ao` Cobra CLI (`backend/cmd/ao`) — a thin client over the daemon for daemon control, project/session/orchestrator management, and worker spawning. - Worker/orchestrator spawn into isolated `git worktree` workspaces, launched inside a `zellij` runtime adapter. - Live per-PR observation via the provider-neutral SCM observer (`backend/internal/observe/scm/`): polling loop, ETag guards, semantic diffing, CI/check/review-thread tracking, and lifecycle nudges for CI failures, review feedback, and merge conflicts. - Agent adapters under `backend/internal/adapters/agent/`: `claude-code`, `codex`, `opencode`, `grok`, `cursor`, `qwen`, `copilot`, `kimi`, plus shared activity-dispatch / hook utilities. - SQLite store (`backend/internal/storage/sqlite/`) with sqlc-generated queries, DB-triggered change-data-capture into `change_log`, and a CDC poller/broadcaster (`backend/internal/cdc/`) feeding in-process subscribers and an SSE replay endpoint. - Session lifecycle manager + reaper (`backend/internal/lifecycle/`, `backend/internal/observe/reaper/`): runtime/activity/PR facts reduced into the small durable session state, display status derived at read time. ## Quick start Requirements: Go 1.25+, [`zellij`](https://zellij.dev/) on `PATH` for the runtime adapter, and `gh` (or `GITHUB_TOKEN`) if you want the SCM observer to authenticate against GitHub. The SQLite driver is the pure-Go `modernc.org/sqlite` — no system SQLite library is required. ```bash cd backend go build -o /tmp/ao ./cmd/ao # Start the daemon and wait for /readyz. /tmp/ao start # Register a local git repo as a project. The id defaults to the lowercased # base of --path; pass --id explicitly when the directory name doesn't match. /tmp/ao project add --path /path/to/your/repo --id your-repo --name your-repo # Spawn a worker session running the default agent. /tmp/ao spawn --project your-repo --prompt "Refactor the auth module" # Inspect what's running. /tmp/ao status /tmp/ao session ls ``` ### Electron app (dev) The desktop supervisor lives under `frontend/` and is started separately: ```bash cd frontend npm install npm run dev # electron-forge start ``` Heads-up: `npm run dev` does **not** start the daemon for you. Start it first (`ao start`, see above) — the renderer attaches to the running daemon over loopback (`127.0.0.1:3001` by default, the `AO_PORT` from the table below). Without a daemon the app opens but shows its daemon-not-ready state. For renderer-only UI work without the Electron shell, use `npm run dev:web` (Vite in a regular browser). ## CLI surface The CLI is intentionally thin: every product command resolves to a daemon HTTP route. Run `ao --help` for the authoritative flag shape; the table below groups what's on `main` today. | Lane | Command | Purpose | | ------------ | ------------------------------------ | ------------------------------------------------------------ | | Daemon | `ao start` | Start the daemon in the background and wait for `/readyz`. | | Daemon | `ao stop` | Graceful shutdown via loopback `POST /shutdown`. | | Daemon | `ao status` | Report PID/port/health/readiness from `running.json`. | | Daemon | `ao daemon` | Hidden internal entrypoint used by `ao start`. | | Project | `ao project add` | Register a local git repo as a project. | | Project | `ao project ls` | List registered projects. | | Project | `ao project get ` | Fetch one project. | | Project | `ao project rm ` | Remove a project. | | Session | `ao spawn` | Spawn a worker session in a registered project. | | Session | `ao session ls` | List sessions (filter by project, include terminated). | | Session | `ao session get ` | Fetch one session. | | Session | `ao session kill ` | Terminate a session. | | Session | `ao session rename ` | Rename a session. | | Session | `ao session restore ` | Relaunch a terminated session. | | Session | `ao session cleanup` | Reclaim eligible workspaces for terminated sessions. | | Session | `ao session claim-pr ` | Attach an existing PR to a session. | | Orchestrator | `ao orchestrator ls` | List orchestrator sessions. | | Messaging | `ao send` | Send a message to a running agent session. | | Utility | `ao doctor` | Local health checks (config, data dir, DB, `git`, `zellij`). | | Utility | `ao completion ` | Generate bash/zsh/fish/powershell completions. | | Utility | `ao version` | Print build metadata. | | Internal | `ao hooks ` | Hidden adapter hook callback. | See [`docs/cli/`](docs/cli/) for the daemon-control intent and command shape. ## Configuration All configuration is env-driven; the daemon takes no config file. The bind host is hard-coded to `127.0.0.1` — the daemon has no auth, CORS, or TLS, and exposing it beyond loopback would be a security regression. | Var | Default | Purpose | | --------------------- | ------------------------------------------------- | --------------------------------------------------------------------------- | | `AO_PORT` | `3001` | Bind port; daemon fails fast if taken. | | `AO_REQUEST_TIMEOUT` | `60s` | Per-request timeout (Go duration). | | `AO_SHUTDOWN_TIMEOUT` | `10s` | Graceful-shutdown hard cap. | | `AO_RUN_FILE` | `/agent-orchestrator/running.json` | PID + port handshake path. | | `AO_DATA_DIR` | `/agent-orchestrator/data` | SQLite DB, WAL files, managed state. | | `AO_AGENT` | `claude-code` | Default agent adapter id used by `ao spawn`. | | `AO_SESSION_ID` | _(unset)_ | Set inside spawned sessions; read by `ao send` and `ao hooks`. | | `GITHUB_TOKEN` | _(unset)_ | Used by the GitHub SCM and tracker adapters. Falls back to `gh auth token`. | Health check: ```bash curl localhost:3001/healthz curl localhost:3001/readyz ``` ## Architecture The daemon is a long-running supervisor. Adapters observe external facts (PR state, agent activity, runtime liveness); the lifecycle manager reduces those into a small set of durable session facts (`activity_state`, `is_terminated`, PR rows). Display status is _derived_ from those facts at read time — it is never stored. SQLite triggers append every user-visible change to `change_log`, and the CDC poller broadcasts those events to in-process subscribers and an SSE stream. Full mental model and load-bearing rules: [`docs/architecture.md`](docs/architecture.md). Package-by-package ownership: [`docs/backend-code-structure.md`](docs/backend-code-structure.md). ## Testing The local gate is the backend Go build and race-enabled test suite: ```bash cd backend && go build ./... && go test -race ./... ``` GitHub Actions is the authoritative pre-merge gate; mirror its commands here when in doubt. See [`AGENTS.md`](AGENTS.md) for the regen workflow when touching the daemon API surface (`npm run sqlc`, `npm run api`). ## Status and roadmap Current `main` ships the CLI surface above, the SCM observer end-to-end (issues [#75](https://github.com/aoagents/agent-orchestrator/issues/75), [#108](https://github.com/aoagents/agent-orchestrator/issues/108), [#109](https://github.com/aoagents/agent-orchestrator/issues/109)), the agent adapter platform, and the CDC pipeline with SSE replay. The Tracker observer ([#112](https://github.com/aoagents/agent-orchestrator/issues/112)) and live `pr_*` event consumers ([#110](https://github.com/aoagents/agent-orchestrator/issues/110)) are in flight. The Electron supervisor under `frontend/` is still a placeholder shell — daemon logic stays in the Go backend. Tracking milestone: [`rewrite`](https://github.com/aoagents/agent-orchestrator/milestone/1) on GitHub. ## Contributing Repo layout and the worker contract live in [`AGENTS.md`](AGENTS.md). Keep changes surgical, follow the package boundaries documented in [`docs/backend-code-structure.md`](docs/backend-code-structure.md), and prefer adding daemon HTTP routes over leaking storage / runtime into the CLI.