Current release: v0.5.77 (Nov 6, 2026) — https://github.com/repo-os/repoos/releases --- url: https://docs.repoos.org/getting-started.md --- # Getting started RepoOS runs inside a repo you already have. It doesn't host your code, and it doesn't ask you to move your work anywhere — it adds a few directories and a local server that reads them. ## Install Choose one: ### curl — preferred ```bash curl -fsSL https://repoos.org/install | bash ``` ::: tip Why curl * **Easiest to update and uninstall** — `repoos upgrade` and `repoos uninstall`, no package manager involved. * **Only method with release channels** — `repoos upgrade --channel beta|rc|canary`. ::: ### Homebrew ```bash brew install repo-os/tap/repoos ``` ### npm ```bash npm install -g @repo-os/repoos ``` ### Bun ```bash bun add -g @repo-os/repoos ``` Bun's installer puts `bun` in `~/.bun/bin`. A new shell does not see it until that directory is on `PATH`: ```bash export PATH="$HOME/.bun/bin:$PATH" ``` ### pnpm ```bash pnpm add -g @repo-os/repoos ``` On a clean Linux account pnpm has no global bin directory yet (`ERR_PNPM_NO_GLOBAL_BIN_DIR`). `pnpm setup` also fails with `ERR_PNPM_UNKNOWN_SHELL` when `SHELL` is unset (common in non-interactive scripts). Set a shell, run setup, then open a new terminal so `PNPM_HOME` is on `PATH`: ```bash export SHELL="${SHELL:-$(command -v bash)}" pnpm setup ``` mise is not a recommended install method. Its npm backend refuses packages under a weekly-downloads threshold unless low-download installs are allowed, and that path still waits out mise's minimum release age, so you get the previous version. `mise unuse --global` leaves a broken shim until `mise prune`. The curl installer puts the release in `~/.local/share/repoos` and a `repoos` launcher in `~/.local/bin`. Machine state (running servers, service registry, check slots) stays in `~/.repoos`. `repoos uninstall` removes the install, the launcher it created, and those state entries, and it prints anything else it left in `~/.repoos`. It does not delete per-repo files. Pipe the installer to `bash` (`curl … | bash`). ## Updating RepoOS Update with the same tool you used to install it. Do not run `repoos upgrade` for a package-manager install: it leaves that install alone and prints the matching command when it can identify the source. | Installed with | Update command | | --- | --- | | curl | `repoos upgrade` | | Homebrew | `brew update && brew upgrade repo-os/tap/repoos` | | npm | `npm update -g @repo-os/repoos` | | Bun | `bun update -g @repo-os/repoos` | | pnpm | `pnpm update -g @repo-os/repoos` | `repoos upgrade --channel beta`, `--channel canary`, and `--channel rc` are available only for the curl install. Package-manager installs follow their package manager's stable release channel. RepoOS runs on **Bun** when it's available and falls back to **Node.js 20.6.0 or newer** otherwise — see [Configuration → Worktrees and runtime](/configuration#worktrees-and-runtime) if you want to pin one. ## Initialize a repo From the root of any git repo: ```bash repoos init ``` Fresh installs keep RepoOS metadata under `repoos/` by default; the interactive prompt can instead use the repo root or another location. Init does not overwrite an existing file. With the default layout it creates: | Path | What it is | | --- | --- | | `repoos.toml` | Configuration. Every field is optional. Always at the repo root. | | `repoos/work/` | One markdown file per task. This is the board. Includes `0001-set-up-repoos.md` (a `done` example) and an inbox starter task. | | `repoos/docs/` | Context an agent needs to work on *this* project — architecture notes, decisions, history. | | `AGENTS.md` | Instructions agents read first. The cross-tool standard; Claude Code, Codex, Cursor, Aider and Zed all read it. Always at the repo root. | | `.env.example` | Names of secrets a fuller setup expects. No values. | | `.gitignore` | Created, or appended when one already exists. Ignores the derived cache, root `.repoos/` runtime state, `.env`, `.env*.local`, `node_modules/`, task and input attachment directories, and `.DS_Store`. | | `repoos/.repoos/canary.txt` | Tracked canary counter. | A new project also runs `git init` and, unless you pass `--no-commit`, commits the scaffold (`chore: initialize RepoOS project`). Init in an existing repo does not make that commit. Run `repoos init` outside a git repo and it starts a guided flow for a brand new project instead. In a terminal it asks a few questions; with no TTY (an agent, a script) pass `--new` and answer them with flags: ```bash repoos init myproject --new \ --description "A tiny social app for book clubs" \ --areas web,api --no-launch ``` See the [CLI reference](/cli#repoos-init-name) for every flag. Don't `git init` first to avoid the prompts — that routes you to the existing-codebase starter instead of the new-project one. Either way the board is never empty: init seeds a starter task. Which starter depends on what's in the repo — if there are no meaningful source files yet (a fresh `git init`, a README-only repo, or only RepoOS's own scaffold) it seeds "Flesh out the product vision and initial architecture"; once there is code to read it seeds "Read this codebase and propose project docs + an initial task backlog". The one-line summary after init says which was chosen and why. Force one with `repoos init --starter vision|codebase`. In an interactive terminal, `repoos init` also asks whether you want to install coding agents. If you opt in, it shows detected agents, lets you select missing ones, and asks before running each agent's install command. Install failures leave the manual command on screen and do not stop initialization. Init never signs you in; it lists sign-in guidance for installed agents that still need authentication. This step is skipped in non-interactive and CI runs. Global `npm i -g` installs can require a writable npm prefix or elevated permissions such as `sudo`, depending on your npm setup. The starter is seeded as an **`inbox`** task, not `ready` — it's a suggestion for you, not work to auto-run, and `created_by` is `repoos-init` so it can be filtered (and archived) once a real backlog exists. Promote it when you want it picked up: ```bash repoos mv 0002 ready ``` Both starters are self-contained enough to work without an agent — read the task, do what it says, and it turns into project-context docs and concrete follow-up tasks. (`repoos/work/0001-set-up-repoos.md` is still scaffolded, but it's marked `done`: it's a worked example of a task file, not work to do.) ## Starting a new project as an agent An AI agent starting a brand-new RepoOS project hits a fork the interactive docs don't cover: the new-project flow asks questions on a terminal, and an agent's shell usually has no terminal. This section is the recipe that works today, and the traps to avoid. ::: warning Use the new-project flow, not `git init` first The guided flow is what seeds the **new-project** starter task. If you run `git init` first and then `repoos init`, `repoos init` only sees "an existing git repo" and seeds the **existing-codebase** starter instead (`read-the-codebase`) — the wrong first task for a project with no code yet. Starting RepoOS outside a git repo is what selects the right starter. ::: ### Non-interactive flags (the supported path) Use a non-interactive `repoos init` that takes the project name, description, and areas as flags, so an agent never needs a terminal at all: ```bash repoos init my-project --new \ --description "A tiny demo project" \ --areas web,api \ --no-launch ``` `--new` runs the guided flow with answers from flags and sensible defaults (commit the scaffold; never launch the console unless `--launch`). See the [CLI reference](/cli#repoos-init-name) for every flag — `--description-file -` reads a multi-line description from stdin, `--layout` picks the repo-root or `repoos/` layout, and `--json` prints a machine-readable summary. Without `--new` and without a TTY, the command refuses and prints the exact `--new` command to run, plus the `git init` warning below. ### Pseudo-terminal fallback (legacy workaround) Before `--new` existed, the only way to drive the flow without a terminal was a real pty. Prefer the flags above; this is kept for older releases. `pty.fork()` hands the process a terminal, then you answer the prompts on its file descriptor: `repoos init` in a non-git directory, with no TTY on stdin/stdout, refuses: ``` This directory isn't a git repo, so repoos init needs interactive prompts. Run it in a terminal, or run `git init` first and then `repoos init` again. ``` The second line is the trap above, not the fix. The fix is to give the process a real terminal. `pty.fork()` hands it one, then you answer the prompts on its file descriptor. ~15 lines, Python 3, no dependencies: ```python import pty, os, sys, time script = "\n".join([ "my-project", # project name (Enter = current directory) "", # layout: Enter = repoos/ subdir "y", # git init + scaffold? [Y/n] "A tiny demo project", # one-line project description "", # task areas to seed (Enter = skip) "", # preview-target stubs? [Y/n] "", # starter check plan? (if offered) "n", # commit the scaffold? [Y/n] "n", # launch the web console? [Y/n] ]) pid, fd = pty.fork() if pid == 0: os.execvp("repoos", ["repoos", "init"]) # the child gets the TTY else: for answer in script.split("\n"): while True: data = os.read(fd, 1024) if not data: break sys.stdout.buffer.write(data); sys.stdout.buffer.flush() if data.rstrip().endswith((b":", b"]")): # a prompt is waiting os.write(fd, (answer + "\n").encode()) break os.waitpid(pid, 0) ``` Run it from the directory that should hold the project. It produces the same files an interactive run would, including the correct `flesh-out-the-vision` starter. The exact prompts shift between releases, so treat the answers list as a starting point and adjust from the output. ### Right after init 1. **Read `AGENTS.md`.** It's the operating loop for this repo — where the board is, how to create tasks, how to hand off. Everything below is in more detail there. 2. **The starter task is a suggestion, not a queue item.** Init leaves `flesh-out-the-vision` in `inbox`. It is not dispatched until someone promotes it (`repoos mv 0002 ready`); don't auto-run it. 3. **Never hand-edit `work/*.md`.** Create and change tasks with `repoos new`, `repoos mv`, `repoos update`, `repoos note`, or the HTTP API — never by editing frontmatter or files directly. 4. **Start the server in a real terminal tab, or as a service.** An agent shell reaps background processes when its command returns, so a `repoos serve` started with `&` from a tool call dies with it. Either run it in a terminal you keep open, or register it as a managed background service: ```bash repoos service install # register a managed background service repoos service start # it survives the shell that started it repoos service status ``` Never run `repoos serve` from inside a short-lived agent command and expect it to stay up. ## Give the project docs Project docs under `repoos/docs/` are the context an agent reads before it starts. RepoOS never invents them and never imposes a structure, but it can bring your own or scaffold a starting point — both are opt-in. Import an existing doc set (a directory, a single file, or a `.zip`): ```bash repoos init --docs-from ~/Downloads/project-docs # or, in an already-initialized repo: repoos docs import ~/Downloads/project-docs.zip ``` The import preserves the folder structure, ignores macOS junk, refuses to overwrite an existing file unless you pass `--force`, and prints what it copied. Add `--dry-run` to see the plan without writing anything. During the guided `repoos init` flow you can instead paste a path at the "Import existing docs from a folder?" prompt. If you don't have docs yet, ask for the starter skeleton: ```bash repoos docs scaffold ``` That writes an index `README.md` with a reading order, plus short `product.md`, `architecture.md`, `conventions.md` and `glossary.md` stubs, each with prompts for what to put there. Nothing is created unless you run that command (or answer yes to the scaffold prompt in the guided flow). `repoos doctor` warns if `AGENTS.md` never points at the docs index, if docs exist that the index doesn't link, or if the docs directory is empty while tasks exist. ## Start the server ```bash repoos serve ``` Check which agents are enabled before you run this. Serve starts the local control plane — a web UI and an API over the same files — and background automation: * The **CTO board monitor** ticks every 5 minutes (`ctoMonitorIntervalMs`, default `300000`). When the `cto` agent has `enabled = true`, that tick launches a coding agent. Turn it off with `enabled = false` on that `[[agents]]` row in `repoos.toml`. A project with no `[[agents]]` rows uses the built-in defaults, which leave the CTO disabled. * The **reviewer** is on by default and starts when a task enters `review`. * The **watchdog** (`watchdog.enabled`, default `true`) can restart a stalled engineer. Set `watchdog.enabled = false` to stop that. It picks a stable port derived from the repo's path, so two different repos never collide; pin one with `servePort` if you'd rather. Stop it with `repoos stop`. The UI is where you'll spend most of your time: the board, agent chats, task diffs, and the review controls all live there. ## Create your first task Either from the UI, or: ```bash repoos new "Fix the login redirect loop" ``` Tasks start in `inbox`, including the starter `repoos init` seeds. Move one to `ready` when it's specified well enough to hand over: ```bash repoos mv 0002 ready ``` (`0001` is the `done` scaffolding example; your seeded starter is `0002`.) ::: warning Let RepoOS write task files Never hand-edit task files. Status, activity history and metadata are written through the CLI and API so the board stays consistent — use `repoos mv`, `repoos update`, and `repoos note` rather than editing frontmatter directly. ::: ## Let an agent work it Assign the task to an agent from the UI. RepoOS creates a dedicated git worktree and branch for it, runs the coding agent there, and streams its output live. Your primary checkout is never touched. When the agent is finished it asks for the task to move to `review` and stops. RepoOS re-runs the check, commits the branch and does the moving — the task stays `active` with a *running checks* badge until that finishes. The agent does **not** merge its own work. Review the diff, then move the task to `done`, which is what actually merges the branch to your trunk. A new project gets built-in reviewer, engineer, pm and CTO prompts seeded on first start, so the roles work without any setup. They carry the review lessons RepoOS learned driving itself: report the whole class of a bug in one pass, read earlier review reports, separate code defects from evidence gaps, check the branch still merges with its base, and flag a task for a human after repeated review passes. Project-specific rules belong in `AGENTS.md` and your own `[[agents]]` text; RepoOS never overwrites them. See [Configuration → Agents](/configuration#agents) to customize a role or adopt a newer default. ## The bar for "done" ```bash repoos check ``` One command is the whole definition of done: build, tests, and whatever else your repo declares (see [Checks before merge](/check) for the full list and what's opt-in). Agents must get this green before handing a task back to you, and it runs again before anything merges. ## Where to go next * [CLI reference](/cli) — every command. * [Configuration](/configuration) — `repoos.toml` and environment variables. * [Concepts](/concepts) — how tasks, worktrees and the lifecycle fit together. * [Running a project with AI agents](/running-with-agents) — a practical loop for driving a board with agents. Starting this repo with an AI agent? See [Starting a new project as an agent](#starting-a-new-project-as-an-agent) above for the recipe and the traps. --- --- url: https://docs.repoos.org/ai-agents.md description: >- Hand the RepoOS website to Claude Code, Codex, OpenCode, Cursor, or another compatible agent, and let it inspect the repository, install RepoOS, and initialize it safely. --- # Using RepoOS with an AI coding agent If you already work with a coding agent, you don't have to install RepoOS by hand. Point the agent at this page and give it the starter prompt below. It reads a short overview first, checks your repository, and asks before it changes anything. Claude Code, Codex, OpenCode, and Cursor are common examples — nothing here depends on which agent you use. This page covers setup. Once RepoOS is installed and initialized, [Running a project with AI agents](/running-with-agents) covers the operating loop: planning tasks, choosing models, review, and close-out. ## How the agent reads RepoOS The public material is built for progressive disclosure, so an agent can start small and fetch more only when it needs it: * **A short overview first.** [repoos.org/llms.txt](https://repoos.org/llms.txt) explains what RepoOS is, who it is for, and the verified install commands. * **The docs index next, only if needed.** [docs.repoos.org/llms.txt](/llms.txt) lists every page with a link to its raw Markdown. For the whole manual in one fetch, use [llms-full.txt](/llms-full.txt). * **One starter prompt.** The text below is the only copy. Every surface that offers to copy it reads the same canonical file, so there is no second version to drift. * **One portable skill.** The [RepoOS Agent Skill](https://github.com/repo-os/repoos/tree/main/agent/skill) follows the [Agent Skills specification](https://agentskills.io/specification). Install that one directory under your agent's own skills location, for example `~/.claude/skills/repoos/`. RepoOS publishes no provider-specific plugin, branded integration, or per-vendor copy. See the [skill page](/agent-skill) for what it covers. Every page is also plain Markdown at the same route with `.md` appended — for example [`/getting-started.md`](https://docs.repoos.org/getting-started.md) — so an agent can fetch the source instead of the rendered HTML. ## The starter prompt Copy this into your agent. It tells the agent what to read, what to inspect, and when to ask. ```md # Get started with RepoOS Help me set up RepoOS for a new project or an existing repo. Before you change anything: 1. Read https://repoos.org/llms.txt. It is the short overview: what RepoOS is, who it is for, and the verified install commands. 2. Inspect this repository before installing or editing anything. Run `git status`, `git remote -v`, and `git log -1 --oneline`. Check whether RepoOS is already installed (`command -v repoos`) and whether the repository is already initialized (`AGENTS.md`, `repoos/work/`, `repoos/docs/`, or `repoos.toml`). 3. Only if that overview is not enough, read the docs index at https://docs.repoos.org/llms.txt and follow only the pages you need. Then: - Tell the owner what you found, including whether RepoOS is already installed or initialized. - If RepoOS is not installed, choose the install method that fits this machine: curl is the default (it needs Bun or Node.js 20.6.0+), and Homebrew, npm, Bun, and pnpm are also supported. Do not use mise. Ask before running a global install. - Before editing, preserve existing files and uncommitted Git changes. Do not reset, clean, or commit someone else's work. - Run `repoos init` only after the owner agrees. - Existing repo, from the repository root: `repoos init` - New project, outside a git repo (do not run `git init` first): `repoos init --new --description "..." --areas web,api --no-launch` - With the default `repoos/` layout, init creates `repoos.toml`, `repoos/work/` (including `0001-set-up-repoos.md` and an inbox starter task), `repoos/docs/`, `AGENTS.md`, `.env.example`, `.gitignore` (created, or appended when one already exists), and `repoos/.repoos/canary.txt`. A new project also runs `git init` and, unless you pass `--no-commit`, commits the scaffold (`chore: initialize RepoOS project`). Init does not overwrite an existing file. An existing repo is not committed for you. - Before `repoos serve`, check which agents are enabled in `repoos.toml` (a project with no `[[agents]]` rows uses the built-in defaults). Serve starts the local server and background automation. The CTO board monitor ticks every 5 minutes (`ctoMonitorIntervalMs`, default 300000). When the `cto` agent has `enabled = true`, that tick launches a coding agent. Turn it off with `enabled = false` on that `[[agents]]` row. The built-in default leaves the CTO disabled. The reviewer is on by default and starts when a task enters `review`. The watchdog (`watchdog.enabled`, default true) can restart a stalled engineer. - Explain what changed, and ask before any significant edit outside the RepoOS scaffold. Do not invent files, commands, or flags. If something is not in the RepoOS overview, the docs, or `repoos --help`, say so rather than guessing. ``` ## What to expect * The agent reports whether RepoOS is already installed (`command -v repoos`) and whether this repository is already initialized (`repoos.toml`). * If RepoOS is missing, it picks a method from [Install](/getting-started#install) that fits the machine — curl is the default (it needs Bun or Node.js 20.6.0+), and Homebrew, npm, Bun, and pnpm are also supported — and asks before running a global install. mise is not a recommended method. * It runs `repoos init` only after you agree. An existing repo uses `repoos init` from the repository root. A new project uses `repoos init --new --description "..." --areas web,api --no-launch` outside a git repo (do not `git init` first). See [Initialize a repo](/getting-started#initialize-a-repo) for the files that creates and for what `repoos serve` starts. * It explains what changed, and asks before any significant edit outside the RepoOS scaffold. ## Permission guidance Tell the agent these three rules before it starts; the starter prompt repeats them so they survive a fresh session: * **Inspect the repository first.** Run `git status`, `git remote -v`, and `git log -1 --oneline` before installing or editing anything. Read what is already there instead of assuming an empty project. * **Preserve existing files and Git changes.** Do not reset, clean, stash, or commit someone else's work. `repoos init` never overwrites an existing file: it creates only what is missing. * **Ask before significant edits.** A global install, a change outside the RepoOS scaffold, or anything that rewrites project files needs your explicit agreement first. ## Keep going * [Getting started](/getting-started) — install, initialize, and run your first task if you would rather do the setup yourself. * [CLI reference](/cli) — every command and flag the agent may use. * [Running a project with AI agents](/running-with-agents) — the operating loop after setup. * [RepoOS Agent Skill](https://github.com/repo-os/repoos/tree/main/agent/skill) — the portable skill directory, starting at `SKILL.md`. --- --- url: https://docs.repoos.org/concepts.md --- # Concepts ## The repo is the source of truth A task is a markdown file in your configured task directory (`repoos/work/` on a fresh install). Its status is a field in that file's YAML frontmatter. Tasks are markdown files — there is no separate board database behind the UI. RepoOS may create gitignored runtime files under `.repoos/` (for example `repoos.db` when login is enabled); those are not the task board. The UI is a view over the task files, and anything derived (the index, caches) can be deleted and rebuilt. This has practical consequences you'll feel immediately: * Tasks are versioned, diffable and reviewable like code. * Task history travels with a clone. Nothing lives in a service you can lose access to. * An agent can read the board with `cat`, and your project's context is sitting right next to the code it describes. ## Git history in the UI The Context page (`/repo`) includes a **History** tab: the repository's `git log`, grouped by day, with branch and path filters. Commits that follow the `type(NNNN):` message convention (for example `docs(0514): …`) link to that task. Opening a commit shows the files it changed and a full diff — the same diff view used for task worktrees. The log is read-only. Checkout, revert, and cherry-pick stay on the command line. The left sidebar also shows a small **canary** digit (0–9) above the git summary. Clicking it starts a deliberately trivial task that walks the full lifecycle (draft through done) by incrementing the digit in `.repoos/canary.txt` in your repo — a smoke test that any failure is in the pipeline, not your product code. The digit reflects that file on disk and advances after a canary run merges. The git row below it is a one-line summary of the checkout you are actually running from: the branch, and `clean`, `dirty (n)` or `unknown`. It describes the **repo root checkout only** — task worktrees are separate, and a task branch moving never flips it. A warning colour means either the checkout is not on the base branch (or HEAD is detached) or there are uncommitted changes; `unknown` is what you see when git could not be read or the last check is older than a minute and a half, and it never means clean. The ℹ button next to it opens the detail: the changed files with their status letters when dirty, the three most recent commits exactly as the History tab lists them (`docs(NNNN):` bookkeeping excluded), how long ago the state was checked, and a link into History. It reads the same data as the History tab and is read-only — committing and switching branches stay on the command line. The state is pushed to every open tab over the event stream when it changes (working-tree writes, branch switches, commits, staging, and RepoOS's own task-file commits), with focus, tab-visibility, reconnect and a slow interval as backstops. One cadence note: git's own state changes are pushed immediately, but an ordinary edit outside the task tree (say, under `src/`) is not watched — watching the whole checkout would be a lot of filesystem noise for one indicator. Those edits show up on the next backstop (window focus, tab visibility, event-stream reconnect, or the 45-second interval), so the row can be up to ~45 seconds behind an edit made with a plain text editor. Staging or committing that edit pushes it at once. ## Status is a field, not a folder ```yaml --- id: "0001" title: Fix the login redirect loop status: ready priority: p1 --- ``` Tasks move through `inbox → ready → active → review → done` by editing that one field in place. Files never move between directories, so a status change is a one-line diff instead of a rename, and two people moving different tasks never conflict. ::: warning Don't hand-edit task files Status, activity log and metadata are written by RepoOS so the board stays consistent. Use `repoos mv`, `repoos update`, `repoos note`, or the UI. ::: ## What each status means | Status | Meaning | | --- | --- | | `inbox` | Captured, not yet specified well enough to act on. | | `ready` | Specified. An agent (or person) can pick this up as-is. | | `active` | Being worked, in its own git worktree. | | `review` | Implementation finished and checks pass. Waiting on a human. | | `done` | Approved and merged. | ## Pipeline view The Work Queue page has two views, switched with the **Pipeline | Board** toggle in the header. **Board** is the default and shows every status. **Pipeline** is a horizontal race track for the work in flight: one lane per task in `active` or `review`, plus recently merged tasks. Your last choice is remembered. Lanes run through six stage columns, left to right: **Coding**, **Checks**, **Handoff**, **Review**, **Close-out**, **Merged**. Each card sits in the column of its current stage and moves backwards too — when review sends a task back, it returns to Coding with a small amber "sent back" note on its lane. `ready` tasks are not lanes; a **Ready · n** count sits at the left edge. The **Merged** column is the tinted goal: recently merged tasks sit in it for ten minutes, then drop off the track. Stuck, needs-input, paused and held are states, not stages: the card stays where it stalled, with a red (stuck), amber (needs input) or green (merged) chip, and held/paused cards render dimmed. Each card shows four lines: id, type and priority; the title; the live step ("Coding", "Running checks 3/5", "Confirming handoff", "In review", "Merging") with time in this state; and the engineer round (`E2`), reviewer round (`R1 ✓`), model(s) and run host (`this Mac` or the remote host name). Click a card to open the task panel, exactly like a board card. The small icon button (pause, resume, or a check mark once merged) acts without opening the panel and is reachable by keyboard. ## Archiving a task Archive parks a task you don't intend to finish right now **without changing its status**. A task archived from `review` is still `review` underneath — it just stops appearing in the board columns, and unarchiving drops it back into that same column. Nothing else changes: the branch and worktree are kept, so an archived task resumes exactly where it left off. Use **Archive task** at the bottom of the task panel and optionally give a reason. Archiving is refused while a run, review, or close-out is still live, because hiding a half-stopped run from the automatic scanners would orphan it — stop the work first. A running preview is not a refusal: archiving stops it (the recorded preview process and its build shell) as part of parking the task. Archived tasks live in a minimised **Archived (n)** list below the board on the Work Queue page. Archiving is orthogonal to status: there is no `archived` status, and it never merges, stops, or deletes anything. From the CLI, `repoos list` hides archived tasks by default and prints a count; `repoos list archived` shows them, and `repoos show ` marks an archived task. `repoos mv` refuses to move an archived task's status — unarchive it first (from the Archived list, or `POST /api/tasks/:id/unarchive`). An archived task that another task `depends_on` does **not** count as done: the dependent stays blocked and reads *“Blocked by archived task #id; unarchive it to unblock”* until the upstream is unarchived. ## Stories A **story** is an optional grouping over tasks: a delivery slice that spans several areas and owners, tagged with a matching `story:` value and optionally described by a markdown file under `stories/`. Forms the shared background for a related set of tasks — why the work exists, decisions already made, the tasks it contains — without repeating it in every task body. A story has no worktree, branch or status of its own; it is complete when all its tasks are done. See [Configuration → Stories](/configuration#stories). Agents get this background too: when a tagged task with a registered story is picked up, the engineer and the reviewer both receive the story's title, the path to its definition file, the sibling tasks (ids, titles, statuses) and a bounded excerpt of the definition in their prompt. So the context you write once into a story steers the work, not just the humans reading the board. ## One task, one worktree When a task goes active, RepoOS creates a dedicated git worktree and branch for it. The agent works there — never in your primary checkout — so you can keep working while an agent does, and several tasks can be in flight without stepping on each other. ## Checks before merge ```bash repoos check ``` This is the single bar for "did this break anything?". It runs the check plan your repo declares in `repoos.toml` — the same command for Go, Gradle/Android, Rust, JavaScript or a mix — and each step ends in a pass, a failure, a timeout, a missing-prerequisite error, or an explicitly-stated skip (see [Checks before merge](/check)). An agent must get it green before handing work back, and it runs again before anything merges. Because it's one command with a non-zero exit code on failure, the same checks works locally, in CI, and inside RepoOS's own close-out pipeline. ## Humans hold the merge Human-assigned tasks follow a separate, inert board pathway. They can move between Inbox, Ready, Active, Review and Done without starting AI work or running checks, review or close-out. The drawer identifies them as human work and offers **Mark done** with an optional completion note. `hold` is not required for a human-assigned task. AI agents may change its board status only when the human explicitly asks them to. An agent that finishes a task asks for it to move to `review` and **stops**. It does not merge its own branch, and it can't — the merge happens only when a human moves the task to `done`. Reaching `review` is a request, not a status edit: RepoOS commits the branch, runs `repoos check` and passes a commit guard first, from whichever route you use (the **Review** button, a board drag, `repoos mv`, or the agent). Until that finishes the task is still `active`. See [Review and close-out](/review-and-close-out). If a reviewer agent is enabled, it reads the branch diff and writes an advisory report for that review — findings, edge cases, suggestions. It changes nothing and it doesn't replace your approval; it's there to make your review faster. ## Your docs directory is the project's memory `repoos init` creates `repoos/docs/` alongside `repoos/work/` by default. It holds the context an agent needs to work on *your* project: architecture notes, decisions and their rationale, incident write-ups, conventions that aren't obvious from the code. This matters more than it sounds. An agent starting a task reads `AGENTS.md` and your configured docs directory to get oriented — so knowledge you write down once stops being re-derived, re-litigated, or re-broken on every future task. ::: tip Your docs directory is for building *your* project. The documentation you're reading now — how to use RepoOS itself — is a separate thing, kept in its own directory in the RepoOS repo. ::: ## AGENTS.md `AGENTS.md` is the cross-tool standard for agent instructions, read directly by Claude Code, Codex, Cursor, Aider, Zed and others. `repoos init` scaffolds one describing the task lifecycle and the rules of your repo. Add a one-line shim only if a tool you use ignores it. --- --- url: https://docs.repoos.org/existing-repo.md --- # Adding RepoOS to an existing repo RepoOS is designed to drop into a repo you already have. `repoos init` is idempotent — it **never overwrites an existing file**, only creates what's missing — so it's safe to run on an established project. ## What `repoos init` adds From the root of your repo: ```bash repoos init ``` By default, RepoOS files live under a `repoos/` subdirectory to keep metadata out of your project source. You can choose a different location or explicitly pick the repo root during the interactive prompt. It creates only what isn't already there. With the default layout: | Path | What it is | | --- | --- | | `repoos.toml` | Configuration. Every field is optional. Always at the repo root. | | `repoos/work/` | One markdown file per task. This is the board. Includes `0001-set-up-repoos.md` (a `done` example) and an inbox starter task. | | `repoos/docs/` | Context an agent needs to work on *this* project — architecture notes, decisions, history. | | `AGENTS.md` | Instructions agents read first. The cross-tool standard; Claude Code, Codex, Cursor, Aider and Zed all read it. Always at the repo root. | | `.env.example` | Names of secrets a fuller setup expects. No values. | | `.gitignore` | Created, or appended when one already exists. Ignores the derived cache, root `.repoos/` runtime state, `.env`, `.env*.local`, `node_modules/`, task and input attachment directories, and `.DS_Store`. | | `repoos/.repoos/canary.txt` | Tracked canary counter. | On an existing repo the inbox starter is `0002-read-the-codebase.md` (read this codebase and propose `repoos/docs/` plus an initial backlog). Promote it with `repoos mv 0002 ready` when you want it picked up. A brand-new project seeds `0002-flesh-out-the-vision.md` instead, runs `git init`, and unless you pass `--no-commit` commits the scaffold (`chore: initialize RepoOS project`). Init in an existing repo does not make that commit. With the default layout, `repoos.toml` persists the configured paths: ```toml workDir = "repoos/work" docsDir = "repoos/docs" skillsDir = "repoos/skills" storiesDir = "repoos/stories" inputsDir = "repoos/inputs" cacheDir = "repoos/.repoos" ``` If `.gitignore` already exists, it is only *appended* to for the RepoOS ignore lines that are missing. An existing `AGENTS.md` is never overwritten: in an interactive terminal, `repoos init` previews a small RepoOS guidance section and adds it only if you explicitly approve it. Non-interactive runs leave it unchanged. Re-running `repoos init` reports "already set up" and changes nothing else. ## Choosing a layout During interactive `repoos init`, you'll be prompted: ``` Where should RepoOS files live? [repoos/] ``` * **Enter** accepts the default `repoos/` subdirectory. * Type a custom path like `.meta/repoos/` to nest it elsewhere. * Type `/` to place `work/`, `docs/`, and `.repoos/` at the repo root (the original layout). `repoos.toml` and `AGENTS.md` always stay at the repo root regardless of the layout choice. ## Defining your areas In an interactive terminal, `repoos init` also offers to seed the task-area vocabulary that powers the drawer's area picker and the PM prompt: ``` Task areas to seed the area picker — comma-separated (e.g. web, cli, api; Enter to skip): ``` Type names (or press Enter to skip) and RepoOS appends real `[[areas]]` rows to your existing `repoos.toml`. If you give areas, it then asks whether to scaffold commented `[[preview.targets]]` stubs for them, since preview targets route by area and the two are usually set up together. Both prompts are skippable, and a repo that already declares any `[[areas]]` is never asked again. You can edit the list later in **Settings → General → Areas** or by hand — see [Configuration](/configuration#areas). ## What it doesn't touch Your source, your `package.json`, your build pipeline, and your existing docs are all untouched. RepoOS adds a few directories and a local server that reads them; it isn't a hosted service and it doesn't ask you to move your work anywhere. If your project uses a build pipeline RepoOS doesn't recognise, the [checks](/check) degrade gracefully rather than failing you for not looking like RepoOS. ## Adopt incrementally You don't have to move your whole roadmap at once: 1. Run `repoos init` and commit the scaffolded files. `AGENTS.md` is what agents read first, so getting it into the repo is what makes agents useful here. 2. Add a handful of tasks with `repoos new` and work them through the lifecycle. 3. Grow `repoos/docs/` as you go — each durable decision you write down once stops being re-derived on every future task. See [Concepts](/concepts). ## Running it outside a git repo Run `repoos init` in a directory that isn't inside a git repo and it switches to a guided flow for a brand-new project instead: it can create the project in a subdirectory, offer a repo-root or `repoos/`-subfolder layout, take a one-line description, and optionally make the initial commit. That description is embedded in the starter task ("Flesh out the product vision and initial architecture"), so the first thing on the board is turning it into a real vision, architecture notes and a follow-on backlog. ::: tip Starting a brand-new project with an agent? Don't `git init` first — that makes `repoos init` see an existing repo and seed the wrong starter. See [Starting a new project as an agent](/getting-started#starting-a-new-project-as-an-agent) for the non-interactive recipe and pitfalls. ::: ## Next ```bash repoos serve # local control plane, plus background agents — check first repoos new "Fix the login redirect loop" ``` Before `repoos serve`, check which agents are enabled. Serve starts the web UI and API, and background automation. The CTO board monitor ticks every 5 minutes (`ctoMonitorIntervalMs`, default `300000`). When the `cto` agent has `enabled = true`, that tick launches a coding agent. Turn it off with `enabled = false` on that `[[agents]]` row. The built-in default leaves the CTO disabled. The reviewer is on by default and starts when a task enters `review`. The watchdog (`watchdog.enabled`, default `true`) can restart a stalled engineer. Then see [Install and first task](/getting-started) for the lifecycle, or [Configuration](/configuration) for `repoos.toml`. --- --- url: https://docs.repoos.org/agents.md --- # Agents An agent is a coding-agent CLI that RepoOS runs headless, plus a model, a set of instructions, and optionally a few skills. You configure all of it on the **Agents** page, and RepoOS drives it — spawning the process, streaming its output into the task, and recording its token spend. Driving a whole board with agents? See [Running a project with AI agents](/running-with-agents) for the practical loop. ## Availability reminders Open **Agents → Reminders** to leave a note for a credit reset, rate-limit reset, or provider returning online. **New reminder** takes text, date, time and an optional agent/model/provider link. Times use your browser’s timezone. The list shows soonest first, with a countdown and upcoming, due, overdue (after 24 hours), snoozed or done state. Due notes stay in the bell and the Reminders tab badge until **Done**, **Snooze** or **Delete**. They also appear as small bright cards in the top bar, just left of the bell: click a card to jump to this tab focused on that reminder, or dismiss the card to hide it from the top bar only (the reminder itself stays in the bell). Clicking a bell note opens this tab. Snooze for an hour, tomorrow at 09:00 local time, one day (24 hours), or a custom date/time. Editing the fire time reopens a completed reminder. Nothing starts agents or changes settings. Notes survive restarts in human-readable `/.md` files — `reminders/.md` by default, or `/reminders/` in a `repoos/` project (the directory is configurable with `remindersDir`; see [Configuration](/configuration)). They are repo-wide, not private per-user notes. RepoOS does not commit each edit immediately, but close-out may checkpoint reminder changes as server-written bookkeeping, so a dirty reminder no longer blocks Move to done. Add and commit them explicitly if you want shared Git history outside that process. ```bash repoos reminder add --text "Check Cursor credit" --at 2026-10-22T09:00:00+08:00 --link agent:cursor repoos reminder list repoos reminder done repoos reminder snooze --at 2026-10-23T09:00:00+08:00 repoos reminder delete --yes ``` These commands require the running server. The pause-allowlist quick path and resume-on-Done option will follow once pause support (#0850) is available. See `docs/reminders.md` for the storage format and API. ## Engineering reports Before handing off after a passing check, engineers write a report draft in the worktree's configured cache directory (`.repoos` by default) at `/engineering-report-drafts/.md`. Use the five required sections and aim for around 1,000 words as a soft target; RepoOS rejects narratives above 1,200 words (the generated change summary never counts), finalizes one immutable report per round, and generates the Git change summary itself. See [Engineering reports](/engineering-reports) for the format and lifecycle. Reviewers receive the latest round in their prompt and must weigh its rationale, experiments, and known limitations with the diff. ## Supported coding agents RepoOS has a driver for eight CLIs: | CLI | Notes | | --- | --- | | `opencode` | The best-supported driver. Structured JSON output, live model discovery, and same-session resume. | | `claude code` | Structured stream output; resume/recovery is less proven. | | `codex` | Structured app-server protocol and a model list. | | `github copilot` | JSON driver with Auto tier selection. | | `qwen code` | Driver present; no machine-parseable output format. | | `kiro` | Driver present. | | `cursor` | The Cursor Agent CLI (`cursor-agent`). Structured stream-JSON, session resume, and model selection. | | `antigravity` | Google Antigravity CLI (`agy`). Structured stream-JSON, model discovery, and exact conversation resume. | A CLI has to be installable headless and drivable over stdin/stdout to be useful here. If a tool is missing from `PATH`, the **Detected Coding Agents** tab tells you whether it's installed and headless-ready, desktop-only, or missing. For agents that report it (Cursor), the tab also shows whether the CLI is signed in and the exact command to authenticate. Use **Check for updates** in the Detected Coding Agents tab when you want to compare installed versions. RepoOS does not check the network during startup or ordinary detection, and it never installs or upgrades a CLI. On demand it uses only a source it can establish from the binary path (currently npm, a Homebrew formula or cask, or an official GitHub release endpoint); otherwise the row says **check manually**. Results are cached for six hours and show the source and checked time. After the first check the button becomes **Refresh update checks**, which re-scans PATH and bypasses the cache. A copyable upgrade command appears only when the source provides a matching safe command; you must run it yourself. Registry failures, timeouts, and opaque vendor versions remain per-agent **could not check** or **check manually** states rather than hiding the detected-agent list. The row also shows a versioned compatibility status. `PATH` detection alone is not certification: **verified**, **upgrade recommended**, **newer than verified**, and **unsupported** describe the adapter contract, not model quality or task success. See the [Supported coding harness versions](/coding-harness-compatibility) table for certified ranges, evidence, and safe upgrade guidance. ### Cursor Agent CLI Install with Cursor's official installer: ```bash curl https://cursor.com/install -fsS | bash ``` RepoOS detects and launches only the `cursor-agent` binary — never a bare `agent` command, which can collide with another tool on `PATH`. Authenticate once with `cursor-agent login` (or set `CURSOR_API_KEY` for automation); the Detected Coding Agents tab shows sign-in state when it can probe it. RepoOS runs Cursor in print mode with `--output-format stream-json` inside the task's dedicated worktree, with `--trust` and `--force` so worktree edits and `repoos check` run without waiting for an approval that can never be answered (the process has no interactive stdin). Follow-up messages resume the exact session Cursor reported; RepoOS deliberately never uses `--continue`, which could attach a different task's most recent session. Models come from `cursor-agent --list-models`, with `default` meaning Cursor's own choice. Cursor's current stream-JSON output does not include token or cost usage. The Tokens page therefore records the session but can show zero usage for Cursor; that is a CLI limitation rather than an indication that RepoOS lost the run. ## The Agents page The **Agents** tab groups the lifecycle roles RepoOS ships with under **Default agents**, followed by **Custom agents** for your own roles. Other tabs: * **Build Your Team** — built-in agents and chat assistants (see below). * **Scheduled Tasks** — recurring or one-time task templates that create ordinary `work/*.md` tasks on a cadence (see `docs/scheduled-tasks.md`). * **Detected Coding Agents** — what's installed on this machine. * **Model Playground** — try a prompt against a CLI/model and compare output. * **Model providers** — live spend where a provider exposes an API (OpenRouter, opencode Go, DeepInfra), plus links to provider dashboards such as Cursor's Spending page. A provider's key is read from RepoOS's `.env` or from a coding agent's own login store, so a provider a harness is already signed into shows as connected without re-pasting the key. GitHub Copilot is a link-out too: GitHub has deprecated the personal-account billing endpoints and offers no public API for individual Copilot subscription, billing or usage data, so its row links to the Copilot settings page instead. Every role card lets you pick the coding agent and model, toggle the role on or off, edit its instructions, and **Test** the combination to see whether the CLI and model actually respond. A test that finds nothing is reported as **cold start** (no output within the CLI's startup window) rather than a hard failure, and a failure shows the actual line the CLI printed — for example `Error: Model unavailable: …` — not a truncated dump of the event stream. Each CLI gets its own startup ceiling (a cold `cursor` or `pi` gets longer than a one-shot `opencode`), so a slow first token is not mistaken for a broken model. **Refresh models** re-probes every CLI's live model list (`opencode models --refresh` for opencode, and the equivalent for each other installed CLI) — model names change often, so pick from live discovery rather than a hardcoded list. Each CLI loads independently: one slow or failing CLI never empties the other dropdowns, a failing one shows its reason (not found on PATH, timed out, not signed in…) with a **Retry**, and the last good list per CLI is saved in your browser so a reload shows it immediately while it revalidates. A model of `default` uses whatever the CLI itself defaults to, except for GitHub Copilot: it means **Auto · Efficiency**, the lowest-cost Auto tier. ### Codex engineering permissions Managed Codex engineering runs and follow-ups use `--dangerously-bypass-approvals-and-sandbox`. This removes the OS sandbox and approval prompts so unattended builds and browser checks can run. In particular, macOS WebKit can abort during application registration in the workspace-write sandbox even when networking is enabled. Commands run with your user's normal access, including access outside the task worktree. A worktree separates Git changes; it is not a security boundary. Use this mode for trusted projects and task prompts, and review changes before merging them into main. Read-only/advisory Codex roles retain their existing permissions. Existing running turns keep their launch permissions; the change applies to new engineering turns and resumed follow-ups after the server loads the new build. ### GitHub Copilot CLI RepoOS offers Copilot's three Auto tiers: **Auto · Efficiency** (the default), **Auto · Balance**, and **Auto · Intelligence**. They choose from models your Copilot account and policy make available; the tier controls the cost, quality, and latency trade-off rather than pinning a named model. RepoOS uses Copilot's documented `--model auto --auto-tier ` flags, so it does not need to scrape the interactive `/model` picker. RepoOS passes Copilot's `--yolo` flag (all tools, paths and URLs) for every role: engineer, PM, reviewer, Debugger, RepoOS Guide, and one-shot authoring. Copilot cannot stop for a human approval prompt during a headless run, and any denial fails the task. Role prompts state the intended work but do not enforce read-only access; the repo's git history is the safety net. | RepoOS role | Intended work with approved tools | | --- | --- | | Engineer | Implement, build, and test in the task worktree. | | Task PM chat | Use RepoOS task-management commands as directed by its prompt. | | Reviewer | Inspect the diff and report findings without editing. | | Freeform PM, Debugger, and RepoOS Guide | Author or inspect as directed by their prompts. | ### Antigravity CLI (`agy`) Install the official CLI with: ```bash curl -fsSL https://antigravity.google/cli/install.sh | bash ``` On Windows, use the official PowerShell installer from the [Installation & auth guide](https://antigravity.google/docs/cli-install). Sign in once by running `agy` interactively. Local runs use the operating system keyring; SSH runs show a browser URL and one-time code to paste back into the remote terminal. A headless API-key setup requires `modelProvider = "gemini"` in Antigravity's settings and `GEMINI_API_KEY` in the process environment. RepoOS never reads, stores, or displays that key. RepoOS invokes only the official `agy` binary from `PATH`, in the task's linked worktree, with the documented `-p --output-format stream-json` protocol. It parses only Antigravity's `init`, `step_update`, and `result` events, including tool output, stderr diagnostics, terminal status, duration, model, and usage fields that `agy` actually reports. Unknown or malformed events are shown as a helpful protocol error rather than copied into the transcript as JSON. Models are read from `agy models`; a pinned model is passed with `--model`, and an unavailable pin fails instead of silently falling back. Follow-ups resume the exact `conversation_id` with `--conversation`. If Antigravity does not report an id, RepoOS starts a labelled fresh turn rather than risking another task's conversation. Headless Antigravity normally soft-denies shell commands because there is no interactive approval prompt. RepoOS therefore uses `--dangerously-skip-permissions` for managed task, review, and check runs so a task cannot wait forever. This is a blanket permission bypass: it can approve commands beyond the worktree, so use Antigravity only with trusted prompts and remember that RepoOS's isolation is the worktree/lifecycle boundary, not a replacement for Antigravity's own sandbox. Because of that, RepoOS refuses to run Antigravity with the bypass anywhere but a task worktree: it can't drive board-level roles that work in the main checkout (Ross, the CTO, the debugger). Read-only uses, such as model tests and PM task authoring, run without the bypass. ### Agent temp directories Each managed agent spawn (engineer, reviewer, board one-shots including the CTO) gets its own `TMPDIR` under `~/.repoos/agent-run-tmp//` instead of the host `/tmp`. It is deliberately outside every git checkout: a temp directory inside the repository makes tests that expect a non-repo directory find the real repo. RepoOS deletes that directory when the run ends (normal exit, timeout, or turn cleanup). If the server dies mid-run, the next boot sweeps orphaned directories after re-adopting any agent children that survived the crash. ### Gemini CLI deprecation The legacy `gemini` executable is no longer part of the **Detected Coding Agents** catalog, and RepoOS does not probe for it. New agent assignments offer Antigravity instead. A saved legacy Gemini selection (`cli = "gemini"`) is preserved and shown with a migration warning in the task and agent editors; RepoOS does not silently rewrite it or invoke Gemini as a fallback driver. ## The lifecycle roles These run as part of a task's life. They're what the `pm`, `engineer`, and `reviewer` names in a task's history refer to: * **engineer** — implements the task. Reads the task file, writes the code in the task's own worktree, runs `repoos check`, and then *asks* for the task to move to `review` (via `repoos mv review` or the handoff signal) rather than moving it. RepoOS finalizes that request when the turn ends: it re-runs the check, commits the branch and moves the status. It never merges. The engineer ends its turn after requesting; RepoOS queues the outcome (pass, or the failing step and reason) for its next turn, and `repoos handoff-status ` answers "did it land?" immediately without the blocking `repoos review`. * **reviewer** — reads the branch diff the moment a task lands in `review` and writes an advisory report: bugs, edge cases, suggestions. It changes nothing and never moves a task. See [Review and close-out](/review-and-close-out). * **pm** — owns the roadmap: moves tasks between statuses and keeps the board tidy. `repoos new-doc` goes through it. * **Ross** — a repository assistant you can chat with. Answers questions about the repo; never edits files or changes task state. * **cto** — an optional always-on board monitor. Off by default; watches for stuck tasks, stale reviews and broken builds. By default it reports rather than acts; opt in to bounded recovery via `cto.actions` in Settings (restart a stalled engineer, refresh main's install, re-queue an environment close-out). A restart **resumes** the conversation after a network stall and starts a **fresh** one after a real crash or a task it has already restarted twice. Each action is rate limited and recorded in the task activity log and the notification bell. `automation.paused = true` is the kill switch: it halts every automatic action — policy auto-approval, safe actions and the idle nudge — while keeping your configuration, so you can resume with one flip. It runs read-only where its CLI supports it, and RepoOS quarantines any stray file a run still creates (moved under `.repoos/quarantine/` and reported in the run's report) so the main checkout is never left dirty. While the board is healthy it makes no model call at all: it only runs the agent when something needs attention, or when the material board signal changes. Every CTO run records what triggered it, and a failed run records a truncated reason, so provider credit/auth failures show up on the Tokens panel instead of disappearing. Tune this with `ctoSkipHealthy` on the Settings page — see [Configuration](/configuration#agents). Its one automatic reminder waits for a genuinely idle engineer: a running check/test/build/browser step, a remote-validation wait, an in-flight review or handoff, an already-queued message, or machine memory pressure holds it and records why. Set the idle window and cooldown with `cto.nudgeIdleMs` and `cto.nudgeCooldownMs` in Settings. When you assign a task to an agent from the UI, RepoOS creates a dedicated git worktree and branch for that task and runs the agent there. A task can override the agent, CLI, and model its reviewer uses without changing the global default. How many agents run at once is governed by `maxConcurrentAgents` in `repoos.toml`; extras queue. The default sizing is derived from your machine's core count — see [Configuration](/configuration#agents). ## Built-in agents are a different thing The **Build Your Team** tab also holds **built-in agents**: Tech Debt, Performance, Architect, Design, Docs Debt, and a Debugger assistant. Don't confuse them with the lifecycle roles above — they are not roles a task moves through: * They run **on demand or on a schedule** (daily, weekly, or manual only), not as part of a task's lifecycle. * Each has its **own** coding-agent and model selection, separate from the lifecycle roles. * They **produce findings**, not implementation: Tech Debt and Performance create tasks in your inbox for each issue; all built-in agents write durable run records under your configured docs directory; Docs Debt fixes what it safely can and bundles the rest into a single task. Each of them — what it scans for, how to schedule it, and what good output looks like — has its own section in [Built-in agents](/built-in-agents). ## Budget Controls: steering agent drivers An **agent driver** is an AI session that operates RepoOS through the CLI/API — overriding engineers, starting tasks, restarting stuck runs. Such a session has repeatedly picked agent + model pairs that are too expensive, so the **Budget Controls** tab (`/agents?tab=budget-controls`) lets you declare a human-approved subset. * **Agent+Models Allowlists for Agent Drivers** lists the allowed coding agents; each one has its own list of allowed models, collapsed by default with a model count (for example `claude code · 2 models`). Expand a row to see its models and remove a model or agent from the row. Add a pair with **+ Add to allowlist**, which opens a modal using the same coding agent + model selector the rest of the page uses; a pair already on the list can't be added twice. * The allowlist is **optional**. Leave it empty and nothing is restricted — agent drivers behave exactly as they do today. * A **human using the web UI is never restricted** and always sees the full list. Only an agent driver — a caller carrying the local CLI token — is checked. * When an agent driver sets an engineer/reviewer override (`repoos override --cli … --model …`, or a `PATCH` on `cliOverride`/`modelOverride`) to a pair outside the allowlist, the server refuses with an error listing every allowed pair. `repoos override --help` also prints the allowlist. * **Pause** an agent or a single model instead of removing it when a provider runs out of credit or is rate-limited. A paused row keeps its Paused chip, optional resume date and reason, and is never selected — engineer/reviewer/ PM/CTO defaults, Start, auto-dispatch, failover and agent drivers all skip it and fall back to the next allowed pair, recording the swap and reason in the task activity log. If every allowed pair is paused, starting a task fails with "All allowed agent+model pairs are paused". Pause from the row or model chip (with an optional resume date/time and reason) or from a shell: `repoos agents pause [--model ] [--until ] [--reason "…"]` and `repoos agents resume [--model ]`. An expired resume date takes effect automatically, with no restart. The allowlist is stored in `repoos.toml` as `[[budget.allowlist]]` rows; see [Configuration](/configuration#budget-controls-agent-drivers). --- --- url: https://docs.repoos.org/built-in-agents.md --- # Built-in agents [Agents](/agents) covers the lifecycle roles a task moves through — engineer, reviewer, pm, and the rest. **Built-in agents** are the other kind: pre-built specialists that audit your repo on demand or on a schedule and report what they find. They live under **Build Your Team** on the Agents page. They are not a task's lifecycle. Nothing routes a task through them, and they never implement anything — they scan, and they hand you findings. ## How every built-in agent behaves Every run produces exactly **two** things, whatever it found: 1. **A run doc** — the configured docs directory's `agent-runs//.md` (`repoos/docs/agent-runs/…` on a fresh install), recording the agent, when it ran, how long it took, what it cost, and **every finding with its evidence** — including a run that found nothing, which is recorded as `ran clean`. The last 10 run docs per agent are kept; older ones are deleted on each new run. This is the receipt you read afterwards, so you never have to watch an agent run to know what it found. 2. **Zero or one inbox task** — never more than one per run. Every finding goes into that single task's body as a structured list, so a verbose scan can't flood your board. A run with no actionable findings files nothing. When a task needs your decision before anything can be implemented, it lands with `needs_input: true` and a `questions:` list in its frontmatter — answer them (or discuss them in the PM chat), remove them, and the task is ready to spec. If a run really did find more than one task's worth of work, the task body says so and asks you to create subtasks **once you've approved the direction**. A finished run also announces itself: the UI toasts it — "Tech Debt Agent finished — 3 findings" — whether you clicked **Run now** or it ran on schedule. Each card on **Build Your Team** is configured independently: * **Enable** — off by default. **Run now** stays disabled until you turn it on. * **Coding agent + model** — its own CLI/model pair, separate from the lifecycle roles. Pick from the CLIs RepoOS detects on this machine. * **Run schedule** — `Daily`, `Weekly`, or `Manual only` (the default). Daily runs once per calendar day; weekly runs once seven days have passed since the last run. `Manual only` runs solely when you click **Run now**. * **Run now** — runs the agent immediately and reports what it did. While a run is in flight, another scheduled or manual run is refused rather than run concurrently. The server checks schedules once a minute and starts at most one due agent per tick. This state — enabled, schedule, last run — is kept in the configured cache directory (`repoos/.repoos/built-in-agents.json` on a fresh install), not `repoos.toml`; it's runtime state, like the rest of the cache directory. Each agent works from a deliberately bounded view of the repository and looks for signal, not a full static analysis. Treat its output as a well-informed first pass, not a verdict. ## Tech Debt agent Scans your source for common debt patterns: * **Outdated dependencies** — pre-release or wildcard version pins, plus a bounded comparison of exact/range pins against the npm registry (offline is never fatal). * **Code duplication** — identical six-line blocks found in two or more files. * **High-complexity files** — files longer than 500 lines. * **Unused code** — exported identifiers no other file references. * **Deprecated APIs** — `var` declarations. **Good output:** at most one inbox task, `type: chore`, `area: tech-debt`, with every finding's file, line, and severity listed in its body, plus the run doc under the configured docs directory's `agent-runs/tech-debt/`. The task arrives with `needs_input: true` because a scan's findings are a proposal, not a work order — answer its questions, spec the ones worth doing, move it to `ready`, and let the normal lifecycle take over. A run that finds nothing creates no tasks, but still writes a `ran clean` run doc. ## Performance agent Reviews your code for performance problems using its configured coding agent and model. It works out what languages and entry points your repo actually uses (manifests, lockfiles, layout) instead of assuming JavaScript, so a Python, Go, Rust or Java project is reviewed on its own terms: * **Blocking operations** — synchronous I/O on an async event loop, CPU-heavy work on a UI or request path, serial calls that should be batched. * **Slow functions** — poor algorithmic complexity, repeated linear scans, expensive setup done on every call. * **Unbounded growth** — caches, listeners or accumulators that are never evicted or unsubscribed. * **Duplicated computation** — work recomputed inside a loop that could be hoisted, or the same payload parsed on every call. **Good output:** at most one inbox task, `area: performance`, with every finding's location and a plain-language description in its body, plus the run doc under the configured docs directory's `agent-runs/performance/`. It lands with `needs_input: true` and its questions, because which of these are worth optimizing — and to what threshold — is your call. As with Tech Debt, an empty review files nothing but still writes a `ran clean` run doc. If the configured model or CLI is unreachable, the run fails with a message on the agent's own card instead of reporting a clean result. ## Architect agent Reviews the shape of the codebase rather than individual defects: tight coupling (a file importing too many siblings), a pattern repeated across many files that wants an abstraction, over-engineering, and large files that could become scalability bottlenecks. It also notes the size of your top-level directories and any architecture-flavoured tasks already on the board. **Good output:** a timestamped run doc under ``` /agent-runs/architect/.md ``` plus at most one inbox task (`area: architecture`) carrying every finding with its recommendation, marked `needs_input: true` — do you agree with the direction these imply before any refactor starts? One task per run keeps a noisy scan from flooding your inbox. ## Design agent Reviews your web UI for quality and consistency — however it is built and wherever it lives. It is **skill-guided**: the model reads a guidance doc describing UI/UX review, then works out from your manifests and repo structure whether you have a web UI at all and where its sources are — React, Vue, Svelte, Angular, plain HTML/CSS/JS, and anything in between — rather than assuming RepoOS's own framework or folder layout. It flags layout and rendering bugs, styling that bypasses your design system, accessibility problems (icon-only buttons, unlabelled inputs, keyboard-inaccessible controls), and interaction-flow friction, and proposes concrete design improvements. **Good output:** a timestamped run doc under ``` /agent-runs/design/.md ``` plus at most one inbox task (`area: design`) bundling every finding with its rationale and suggested fix, marked `needs_input: true`. If your repo has no detectable web UI, the run doc says so plainly — "no web UI detected" — rather than reporting a misleading zero. A model or CLI failure surfaces on the agent's own card, as with the other built-ins. ## Docs Debt agent Checks that your documentation still tells the truth about the code. Like the Performance and Design agents, it is **skill-guided**: the model reads a guidance doc (`agents/skills/docs-debt.md` within the configured docs directory, when you provide one) describing what documentation debt means, then verifies concrete, checkable claims in `AGENTS.md` and your configured docs directory against the actual repository. It finds where your code really lives rather than assuming a language or layout, and it distinguishes claims about *your* code from a doc's prose naming some third-party tool's own convention — so it won't flag a formatter's config key or another agent's parameter name as a missing symbol. It fixes what it safely can, but never on its own say-so. A proposed fix is applied and committed only when an independent, deterministic gate confirms both halves against the files on disk: the doc still contains the exact text being replaced, and the repo actually contains the replacement. Anything that doesn't clear that gate — and any change that needs a judgment call — is left alone for a human. Auto-applied fixes are capped at five per run. **Good output:** usually the best kind — the docs already match the code, so there's nothing to report (and the run still writes a `ran clean` run doc under the configured docs directory's `agent-runs/docs-debt/`). When there are real findings, they're bundled into a **single** inbox task (`area: docs-debt`), not one task per finding, each entry naming the doc, line, evidence, and a suggested fix. That task lands with `needs_input: true` — for each claim, should the doc change or the code? The run banner also links straight to that task and lists any docs it corrected on its own. ## Debugger The Debugger is a built-in agent's neighbour but not one of the scanners: it's a chat assistant. Paste a bug, stack trace, or error and it gives you a diagnosis. It has no schedule and no **Run now** — you talk to it from its floating head, next to Ross and the CTO. It also earns its keep without being asked: when a task fails hard enough to raise its **waiting for you** banner (a crashed reviewer, an agent that exited with an error, failed checks, a stuck run), the Debugger runs once in the background and boils the raw error down into a one-line **tl;dr** — what happened and what to do next. You'll see it in the task drawer, just above the tabs, on every tab; the banner and the raw logs below stay as they were, for anyone who wants the full story. The line is best-effort: if the Debugger is off (or its own run fails), nothing extra appears, and it disappears when you handle the failure — dismiss the flag, start a fresh review, or move the task along. Each diagnosis is booked on the task's Tokens tab under `debugger`. A failed **Move to done** gets a tl;dr too. Merge conflicts and failed checks are diagnosed by the Debugger as above; the failures whose cause is already known — a timed-out close-out, uncommitted changes, a branch that couldn't sync with main, a publish error — show a fixed one-line tl;dr instead, with no model run, so it appears even when the Debugger is off. ## Where `repoos check` fits Built-in agents don't run your tests, and their findings are advisory. The checks that determine whether code is ready are separate — see [Checks before merge](/check) for exactly what `repoos check` covers and what's opt-in per repo. --- --- url: https://docs.repoos.org/coding-harness-compatibility.md --- # Coding harness compatibility Detection on `PATH` means only that RepoOS found a binary. It does not promise that the adapter can safely drive that release. RepoOS keeps a small, versioned contract for each drivable harness and checks the installed version against its supported line and any recorded certification. ## Statuses * **Verified** — the release family is covered by a real RepoOS adapter contract suite and a recorded evidence source. * **Upgrade recommended** — the installed release is older than the supported line. RepoOS still permits work when local capability checks pass. * **Newer than verified** — the release is newer than RepoOS's last tracked certification. It is not blocked; run a compatibility probe before important work — see [Probes, privacy, and upgrades](#probes-privacy-and-upgrades). * **Unsupported** — a known incompatible family or a required local capability is missing. * **Not yet probed** — RepoOS could not parse a version or has not yet validated that harness with an in-repo contract suite. Compatibility is narrower than model quality, cost, or task success. A green model-selection check is not certification of the complete adapter contract. ## Supported coding harness versions | Harness | CLI id | Binary | Supported range | Newest certified | Notes | | --- | --- | --- | --- | --- | --- | | **OpenCode** | `opencode` | `opencode` | `>=2.0.0 <3.0.0` | **2.0.11** (2026-09-22) | Full 8-seam certification. Use `--standalone` for isolated probes. | | **Claude Code** | `claude code` | `claude` | `>=2.0.0 <3.0.0` | **2.1.285** (2026-10-04) | Full 8-seam certification. Requires `--verbose` with stream-json. | | **Codex** | `codex` | `codex` | `>=0.100.0 <1.0.0` | **0.160.0** (2026-10-04) | `codex exec --json --approve-for-me`; `--approve-for-me` precedes `resume` subcommand. | | **Cursor Agent** | `cursor` | `cursor-agent` | `>=2026.0.0 <2027.0.0` | **2026.10.1** (2026-10-02) | Stream-json mode; `-f/--force` bypasses approval prompts. | | **Kiro** | `kiro` | `kiro-cli` | `>=2.0.0 <3.0.0` | **2.27.1** (2026-10-04) | Plain-text output; session-continuation and structured-events skipped (captured post-run). | | **Antigravity** | `antigravity` | `agy` | `>=1.0.0 <2.0.0` | **1.2.16** (2026-10-04) | Gemini-backed; `--dangerously-skip-permissions` for unattended work. | | **GitHub Copilot** | `github copilot` | `copilot` | `>=1.0.0 <2.0.0` | **1.0.91** (2026-10-04) | `--output-format json` JSONL; `--no-ask-user --yolo` for headless. | | **Qwen Code** | `qwen code` | `qwen` | `>=0.1.0 <1.0.0` | Pending | Claude-compatible interface; `--yolo` for headless. Requires `--auth-type` configured. | | **Crush** | `crush` | `crush` | `>=0.97.0 <0.98.0` | Pending | Plain-text headless runs; session-continuation and structured-events skipped (session id and usage captured post-run via `crush session list` / `session show --json`). Pre-1.0, so the range is narrow. | | **pi** | `pi` | `pi` | `>=1.0.0 <2.0.0` | **1.0.0** (2026-10-04) | Strict JSONL event stream (`--mode json`) with a session header and usage, documented `--session` resume, and no approval prompts in a non-interactive run. | | **Muse Code** | `muse` | `muse` | `>=1.0.0 <2.0.0` | **1.4.14** (2026-11-05) | Full 8-seam certification. `muse exec --json` MSP-envelope stream; UUID-only `--session-id` resume; `--trust-workspace` + `--approval-mode never` every turn; `--disable-write --disable-shell` for advisory turns; tokens reported, cost not. | This table is derived from `src/core/agent-compatibility.json`. Update that manifest and add contract evidence together when certifying a release. Do not silently widen a range because a newer binary happens to start. ## Probes, privacy, and upgrades The default detector and `repoos doctor` are offline and token-free. They read the local binary version and static contract metadata; they do not send version telemetry or collect prompts and project code. ### Running a live probe A live compatibility probe is available on request and is opt-in: ``` repoos doctor --probe opencode --yes ``` This runs the harness's adapter-contract suite inside an isolated temporary directory, exercising eight seams: version detection, help/flag shape, model discovery, a headless one-shot, structured event parsing, permission/auto mode, session continuation, and cancellation. The one-shot, resume, and cancellation seams each start a real harness run, so the probe **may consume provider tokens**. The command warns clearly about this, asks for confirmation when you are at a terminal (pass `--yes` to skip the prompt), and cleans up the fixture when it finishes. Run a probe when: * the Agents page marks your installed harness **newer than verified** and you want to start important work with it, or * you are a maintainer certifying a release — see below. ### `--binary` override Both `repoos doctor --probe` and `repoos certify` accept `--binary ` to probe a specific binary instead of resolving from `PATH`: ``` repoos doctor --probe opencode --binary ~/.opencode/bin/opencode --yes repoos certify opencode --binary ~/.opencode/bin/opencode --yes ``` This is useful when you have multiple versions installed or the binary is not on `PATH` under the expected name. ### `--model` override Both commands also accept an optional `--model ` that pins the model used for the probe's one-shot and resume runs. Use it when a harness picks its default model from your environment and that default is not usable — for example pi prefers a provider whose API key is set in your shell over its stored login, so a stray `OPENAI_API_KEY` can make the one-shot fail with a 401. Currently only pi honours it; other harnesses ignore it. ``` repoos doctor --probe pi --model openrouter/deepseek/deepseek-v4.1-flash --yes repoos certify pi --model openrouter/deepseek/deepseek-v4.1-flash --yes ``` ### Shared machine-wide detect cache The detected binary and version information is currently per-project (stored in the RepoOS server's in-memory state and refreshed on page load). There is no cross-project shared cache for detection results, but compatibility *contract* data (`src/core/agent-compatibility.json`) ships with RepoOS itself — every project using the same RepoOS version sees the same certification status without re-running probes. ## Certifying a release (maintainers) `repoos certify` runs the probe and, when every seam passes, writes the certification evidence back into `src/core/agent-compatibility.json` automatically. This is the maintainer path from "probe passed" to "all users see verified." ``` # Full probe + manifest write in one step: repoos certify opencode --yes # Probe a specific binary path: repoos certify "claude code" --binary /usr/local/bin/claude --yes # JSON output (for CI / scripting): repoos certify opencode --yes --json # Re-probe a version that is already certified (skipped by default): repoos certify opencode --yes --force ``` By default `certify` reads `--version` first and skips the live probe (no tokens spent) when the installed version is already covered by the manifest's `newestCertifiedVersion`. Pass `--force` to run it anyway. When certify passes all seams it: 1. Updates `newestCertifiedVersion`, `verifiedAt`, and `verificationSource` in the manifest. 2. Prints the path of the updated file and suggests the commit command. 3. Exits 0. When any seam fails the manifest is **not** updated and the command exits 1. ### Weekly CI certification A GitHub Actions workflow (`.github/workflows/certify-harnesses.yml`) runs `repoos certify` weekly for headlessly-installable harnesses (opencode, claude-code, codex). It requires the corresponding API key secrets (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`) to be configured in the repository. When all seams pass it opens a pull request with the updated manifest. This keeps the shipped compatibility data current automatically. ### What each seam checks | Seam | What passes | | --- | --- | | `version` | `--version` exits 0 and prints a parseable semver triple | | `help` | `--help` exits 0 and prints usage text containing `run`, `usage`, `options`, or `command` | | `model-discovery` | `models` subcommand exits 0 (no output is fine for server-backed CLIs) | | `headless-one-shot` | A one-shot run completes, exits 0, and the output contains a recognizable answer | | `structured-events` | The output contains at least one recognized event/line in the CLI's structured format | | `auto-permissions` | The run used a permission-bypass flag (`--auto`, `--dangerously-skip-permissions`, `--yolo`, `-f`, etc.) and completed | | `session-continuation` | A session ID was captured from the first run and a `--resume` follow-up completed | | `cancellation` | A run starts and exits cleanly after SIGTERM | ### Adding a new harness To add contract templates for a new harness: 1. Add the harness to `KNOWN_AGENTS` in `src/core/detect.ts` (cli, binary, etc.). 2. Add a `ContractCommandTemplates` entry in `src/core/agent-contract.ts`: * `version()`, `help()`, `models()` (return `null` when no listing command exists) * `run(dir, prompt)`, `resume(dir, sessionId, prompt)` — use the exact flags the driver uses * `parseRun(stdout)` — extract `sessionId`, `hasAnswer`, recognized event count 3. Register it in `CONTRACT_TEMPLATES`. 4. Add a stub entry in `src/core/agent-compatibility.json` with `newestCertifiedVersion: null`. 5. Run `repoos certify --yes` and commit the updated manifest. RepoOS never installs, upgrades, or changes a harness automatically. Upgrade or roll back a harness using its official installer and then refresh the Detected Coding Agents tab. Keep the previous release available if a rollback is needed. --- --- url: https://docs.repoos.org/review-and-close-out.md --- # Review and close-out A task with a feature branch reaches `done` through review. This page covers the two halves of that: the **review process** — what happens while a task sits in `review` — and the **close-out pipeline** that runs when you move it to `done`. ## Why an agent can't merge itself When an agent finishes a task it hands it off and stops. It does not merge its own branch, and it can't: the merge happens only when a human moves the task to `done`. That's the whole design — agents do the work, and you review and decide what merges. ## Getting a task into `review` Moving a task to `review` is a **request**, not a status flip. RepoOS passes the commit guard and commits the branch, runs `repoos check`, verifies that the tested tree stayed unchanged, and only then moves the task. Every route into `review` goes through that same finalization — the **Review** button in the task drawer, dragging a card into the review column, a `repoos mv review` from a terminal, or an agent's own handoff. Nothing reaches `review` on the commit guard alone. Until it finishes, **the task stays in `active`** and the card reads *running checks*. That is deliberate: the alternative is a task that claims to be ready for review before anything verified it. If the check fails, the task stays `active` with the reason shown, the work is untouched, and you can fix it and ask again. **Review** opens a small dialog: * **Run checks** (default) — the full finalization described above. * **Skip checks** — the commit guard only. It is recorded in the task's activity log as "review without checks", and **Move to done** still runs the full check before it merges, so this skips the early pass, not the gate. Use it when you already know the check is green and do not want to wait for it twice. Dragging a card into the review column asks the same question. Agents never get the skip option. ## The reviewer agent If a reviewer is enabled on the [Agents](/agents) page, RepoOS runs it automatically the moment a task lands in `review`. The reviewer reads the branch's diff in the task's own worktree and writes a short report — bugs, edge cases, suggestions — shown in the task drawer next to **Move to done**. Each numbered pass is committed with the task under `work/reports//review-.md`, next to the engineering rounds, so the review history survives a fresh clone; a local cache mirror keeps the drawer populated while the task is still in review. It's advisory. It changes nothing and never replaces your approval. Its verdict is one of three lines: * `` `good to go` `` — correct and complete. * `` `needs some work` `` — close, but worth fixing first. * `` `back to the drawing board` `` — off the mark. A review run counts as complete only when the report includes one of those verdicts. If the agent stops with partial output and no parseable verdict, the run is marked **incomplete** (the partial report is kept for debugging), the pass counter does not advance, and you can use **Review again** to retry. ### Auto-bounce: why a task can move back to `active` The reviewer runs on **every** `review`, not just the first one. If new commits land on the branch while the task sits in `review` — you pushed a fix, or an agent did — RepoOS reviews the new head again. A verdict of anything other than "good to go" **auto-bounces** the task back to `active`: the findings are sent to the engineer session, which is expected to fix them and re-hand off to review. The task's `review_rounds` counter goes up. The one exception is a `needs some work` whose *only* stated blocker is stale handoff evidence (the reviewer marks it `STALE-EVIDENCE-ONLY`): the change is fine, only the captures are old, so bouncing the engineer would burn a turn on nothing. That task **stays in `review`** — never bounced back to engineering. **Auto-refresh stale review evidence once** is on by default (Settings → General). RepoOS re-captures the evidence at the current HEAD and starts one new review automatically, and a capture is attempted at most once per reviewed HEAD so a stubborn stale marker cannot loop. With the setting off, or when the automatic capture cannot run (a live engineer/reviewer, a dirty worktree, or a moved HEAD), it simply waits: use **Refresh evidence** in the Changes tab (or `repoos verify `) to re-capture on the current HEAD, then **Review again** in the UI or `repoos review again `. A second exception is **`EVIDENCE-GAP-ONLY`**: the code is acceptable but handoff shots or verification are missing or unusable (not stale). The task stays in `review`, automatic re-capture runs without counting a review round, and after two failed repairs RepoOS flags **Handoff evidence still missing** (`evidence-gap-exhausted`). See `docs/review-evidence-gaps.md`. This is deliberate self-correction, not a failure. If you move a task to review and then find it back in `active`, check its activity log — you'll see the review round and the findings that caused it. Auto-bounce is capped at **2 rounds** (`MAX_AUTO_REVIEW_ROUNDS`). Past that, RepoOS stops and leaves the task for a human rather than looping forever. It also stops early and escalates if the reviewer flags the task's own relevance — an obsolete task needs a scoping decision, not more engineering. ### Repeated review classes and the human-attention flag A review loop is not always one stubborn bug. A task can go through many `active` → `review` passes when each pass finds one more instance of the same class — lifecycle/teardown ordering, an unhandled spawn error, a config key registered in one place but not the others. The built-in reviewer prompt (the shared part every RepoOS project gets, plus the default reviewer role) is built to break that loop: * It names the **class** of each bug, greps the diff and the touched files for every other instance, and lists them all in one report instead of holding findings for later passes. * It reads the task's newest earlier reports first, verifies each finding was actually fixed, and does not re-report a fixed item as new. * It separates code defects from **evidence-only** gaps (`EVIDENCE-GAP-ONLY` / `STALE-EVIDENCE-ONLY`) and checks that each declared shot's target and route can really render its declared state. * Before `` `good to go` `` it checks the branch still merges cleanly with its base and names any conflicting files. After **5 completed review passes** on one task (Settings → General → **Flag repeated review classes after**, `review.humanFlagAfterPasses`), the next report opens with a `Repeated review classes:` summary, and the task is flagged for a human as **Repeated review classes — human check** (`review-human-attention`). This is deliberately **separate from** the auto-bounce `review-rounds-exhausted` backstop: it counts every completed pass (manual **Review again** included) rather than auto-bounces, and it fires earlier. Read the newest report, then send it to the engineer, fix it yourself, or rescope the task if the loop is not converging. The flag clears when a clean review or a new engineer run confirms progress. The same instructions ship in the built-in reviewer, engineer, pm and CTO role prompts. An existing project keeps its own `[[agents]]` text; see [Configuration → Agents](/configuration#agents) for how to adopt a newer default without overwriting custom rules. ### Automated verification: when RepoOS clamps a clean verdict After the reviewer writes its report, RepoOS runs two **mechanical checks** and appends a `## Automated verification` section to the report. If one fails, a reviewer's `` `good to go` `` is **clamped to `needs some work`** and the task auto-bounces with the reason. The activity log records why, and the message sent to the engineer opens with a **Why this was sent back** line, so an agent that cannot see the drawer still knows what to fix. The two checks are: * **Browser console errors** — only when the task's handoff browser evidence was required. Native/non-web work is skipped, not failed. * **Guard negative-test evidence** — when a check *guard* was materially changed, a test must prove bad input is rejected, not only that valid input passes. The guard check is **narrow on purpose** (#0762). It only looks at guards a project actually declares — `[[check.steps]]` rows whose `kind` is a built-in RepoOS guard (`theme-contrast`, `hardcoded-colors`, `bare-require`, `task-assets`, `css-layers`, …) — plus RepoOS's own `src/commands/check.ts` in this repo. Adding an *unrelated* `repoos.toml` block (`[release]`, `[[distribution]]`, `[[shot.targets]]`, `[[preview.targets]]`, `[[agents]]`, …) never counts, so it can no longer clamp a clean review by accident. Two Settings (General tab, `[reviewVerification]` in `repoos.toml`) tune it for projects whose tests are not JavaScript/TypeScript: * **Guard negative-test review check** (`reviewVerification.guardTestCheck`, default on) — the kill switch. Turning it off skips the check entirely. * **Guard test-file globs** (`reviewVerification.testGlobs`, default the JS/TS `*.test.ts`/`.tsx`/`.js`/`.mjs` globs) — set these so a Swift, Python or Go test can satisfy the check (e.g. `**/*Tests.swift`, `**/test_*.py`, `**/*_test.go`). ## Skill suggestions This pass is deliberately conservative, and **off by default**. When enabled, RepoOS analyses a task's session transcript only after the task has genuinely reached `done` — never at `review`, when the outcome is not yet verified. A reusable skill is a high bar: a stable procedure that helps on future, materially different tasks, with real decisions/branches and evidence it saves repeated investigation. One-off fixes, task-specific checklists, test ideas, repository-local conventions, review feedback, and failed or unverified work are rejected. When a candidate clears that bar, the first occurrence is persisted internally and creates nothing. A task titled `New Skill Suggestion: ` with a draft `SKILL.md` is created only once the candidate is corroborated by a second independent completed session. A single session never creates a suggestion; a named, stable external tool/API workflow is recorded as extra evidence but does not substitute for corroboration. The draft states its evidence — the source task IDs (and the named external workflow, when there is one), the repeatable trigger, and why a test/instruction/task is insufficient. It is a normal task in your inbox — **not** a live skill. Nothing goes live until you read the draft, create `skills//SKILL.md` from it, and close the task. * At most **one** suggestion task is created per procedure. Any other candidate procedures are listed inside that one task's body, never as separate tasks. * The originating task's **Review** tab shows a one-line `Skill suggestion: #` note linking to the created task. * It is **off by default**. Turn it on under **Settings → Auto-suggest skills from completed sessions** (`skillSuggestions = true` in `repoos.toml`); off means no analysis, no suggestion tasks and no note. The analysis runs on the same LLM infrastructure as the reviewer, and its token spend appears in the task's Tokens tab like any other role. ## Approve and merge When you're happy, move the task to `done` — from the board, the task drawer, or `POST /api/tasks/:id/done`. That's what starts the close-out pipeline. Until then the worktree stays open and nothing has merged. This workflow is the same with or without a Git remote. A remote does not require a GitHub pull request: RepoOS owns review and close-out unless you explicitly choose a separate external workflow. `repoos mv done` only changes task metadata; it does not start close-out or merge code. An explicitly authorized hotfix already committed on the primary branch is a separate case. If it has a task record with no branch and is not in `review` or already `done`, the same `/done` endpoint checks the primary checkout and records release without a candidate merge. This is not a shortcut for an unmerged feature branch; do not clear its branch metadata to use this path. ## Parking a task you're not ready to merge A `review` task that has exhausted its review rounds, or that you simply do not want to merge yet, does not have to stay in the Review column demanding action. **Archive task** at the bottom of the task panel parks it without merging, stopping, or deleting anything: the status stays `review` underneath, the branch and worktree are kept, and the task moves to the **Archived** list below the board. Add an optional reason, and unarchive it later to drop it back into the Review column exactly where it left off. See [Concepts → Archiving a task](/concepts) for the full behaviour: why archiving is refused while a run, review, or close-out is live, and why a running preview is stopped as part of archiving rather than refusing the archive. ## The Move-to-done pipeline Close-out runs as a job with five phases. It works in a **separate candidate worktree** (a sibling of your checkout, such as `/-worktrees/repoos/integrate/`, on branch `repoos/integrate/`), never in your primary checkout, so a failed close-out can't leave your working tree dirty. 1. **queued → syncing** — first runs a cheap, non-destructive pre-check of whether the branch really conflicts with your primary branch; a real source conflict skips straight to the automatic repair below, without building a candidate. Otherwise it creates (or resets) the candidate worktree from the current primary branch. When the primary checkout already has `node_modules`, it reuses that directory by symlink rather than performing a cold install. If the candidate still has no usable `node_modules` (for example the primary checkout was never installed), close-out runs a frozen install in the candidate before the gate — unless the check plan's first full-profile step already installs dependencies. 2. **syncing → validating** — merges the task's feature branch into the candidate. RepoOS preserves the closing task's own bookkeeping file from the task branch; a source conflict is left for the repair flow below. 3. **validating** — re-checks the primary branch first: if it advanced since the candidate synced, the job discards the candidate and resyncs before validating. Then it builds and runs `repoos check`. A real check failure stays in the branch: fix it there and retry. 4. **publishing** — takes the repo lock, confirms the primary branch hasn't moved again, and fast-forward-or-merges the candidate into it. If it did move, it goes back to step 2 and self-heals. 5. **cleanup → done** — removes the candidate and the task's own worktree and branch, and marks the task `done`. ### Uncommitted files pause the close-out Close-out only ever carries a branch's **commits**, so uncommitted changes are never part of what it tested. Before starting, RepoOS checks both checkouts and, if either has uncommitted files, stops with a dialog listing them: * **Your primary checkout** — the merge would refuse to run over them. * **The task's worktree** — the close-out would delete them along with the worktree. This is usually a fix applied after the last handoff commit (a reviewer's change, a late edit), and it has not been through any check. **Commit & continue** commits them — in the worktree's case on the task branch, through the same commit path a handoff uses, so the close-out's own build and check then validate the result. **Cancel** changes nothing: the task stays in `review` with every file exactly where it was. Once a close-out is running, routine server-written churn that appears on the primary checkout mid-job does not pause it. At publish time a dirty file under the task directory, `inputsDir`, `storiesDir`, `schedulesDir` or `remindersDir` (or a dirty `repoos.toml`) is checkpoint-committed automatically, and main advancing only by commits in those directories counts as non-code drift, so the candidate is not rebuilt. A dirty **source** file still pauses the close-out exactly as above — the exemption is per-directory and fails closed for anything else. Reminder and schedule files are server-written bookkeeping like task files (#0860). **Engineer checkpoint after handoff (#0834):** if the only new commits on the branch since handoff are automatic `WIP: engineer self-check checkpoint` commits (from a scoped `repoos check` while the task sat in `review`), Move to done starts **checkpoint recovery** instead of showing "Worktree changed after handoff": the handoff gate runs again on the new HEAD, a delta-only review covers just those commits, and close-out continues when that review is `good to go`. While it runs the card shows **re-reviewing checkpoint…** so the task never sits silently in review; a delta verdict that asks for changes bounces the task back to `active` with the findings, and a gate failure leaves the usual close-out error in place (retry Move to done, or send the task back to the engineer). Any real source edit or a dirty tree still blocks with the usual dialog (discard or send back to the engineer). RepoOS never deletes a worktree that has uncommitted work on its own. If one is left over (for example a close-out that raced a new edit), it is kept, named in the task's `needs_input` detail, and reported by `repoos gc` until you deal with it. The one exception is `work/*.md` dirt whose bytes are identical to main's canonical task file — that is provably redundant, so the automatic sweep may reclaim it; unique task content is always kept. The same rule covers **Restart → Start clean**, the one place a worktree *is* discarded on purpose: the confirmation lists the uncommitted files it is about to throw away, so you can commit them first (or resume the worktree) instead of discovering later that they were gone. A **docs-only fast path** skips the build and check when the merged diff touches nothing but documentation: every changed path under your configured docs directory, or ending in `.md`. There is no "mostly docs" scoring; any other path runs the full set of checks. ### Stopping a close-out The task drawer keeps its header chip brief and places the selected status card below the preview row. When several conditions apply, it shows one status by priority: waiting for you, incomplete review, merge blockers, handoff error, exhausted checks, then close-out progress, then active handoff/check/reviewer/work progress. Close-out progress (`integrating · · `) is that status line, full width under the preview row. If a higher-priority card is already there, the step folds into that card. Open **Debug → Status details** for the full checklist, failure text, timing, and guidance; the Review and Logs views retain their reports and output. The header keeps one short issue chip when needed, and the task path is clamped to two lines. Select the info icon on a status card for its action guidance; the same full text is available in **Debug → Status details**. A close-out can get stuck — a flaky check, a test timeout, a runner that never returns. While a task is in the pipeline, **Move to done** leaves the action row and the drawer shows **Stop MTD** beside **Stop work**. The step and elapsed time stay on the status line, so the action row does not reflow as the timer changes. Stopping cancels the in-flight job, tears down the throwaway candidate, and leaves the task in `review` with its branch untouched, so you can inspect what happened and click **Move to done** again. Once the candidate has merged into your primary branch (the cleanup phase) it is too late to stop — the job finishes on its own. You no longer have to babysit a hung close-out, though: every attempt also has an automatic wall-clock budget (`closeOut.timeoutMs`, **6 minutes** by default, configurable in Settings → General → "Close-out timeout", `0` for no limit). A close-out that runs past it is aborted the same way — candidate torn down, branch untouched, task still in `review` — but unlike Stop MTD it is recorded as a **retryable failure** with a `close-out timed out after …` reason and an error card, so a pathologically slow run is visible instead of silently disappearing. Retries and remote validation spend the same budget; see [docs/close-out-pipeline.md](../docs/close-out-pipeline.md) for the details. ### Merge conflicts repair themselves The first time two tasks are in flight at once, one of them may conflict with the primary branch on a real source file. This is **expected behaviour, not a failure state**: * A conflict whose **only** path is the closing task's own bookkeeping file (`work/-*.md`) is pure bookkeeping — RepoOS takes the primary branch's copy and continues, with no engineer round-trip and no feature review needed (#0754). This is why a stray status/activity-line conflict can never block a Move to done. * A **narrow, provably-safe conflict** on a task that already passed review — both sides purely *adding* distinct lines at distinct places (the classic "two tasks each registered a new CLI command" shape), a lockfile, or generated output — is resolved by RepoOS **in an isolated candidate** against current main, without sending the work back through engineering or a full feature review. The pipeline shows **resolving integration conflict**; the original review stays tied to the commit it approved, only the resolution delta is reviewed, and the combined gate runs once on the resolved candidate before it publishes. * A conflict on **anything else** (an edit rather than an append, files that overlap, a path RepoOS cannot classify confidently, or a task with no prior review) is non-retryable — retrying would derive the same conflict. RepoOS automatically hands off to an engineer session **in the feature branch's own worktree** to merge the primary branch into the branch and resolve it there. When that session finishes, close-out is re-enqueued and retries on its own. A conflict limited to the closing task's own bookkeeping file is the one exception: it needs no prior review, as described above. The narrow path is deliberately conservative: staying inside a conflict hunk is **not** treated as proof of semantic safety. If a resolution would change behaviour, expand scope, or cannot be classified with confidence, it takes the full engineering-and-review path instead. So a task that appears to bounce between `active` and `review`, or re-runs its engineer, is usually a conflict repairing itself. You don't have to click anything; watch the activity log for the reason — a conflict resolved in the candidate says so plainly, and never looks like failed development. ### Manual merges: same rule applies When an agent manually merges `main` into a task branch (outside the close-out pipeline), the same conflict-resolution rule applies: if git stops on a conflict in `work/-*.md`, take the primary branch's copy — it is pure bookkeeping. See AGENTS.md, Rules section, for the exact `git checkout --theirs` steps, and also the note about rebuilding after merge before running `repoos check`. ### Seeing the conflict, and keeping the error To see exactly what conflicts, open the task's **Debug** tab and choose **Merge conflict** (the error card's **View the conflicts** button jumps there). It lists each conflicted file in the same expandable view as the **Changes** tab: red lines are the primary branch's version, green lines are the task branch's. It is computed live against the current primary branch without touching any worktree, so it empties as soon as the conflict is resolved. A failed Move to done stays on the card until the task is retried successfully or you dismiss it with the **×** on the card. A page refresh no longer hides it. Every close-out also reports its outcome to the top-bar **notice bell** — merged into main, failed, or timed out — with the server's finish time, so you can see how a run ended even if you closed the tab while it was working. See [Notices and notifications](/notifications) for the bell and its per-type sound and push toggles. ## Previewing a task's changes You can preview the running app from a task's branch without merging it. Click **Preview** on an `active` or `review` task and RepoOS starts a read-only instance from the task's worktree at an OS-assigned port. Previews are **server-owned and on demand**: nothing auto-launches one, and at most **one preview runs at a time**. Requesting a new preview evicts whichever one was running (FIFO). A preview stops on its own when the task leaves `active`/`review`. If your repo has [auth](/configuration#authentication) enabled, the preview runs behind it like the rest of the server, so you'll hit a login screen even locally — you don't need a real inbox, see the dev-login note in [Troubleshooting](/troubleshooting#logging-into-a-local-preview). Auth is off by default, so most repos skip straight to the running app. For a UI-visible change, screenshots are captured **automatically** (#0594): when a task moves to review and its diff touches any preview target's `[[preview.targets]].paths` globs, the server runs the capture itself through the managed preview — the engineer only writes a `## Shots` list into the task body declaring which pages/states to shoot (see [`repoos shot`](/cli#repoos-shot), especially if the interesting state is inside a drawer or modal that `/` does not show; a `highlight` selector outlines what changed). The capture is conservative by design (#0603): every shot is captioned with why it exists — `declared: