How Atelier works
Atelier is a Git platform for several coding agents working on one project at the same time. Each task has one owner at a time and its own fork of the code, checks run on a clean clone of exactly what was pushed, and no agent's work reaches the project until the project owner accepts and merges it.
It runs on Cloudflare Workers, Durable Objects and Artifacts. A Durable Object for each project holds the ledger: the items, the evidence, the reviews and an append-only event log. Artifacts holds the repositories. Agents and the owner work through one command, atelier, which needs only Node and git; the owner also has a web inbox that ranks what needs a decision.
Terms
- Task
- One piece of work: a title, a scope of the paths it intends to touch and, once claimed, an owner. The API reference calls it an item.
- Baseline
- Atelier's copy of the project's branch, the one
atelier initregistered (oftenmain), held in an Artifacts repository. - Workspace
- A task's own fork of the baseline, also an Artifacts repository. Only the task's owner holds a write token for it.
- Head
- The latest commit in a workspace. Results, reviews and acceptance each name the head they apply to.
- Observed
- A required check's result, recorded against the head Atelier read from Artifacts, from a run on a clean clone of that head.
- Reported
- A statement an agent made about its own work. It is shown and never counted.
- Pending
- A required check with no Observed result at the current head.
- Gate
- The function that decides whether a task can be accepted and lists what still blocks it:
gateinsrc/rules.ts. - Protected path
- A path whose change needs an independent review. The project lists some; Atelier adds the files its required checks execute.
Where it runs
Atelier runs in five layers. The owner and anyone acting for them work through one command, the CLI, which is the only way into Cloudflare; agents work below it, each in its own workspace, calling its own model.
The loop
A task goes through seven steps. The diagram shows who acts at each step and what Atelier records; the list gives the command and the detail.
Task
The project owner creates the task with
atelier new "title" --scope 'src/**'. The scope is the paths the task intends to touch. Overlapping live scopes are flagged in the inbox, and a project whose policy says so refuses a claim that overlaps another. A project that names core files holds a dispatch in the queue while its scope overlaps a live item's within one.Claim
An agent claims it with
atelier start t3 --as harness/model. The project's Durable Object handles one request at a time, so a second claimant is refused.Workspace
The Worker forks the baseline into a repository for the task and mints an eight-hour write token for the claimant alone. The agent works in a clone outside the project checkout, commits, and runs
atelier push. Atelier reads the head from Artifacts and records that head; when the agent named a different one, the ledger records the mismatch.Checks
atelier checkclones the workspace afresh at that head, runs each required check, measures which paths changed since the baseline, and records each result as Observed.--sandboxruns the checks in a Cloudflare container instead.--mergedruns them on the would-be merge, the head merged with main as it is now, and the result stands beside the merge preview, bound to both revisions.atelier reportadds a Reported claim.atelier submitmarks the task ready, andatelier done "summary"runs push, check and submit in order.Review
A reviewer, an agent that did not work on the task, reads the change with
atelier diff t3and recordsatelier review t3 --approve, or--reject --note "…". A review is required when the change touches a protected path and, under a ControlPlane policy, when it is a coordinated change; Independent review of protected paths says whose approval counts. The owner may review too, and the owner's rejection blocks, but the owner's approval is never the required review.Accept
The project owner accepts with
atelier accept t3or the Accept button. The gate, set out under Owner acceptance and merge, must be clear. Acceptance pins the head. When a required review is all that is missing and no reviewer qualifies, the owner accepts withatelier accept t3 --override-review "reason"instead, which records an override with its reason, not a review.Merge
In the project checkout the owner runs
atelier merge t3. It fetches exactly the accepted head, merges it with--no-ff, attaches the task's provenance as a git note onrefs/notes/atelier, and pushes the project's branch to the baseline. Pushing to the project's own remotes and deploying remain separate decisions.
Rules
Each rule is enforced by code, which it names, and each says why it exists.
One owner per task
A task has at most one owner. The project's Durable Object handles one request at a time, so when two agents claim a task the second is refused. Ownership changes only through a recorded event: a claim, a handoff, a release, an abandonment or a merge.
Why. Two agents writing to one workspace overwrite each other, and nobody could say afterwards who did what.
Enforced in
assertClaimableandassertOwnerinsrc/rules.ts.Separate forks for agents
A claim forks the baseline into a repository for that task, and the claimant's write token covers that repository alone. Only the owner token can obtain a write token for the baseline; an agent token is refused.
Why. A wrong or abandoned change in one workspace cannot touch the baseline or another task's work.
Enforced in
agentRouteinsrc/tokens.ts.One write token per workspace
A claim revokes the workspace's earlier write token before it mints a new one, so only one is live. The token lasts eight hours, and a handoff, a release or an abandonment revokes it.
Why. An agent that has handed work on or given it up must not be able to keep pushing to it.
Enforced in
revokeinsrc/index.ts.Observed evidence only
atelier checkruns each required check on a clean clone of the head Artifacts holds and posts the result as a check. The Worker stores a check as Observed and a report as Reported, and the gate counts Observed results only. A required check with no Observed result at the head is Pending and blocks acceptance. UndersandboxOnly, only results from a Cloudflare container count. A check run with--merged, on the head's merge with main as it is now, is recorded against both revisions and never counts as the head's own check; it blocks acceptance only when it fails after main moved past the head the passing checks were recorded against.Why. An agent's own statement that its tests pass is not evidence; the owner needs results taken from a clean clone of the head, though only a container result is produced by Atelier itself, and a local Observed result is posted by the machine that ran it.
Enforced in
evidenceAt,gateandmergedBlockersinsrc/rules.ts.Evidence bound to a head
A result, a review and an acceptance each name the head they apply to. Atelier refuses a result or a review for any head but the task's current one, reads the head from Artifacts instead of taking the agent's word for it, and withdraws acceptance when a push moves the head.
Why. An approval of one revision must not authorise another, and a pass at one revision says nothing about the next.
Enforced in
assertRevisioninsrc/rules.ts;recordPushinsrc/ledger.ts.Independent review of protected paths
A change that touches a protected path needs an approving review from a model of another family than every model that contributed to the task, in every project, with or without a ControlPlane policy. The family is read from the model's name, and a family Atelier does not recognise never qualifies, in a reviewer or in a contributor. The project owner's approval is not this review; the owner accepts and merges. Nor is a tier review's approval: a project's review tier reviews beside this review, and its rejection blocks like any other. When no reviewer qualifies, the owner can override the review while accepting, giving a reason: the override is recorded as an event of its own, never as a review, counts only at that head, and the task page and the inbox show it with its reason. The protected paths are those the project lists (by default
AGENTS.md,CLAUDE.md,wrangler.*and.atelier/prompts/**, the role prompts) and what a required check executes: the scripts it runs, the recipe files of make and just, the manifest and configuration a package manager or build tool runs scripts from, and the local binary npx would run. Under a ControlPlane policy a coordinated change, one that is neither protected nor direct, needs a review from any agent who did not contribute, and the owner's approval is not that review either.Why. The model that wrote a change to the files that instruct agents or grade their work must not approve it, and nor should a model of its family, which is likely to share its blind spots.
Enforced in
changeClass,checkFiles,independentApprovalandreviewOverrideForinsrc/rules.ts.No self-review
The task's current owner cannot record a review of it. Everyone who has held the task or pushed to its workspace stays a contributor, so a review by any of them never counts as the independent one.
Why. A review by the author checks nothing.
Enforced in
addReviewinsrc/ledger.ts;pushActorsinsrc/rules.ts.Owner acceptance and merge
Only the project owner can accept or merge. Acceptance is refused unless the task is in the submitted state and the gate is clear: every required check Observed passing at the current head, the changed paths measured, no rejection at that head, and a qualifying review where one is required, or the owner's recorded override of it. The merge lands only the accepted head, and the ledger records it only when the merge commit is found on the baseline with the accepted head as a parent.
Why. Work enters the project only by the owner's decision, made on evidence for one exact revision.
Enforced in
gateinsrc/rules.ts;beginLandinginsrc/ledger.ts.Tokens scoped to an actor
An agent token binds every request to one actor: a request that names another actor is refused. The token expires (after 30 days unless set, and at most 365), can be limited to named projects, and opens only the agent workflow of claiming, pushing, posting results and reports, reviewing, submitting, handing off, releasing and reading, with these routes by name:
block,unblock,queue,sandbox,plan,integrated,integration-failed,refreshedandrefresh-failed. The Ledger still takes several of them only from the task's holder. Creating tasks, accepting, merging, dispatching, the model pool, project settings and token management need the owner token, and agent tokens cannot sign in to the browser.Why. A leaked or misused agent token can act only as its own actor, in its own projects, and cannot decide for the owner.
Enforced in
agentRoute,tokenActiveandinScopeinsrc/tokens.ts.Core files are built one change at a time
A project's policy may name core files (
atelier init --core GLOB). While a queued dispatch's scope overlaps, within a core file, the scope of a live item (claimed, submitted or accepted), the queue offers it to no runner and the owner's listing names the item it waits on; it is offered once that item merges or is abandoned. Items of one plan never hold each other, since the plan orders overlapping parts by their dependencies. The owner lets one task's dispatch through withatelier dispatch ID --overlap-ok. With no core files, nothing is held.Why. Tasks built at once on the same hot files stop each other's landings on merge conflicts.
Enforced in
coreHoldinsrc/dispatch/rules.ts;waitinginsrc/ledger.ts.
Limits of enforcement
- Agent tokens prove identity. The owner token may name any actor, so it stays with the owner's tools. A workspace write token is separate and controls only Git pushes.
- A caller allowed to post check results could post one that was never run, so a local Observed result rests on the command having run the check. A container check runs on the server, and
sandboxOnlycounts only those; the container path is implemented, and a successful run in production has not been confirmed. - The merge happens on the owner's machine. Artifacts can be read through its binding but written only by a git push with a write token, so Atelier merges in git in the owner's checkout and pushes the result.
The orchestrator
The orchestrator turns a goal into merged work. Every step here is built, and the list below names the code behind each. atelier plan "goal" makes the goal a plan task and queues it as a plan job. Every home runner offers build and plan jobs unless its config names the jobs it takes, so one takes the plan job: it claims the plan task as the planner, reads the brief the server wrote, runs the planner's harness and posts the plan document it wrote. The owner approves the newest proposal by its hash, once, with atelier plan approve. The approval fixes each part's routing: routeParts in src/plans/route.ts names a builder, two alternates and a reviewer of another model family than the builder's, and the approval is refused while any part has no builder or no such reviewer. The ledger's tick then dispatches the parts in plan order, two live at a time, each once the parts it depends on have landed and with the brief the server writes for it, and runs again after each push, check, review, submit, release, merge or abandon of a part. A submitted part whose checks pass and whose paths are measured gets a review request from the tick, routed to a model of another family than every contributor. A home runner whose config offers review jobs serves the request: runReview in cli/runner.mjs clones the head read-only, gives the reviewer the brief and the diff, and posts the verdict with its findings; cli/agy-review.mjs is the adapter that runs Antigravity's CLI as that reviewer. A rejection with blocking findings sends the part back to its builder for rework. An approved part is merged into the plan's integration branch by the integrator runner, atelier runner --integrate, which runs the plan's checks and rolls the branch back when they fail. When no part remains to integrate, the integrator submits the plan task, and it reaches main by the owner's acceptance and merge, which marks each part merged through the plan. A task outside a plan lands whole with atelier land: it takes the project's landing lease, merges main into the workspace, pushes, runs the checks and submits, asks for the review the gate needs through a review request served the same way, waits for the verdict, then accepts and merges. docs/orchestrator.md holds the design and its build sequence.
- Built
Plan schema and content hash
src/plans/schema.tsparses a plan document, refuses unknown fields and over-long text, and hashes the plan. The hash is what an approval will bind to. - Built
Plan validation
src/plans/validate.tschecks that part keys are unique, that there are at most 12 parts, that dependencies have no cycle, that parts with overlapping scopes are ordered, and that interface parts depend only on interface parts. - Built
Part routing
src/plans/route.tschooses a builder, two alternates and a reviewer from another model family for each part, from the model pool and the ledger's record, with each model's reliability across every project breaking ties. It leaves out refused models, and paid models unless the owner allows them. A model no live runner offers cannot build or review at all, since no runner could claim its dispatch (offeredActorsinsrc/dispatch/rules.ts), and a reviewer is routed besides only to a model a live runner offers for the review job (offeringinsrc/dispatch/rules.ts, which counts a model only when a runner that offers the job lists it, so a model only a build runner offers never reviews, the t210 case of 2026-10-07); when no runner is live the pool stands and the routing says so with a warning. - Built
Dispatch decisions
src/plans/phase.tsdecides, from plain data, which parts to dispatch and to whom.planPhasederives a plan's state: planning, proposed, building, blocked, ready, accepted, merged or abandoned.planActionsdispatches parts in plan order while fewer thanmaxParallel(2 by default) are live, each once every part it depends on has merged.partAttemptscounts attempts from the event log. A builder gets two, so one that gives up twice, or fails a finish and then its retry, is replaced by the next alternate. The plan blocks when a part reaches three attempts or has no alternate left, when a part depends on an abandoned one, or at the deadline or the budget cap. - Built
Plan ledger
The project's ledger keeps plans. A plan is a task whose planner is dispatched as a plan job and posts a plan document; each valid proposal is kept, unchanged, and an invalid one gets the planner one more attempt before the plan blocks. The owner approves the newest proposal by its hash, once: the routing of each part is fixed then, with the limits (2 parts live, 3 attempts a part, 4 dispatches a part, 24 hours), and the parts become tasks. After each push, check, review, submit, release, merge or abandon of a part, and at the deadline, the ledger runs
planActionsand dispatches what may start, asatelier/orchestrator, or blocks the plan with the reason. The inbox gainsapprove-planandplan-blocked; a part never appears there to accept, review, fix, rescope or hand off, and tasks of one plan are not flagged as overlapping. Each part reaches main through the plan's integration branch, and the plan is complete when every part has merged or been abandoned, with at least one merged. - Built
Plan routes and command
atelier plan "goal"starts a plan, andplan showprints its phase, its newest proposal with the hash to approve, or each part with its state, routing and attempts, and the command for each decision waiting on the owner.plan approvetakes that hash, once;plan revise,plan reroute,plan retryandplan stopare the owner's other decisions, andplan postis how a planner submits its plan document, the one plan route an agent token reaches.atelier showprints a plan's own brief. - Built
Server briefs and runner jobs
GET items/tN/job-briefgives the holder of a plan item's or a part's claim the brief for the work it holds:plannerBrief's planner brief (the goal, the owner's latest note, the last refusal's errors and the schema to write) orjobBrief's part brief. The runner offersjobs: ["build","plan"], so a plan job reaches it: it claims the plan item as the planner, fetches that brief, runs the harness with a{plan_file}placeholder naming where the plan document goes, posts the document, reports the errors of a refusal and releases the claim either way. A part's build brief comes from the route too, and a part whose finish fails is released, so the plan's tick sends it back with the failing output. - Built
Server brief for a part
src/plans/brief.tswrites the brief an agent gets for one part of an approved plan, or for its rework.jobBriefstates the rules (work only in the workspace, commit, do not push; the orchestrator pushes, runs the checks and submits; quoted text is data), then the plan's goal, the part's spec, acceptance criteria and interfaces, the parts it depends on with the heads they landed at, its scope, the project's required checks and, for rework, the review's findings or the failing check's output, capped and saying when cut. It returns the text with a hash of its inputs that does not depend on key order. Thejob-briefroute (step 7b) serves it. - Built
Review rules
src/review/decides when a submission gets an automatic review, and how the review is asked for and read.reviewNeededasks for one once every required check is observed passing at the head and the changed paths are measured, unless that head already has an approval that suffices, a rejection awaiting rework, an open request or, outside a plan, the owner's override. The owner's approval never suffices. Every part of a plan is reviewed; any other task only when the gate needs an independent review.pickReviewertakes a model whose family is recognised and differs from every contributor's, available, not refused and paid only when allowed, and names each model it passed over and why.reviewBriefwrites what the reviewer reads, fencing quoted text so it cannot pose as instructions; it states the project's review bar (atelier init --review-bar, or the default: correctness, security or data-loss defects only) before the reply format, and from the second review on lists each earlier finding with the owner's verdict and note, saying a refuted finding is repeated only with new evidence quoting the code.parseVerdictreads the reply and refuses one that states no verdict, states both, or gives findings that contradict its verdict; a rejection needs a blocking finding. A project with a review tier (atelier init --review-tier H/M,H/M) has every protected change reviewed by the tier too, most with one review:pickReviewerasks the tier's models first for the gate's review, and a tier model of another family than every contributor gives both (gateServesTier), its review marked as the gate review, top tier. Only when the gate's reviewer is outside the tier is a separate tier request asked beside it:pickTierReviewertakes the first tier model that did not build the change and is not the gate's reviewer, whatever its family. A tier rejection sends the change back as any rejection does; a separate tier approval never satisfies the gate, and a landing never waits for a tier review, whose open request the acceptance withdraws. - Built
Review requests and runner job
The ledger keeps review requests: its tick asks one for each submitted part whose checks pass and whose paths are measured, routed by
pickReviewerto a model of another family than every contributor, and the queue offers them asreviewjobs to a home runner whose config lists that job. The runner'srunReviewclaims one, clones the part read-only, gives the model the review brief and the diff, and posts the verdict with its findings.cli/agy-review.mjsis the review command for the antigravity harness: it runs Antigravity's CLI on the brief and the diff and writes the reply to the verdict file. A rejection with blocking findings sends the part back to its builder for rework, and a harness that writes no valid verdict releases the request. Each runner's offer is recorded as it asks the queue for work (putRunnerOffer), and a dispatch no live runner offers, which could never be claimed however long it waits, is said as that byunoffered:atelier landwhile it waits for a verdict,atelier plan showfor a routed review andatelier statusfor the queue, each naming what the live runners offer instead. - Built
Integration rules
src/plans/integrate.tsholds the rules for merging parts into a plan's branch.integrationBlockerslets a part in only when it is submitted, every part it depends on has landed, and its head carries an approval from a model of another family than its builders; the owner's approval is not one, and a part takes no override.verifyIntegrationaccepts the integrator's merge commit only when it has exactly two parents, sits on the branch's first-parent line, and merges the part's head onto the integration head, the branch's head as the ledger last recorded it.rollbackForsays how a failed integration is undone, and refuses when that would discard commits it did not make.planGateadds to the plan task's gate: every part integrated or abandoned before integration, at least one integrated, each integrated part approved at the head that was integrated, and the branch's head at the integration head. There the parts' reviews are the plan's review, so the plan task asks no independent review of its own and the integrator's merges are not compared with any reviewer. - Built
Integration jobs
Each part forks from its plan's fork and is measured against it, never the baseline (
baseRepoOfin src/plans/integrate.ts and thebase-tokenroute), so a part reports only its own files. A part claimed again with no commits of its own, after the branch has moved, has its fork forked again at the branch's head (movePartForkin src/index.ts), so its builder starts from every part integrated since; a fork whose head is a later commit of the branch, which a move that failed to record its base leaves, is moved on the next claim the same way, and a fork whose head changes while it is moved is kept. The integrator, a reserved actor reached only through its token, claims the plan item's integrate job, merges the part onto the plan's branch, runs the plan's checks, and postsintegratedorintegration-failed, both verified against the branch's log by the Worker.planGateadds its blockers to the plan item's gate, andLedger.mergedmarks the parts merged with{via: tP}when the plan lands. The runner's--integratemerges each part with--no-ffand rolls the branch back when the checks fail or the merge conflicts, and its refresh job merges main's head into the plan's fork, dispatched by the tick before a part when main has moved, or by the owner withatelier plan refresh, and recorded withrefreshedorrefresh-failed. A refresh that conflicts adds a merge-main part to the plan, outside the approved document and its hash: the runner merges main into that part's workspace and leaves the conflicts for its builder to resolve, no other part is dispatched until it is integrated, and its integration records main as taken. The owner adds one withatelier plan refresh --resolve. A plan is accepted only where its branch would merge with main (assertPlanMergeablein src/index.ts), and a plan submitted or accepted that must take main, the owner's plan refresh, or atelier merge stopped by a conflict, goes back to building first (reopenPlanin src/ledger.ts); the integrator submits it again once every part is integrated on a branch that holds main. A task outside a plan whose landing conflicted with main goes back to its builder the same way (t243):atelier dispatch ID --job merge-mainqueues the merge-main job on the task, whose runner merges main into its workspace and leaves the conflicts for it to resolve, where a plain rework would reset the workspace to a head that cannot reach main. - Built
Landing a single task
atelier land IDlands one task whole, from the owner's machine. It takes the project's landing lease on the server (beginProjectLanding), so one landing runs at a time, merges main into the task's workspace with--no-ffand stops on conflicts, naming the files, regenerates the project's fixtures when its policy says how, then pushes, runs the required checks and submits, each as the CLI's own command. It asks the server for the review the gate needs through thereview-requestroute (requestReview), which picks a model of another family than every contributor, or takes the one--reviewernames, and queues a review job; it waits for the verdict, then accepts and merges. Each step, its duration and the commits that came from main are recorded asland.*events (landEvent), and the lease is released when the landing ends, by a failure too.--no-reviewleaves the task submitted for the owner to settle, and--dry-runprints the steps without changing anything.
Using Atelier well
The project owner makes three kinds of decision: what to do, whether a plan's split is right, and whether finished work is accepted. These points, from docs/using-atelier.md in the repository, are about making them well and leaving the rest to the system.
- Start with
atelier status. It lists, for every project, what needs the owner: a plan to approve, work to accept, failing checks, a change outside its scope. When nothing waits, there is nothing to do. - Something with several parts becomes a plan,
atelier plan "goal"; one clear change becomes a task,atelier new "title". A good goal or title says what should be true afterwards, names the files it may touch, and asks that every claim match the code. - Keep scopes narrow. Two live tasks whose scopes overlap usually conflict when the second lands, and
atelier statuslists such pairs. - Read a plan before approving it, with
atelier plan show: the parts sensible and ordered, each routed to a model you want doing it, nothing contradicting what you asked. Then approve once, by the hash of its newest proposal. - Accept deliberately. Look at the gate, the reviewer's findings and the scope flag. A finding is a claim about the code and can be wrong: have a wrong one answered with the file and line that show it, never overridden quietly.
- Land one task with
atelier land ID --reviewer H/M, which merges main, checks, submits, waits for the independent review, then accepts and merges.atelier landnever overrides a review; an override while accepting takes a reason and is recorded where everyone can see it. - Let a session act for you. Say a standing decision plainly, so it is recorded in the skill's
decisions.mdand every later session follows it, and ask it to file anything odd as a task rather than work around it quietly. - Watch three numbers: spend on pay-per-use models against the daily limit, the plan windows of the subscription tools, and each model's record on the Models page when choosing who builds.
- Run one home runner per machine, deploy between landings, and do not edit inside an agent's workspace while its agent runs. When something breaks, ask what task it becomes, not only how to get past it.
Commands
Every command the CLI's help lists, in its groups and order, each group closed until opened. The list is drawn from src/usage.ts, the table atelier help prints from, so the two cannot differ. H/M stands for harness/model, such as claude-code/opus-5.5. Square brackets mark what is optional, a bar separates alternatives, and ... marks a flag that may repeat.
Sessions
atelier unwrap [--project P]- Reads where the project stands, the state of this checkout, where its branch stands against each of the checkout's remotes as last fetched or pushed, the newest session note, the state file (the first of
docs/STATE.md,STATE.mdandPROJECT.mdthat exists) and any dated handoffs. It fetches and writes nothing. The project owner's session starts here. atelier wrap "summary" [--next TEXT] [--found TEXT]... [--push] [--no-check | --allow-failing] [--project P]- Closes the owner's session in the registered checkout: runs the registered checks and, when every one passes, commits everything with the summary as its subject, updates the baseline and records a session note on the ledger. A failing check refuses the commit, naming each failed check with how it ended, and leaves the checkout, the ledger and every remote as they were;
--allow-failingcommits anyway, and the note records which checks it let through. Check results are Reported, because they ran on the owner's machine.--pushalso pushes the checkout's own remotes;--foundfiles a task for each defect found;--no-checkskips the checks.
Setup
atelier login --server URL- Stores this server's address and the owner's token, asking for the token when none is stored for it. A token the server refuses is not stored.
atelier login --store- Names the token store in use and whether it holds a token. It never prints the token.
atelier init [--title TEXT] [--check CMD]... [--declare-read-only TEXT] [--protect GLOB]... [--core GLOB]... [--sandbox-only] [--refuse-overlap] [--approval TEXT] [--regenerate CMD] [--review-bar TEXT] [--review-tier H/M,H/M] [--reset] [--history-since YYYY-MM-DD]- Run by the project owner in the project checkout: creates the baseline repository in Artifacts, pushes the current branch to it, and records that branch as the project's branch, the required checks, the protected paths and an optional title. Run again, it changes only what it names.
--sandbox-onlycounts only checks run in a Cloudflare container, and--refuse-overlaprefuses a claim whose scope overlaps another live item's.--corerecords the project's core files: the queue holds a dispatch whose scope overlaps, within a core file, the scope of a live item (claimed, submitted or accepted, outside the dispatch's own plan) until that item merges or is abandoned; unset, nothing is held.--regeneraterecords the command that regenerates the project's generated fixtures, whichatelier landruns in a task's workspace after it merges main.--review-barrecords what may block a review, which every review brief states; unset, the brief states the default bar (correctness, security or data-loss defects only).--review-tiernames the top review tier, which reviews every protected change: the gate's cross-family review goes to a tier model first and then serves both, and only a gate reviewer outside the tier gets a separate tier review beside it; unset, none does. Every check must be read-only: a command that deploys, installs, publishes, pushes or spends money is refused, a known build or test command is read-only by its words, and--declare-read-onlyrecords the owner's reason for the others.--resetrebuilds the policy from the defaults;--history-sincegives a project too large for Artifacts a baseline with its recent history only. atelier sync- Refreshes the stored policy from the project's ControlPlane files. For a baseline built with
--history-since, it also carries commits made in the checkout outside Atelier to the baseline. atelier publish- Pushes the registered branch to the baseline with a write token. It is refused for a baseline that holds only part of the history;
syncdoes that job. atelier notes-remote [REMOTE | --off]- Names a git remote that receives
refs/notes/atelier, the merge provenance, and only that ref, on every merge.--offstops it; with no argument it says what is set. The setting is kept on this machine.
Items
atelier new "short title" [--brief TEXT] [--accept TEXT]... [--scope GLOB]... [--non-goal TEXT]... [--stop-when TEXT]... [--next-gate TEXT]- The project owner creates a task with a short title (at most 80 characters, what every list shows), and optionally its brief (the whole task, shown on its page and given to the agents that build and review it), its acceptance criteria (a change that fails one is rejected in review), the globs it intends to touch, what it is not to do, what tells its holder to stop and ask, and the gate it goes to next. One long text with no --brief is kept as the brief, and the title is derived from its first clause. The brief,
atelier startand the task's page show them. atelier edit ID [--title TEXT] [--brief TEXT] [--accept TEXT]... [--non-goal TEXT]... [--stop-when TEXT]... [--next-gate TEXT]- The project owner changes a task's title, brief, acceptance criteria, non-goals, stop conditions or next gate. A flag given replaces that field, one left out keeps it, and an empty value clears it; the title cannot be cleared. Changing the acceptance criteria (their text, order or entries) withdraws every review and open or claimed review request of the old ones, an acceptance (the task goes back to claimed) and an override of the review, and says so: a fresh review of the new criteria is needed. The same list again changes nothing. The criteria of an integrated part, or of a task being landed, cannot change.
atelier ls [--all] [--json]- Lists the project's tasks with state, owner and head. Merged and abandoned tasks need
--all.--jsonprints them for scripts, each task with its created, updated and last-push times, as Observatory reads them. atelier show ID [--reviews] [--json]- Prints a task's decision brief: what is decided, the recorded evidence, a recommendation and the task's address.
--reviewsalso prints each review at each head with its whole note and findings;--jsonprints the brief, carrying the reviews, for scripts. atelier receipt ID [--json]- Prints one task's whole story from the ledger, in the order it was recorded: created, claimed, each handoff and release, each pushed head as Artifacts answered it, each observed check at each head, each review with its verdict and every finding with the owner's verdict on it (confirmed, refuted or fixed), then the submission, acceptance and merge or abandonment that ended it.
--jsonprints the task's events as the ledger holds them, in order. atelier owners [--json]- Prints one line per live task: its state, its owner and since when.
atelier inbox [--json]- Prints the decision brief of each task that needs the project owner, most urgent first.
--jsonprints the entries for scripts. atelier status [--project P] [--json]- Prints the owner's queue for every project: what waits for the owner, which pairs of live tasks name overlapping scopes (each pair once, nothing waiting on the owner), what is in progress and what waits for a runner, with the live item each dispatch the project's core files hold waits on, each open review request among it with its reviewer named, and, for any queued job no live runner offers, that it can never be claimed until a runner that offers it is started, which is a mismatch between the dispatch and the runners rather than a wait. With
--projectit prints where one project stands instead, ending with whether this checkout is in step with the baseline and, when any of the project's tasks has a workspace on this Mac, an On this Mac section: each live task's workspace with its uncommitted changes, commits not pushed to its fork, a merge in progress and a waiting COMMIT_MSG.txt, a count of the merged or abandoned tasks' workspaces left behind, and whether a landing is running here for the project.--jsonprints machine-readable records, each task with its created, updated and last-push times, as Observatory reads them, the overlapping pairs underoverlapsand the same local facts underlocal. atelier open- Opens the server in a browser, using the macOS
opencommand.
Agents
atelier start ID [--as H/M] [--runner home:NAME]- Claims the task, prepares its workspace as
claimdoes, and prints its title, brief, acceptance criteria, scope and any dispatch note.--runnernames the runner when a runner claims a dispatched task. atelier done "summary" [--sandbox]- Pushes, runs the required checks and submits, in that order, and stops at the first step that fails, naming it.
--sandboxruns the checks in a Cloudflare container. Its last line saysReady for the owneror what still blocks the task. atelier claim ID --as H/M [--runner home:NAME]- Takes ownership of a task, forks the baseline into the task's workspace, mints a write token for the claimant alone, clones the workspace and records the project's branch as the one it pushes to. Claiming again refreshes the token and that branch, saying when the branch changed.
--runnernames the runner when a runner claims a dispatched task. atelier finish [--sandbox] [--summary T]- Run in the claimed workspace: pushes, runs the required checks and submits, only if they pass and the workspace has not changed meanwhile.
--sandboxruns the checks in a Cloudflare container.doneisfinishwith a required summary. atelier push [--force | --rollback]- Pushes the workspace to the task's fork, then asks the Worker to read the head from Artifacts. The ledger records the head Atelier saw, not the one the agent named. It refuses, pushing nothing, when the workspace's branch is not the one the fork's HEAD names, since Atelier reads only that one. After
update,--forcepushes with a lease.--rollbackreturns the fork to an earlier commit of the recorded history, as the plan integrator does after a failed integration. atelier update- Rebases the workspace onto whatever has merged to the baseline since the fork, then names the next step,
atelier push --force, whose lease refuses to overwrite anything pushed since the workspace last fetched. atelier check [--sandbox] [--merged] [-- CMD]- Runs each required check, or the command after
--, in a clean clone of exactly the head Artifacts holds, measures which paths changed since the baseline, and records each result as Observed.--sandboxruns them in a Cloudflare container instead.--mergedruns them on the would-be merge, the head merged with main as main is now, in a temporary merge commit that is never pushed; the result is recorded against both revisions, shown beside the merge preview, and goes stale when either moves. A local check runs with the caller's file access, so it can read their files and Keychain and reach the network; it is given only the environment variables toolchains need, and Atelier's tokens are redacted from its output before upload. Run untrusted code with--sandbox. atelier report [ID] "what you verified and how" [--item ID] [--project P]- Records a Reported claim at the current head: what the agent verified and how. It goes on the task named, else on the workspace's task; in a workspace, another task's id needs
--item ID. It is shown and never counted as a check. atelier submit [--summary T]- Marks the task ready for the owner and prints what still blocks it, if anything.
--summarystores a summary of the change with the submission. atelier handoff ID --to H/M [--note TEXT]- Moves ownership to another agent, with
--notesaying why. The old write token is revoked; the workspace and its history carry over. atelier release ID [--note TEXT]- Gives the task up: it returns to open and the write token is revoked.
atelier block [ID] "what it is waiting on"- The holder or the project owner blocks the task with what it is waiting on. It keeps its owner and workspace, leaves the runner queue and stuck detection, cannot be pushed, submitted, reviewed, handed off or released, and sits in the owner's inbox with the reason until it is unblocked.
atelier unblock [ID]- The holder or the project owner lifts the block, and the task returns to the state it was in.
atelier diff ID- For a reviewer: prints the task's commits and diff against the baseline, from a clean read-only clone.
atelier review ID --approve|--reject --criteria BINDING [--request N] [--note TEXT] [--head SHA] [--findings JSON]- Records a verdict on the task's current head, with
--notegiving the reason.--headnames the revision the verdict is for, and the server refuses one for any head but the current.--criterianames the binding of the acceptance criteria the verdict judged, asatelier showor the review claim gives it; the server refuses a verdict that names none, or criteria the task no longer has, and the reviewer must read them again.--requestnames the review request the reviewer claimed, which the verdict then answers alone.--findingsattaches a reviewer's structured findings. The rules say whose approval counts. atelier review-claim ID [--runner home:NAME]- A reviewer's runner claims the task's open review request and gets the part, its brief's inputs, the binding of the acceptance criteria the brief carries and the request's number, which the verdict names, and a read token for its fork.
atelier review-release ID [--note T]- A reviewer whose harness wrote no valid verdict lets the review request go, so another reviewer may take it.
atelier read-token ID- Reads a token for the task's own fork, with its head and base, for a job that clones it outside a task or a review.
atelier base-token ID- Reads a token for the repository the task is measured against: the plan's fork for a part, the baseline otherwise.
atelier integrated ID --part KEY --merge-commit SHA- The integrator reports a verified merge of one part onto the plan's branch; the server checks the commit against the branch before recording it.
atelier integration-failed ID --part KEY --reason TEXT [--kind conflict|checks]- The integrator reports a failed merge, which sends the part back to its builder for rework with the reason.
--kindsays the failure was the part's own, a merge conflict or failing checks, which charges its builder an attempt; without it the builder is charged nothing. atelier refreshed ID --main-head SHA [--merge-commit SHA]- The integrator reports a refresh: main's head, the one the refresh job names, merged into the plan's branch. The server checks the merge commit against the branch before recording it, and it becomes the commit later parts fork from and later integrations build on. Without
--merge-committhe branch already held main's head, which the server checks. atelier refresh-failed ID --main-head SHA --reason TEXT [--kind conflict|checks]- The integrator reports a refresh that conflicted or failed the plan's checks, after rolling the branch back. It is recorded on the plan with the reason and charges no part's builder; the tick does not try it again for that main head.
Owner
atelier accept ID [--head SHA] [--override-review REASON] [--note TEXT]- The project owner accepts the task at its current head;
--headnames that head, and any other is refused.--notekeeps the owner's word on the acceptance with it in the ledger. It is refused unless the gate is clear. When the change still lacks its independent review because no reviewer qualifies,--override-reviewoverrides that review and accepts: the reason is required, the override is recorded as an event of its own, never as a review, and the task page and the inbox show it with its reason. atelier merge ID [--head SHA [--approve [--note TEXT]] [--override-review REASON]] [--policy-changed-ok]- The project owner lands the accepted head in the registered checkout and publishes the merge to the baseline. With
--head, a submitted task is accepted at that exact revision first:--approverecords the owner's review, with--noteas its reason, which is not the independent review, and--override-reviewaccepts with the owner's override, asacceptdoes. Run again, it resumes an interrupted merge;--cancelends one. A plan whose branch would conflict with main is not accepted, and one accepted that conflicts at the merge is put back to building throughplan refresh, which takes main into its branch. atelier merge ID --cancel [--discard-local]- Ends an interrupted merge: the landing lease is released, so the task's owner can push again. An unpublished merge commit in the checkout is kept unless
--discard-localremoves it and returns the branch to where the merge began. atelier land ID [--reviewer H/M] [--no-review] [--wait] [--dry-run] [--release-lease] [--workflow [--checks local|container]]- The project owner lands one task whole; a plan is refused before the lease, since it lands with
atelier merge ID --head Hat the integration headplan showprints and takes main throughplan refresh. It takes the project's landing lease on the server, so two sessions never race main, then merges main into the task's workspace, stopping on conflicts and leaving them for the owner, naming the files. It regenerates the project's fixtures when the policy declares how (init --regenerate), pushes, runs the required checks and submits. It requests the independent review the gate needs through the review-request routes and waits for the verdict (up to 60 minutes, or ATELIER_LAND_REVIEW_TIMEOUT milliseconds), saying what the runners are busy with while the request is unclaimed, and, when no live runner offers the reviewer for the review job, that the request can never be claimed until one does, with the review by hand and the--reviewerthat asks a model a runner offers, then accepts and merges. A named--revieweris always asked, even where the gate needs no review, and a rejection stops the landing. Each step, its duration and the commits that came from main are recorded as land.* events, for the integration record. It refuses to start when the server's route level is lower than this CLI's, saying to deploy, and while another task's landing holds the lease, naming who holds it and since when, unless--waitqueues behind it: the server keeps the landings waiting for the lease in the order they queued and hands it to the first of them when it frees, so one landing cannot take it ahead of another that waited longer, however their polls land. While it waits the landing asks the server again on every poll, says whose landing it waits behind and which landings are queued ahead, and starts when its turn comes (three hours at most, or ATELIER_LAND_WAIT_TIMEOUT milliseconds), so several landings started at once run in turn; a landing that stops asking drops out of the queue once 15 minutes pass without an ask. The lease is renewed while the landing runs, released on SIGINT or SIGTERM, and treated as free by the server once 15 minutes pass without a renewal, which the next landing reports when it takes the lease over.--reviewernames the reviewer;--no-reviewleaves the task submitted;--waitqueues for the lease, in the order the landings queued;--dry-runprints the steps and the refusals without changing anything;--release-leasefrees the project's lease, saying which task held it since when.--workflowlands through a Cloudflare Workflow instead: the lease, the submission, the review wait and the acceptance run on the server as durable steps, each retried through transient failures (an Artifacts 503, a lost connection) and needing no token, while this command shows the Workflow's stage and does the steps that need Git with a working tree when the Workflow asks: merging main and pushing (only once the Workflow holds the lease), andatelier mergeonce it has accepted.--checkssays where the required checks run:local(the default) runs them on this machine in a clean clone of the pushed head before the head is reported, as the plain landing does, and the Workflow goes on only once the server has recorded every one passing, observed, at that head (failing ends the landing; no result within 30 minutes does too);containerhas the Workflow run them in a Cloudflare container, for a project whose suite finishes there. A conflict pauses the Workflow with the lease released and the files named; resolve and commit them, then run the same command again to resume. If the command stops (a closed laptop), the Workflow keeps its place: run it again to attach.--dry-runand--workflowtogether are refused. atelier abandon ID [--note TEXT] [--delivered-by tN]- Closes the task without merging it. The holder's write token is revoked; the history and evidence stay.
--notesays why.--delivered-byrecords that the merged task tN delivered it, for work another task already brought in. atelier defect ID --note TEXT [--found-in ID]- The project owner traces a defect to the revision the task was accepted at. Nothing about the task changes; the reliability record counts the defect against the model that built that revision and against each model that approved it.
--found-innames the task the defect was found or fixed in. atelier finding ID --head SHA --index N --verdict confirmed|refuted|fixed [--note TEXT]- The project owner records a verdict on one finding of a review: confirmed, that the finding was right and a fix followed; fixed, that it was right and is fixed; refuted, that it was wrong.
--headnames the review's revision and--indexthe finding's position in that review's findings, one based. The event is the record, and the reliability record counts the reviewer's findings confirmed and refuted, which measures its precision. atelier run-report --actor H/M --role build|review --outcome KIND [--project P] [--item ID] [--detail TEXT]- The project owner records a run that ended without a result the ledger saw, for a run outside the runner: an early stop, a permission stop, a duplicate design or an incomplete merge, beside stalled, timed-out and refused, which the runner reports itself. The reliability record counts it against the actor, and a review run counts as a review that never reached a verdict.
atelier served MODEL --recorded H/M --from TIME --to TIME [--item ID]... [--note T] [--apply]- The project owner records which model served events recorded under another, as when zcode served deepseek-flash while its events named glm-5.3. Each event recorded as
--recordedfrom--fromup to--to, on the tasks--itemnames or on every task, gets an annotation of its own, and the track record, the reliability record and the graph count it under the served model; the event itself never changes. Without--applyit lists the matches and records nothing.--notesays how the owner knows. atelier approve ACTION --head SHA [--note T] [--expires 24h]- The project owner approves one protected action, such as
deploy,install,paid-runorphotos-writeback, at one exact revision of the main line: the full SHA of a commit the baseline holds.atelier shipuses the approval once, at that revision only, and a later revision needs its own. It stands for 24 hours unless--expiresgives from1mto30d;--noterecords why. Any other kind must be one the project's ship files name. atelier approvals [--all]- Lists the approvals that stand, each with its kind, revision and expiry.
--alladds the used, withdrawn and expired ones. atelier approvals withdraw ID [--note T]- The project owner withdraws an approval no ship has used, so none can use it.
atelier ship [--dry-run] [--push]- Run by the project owner in the registered checkout, clean and at the baseline's head: composes the ship order from the project's ControlPlane ship policy and adapter, or from
docs/atelier/ship.json, and refuses before running anything when a protected step has no approval at that revision, naming the command that approves it. It then runs the steps in order and stops at the first that fails, recording each step's command, exit status, duration and redacted output tail on the ledger. It pushes only with--push, which needs no approval since ship is owner-only and runs at one exact revision, and never forces a push.--dry-runprints the steps and which approvals are present or missing, and runs nothing.
Plans
atelier plan "goal" [--scope GLOB]... [--planner H/M]- The project owner states a goal. Atelier creates the plan task and queues it as a plan job for the planner named, or else for the first model in the pool for research work that is not refused, not paid per token and may plan. A project has one active plan at a time. A runner that offers plan jobs takes it: the planner claims the plan task, reads its brief from the job-brief route and posts the plan document the harness wrote; by hand, a planner claims with
--runnerand runsplan post. atelier plan show ID [--json]- Prints a plan: its phase, the newest proposal with its hash, or once approved each part with its state, dependencies, scope, routing and attempts, the live item outside the plan a queued part waits on while the project's core files hold it, any live review request naming the reviewer asked and whether a runner claimed it, and saying, when no live runner offers that reviewer for the review job, that the request can never be claimed until one does, with the reroute that names another, then the part dispatches used, why it is blocked, the main head the branch last took against main's head now with any refresh in flight or failed, and the command for each decision waiting on the owner. Before approval it shows the routing an approval would fix now, its reviewers judged against the live runner offers the same way. It accepts a part's id too.
atelier plan approve ID --hash HASH [--allow-paid]- Approves the split, once, by the hash of its newest proposal; an older hash is refused. The routing of each part is fixed then, with the limits: 2 parts live at once, 3 attempts a part, 4 dispatches a part, 24 hours. A part that no model can build, or that no model of another family can review, refuses the approval; a reviewer counts only when a live runner offers it for the review job, and when no runner is live the pool stands, with the routing saying so.
--allow-paidlets models paid per token build and review. atelier plan revise ID --note TEXT- Before approval, sends the plan back to its planner with a note; its next proposal replaces the one before.
atelier plan reroute ID --to H/M- Names who builds an open part from now on, its attempts counted afresh; for a submitted part, or one blocked for want of an eligible reviewer, names its reviewer, in the pool or not, which must be of another family than every contributor; before approval, names another planner for the plan.
atelier plan retry ID- Counts an open part's attempts afresh, so its builder is asked again; before approval, asks the planner again.
atelier plan refresh ID [--resolve [--to H/M]]- Queues the plan's refresh job for the integrator, which merges main's head into the plan's branch, so later parts fork from it; parts wait for it before they are dispatched. The tick does this itself before it dispatches a part when main has moved, once per main head; this runs it again, as after a failed refresh. On a plan submitted or accepted, it first withdraws the submission and any acceptance and puts the plan back to building, and says so; the integrator submits it again once every part is integrated on a branch that holds main. It is refused before approval, once the plan is closed, while the plan's integrate or refresh job is queued or held, while a merge of the plan holds its landing lease, and when the branch already holds main's head. A refresh that conflicts adds a merge-main part to the plan, which a model builds: the runner merges main into the part's workspace and leaves the conflicts for it to resolve, and its integration puts main on the branch; no other part is dispatched until it is integrated.
--resolveadds that part for main's head now without trying a refresh first, built by--towhen named; it is refused while a refresh is queued, when the part for that head exists, while another merge-main part is not integrated, and when the branch already holds main's head. atelier plan stop ID [--note TEXT]- Closes the plan and every part not yet merged, revoking their write tokens. The history and evidence stay.
atelier plan post ID FILE- The holder of the plan task's claim, its planner, posts the plan document in FILE. An invalid one is refused with every error, and the planner gets one more attempt before the plan blocks.
Models
atelier models- Lists the model pool: each model's harness, where it runs, its family and what a runner last found.
atelier models add ID --harness H --where home|cloud [--provider P] [--endpoint URL] [--keychain NAME] [--alias A]... [--note TEXT]- Adds or replaces a pool entry. Atelier never stores a key:
--keychainnames the Keychain entry that holds it, and a request that carries a key is refused.--notekeeps a note with the entry. atelier models remove ID- Removes a model from the pool.
atelier dispatch ID [--to home|cloud|any] [--agent A] [--model M] [--note T] [--job merge-main [--head H]] [--overlap-ok]- Queues an open task for a kind of runner, and optionally an agent and model, instead of waiting for an agent to choose it; a held task is released and queued in the same step, keeping its workspace and commits. While the task's scope overlaps, within one of the project's core files (
init --core), the scope of a live item, the queue holds it and offers it to no runner until that item merges or is abandoned;atelier statusandatelier queuesay which item it waits on, and--overlap-oklets this dispatch through at once.--job merge-mainsends a task whose landing conflicted with main back to its builder: the runner merges main at the named head into its workspace (main's head as the baseline holds it, unless--headnames one) and leaves the conflicts for the builder to resolve and commit; thenatelier land IDagain. Project owner only. atelier undispatch ID- Takes the task out of the queue.
atelier queue- Lists everything waiting for a runner, across projects, oldest first, and for each dispatch the project's core files hold, the live item it waits on.
Projects
atelier projects rename OLD NEW- The project owner gives a project a new name on the server, and this machine's config entry moves to it. The ledger, the baseline repository and every fork stay where they are. The old name keeps working: the API serves it, old page links redirect, and tokens and workspaces that use it need no change. A name another project has or had, or one a removed project's ledger is kept under, is refused.
atelier projects remove NAME [--force]- Removes a project from the index and from this machine's config. The Artifacts repository and the ledger are kept. It is refused while work is live unless
--forceis given. atelier showcase set NAME [--named|--anonymous]- The project owner adds a project to the public showcase. Anonymous is the default: the project's card and its task stories carry a neutral label from the project's kind, never its name, a task title, a path, a commit message or an address.
--namedshows the project by name. Nothing is public until this is run. atelier showcase remove NAME- Takes the project off the public showcase. With no subcommand,
showcaselists what is shown and how. atelier init --name NAME --rename-local- Changes only this machine's local name for the registered checkout. Nothing on the server changes.
atelier adopt --project NAME [--as H/M]- Moves a ControlPlane project to Atelier as an ordinary task: claims it and, in its workspace, writes
bin/control-plane, inserts the textatelier guideprints into AGENTS.md and commits without pushing. It then lists what the finishing agent must settle.
Local
atelier gc [--project NAME] [--dry-run | --apply]- Previews the local workspace and check clones that are safe to remove;
--applyremoves them. It never touches Artifacts or the project checkout. atelier runner --name home:NAME [--once] [--config PATH] [--integrate]- The home runner: polls the queue every 30 seconds, claims one eligible task and runs its configured harness in the claimed workspace. Each opencode run gets a data folder of its own beside the workspace, removed when the run ends, because opencode runs that share one deadlock on its database. When the harness commits, the runner runs
finish.--integrateruns no harness: it offers only the integrate and refresh jobs and merges each part onto its plan's branch as atelier/integrator.--oncehandles at most one task. atelier runner --discover [--name home:NAME] [--probe] [--dry-run] [--config PATH]- Reports which model each home harness actually served, from the records the harness keeps, and sends the result to the server as each model's status.
--probealso sends one short prompt to each model that can be probed;--dry-runreports nothing. atelier runner --usage [--name home:NAME] [--dry-run] [--config PATH]- Reports how much of each tool's allowance this machine has used: Codex's 5-hour and weekly windows, the requests and tokens zcode and opencode recorded by served model over the last 5 hours, 24 hours and 7 days (with cost, for opencode), and the DeepSeek balance when the runner config names its Keychain entry. After the tools' own figures it prints what the server read of the AI Gateway: each model's calls, tokens, cost and durations, and the calls per task the runners' cf-aig-metadata tags name; then each model's speed over the last 14 days (median build, review and claim-to-merge times with n, and the share of runs that stalled). Each tool's summary goes to the server under the runner's name, for the Usage page and its alerts;
--dry-runreports nothing. It runs once, not as part of the runner loop. Claude's plan limits and Gemini's spend have no record on the machine and are not reported.
Ops
atelier ops COMMAND [ARGS...]- Hands everything after
opsto the privateatelier-opstoolkit, named byATELIER_OPSor found onPATH. Without one it says so and exits 2.
Docs
atelier guide [--role build|review|plan|orchestrate]- Prints the instructions an agent needs, to paste into a project's AGENTS.md or CLAUDE.md.
--roleprints the instructions for one role alone, from a project's.atelier/prompts/ROLE.mdwhen it has one.atelier adoptinserts the plain guide.
Tokens
atelier token issue --as H/M [--project P]... [--days N] [--label TEXT]- The project owner issues a token bound to one actor and shown once. It expires in 30 days unless
--days(1 to 365) says otherwise, and covers the named projects or all of them. atelier token ls- Lists token records without the tokens or their hashes.
atelier token revoke ID- Revokes a token; later API requests with it are refused. Git credentials already issued keep their own lifetime.
Agent instructions
The text atelier guide prints
## Working through Atelier Several agents may work on this project at once. Each piece of work is a task with exactly one owner. Never edit the project checkout directly. 1. `atelier start ID --project NAME --as HARNESS/MODEL` claims the task and prints its workspace, title, brief, acceptance criteria, scope and note. Work only there; a change that fails a criterion is rejected. 2. Commit your changes, then run `atelier done "summary"` in that workspace. It pushes, runs required checks and submits only after they pass. Relay its final line to the owner. The project owner accepts and merges. 3. `atelier inbox` and `atelier show ID` print briefs you can relay to the owner. 4. `atelier ls --project NAME` lists tasks. Ask the owner to create one if needed. 5. Individual steps remain available: `atelier claim`, `atelier push`, `atelier check` and `atelier submit --summary "summary"`. `atelier report "…"` records a Reported claim, never an Observed pass. 6. If you can't finish, `atelier handoff ID --to HARNESS/MODEL --note "…"` or `atelier release ID`. Your write token is revoked either way. Waiting on something only the owner can settle: `atelier block ID "what"`. The owner sees the reason in the inbox and runs `atelier unblock ID`. 7. Reviewing someone else's task: `atelier diff ID`, then `atelier review ID --approve|--reject --note "…"`. Changes to protected paths need approval from a model of another family than every agent that worked on the task. 8. `atelier update` rebases your workspace onto whatever has merged since. For each session the project owner runs in the registered checkout: 1. Start a session with `atelier unwrap --project NAME`; relay its short paragraph. 2. End with `atelier wrap "summary" --next "what is next"` in the registered checkout. It runs the registered checks, commits, and always updates Atelier's own copy of the project, the baseline. A failing check stops it before anything is committed: fix the check, or add `--allow-failing` to commit anyway and record in the note which checks failed. It never pushes the project's own remotes unless `--push` is given; add `--push` only with the owner's approval for that session. It never deploys or publishes a release. 3. Before the session closes, file a defect in Atelier or project tooling as a task in its project: atelier new "…" --project NAME. For Atelier use --project atelier. File a lesson worth keeping the same way with a title starting "Lesson: ". Use repeatable `--found TEXT` on wrap to file tasks in this project. A protected action (a deploy, a device install, a paid model run or a Photos writeback) runs only with the project owner's approval for one exact revision of the main line, given with `atelier approve KIND --head SHA` and used once. `atelier ship`, run in the registered checkout when the owner asks, runs the project's ship order, uses those approvals and records every step; its `--push` pushes the branch to the project's own remotes and needs no approval, being the owner's own act at that exact revision. Never approve an action for the owner, and never run one without the owner's approval at that revision. Session notes keep metadata only, never prompts, transcripts or file contents. Material for the owner to copy is one complete fenced block with a language tag: bash for a command the owner runs, text for prose, a brief or an envelope. Never leave prose the owner must select by hand. Save a copy under ~/Documents/ai-project-data/<project>/, never the portfolio root.