Use when the user's cwd contains .orchestrator/ or tasks.json (a project managed by the orch CLI). Explains the task DAG model, where runtime state lives (SQLite), how to inspect it without editing tasks.json, how to legally move a task between states, and which commands are safe from an agent session. Load on demand — no need to keep in system prompt.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of Orch?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/hectorcanaimero-orch)
---
name: orch
description: Use when the user's cwd contains .orchestrator/ or tasks.json (a project managed by the orch CLI). Explains the task DAG model, where runtime state lives (SQLite), how to inspect it without editing tasks.json, how to legally move a task between states, and which commands are safe from an agent session. Load on demand — no need to keep in system prompt.
---
# Orch — task orchestrator operating manual
`orch` is a local CLI that walks a `tasks.json` DAG and dispatches each task
to Claude / Codex / OpenCode / Gemini in parallel, opens a PR per task, polls
CI, and shows the whole thing on a stakeholder dashboard.
**Getting `orch` on this machine:** it is a single static binary (Linux and
macOS, `amd64`/`arm64`). Check `orch --version` first; if it is missing, ask
the user before installing anything, then use one of:
```bash
curl -fsSL https://raw.githubusercontent.com/Guria-Studio/orch/main/scripts/install.sh | sh
```
The script verifies the release checksum and installs to `~/.local/bin`
(`INSTALL_DIR=...` to override). A tarball from the Releases page works too.
The old Python package (`pipx`, `v0.11.0-py`) is frozen; both read the same
`tasks.json` and `config.yaml`. Repo: <https://github.com/Guria-Studio/orch>.
**The skills themselves:** `orch install-skills --all` installs this skill and
the planning pipeline below into Claude Code (`~/.claude/skills/`); add
`--target codex`, `--target opencode` (a section in the project's `AGENTS.md`)
or `--target cursor` (`.cursor/rules/`) for other agents.
---
## What this project looks like
Every orch-managed project has:
- `tasks.json` — the DAG (task ids, deps, model assignment, files, spec_ref).
**Static input, not the source of runtime status.**
- `.orchestrator/config.yaml` — single config file (concurrency, budget,
dispatch, github, notifications, dashboard, presentation).
- `.orchestrator/model_router.yaml` — `{tasks.json model string → CLI
invocation}`. Stub by default; populated by `orch router add-missing`.
- `.orchestrator/state/<project_id>/orch.db` — **SQLite runtime store**.
This is the single source of truth for task status once dispatch has
started. Tables: `projects`, `tasks_definition`, `tasks_runtime`,
`runs`, `dispatches`, `events`, `spend`, `milestones`.
- `scripts/task-{start,finish,block}.sh` — the shell-out protocol a
dispatched agent runs to signal state transitions, when it has no MCP
tools.
- `.mcp.json` — points an MCP-capable agent at `orch mcp`, which serves the
same transitions as tools (and five read-only ones the scripts have no
equivalent for). Written by `orch init` since G6.4.
- `.github/workflows/orch-ci.yml` — CI hook auto-generated by `orch init`
(skipped when a workflow already exists).
A project still on the legacy file backend (`state.backend: file` in
`config.yaml`, or a `.orchestrator/state/events-*.jsonl` with no `orch.db`
next to it) has no runtime database yet — run `orch migrate` once before
anything below about reading or transitioning state applies.
## Hard rules — read these before touching anything
1. **Never edit `tasks.json` status in place.** Runtime status lives in
`tasks_runtime`. Use `orch task set --id ID --status STATUS` or one of
the `scripts/task-*.sh` helpers. Direct edits are silently discarded.
2. **Never run `git worktree add -b orch/...` by hand** inside a project
with `dispatch.worktree_mode: true`. `orch run` owns those
branches — a manual create leaves an orphan branch that blocks the
next dispatch.
3. **Never bypass `orch task set` transitions.** Legal transitions are
enforced by SQLite; forcing a state via `sqlite3` CLI can leave the
dashboard, dispatcher, and `orch status` reporting different values.
4. **Model names in `tasks.json` are contract.** They resolve through
`model_router.yaml`. If the router doesn't have an entry for a model
the task references, `orch validate` fails loudly — run
`orch router add-missing --yes` before re-dispatching.
## How to read state (safe from any agent session — read-only)
```bash
orch status # human table
orch tasks --status todo,in-progress # narrower view
orch events <TASK_ID> # tail events for one task
orch logs <TASK_ID> # tail the task's log
orch graph # emit the DAG (DOT)
orch doctor # read-only environment preflight
orch validate # static graph validation
```
Direct SQL lookup when you need it (still read-only):
```bash
sqlite3 .orchestrator/state/<project_id>/orch.db \
"SELECT task_id, status, last_model FROM tasks_runtime
WHERE status != 'done' ORDER BY task_id;"
```
## Reporting back from a dispatched task
If you were launched by `orch run`, your prompt names two channels and you use
**one**:
```
orch_set_status task_id "F1.T2", status "done", note "<what you did>", author "<your model>"
orch_block task_id "F1.T2", reason "<why>", author "<your model>"
```
or, with no MCP tools:
```bash
scripts/task-finish.sh F1.T2 "<what you did>" "<your model>"
scripts/task-block.sh F1.T2 "<why>" "<your model>"
```
Three things about that note, all of which cost real work when missed:
- **It is the next task's context.** Every task that depends on yours gets it
rendered in its own prompt under `Completed dependencies (context):`. A note
reading "done" tells the next agent nothing.
- **Pass an author.** It is how orch tells a report from its own bookkeeping —
the engine writes `dispatched to …` and `dispatch succeeded` under the author
`orch`, and a note attributed to `orch` is read as bookkeeping and never
shown downstream.
- **The task is already `in-progress`.** The orchestrator moved it before
launching you. Never run `scripts/task-start.sh` yourself.
The other five tools are read-only: `orch_list_tasks` (with `ready: true` for
what could be dispatched now), `orch_get_task`, `orch_context` (your task plus
what its dependencies reported), `orch_events`, `orch_budget`. See
`docs/MCP.md` in the orch repo.
## Leaving a lesson for the next tasks
When you learn something a later task in this project should know — a
convention, a trap you fell into, what fixed a failure — record it once with
`orch_learn` (`title`, `lesson` of a few lines, optional `area` paths or globs
and `tags`). It is written as a markdown file under `.orch/knowledge/` in your
working dir and committed with your work, so it reaches the base through your
PR; later tasks touching its area get it in their prompt under `Project
knowledge`. `orch_knowledge_search` (`query`) searches the lessons already
there. Both work only when the project sets `knowledge.enabled: true` (what
`orch init` writes). The operator reads and edits them with `orch knowledge
list`, `show`, `add`, `rm` and `stats`.
## Reporting a problem with orch itself
When **orch** (not the project) gets in your way — a wrong status, a refused
tool, a message that misled you — or you notice what it should do better or
does not do at all — a command or flag you looked for, a step you had to do by
hand that orch could do — report it with
`orch_report_finding` (`type` bug|improvement|feature, `title`, `summary`,
optional `evidence`, `repro`, `suggested_fix`, `confidence`). It queues the
report for the operator, who reviews it and sends it as an issue on
Guria-Studio/orch, so keep it about orch: no secrets, no project code or
names. It searches first and returns an existing or queued report instead of
queueing a duplicate; if it lists similar issues, read them
and call again with `confirm_new: true` only if yours is different. It works
only when the project sets `report_findings.enabled: true` (what `orch init`
writes; a config without the key is off); when off, tell the operator instead. Then carry on with your task.
## How to transition a task
A task's status only ever moves along one legal path:
`backlog → todo → in-progress → done | blocked`, with `blocked → todo` to
recover and `done → todo` as the only reopen. `orch task set` and
`orch task-status` both enforce this — an illegal move (e.g. `done` straight
to `in-progress`) is rejected, never silently coerced.
```bash
orch task set --id F1.T2 --status done
orch task-status F1.T2 in-progress --author me --note "picking this up"
orch reset # revert stuck in-progress → todo (dry-run first)
```
`orch reset` is dry-run by default — it prints what it would revert. Pass
`--requeue` to actually apply it.
`orch task set` only changes status in this binary: its `--model` and
`--backend` flags exist but refuse to run. There is no milestone to assign: a
milestone is a phase. To change a
task's model, edit `Model` in its spec and re-run `orch atomize` (see
`orch-tasks`). A running `orch run` stops on Ctrl+C (SIGINT) or SIGTERM: it
dispatches nothing new, waits for what is in flight and exits 130; a second
signal kills the in-flight agents.
## Migrating an old file-backend project
A project that predates the SQLite backend (or was scaffolded with
`state.backend: file`) needs a one-time import before `status`/`tasks`/
`task set` mean anything:
```bash
orch migrate --dry-run # see what would be imported, touches nothing
orch migrate # import + backs up the old state dir first
```
`orch migrate` is deprecated the day it ships — it exists only to carry
history forward once, not as a command you run repeatedly.
## When the user asks about the dashboard / stakeholder view
```bash
orch dashboard # local read-only server
orch dashboard --profile stakeholder # curated client view
orch dashboard --tunnel # Cloudflare quick tunnel; prints token links
orch notify test # verify Slack/Discord webhook
orch notify digest # print stakeholder digest (cron this)
```
## Provider concurrency + budget
- Concurrency caps live in `config.yaml → concurrency.per_provider`.
- Budget guardrails: per-provider token windows in `.orchestrator/budgets.yaml`
(preset chosen by `budgets_preset` in config.yaml), plus
`budget.per_dispatch_usd` as claude's per-attempt `--max-budget-usd`. No
project-wide USD limit. A task waiting on a capped provider shows
`defer_reason: blocked-by-budget:…` in `orch status --json`.
- Silent-fail on Slack/Discord: a broken webhook must never take down
the dispatch loop.
## DAG resolution — how tasks become "ready"
A task is `ready` when:
- Its own status is `todo`.
- Every dep listed in `tasks.json` is `done` in `tasks_runtime`.
- It matches the `--only` glob (if the operator passed one).
Dependencies of blocked tasks do NOT unblock — a blocked task stops its
subtree until an operator resets it.
## Planning new work — the pipeline skills
New work reaches `tasks.json` through four documents, each with its own skill:
| Skill | Writes | From |
| --- | --- | --- |
| `orch-discover` | `docs/arch/000-discovery.md` | the code, once, on a repository that has some |
| `orch-prd` | `docs/prd/NNN-<slug>.md` | an idea |
| `orch-arch` | `docs/arch/NNN-<slug>.md` | the PRD and the code |
| `orch-spec` | `specs/f<N>-<slug>.md` | the architecture |
| `orch-tasks` | `tasks.json`, via `orch atomize --apply` | the specs |
`orch-plan` runs all four with a stop for the user after each document and
before anything is applied. Never write tasks into `tasks.json` by hand when
a spec exists for them: the next `orch atomize` would report them as orphans.
## Where to find more
- `orch --help` and `orch <verb> --help` — the source of truth for flags.
- `docs/MANUAL.en.md` / `docs/MANUAL.es.md` in the orch repo — deep dives.
- `docs/CLI.md` — what the Go rewrite of the CLI implements today, if
you're on that binary.
- `docs/MCP.md` — the `orch_*` tools and how `.mcp.json` wires them.
- `docs/DELIVERING-TO-STAKEHOLDERS.md` — how to hand the URL to a client.
- `docs/brainstorm/next-sprints.md` — living roadmap.