Concepts
Tiller holds the structure, the gates, and the state of a software project. The agent does the reasoning. The human approves at the gates. Everything below is that one sentence, unpacked.
The tree
Section titled “The tree”Work is a single hierarchy: epics, then features, then tasks. Three shelves of leaf work sit beside the tree rather than inside it: bugs, chores, and tweaks. A shelf is a flat, ordered list of one kind of leaf work, with no parents or children (more on those below). Each grain carries more detail than the one above it. An epic is a narrative. A feature is a narrative plus a specification and an acceptance contract. A task carries the implementation detail. A pull request represents exactly one node, a task by default, or the feature or epic when the review grain moves review upward. Every node has a stable id (E-mu0v91, F-dv5ppv, T-h389ih) and a human key path (foundation, foundation/app-scaffold, foundation/app-scaffold/wire-the-build). The id survives renames; the key is how people talk about it.
Every node is two files. The .md is prose and it’s yours: intent, specification, acceptance criteria. The .yml is state and it’s tiller’s: status, owner, gate results, revisions. That split is what lets the CLI churn state all day without touching a word a human wrote, and it’s what keeps two people’s work from colliding in a merge.
Initial decomposition proposes epic and feature narratives through the full known initial scope. Features get detailed specifications, acceptance contracts, and tasks just in time, normally one named feature at a time rather than the entire future tree.
An epic is a bounded delivery increment, not the permanent home of a subsystem. Recommend the progression from documented consumer outcomes, including operators, developers, and API consumers, and interleave product work with the small platform increments it genuinely needs. Related capabilities can recur in later epics. Design shared machinery with later needs in mind without implementing all of them before its first consumer.
Features express honestly acceptable outcomes; their own contracts must be satisfiable at that boundary. Keep one unfinished feature when no sensible split exists rather than presenting incomplete behavior as complete. Tasks may be technical implementation units. True execution prerequisites belong in depends_on; preferred sibling sequence belongs in tiller order. Eventual architectural integration alone does not establish a prerequisite, and zero cross-epic edges is valid for independent work.
The lifecycle and its gates
Section titled “The lifecycle and its gates”Each grain moves through a short list of states, and the states are the queue. draft is the backlog, specced and ready are on deck, active and in_progress are in motion, and done is done. An agent can drive any node to the edge of done. But three crossings belong to the human, and tiller marks them as such on every surface:
- The epic gate,
tiller approve epic. The human approves the shape of the tree, not the details. - The plan gate,
tiller approve feature. The human approves a feature’s specification, its acceptance contract, and its tasks in one act. The tasks ride that gate fromproposedtoready, and each one’s spec gets pinned as its accepted basis, the exact revision of the prose the human approved. - The merge. Every task reaches
in_reviewthroughtiller submit task. At task grain, the task owns the PR. At feature or epic grain, the task records branch-and-head provenance and rides the reviewed node’s shared PR. Only a human merge crosses the work todone, and tiller learns of it by watching git (tiller sync), never by being told.
Everything above a task still completes by rollup. A feature is done when its tasks are done and its own required gates have run green; an epic is done when its features are. At a coarse review grain, one feature or epic merge can cross several riding tasks together, and no feature or epic gains a separate in_review lifecycle state.
Completion is history, not a permanent ban on continuation. New work serving the same bounded outcome can be added beneath a done epic or feature; a distinct outcome or delivery phase warrants a new increment, even in the same subsystem. Additions keep their ordinary specification and approval gates. The addition itself does not immediately change the parent’s stored status: normal sync reopens the rollup, clears current parent completion/review fields, and stales feature gates as appropriate. Completed tasks and terminal feature/task prose remain accepted history. Cancelled or archived ancestors are not executable continuation targets.
Review grain
Section titled “Review grain”Review grain decides where the human reviews work, without changing how tasks get planned, claimed, checked, or recorded. The default is task: one PR per task. At feature grain every task still works on its own branch, the agent merges each submitted task into a shared feature review branch, and one PR opens once every live task in the feature reaches in_review or done. epic repeats that shape across the features riding one shared epic branch. Bugs, chores, and tweaks ignore the setting; each always owns its own PR.
| Resolved grain | PR represents | Execute stops when |
|---|---|---|
task |
one task | that task reaches in_review with its own PR or local review reference, and its state commits are published when a remote exists |
feature |
one feature | every live task is in_review or done, feature gates are green, and the feature review and state commits are recorded and published |
epic |
one epic | every riding feature’s live tasks are in_review or done, its gates are green, independent overrides are done, and the epic review and state commits are recorded and published |
Green checks are intermediate. The agent commits and pushes, creates or reuses the PR, records its number with tiller submit, and pushes the submission state. Tiller records these facts but never pushes or opens a PR itself. A project with no remote records a local review reference instead.
The setting can live at three homes, and the most specific explicit value wins:
tiller configure project --review-grain featuretiller configure epic foundation --review-grain epictiller configure feature foundation/auth --review-grain taskA feature can only say task or feature; epic participation comes from inheritance. Choose the grain before work starts: Tiller refuses a change that would reinterpret submitted or started work. The review grain contract carries branch assembly, every refusal, and recovery of an aggregate review that merged before it was recorded.
Who does what
Section titled “Who does what”Three acts, three actors, and tiller keeps them apart on purpose. The agent reasons: it reads the inputs and the tree, writes the prose, does the work, runs the gates, and proposes. Tiller records: every conclusion lands through a command into the state files and the event stream, illegal moves get refused, and the next move gets named. When an agent skill finishes a run, tiller readout <skill> prints its readout, a fixed summary of what happened, what was verified, and what needs the human, which the agent reproduces verbatim. The human approves: the tree, each plan, the review gates, the answers to questions, and the merge.
Tiller can’t make an agent follow the process and doesn’t pretend to. On one machine the agent and the human share a filesystem, a shell, and git credentials, so any check that tried to stop the agent from running a human-only verb would be theater. The human-only gates are guidance the skills and orientation.md ask the agent to honor. The one boundary that actually holds is the merge, and only a human performs it. The developer drives, and the developer answers for the result.
tiller status <noun> <node> names the legal next moves from any state, with nothing executed. A command that refuses says why and what to do about it. Exit 1 is a business answer (a red gate, an illegal move), 2 a bad call, 3 a broken environment.
Contributors and claims
Section titled “Contributors and claims”Identity lives in the repo. A committed roster in .tiller/tiller.yml says who may hold work, and tiller add contributor and tiller remove contributor, deliberate human acts, maintain it. A gitignored .tiller/identity.yml, written by tiller join --as <id>, says who this checkout is. There’s no global config and no machine default; a fresh clone carries the roster and runs its own join.
New tasks start unclaimed, no matter who creates or approves them. tiller claim task <key> reserves one task for you, and bugs, chores, and tweaks have the same claim verbs. Before the work starts, tiller release returns your reservation to the unclaimed pool, and tiller reassign, a human decision, moves it to someone else. Taking over another person’s reservation with tiller claim needs --from naming its current holder and an explicit human handoff. Switching your checkout’s identity to grab work is never the way to do it.
The first start fixes the owner for good. After that, nothing reopens ownership: not resuming, checks, review, cancellation, or completion. A task that is cancelled before it ever starts keeps the owner it had, too. Features and epics have no owner and no claim, and a claim on a task never spreads to its parent or siblings.
The first task start in a ready feature makes the feature active and records the branch the task works on, plus the shared review branch when the review grain calls for one. Dependencies, base branches, open questions, retired ancestors, and review-round guards still apply at start. When the human says a feature can go ahead despite an open question, tiller approve feature <ref> --assume-question <Q-id> --reason <text> records that assumption for the feature only. It doesn’t move the feature’s state, and its tasks don’t silently inherit it. Recorded identity is workflow discipline, not authentication: it says who directed an action, and judgment verbs keep their own rules about which ones need a human.
A feature or epic lists its contributors instead of an owner. A contributor is anyone who owns a started task beneath it, including tasks that are done, cancelled, or transferred, and tasks under a cancelled feature. Holding an unstarted reservation, reviewing, creating work, or owning an attached bug, chore, or tweak doesn’t make someone a contributor. tiller ls features --contributor <id> finds where a person has contributed, and tiller ls tasks --owner <id> finds what is assigned to them. A person’s current work is every unfinished assignment they hold, whether it is proposed, blocked, checked, or in review, not everything under a feature they once worked on. Shared closeout work, such as the final feature check after the last task lands, shows up once per feature or epic rather than once per contributor. When several people share one feature or epic PR, agree among yourselves which one updates it at a time. A suggested route is a suggestion, not permission.
Exceptional transfer
Section titled “Exceptional transfer”Handing started, unfinished work to someone else is a human decision. The agent runs tiller transfer task|bug|chore|tweak <ref> --to <contributor-id> --reason <text> only on an explicit instruction that names the work and the recipient. Before start, use reassign instead.
Transfer doesn’t relabel the original. It cancels the original and keeps its prose, attribution, branch, review, and evidence as history. Then it creates a replacement of the same kind with a new ID and key, claimed by the recipient, approved and ready but not started, with a fresh accepted basis and links in both directions between the two. The replacement inherits no branch, review, passing checks, attestations, or evidence. The recipient starts it with the command transfer prints, and carries the implementation over with ordinary Git.
The approved scope has to be unchanged. If the work needs a different specification, that goes through human review or an amendment, and there is no flag to skip it. Transfer refuses when the original already belongs to the recipient, when the work is already finished, or when a started, unfinished task depends on it. Unstarted dependents are pointed at the replacement, links to finished work stay as history, and questions, pauses, attachments, and carrier links keep working.
Tiller doesn’t touch Git refs or the code host. At task, bug, chore, or tweak review grain, close the old PR without merging it and open a new one. At feature or epic grain, keep the unmerged shared PR, update it with the replacement, and rerun the affected checks and acceptance. Commits and approvals already on that PR don’t disappear. If the original’s review has already merged, run tiller sync and handle the rest as forward work instead.
Gates and evidence
Section titled “Gates and evidence”Required gates are build, tests, and evals. They’re command-backed, configured in tiller.yml, and they block done. Optional review gates (code, security, performance, accessibility) are attestation-backed and non-blocking, visible encouragement rather than enforcement. tiller check runs the required gates for a node and records the result on it, with the revision it ran against. tiller eval runs the acceptance contract, and tiller attest records a human’s review. A gate result goes stale when the thing it verified moves, so last week’s green can’t quietly stand in for this week’s.
Corrections, drift and amendments
Section titled “Corrections, drift and amendments”Approval creates an accepted basis and structural history. It doesn’t freeze cosmetic titles, epic narrative, additive child work, soft order, or same-scope prose on a non-terminal feature or task. The route depends on what the correction changes:
| Route | Use it for | What happens next |
|---|---|---|
| Direct | A display title at any state, approved epic narrative, one more task under an approved feature, soft order, or a dependency edge before affected work starts | Run the mapped command or edit human-owned epic.md. An additive task gets its own task approval; the other direct changes need no new gate. |
| Refresh | Same-scope accepted prose on a non-terminal feature or task | Edit the Markdown, review the active_basis drift, then a human runs approve --refresh-basis. State does not move; the accepted bytes do. A wrong fact found while executing a task is instead a departure recorded in its commit and review, with task.md unedited. |
| Return and reapprove | A ready, unstarted feature or task plan whose original approval should be replayed | return moves it back across the pre-work gate, the plan is revised, and the ordinary approval happens again. |
| Amend | Genuine replacement, cancellation, or a supported structural batch | Stage supported operations with preconditions and stop for amendment approval. Done or cancelled feature and task prose stays historical; corrections move forward through additive or replacement work with supersession where appropriate. |
Amendment cannot link, unlink, or order. revise re-pins non-terminal prose, not dependencies; it does not unlock started work. An in-place hard-edge edit on unchanged started work remains unsupported, even where a refusal hints at amendment. A genuine replacement can carry prerequisites on fresh eligible work, never a replacement manufactured just to evade a lock. A fresh task under an active feature can still receive legal sibling prerequisites.
An unchanged, unstarted feature can move to another epic through a reviewed move-feature amendment that keeps its identity, and features from different epics may interleave when their real prerequisites allow it. How skills route correction feedback has the eligibility rules for a move and what an epic ordering cycle means.
An amendment may stage an epic and then its features in one batch. A new feature’s tasks follow materialization and ordinary specification. Approval appends new epics to root soft order, not to whatever position the narrative suggests; intended placement needs a separate explicit tiller order, whose supplied sibling list replaces the prior list and may be partial. Post-approval hard links remain legal only while the dependent is eligible. A planning request authorizes the proposal, not its approval or an unsolicited broader replan.
# direct display correction, at any statetiller rename feature foundation/app-scaffold --title "Application scaffold"
# direct additive work under an approved feature, with its own gatetiller add task foundation/app-scaffold/document-setup --title "Document local setup"tiller approve task foundation/app-scaffold/document-setup
# accept corrected same-scope prose without moving statetiller approve feature foundation/app-scaffold --refresh-basis
# replay a ready plan's approval before work startstiller return task foundation/app-scaffold/document-setup --reason "revise the setup contract"
# a post-start structural correction is reviewed historytiller add amendment app-scaffold-reshape --title "Reshape application setup"Before approval, prose feedback re-enters the proposal seam. decompose can rename a draft, task-free feature’s key and move it between draft epics, record eligible hard-edge corrections, or remove unwanted proposal nodes before returning to the epic gate. specify revises feature plans and proposed tasks at the feature gate. Unchanged feature relocation outside the direct rename window, including a specced plan, uses the reviewed move route, not cancellation and recreation. tiller remove is permanent proposal deletion, not cancellation, and it accepts only a proposed task, a task-free draft feature, or a task-free draft epic subtree.
Approving a feature plan pins its spec and contract, and each task’s spec, as accepted_against revisions. Edit one afterwards and tiller reports active_basis, and start, check, and submit refuse until a human follows the refresh, return, or amendment route above. tiller drift sweeps the other markers too: a done node whose spec or code surface no longer matches what was verified (stale_spec), a plan made under an assumption whose answer has since arrived (answered_question), or a recorded surface or eval reference that no longer exists. Detection is tiller’s, the proposed fix is the agent’s through mend-drift, and approval is the human’s.
tiller intake starts the amendment path from an external review or field report. It lands the document under .tiller/feedback/ and opens the proposed amendment it implies. The agent still classifies each finding first, so lightweight corrections stay direct and only the structural casualties enter the batch.
Bugs, chores, and tweaks
Section titled “Bugs, chores, and tweaks”Choose a Bug for a defect: observed behavior violates an agreed expectation. Choose a Chore for housekeeping without code side effects, such as documentation or administrative upkeep. Choose a Tweak for a minor adjustment that may change code. Choose a Task under a feature for substantive planned work. These are choice guidelines, not file-diff restrictions: Tiller does not enforce a no-code rule for Chores.
For example, changing a completed button from “Save” to “Save changes” to improve the wording is a Tweak, even when the label lives in application code. If the button text violates its agreed requirement, record a Bug instead. A new button or a broader interaction redesign belongs in planned Task work.
Keep changes forward-only. Never reopen or rewrite done work to express a new request. Add a new Bug, Chore, Tweak, or Task with attachment or source context as appropriate; the completed record stays history. Adding planned descendants may recompute feature and epic rollups, but it does not reopen merge-backed done execution nodes.
Bugs, Chores, and Tweaks are leaf work nodes beside the tree, at .tiller/bugs/<key>/, .tiller/chores/<key>/, and .tiller/tweaks/<key>/. None has parents or children. Bug contracts describe reproduction, expected and actual behavior, and fixed-when. Chore and Tweak contracts describe what, why, and done-when. A Tweak uses tweak.md, tweak.yml, a canonical tweaks/<key> address, and a TW- ID.
Under the surface bugs, chores, and tweaks carry the task’s own lifecycle: proposed (captured, awaiting triage), ready (triaged by a human’s approval), in_progress, check, in_review, done. Each carries its own branch and its own PR, so a shelf node reaches done the way a task does. A human merges, tiller sync observes it, and nobody marks it by hand.
attached_to records where a bug, chore, or tweak was found (an epic, feature, or task id) and it’s provenance only, reading context for the agent, never a parent and never a gate. resolved_by is a different pointer, the tree work whose merge actually fixes the shelf node, set with tiller resolve. A resolved node reads the derived phase carried. It keeps its own stored state, drops out of the queue, and moves with its carrier, crossing to done with done_basis: carried in the same run that records the carrier’s own done.
capture is the agent skill for this seam. Given an investigation or a developer’s description, it writes one complete proposed contract, with source, attachment, and shelf dependencies where they apply, commits it, and stops. It never approves, claims, starts, resolves, or cancels the node it just wrote. Triage stays a human act. tiller approve bug, tiller approve chore, or tiller approve tweak is what moves a captured contract from proposed to ready, the same way approve feature is the plan gate for a feature.
Once claimed, a bug, chore, or tweak ranks like any other owned work. The reader’s own ready or in-progress tasks come first, then their owned bugs, chores, and tweaks in shelf order. An unclaimed bug, chore, or tweak is never a ranked next move, and neither is a carried one, since its motion belongs to its carrier. The console’s Fix lens is the board for all of it, six columns in task vocabulary, Proposed through Closed.
tiller add bug blank-on-reload --title "Form blanks on reload" --attach foundation/app-scaffoldtiller add tweak button-text --title "Clarify save button text" --attach foundation/app-scaffold# Complete .tiller/tweaks/button-text/tweak.md, then await human triage.tiller approve bug blank-on-reloadtiller claim bug blank-on-reloadtiller start bug blank-on-reloadtiller check bug blank-on-reloadtiller submit bug blank-on-reload --pr 51# ... a human reviews and merges the PR ...tiller syncExisting-code baseline
Section titled “Existing-code baseline”A brownfield or legacy-migration project starts from code that predates Tiller, so routing sends
the agent to derive-baseline first: it writes as-is design docs for the existing code and records
what each one describes. A human confirms each doc with tiller approve design, and ordinary
decomposition and work routing resume once one doc is confirmed. After that, drift watches the
confirmed docs against the code they describe, and mend-drift proposes the prose repair. The
skills page covers what the skill does, and the
artifact schema defines the ledger.
Managed-project independence
Section titled “Managed-project independence”Tiller manages the development workflow, not the project’s ability to run. Setup, build, tests, CI, packaging, deployment, runtime, and merge eligibility must work without Tiller installed, access to its releases, or .tiller/ operational or state-validation inputs. This extends the same independence the harness has to the managed project. Even optional Tiller CI jobs are out of bounds.
Local Tiller may run an independently runnable command such as bin/ci and record its result, but bin/ci must not call Tiller. Planning and evidence can stay committed in .tiller/ without becoming application or CI gate inputs. Planning-only CI uses ordinary repository tooling and runs full project checks whenever classification is uncertain, never a blanket planning-path skip or replacement Tiller validation.
Tiller’s own implementation, tests, releases, and disposable verification are exempt. The distribution contract owns the detailed boundary and conservative planning-only CI pattern.
The surfaces
Section titled “The surfaces”Tiller is one static binary with the console’s assets and the skill text embedded, so the CLI, the console, the generated orientation, and the skills always agree with each other. It reads and writes .tiller/ in your repository, under git, next to the code. A coding agent reaches it three ways that are really one: the CLI, the skills served by tiller guide, and the committed .tiller/orientation.md. tiller join wires a harness by writing files it already watches (a managed block in AGENTS.md, a redirect in CLAUDE.md, thin skill shims), and the dependency arrow points the safe way. The harness never depends on tiller. Remove tiller and the harness doesn’t notice.
The console, tiller serve, is a small set of lenses over that same tree: Home (the desk, what needs you and what’s in flight), Explore (browse, filter, search, and a map of the whole project with its dependency arcs), Build (the board), Fix (the shelf board), Report (numbers and charts on how the project is going over time), History (what changed since you last looked), and the node page each of those opens into. The console has the full tour.
Getting a project onto tiller
Section titled “Getting a project onto tiller”Install once per machine, init once per repository, add contributor once per person, join once per checkout (each Git worktree included), then hand the repository to your agent to decompose and approve the tree it proposes. The Quickstart walks it with real output.
The diagram below is the greenfield path. Brownfield and legacy-migration insert derive-baseline
and human confirmation after join and before ordinary decomposition; see
Existing-code baseline.
After onboarding, tiller upgrade keeps the binary and the current checkout’s schema and generated
guidance current, and tiller upgrade --project-only maintains a checkout offline with the running
binary. join selects identity; it is not routine maintenance. The
Quickstart has the commands.
Where things live
Section titled “Where things live”.tiller/ tiller.yml project, contributors roster, gates, schema version orientation.md generated; the agent's front door (committed, do not hand-edit) identity.yml who this checkout is (gitignored) local.yml your own preferences for this checkout (optional, gitignored) design/ your input documents feedback/ documents landed by tiller intake amendments/ reviewed, recorded changes to the plan decisions/ open questions and architecture decision records reviews/ code-review files written by the code-review skill events/YYYY/MM/DD/ one immutable event per file epics/<key>/ epic.md epic.yml features/<key>/ feature.md feature.eval.md feature.yml tasks/<key>/ task.md task.yml bugs/<key>/ bug.md bug.yml chores/<key>/ chore.md chore.yml tweaks/<key>/ tweak.md tweak.ymlThe design documents under Design carry every field, state, and rule in full. This page is the shape of it.
Glossary
Section titled “Glossary”- Accepted basis: the revision of a node’s prose a human approved, pinned at the gate; an edit afterward is drift.
- Amendment: a reviewed batch of structural changes to approved work, applied only on human approval.
- Attestation: a human’s recorded review on an optional review gate, through
tiller attest. - Bug: shelf work for a defect, where observed behavior violates an agreed expectation.
- Carried: a shelf node resolved by tree work; it reaches done when its carrier does.
- Chore: shelf work for housekeeping, such as documentation or administrative upkeep.
- Claim: a reservation of one ready task or shelf node; the first start fixes its owner.
- Contributor: a person on the committed roster; on a feature or epic, an owner of one of its started tasks.
- Drift: a recorded basis, surface, or assumption that no longer matches the files;
tiller driftlists it. - Epic: a bounded delivery increment, written as a narrative, approved at the epic gate.
- Feature: an acceptable outcome under an epic, with a specification and an acceptance contract.
- Gate: a check recorded on a node; required gates block done, review gates do not.
- Orientation: the generated
.tiller/orientation.md, the first page an agent reads. - Question: an open decision recorded as a node, which can hold the work it names.
- Readout: the fixed summary
tiller readout <skill>prints at the end of an agent skill’s run. - Review grain: where the PR sits for tree work: the task (default), the feature, or the epic.
- Rollup: how features and epics reach done, from their children’s done plus their own gates.
- Shelf: a flat, ordered list of one kind of leaf work beside the tree: bugs, chores, or tweaks.
- Skill: guidance for one agent seam, served by
tiller guide <skill>. - Sync:
tiller sync, which observes merges in git and records the done crossings they imply. - Task: the unit of implementation under a feature, worked on its own branch.
- Tweak: shelf work for a minor adjustment that may change code.