Atelier · Operator guide · Building with the /atelier skill
You talk to the orchestrator · the orchestrator runs the factory
/atelier is the operator skill for driving the software factory in plain language. You describe the work; it translates your intent into a precise prompt, picks the right workflow, launches it, watches the trace, and reports back. It is a thin discipline layer with one firm boundary: the orchestrator runs the system - it never does the coding work itself. Teams of agents inside the workflows do that.
This guide is a working reference for prompting the skill: how it behaves, the shape of a good ask, a gallery of copy-paste examples, and a deep section on spawning sandboxes so a run lands on its own branch and opens a PR instead of committing to your working tree. New to the factory itself? Start with the field guide.
Invoke it with /atelier (or just describe factory work: "run an ADW", "manage the roster", "spin up a sandbox"). It is an orchestrator. Its whole job is the loop below; everything it will and won't do follows from that.
adws/adw_data/ is read-only to itThe governing line, quoted from the skill: "The intent is theirs. The precision is yours." If it thinks a different workflow or model fits better, it says so in its own message and still launches what you asked for.
/atelier does when you invoke itOn startup the orchestrator does exactly three things, then stops and waits for you. It deliberately does not volunteer a status dashboard, query past runs, or survey your repo - that would spend context on guesses before it knows the task.
ls adws/adw_*.py and each script's one-line Phases: chain. The files are the only authority; it never launches from memory.| ADW | Chain | Reach for it when |
|---|---|---|
| adw_scout | engineer → scout | read-only recon; nothing changes |
| adw_plan | engineer → plan | you want the plan to read before any build |
| adw_plan_build_test | plan → build → test | a real change with a verify gate |
| adw_simple_sdlc | plan → build → test → review → document, commits as it goes | the work is real and its shape is not obvious |
Illustrative rows - the actual menu is whatever your repo's adws/ holds, read fresh each session. If the factory isn't installed, it says so in one line instead of the table.
You can talk to it however you like; it will sharpen your words for you. But the more precise your ask, the less it has to infer - and the prompt it builds is read by every agent in the chain, so precision compounds. When it matters, give it the four lines it's aiming for anyway:
<the ask - one imperative sentence>
Where: <the files or dirs involved>
Done means: <the observable result - a response shape, a passing test, a rendered element>
Out of scope: <what should NOT change, named so nobody adds it>
Vague - makes it guess
"can we get tags on posts, sorted by popularity"
"Popularity" could be a sort, a score, a UI. No files, no stopping point. The chain pays for every ambiguity.
Sharp - one reading only
"Add GET /api/tags returning {tag, count} across all posts, sorted by count desc then tag asc."
Same idea, same scope - but "popularity" is now a sort order and the endpoint shape is fixed.
Leave the plan to the planner unless you have an opinion - if you do, state it and the orchestrator carries it word for word. And don't address the harness in your ask ("use the reviewer", "retry twice", "then commit"): those are chain choices, decided by which workflow runs, not by prose the agents would read. Want a review phase? Ask for a workflow that ends in one.
Copy, adapt, send. Each block shows what you'd type and what the orchestrator does with it. It always reports back the exact prompt it sent, the workflow it chose, and the adw_id so you can watch.
adw_scout), and reports the findings. No file is touched - the scout's write boundary is empty.GET /api/tags endpoint returning {tag, count} sorted by count desc. Don't build yet - I want to read the plan first.adw_plan), prints the adw_id, and surfaces the plan envelope. Nothing lands but specs/.--adw-id <same>, so the builder inherits the planner's context and handoff files intact. This is how you chain workflows across turns./health endpoint that returns 200 {status:"ok"}, with a test. Take it end to end.adw_plan_build_test or adw_simple_sdlc) - plan, build, verify against the test gate, and for the fuller chain, review and document, committing as it goes.--config <that>.config.yaml) and names it back to you. It warns that switching rosters mid-session starts the builder fresh (a joined run can't resume an agent created on a different model) - deliberate, but you lose the builder's accumulated context.just phases <id> / just tail <id>) and reports which phase is running, the sequence so far, and any gate violations verbatim - never a guess.Long ask? The orchestrator writes it to requests/<slug>.md and passes the path - every workflow accepts inline text or a file. It asks at most one clarifying question, and only when two readings would produce different code.
By default a run executes at the repo root and commits to your current branch. A sandbox quarantines it instead: an isolated, persistent git worktree on a named branch, provisioned once and reused across runs. The run's trace still lands in the shared db, so you observe it identically - but its file changes never touch your working tree, and a land hook can open a PR when you're happy.
A plain "run this" goes to the repo root, on your current branch. To get a sandbox, say so - "in a sandbox", "on its own branch", "open a PR". Sandbox-bound runs go through the launch queue, so a worker must be draining it (just worker); the worker is the only thing that provisions a worktree and turns a queued row into a live run. The orchestrator never spawns a process or touches a worktree itself - it writes the intent; the worker disposes.
Create-and-run in one step - the common case
/api/tags endpoint in a new sandbox - plan, build, test, and open a PR when it's green.feat/api-tags-endpoint. The worker provisions the worktree, runs the chain with cwd=<worktree>, and on green the land hook pushes the branch and opens the PR. You get the PR URL back.Name the branch yourself
feature/PROJ-233_tag-counts.feat/fix/chore/docs names.Ask for a fuller environment (Level 2)
worktree_env sandbox.services.up), and scoped env - once, at create. Requires the project to declare a worktree_env profile in its sandbox: config; if it doesn't, the orchestrator says so rather than pretending.| Level | Buys you | Provisioning |
|---|---|---|
| local default | nothing - runs at the repo root, exactly as a direct launch | none |
| worktree L1 | write isolation: a persistent branch workspace | git worktree add on a named branch |
| worktree_env L2 | the above + isolated deps, per-sandbox ports, services, scoped env | + setup, allocated ports, services.up, injected env |
Parallel work - two sandboxes, not two runs in one
Iterate, then land or tear down
land_requested on the first (worker runs the land hook once in the worktree - pr / merge / manual - then returns it to active; landing never destroys anything) and shutdown_requested on the second (worker runs services.down, removes the worktree, marks it gone). Shutdown is the only teardown - and the branch and its commits survive in .git; shutdown reclaims the working tree, not the work.request → provisioning → active ⇄ (run, run, run…) ⇄ landing → shutting_down → gone
A sandbox outlives every run it hosts - real feature work is iterative (run, inspect, run again in the same warm tree). Ask the orchestrator "what sandboxes are active?" and it reads the sandboxes table: id, level, status, branch, and the last land result.
The orchestrator doesn't only launch what exists; it helps you shape the factory itself. These edits are deliberate and reviewable - a new workflow script, a roster change - never improvised mid-run.
Compose a new workflow
adw_*.py composing those phases, following the hard rules (typed envelopes, gates validate claims, every phase earns a one-sentence description).Retune the roster
sssf.config.yaml - one field, one line diff, comments intact. Re-validated by the engine at run time.Scope an agent's reach
database/migrations/ and auth.protected_files - enforced after every agent call in permissions.py; unauthorised writes are rolled back and the phase dies.Keep the engine current
<file>.atelier-new - your roster and prompts are never touched.Each agent runs on claude_code (the default - Claude via the Agent SDK using your local claude CLI login, no API key; starter roster is anthropic/claude-sonnet-5) or pi (non-Anthropic models via the pi CLI). Any anthropic/* model is always routed through claude_code - the roster can't mis-route it. Your repo's root AGENTS.md (else CLAUDE.md) is injected into each claude_code agent so it sees your project's conventions.
Once a run is launched, the orchestrator reads the same live SQLite trace the cockpit does (WAL mode - reads never block the running agents) and narrates it. Its report, in order:
adw_id - everything keys off it: just phases <id>, just tail <id>, just procs <id>Every phase defaults to fail and must earn success - a clean exit flips it, and an agent phase additionally needs its envelope to parse and all gates green. So a phase showing fail may simply never have completed, and queued means it never started. The orchestrator won't dress a partial run up as a success. For a visual view, register the repo in the central cockpit (atelier.projects.json) and watch runs as swim lanes; the just recipes are the headless equivalent.
Operator guide - a companion to the field guide and the build plan. · The skill and its cookbooks live in the repository under .claude/skills/atelier/. · Prompt for intent and precision; say "in a sandbox" when you want isolation; let the orchestrator run the system while the agents inside do the work.