Skip to content

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

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 withUpdate command
curlrepoos upgrade
Homebrewbrew update && brew upgrade repo-os/tap/repoos
npmnpm update -g @repo-os/repoos
Bunbun update -g @repo-os/repoos
pnpmpnpm 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 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:

PathWhat it is
repoos.tomlConfiguration. 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.mdInstructions agents read first. The cross-tool standard; Claude Code, Codex, Cursor, Aider and Zed all read it. Always at the repo root.
.env.exampleNames of secrets a fuller setup expects. No values.
.gitignoreCreated, 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.txtTracked 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 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.

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 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.)

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 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 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 ​

Starting this repo with an AI agent? See Starting a new project as an agent above for the recipe and the traps.

FSL-1.1-MIT — free to use, self-host and modify; converts to MIT two years after release.