# autonomOS — Agent Development Guide ## Start Here 1. Read [`README.md`](README.md) — project overview, monorepo structure 2. Read [`docs/FEATURES.md`](docs/FEATURES.md) — feature specifications and design intent 3. Browse [`docs/decisions/`](docs/decisions/README.md) — all architectural decisions (one file per ADR, with an index) with context and rationale 4. Read [`docs/ROADMAP.md`](docs/ROADMAP.md) — current priorities and what to work on 5. Read [`docs/RESEARCH.md`](docs/RESEARCH.md) — research findings, competitor analysis, learnings ## Project Vision autonomOS is a **mission control platform for autonomous agents** — a terminal dashboard that spawns Claude Code sessions, tracks their status via hook telemetry, and enables multi-agent coordination through a messaging gateway. **Current state:** Terminal dashboard + session management + hook relay + multi-agent gateway + MCP tools. The orchestrator/projects/workspaces model described below is the long-term vision, not yet implemented. **Core concepts (future):** - **Orchestrator** — PM agent, the main interface. Understands project goals, delegates to workspace agents, tracks progress. - **Projects** — Logical goals with roadmaps. Can span multiple workspaces. Multiple projects per workspace. - **Workspaces** — Physical repositories, auto-discovered. Each has active agent sessions. Two paths that share a common core: - **Dev Path** — control plane for agent tools (Claude Code, etc.) - **Robot Path** — persistent agent platform for robotics (aspirational, future) ## Monorepo Structure ``` autonomOS/ ├── packages/ │ ├── dashboard/ # Web UI — observability & control │ │ └── src/layout/ # dockview tabs + split panes (ADR-047, the only layout engine) │ ├── server/ # Hono + node-pty — API, WebSocket, PTY management │ │ ├── src/gateway/ # URI-based message router + platform adapters │ │ ├── src/channel-server/ # Standalone MCP subprocess (server:autonomos) │ │ └── src/mcp/ # Shared MCP tool definitions (used by both servers) │ └── core/ # Shared agent abstractions & types ├── docs/ │ ├── decisions/ # Architectural Decision Records, one file per ADR (append-only) │ ├── FEATURES.md # Feature specifications (F-001 through F-016) │ ├── ROADMAP.md # Current priorities │ ├── RESEARCH.md # Research findings & competitor analysis │ ├── VISION.md # Project vision │ └── research/ # Deep-dive research topics ├── CLAUDE.md # This file — agent development guide └── README.md # Project overview ``` ## Key Systems ### Hook Relay (`--settings` inline curl) Every spawned session gets `--settings` with inline hook entries for all 13 Claude Code events. Each hook runs `curl -d @- $AUTONOMOS_SERVER/api/hooks/$SESSION_ID`. The server processes events for agent status tracking (`deriveStatus()` state machine) and notification generation (SendUserMessage, Stop, Notification, PermissionRequest). **Events:** SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure, Stop, Notification, PermissionRequest, SubagentStart, SubagentStop, PreCompact, PostCompact, SessionEnd ### Session Spawning Flags Sessions are spawned with: `--session-id` (pre-generated UUID), `--brief` (enables SendUserMessage), `--append-system-prompt` (autonomOS context + MCP tool descriptions), `--settings` (hook relay), the agent's permission-mode flags (ADR-045 + ADR-061 — `ask` emits no flag, `bypass` emits `--dangerously-skip-permissions`), and optionally `--dangerously-load-development-channels` / `--channels`, and `--mcp-config` (channel server subprocess). ### Auto-Trust `attachStartupWatcher()` monitors PTY output for Claude Code's interactive trust prompts and auto-dismisses them. Watches for "Yes, I trust this folder" and "WARNING: Loading development channels" needles after ANSI stripping. Configurable via settings panel toggle (default: ON). ### Agent Communication (URI-based) Agents communicate through the gateway using one scheme: **`agent://name`**. There is no broadcast and there are no platform schemes — both were removed in ADR-064 because both reported success for messages that never arrived (`broadcast://` ack'd unconditionally, even to a fleet of zero; `slack://`'s only adapter was a stub whose `send()` was a `console.log`). **`send()` succeeds only if the destination ACCEPTED the message** — for Claude Code, the write landed on an open, registered channel-server socket; for Codex, the agent's `app-server` daemon replied to `turn/start`. It is NOT a receipt that the agent read it. Any other result explains why it did not arrive, and a message reported as not-yet-delivered is retried automatically — **do not re-send it** (a duplicate makes a Codex agent execute the same instruction twice). ### MCP Tool Architecture Tool definitions live in `packages/server/src/mcp/tools.ts` — shared between: - **HTTP MCP server** (`mcp.ts`) — served on the internal Unix control socket (`$configDir/control.sock`), NOT the public port (ADR-055); reachable only by same-user processes on the box, and still token-gated - **Channel MCP server** (`channel-server/`) — for autonomOS-spawned CC sessions Both servers expose: `create_agent`, `list_agents`, `kill_agent`, `set_manager`, `get_org_chart`, `list_templates`, `create_template`, `self_exit`, `create_schedule`, `list_schedules`, `get_schedule`, `update_schedule`, `delete_schedule`, `run_schedule`, `list_env_presets`, `create_env_preset`, `update_env_preset`, `delete_env_preset`. The channel server also has `send` (requires gateway WebSocket). ### Base Context Injection Every autonomOS-spawned session gets `--append-system-prompt` with: 1. Base autonomOS context — "You are running inside autonomOS" + available tools 2. Per-agent instructions (if provided via `create_agent`'s prompt/systemPrompt params) Use `--append-system-prompt` (preserves CC defaults + CLAUDE.md). Use `--system-prompt` only for full override. ## Key Conventions ### Decision Records (CRITICAL) Every architectural decision is its own file in [`docs/decisions/`](docs/decisions/README.md): `ADR-NNN-.md`, browsable by number and title in GitHub's folder view (`make adr-index` prints a table with date, status and supersession; it is never committed, ADR-157). Start one with `make adr NEW="Short title"`. It takes the next free number (checking origin/main AND open PRs) and writes a template. Don't append to `docs/DECISIONS.md` (it's a pointer stub now, and CI rejects entries there). Each entry must include: - **Date** (YYYY-MM-DD) and **Decided by** (human vs agent) - **Context**: why this decision was needed - **Decision**: what was chosen - **Rationale**: why this over alternatives - **Alternatives considered**: what else was evaluated - **Source**: where the decision happened (Discord channel, CC session, etc.) The labels are exact (`**Alternatives considered:**`, not `**Alternatives:**`). `make check`, and therefore CI and the pre-push gate, rejects a new ADR that is missing a field, still holds a template TODO, or reuses a number. Never delete or modify past entries; the migrated ones are hash-locked in `docs/decisions/legacy-manifest.json`. If a decision is reversed, add a new entry referencing the old one (an optional `**Supersedes:** ADR-NNN` field, or `part of ADR-NNN` / `ADR-NNN (part: …)`, feeds the `make adr-index` table). If two parallel PRs pick the same number, whoever merges later runs `make adr-renumber FILE=docs/decisions/ADR-NNN-….md`: one file changes, nothing else. Main doesn't require up-to-date branches, so both can occasionally merge; main's CI then goes red with the same message, and whoever merged later runs that `make adr-renumber` in a follow-up PR. There is no bot for this (ADR-157). A branch that still appended to the old `docs/DECISIONS.md` moves its entry with `make adr-import REF=HEAD` (steps in `docs/decisions/README.md`). ### Research & Learnings All research goes in `docs/RESEARCH.md` or `docs/research/` subdirectories. When investigating competitors, frameworks, or approaches: - Document what you found with links - Note what's relevant to autonomOS - Include your assessment (not just raw info) ### Commit Messages - `feat:` — new features - `fix:` — bug fixes - `perf:` — performance improvements - `refactor:` — structural changes - `docs:` — documentation changes - `research:` — research findings - `init:` — initial setup ### Terminology - **UI says "agents"** — sidebar, buttons, labels - **Code says "sessions"** — types, APIs, server internals - Both refer to the same entity — a managed CC PTY process ### Session Naming CC owns session names via JSONL `customTitle`. `titleCache.ts` reads them (256KB tail scan, mtime-cached). The `--name` flag sets the initial name at spawn. `/rename` updates it. The titleCache is more reliable than the SDK's `listSessions()` (which only reads 64KB). ### Development Philosophy - **Personal tool first** — ship for Terry, generalize later - **Both paths share core** — abstractions should work for dev agents AND robots ## What NOT to Do - Don't make architectural decisions without recording them in `docs/decisions/` (`make adr`) - Don't start building without checking ROADMAP.md for priorities - Don't ignore existing research — check RESEARCH.md before investigating something - Don't over-engineer for the robot path yet — it's aspirational - Don't define MCP tool schemas directly in `mcp.ts` or `channel-server/index.ts` — they go in `mcp/tools.ts` ## Agent Workflow When working on this repo: 1. Check ROADMAP.md — what's the current priority? 2. Check `docs/decisions/` — has this been decided already? 3. Do the work 4. Update ROADMAP.md if priorities shifted 5. Add any new decisions to `docs/decisions/` (`make adr NEW="…"`) 6. Update RESEARCH.md with any new findings