Atelier · Operator guide · Building with the /atelier skill

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.

01 What the skill is - and what it refuses to be

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.

What it does

  • Translate your ask into the prompt the workflow receives - clearer, not different
  • Choose the workflow (ADW) whose shape fits the work, or the one you named
  • Launch it - directly, or bound to a sandbox / the launch queue
  • Observe the live trace in SQLite and report phase status plainly
  • Author & tune the factory: create workflows, retune the agent roster

What it won't do

  • Do the work itself - never plans, builds, or edits your app in an agent's place
  • Drop or soften a requirement - your intent is carried forward verbatim
  • Swap rosters or models silently - a different roster is a different cost and result; it asks
  • Fabricate a status - it reads the real trace; a partial run is never dressed up as success
  • Touch the run record - the session trace under adws/adw_data/ is read-only to it

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

02 First contact - what /atelier does when you invoke it

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

  1. Reads the system map - the overview cookbook that describes the factory and the stamped layout.
  2. Lists the workflows on disk - ls adws/adw_*.py and each script's one-line Phases: chain. The files are the only authority; it never launches from memory.
  3. Prints them as a table - name, chain, when to reach for it - and waits for your request.
ADWChainReach for it when
adw_scoutengineer → scoutread-only recon; nothing changes
adw_planengineer → planyou want the plan to read before any build
adw_plan_build_testplan → build → testa real change with a verify gate
adw_simple_sdlcplan → build → test → review → document, commits as it goesthe 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.

03 How to prompt it - the four-line shape

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.

Say WHAT and DONE, not HOW

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.

04 Prompt gallery - the everyday moves

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.

You sayWhere does rate limiting live in the API? Just look - change nothing.
OrchestratorRecognises a question, launches a read-only recon workflow (adw_scout), and reports the findings. No file is touched - the scout's write boundary is empty.
You sayPlan a GET /api/tags endpoint returning {tag, count} sorted by count desc. Don't build yet - I want to read the plan first.
OrchestratorLaunches plan-only (adw_plan), prints the adw_id, and surfaces the plan envelope. Nothing lands but specs/.
You sayGood, build that plan.
OrchestratorResumes the same session with a build-first chain --adw-id <same>, so the builder inherits the planner's context and handoff files intact. This is how you chain workflows across turns.
You saySmall, well-understood change: add a /health endpoint that returns 200 {status:"ok"}, with a test. Take it end to end.
OrchestratorPicks a complete chain (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.
You sayHave Opus plan this one, then build on the default roster.
OrchestratorResolves "Opus" to the roster whose planner is that model (--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.
You sayHow's the tags run doing?
OrchestratorQueries the live trace (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.

05 Spawning sandboxes - runs on their own branch

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.

Isolation is opt-in - you must ask for it

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

You sayBuild the /api/tags endpoint in a new sandbox - plan, build, test, and open a PR when it's green.
OrchestratorCreates a sandbox and enqueues the run into it in one transaction (no orphan if enqueue is rejected). Your request doubles as the sandbox purpose, so a cheap namer model turns it into a readable branch like 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

You sayRun this in a sandbox on branch feature/PROJ-233_tag-counts.
OrchestratorPasses the branch verbatim (it wins over an auto-named purpose). The worker checks it out if it exists, else forks it off HEAD. Use this for ticket conventions the namer can't produce - it only emits lowercase feat/fix/chore/docs names.

Ask for a fuller environment (Level 2)

You sayThis needs the test database and its own port - run it in a full worktree_env sandbox.
OrchestratorRequests the L2 level, which provisions the worktree plus isolated deps, allocated ports, backing services (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.
LevelBuys youProvisioning
local defaultnothing - runs at the repo root, exactly as a direct launchnone
worktree L1write isolation: a persistent branch workspacegit worktree add on a named branch
worktree_env L2the 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

You saySpin up two sandboxes - one for the tags endpoint, one for the search fix - and run them side by side.
OrchestratorCreates two sandboxes and enqueues one run into each. Parallelism is across sandboxes; two runs in the same tree would re-introduce the write collision isolation exists to remove, so same-sandbox runs serialize by design.

Iterate, then land or tear down

You sayThe tags branch looks good - land it. And shut down the search sandbox, I've merged that one.
OrchestratorFlips 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.

The sandbox lifecycle, in one line

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.

06 Beyond running - authoring and tuning the factory

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

I keep wanting plan → build → test, no review or docs. Make me that chain.
Writes a new thin adw_*.py composing those phases, following the hard rules (typed envelopes, gates validate claims, every phase earns a one-sentence description).

Retune the roster

Give the reviewer more thinking budget and point the builder at a stronger model.
Surgically edits sssf.config.yaml - one field, one line diff, comments intact. Re-validated by the engine at run time.

Scope an agent's reach

Keep any builder out of database/migrations/ and auth.
Adds those to protected_files - enforced after every agent call in permissions.py; unauthorised writes are rolled back and the phase dies.

Keep the engine current

Pull the latest Atelier engine improvements into this repo.
Runs the updater, which moves only managed engine files by content hash and parks any conflict as <file>.atelier-new - your roster and prompts are never touched.

Backends, briefly

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.

07 After launch - how it watches and what you get back

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:

Reading run health honestly

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.