Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Design Turns

A plan turn answers in a reply. Some plans should outlive the conversation: a design document or an RFC, kept in the repository as the record of what was decided and why. A design turn is a plan turn that may write that document, and nothing else.

The document is your project's, not heph's. It lives where your project keeps such documents, in the form your project uses, and is reviewed and committed like code. Heph is told only where those documents live:

# .heph/config.toml
[design]
paths = ["docs/designs/**/*.md"]

What a design looks like is your convention; teach it the way you teach any convention, in AGENTS.md or a skill.

The workflow

/design how should we rate-limit the API?
  ... several turns of discussion; ask it to write the design ...
  ... review the document hunk by hunk ...
/commit
/code --clear --implement

Three commands carry a design from a conversation to a build.

/design

/design                  enter design mode, sticky until /code
/design <prompt>         enter it and send the prompt as its first turn
/design --tools local    the same, with a named tool set
heph --design            start a session in it
heph exec --design '<prompt>'

A design turn reads with a tool set, research unless you name another, as a plan turn does. It also has edit, create, search_replace, and markdown_format, confined to [design] paths. Before a call writes outside those paths, heph pauses for its own code-mode confirmation, as it does for calls to absent execution tools. request_code lets the model request the same pause immediately when you explicitly ask for work needing code-mode tools or writes outside those paths. Press y to switch modes and resume the same turn through normal permissions; n or Esc keeps design mode and stops the turn. Nothing is written before confirmation. In non-interactive heph exec, the turn stops without switching. shell and everything else that runs are absent until the mode changes. The model is told:

This is a design turn. Your writes are confined to docs/designs/**/*.md, and you have no execution tools: read and reason, answer questions, clarify scope, and when the developer asks, write the design there in the project's own form. Do not attempt or announce an edit outside those paths.

The same scope guardrails as plan turns apply: a general question or a real session ID does not ask for implementation or live inspection. The model may clarify whether you want a specific investigation using code-mode tools, but that question does not replace heph's mode-switch confirmation.

With no [design] paths, /design refuses and names the line to add.

A design turn ends like any turn that changed something: the gates run, so a gate that checks your documents' formatting checks the design, and the review shows the document hunk by hunk. The review is where you edit the design before it is built; a rejected hunk with a comment goes back to the model as any rejection does.

The status bar shows design while the mode is on. /design from plan mode keeps the conversation, so a plan that turns out to deserve a document is one command from being one.

Review and commit

Commit the design with /commit before any code is written. The commit is the approval: nothing builds a design that has accepted changes /commit has not published. A design that is decided and never built is still a decision, and the repository says so.

/code --clear --implement

/code                                    leave the mode; context kept
/code --clear                            leave it and start the model fresh
/code <prompt>                           leave it and send the prompt
/code --implement [<path>...]            leave it and start the build
/code --clear --implement [<path>...]    the handoff
/code --clear --implement docs/designs/rate-limiting.md start with the schema
heph exec --implement docs/designs/rate-limiting.md

--clear is /clear and the mode change in one step: the next turn is sent nothing of the earlier ones, and live token/cache counters restart. Persisted spend remains. If the clear is refused, the mode does not change either.

--implement builds the first prompt and sends it:

  • Which design. The paths you give. With none, every file under [design] paths that a design turn of this conversation changed and that no earlier --implement named. A design written in another conversation is named by path. Words after the paths are added to the end of the prompt.

  • What the model is sent. Which documents to build and the commit they were read from, then each document's text in full. The text is in the prompt, not read with a tool, so it stays in the model's context for the whole build. When this conversation wrote the design, the model is told the discussion is in earlier turns that search_history can find, to look once for a question the document leaves open, and not to reopen what the document decided.

  • Where it runs. /code returns to the class the session started as, so the build runs on the coding tier.

--implement refuses while a review is waiting, while a design path has accepted changes not yet committed (the design is not committed; /commit first), and when there is no design to build.

The pair is the handoff. Without --clear, the build carries the whole design conversation, which a short conversation can afford; the status bar's cost will tell you.

heph exec --implement <path> builds in a new conversation of its own, named build- and the document's name, so it never touches the conversation you were working in. It starts from --base or [git] base_branch, so the design must be committed on that branch; if it was committed on the design conversation's own branch, pass that branch:

heph exec --implement docs/designs/rate-limiting.md --base heph/rate-limiting

Nothing is created if the document is not there, and heph --continue build-rate-limiting opens the new conversation afterwards.

To build in the conversation that wrote the design instead, as /code --clear --implement does, name it:

heph exec --continue rate-limiting --implement docs/designs/rate-limiting.md

Its context is cleared first, and stderr says so.

Acceptance checks

Configure design checks with modes = ["design"] on a [[gates]] entry, code test suites with modes = ["code"], and shared checks without modes. Both mode and path restrictions must match. Existing unscoped gates keep their behavior; design mode alone does not skip a test suite. At /commit, accepted unpublished code still selects code checks even after a switch to design. Mixed publications run both sets, each eligible entry once against the combined candidate. See Acceptance gates for examples.

Designing on one model, building on another

Plan and design turns run on the tier whose roles include design, which in the built-in profiles is the same frontier model that codes. To design on a stronger model and build on the tier below, give design a tier of its own:

[profiles.handoff]

[profiles.handoff.tiers.architect]
models = ["anthropic/claude-fable-5-1"]
roles = ["design"]
effort = "max"

[profiles.handoff.tiers.frontier]
models = ["anthropic/claude-opus-5"]
roles = ["coding", "review"]
heph --profile handoff

--review turns stay on the review role; move it to the architect's tier if you want the stronger model to review too (Tiers and Profiles).

When the design is wrong

A small correction the builder can make itself: the design paths are in its catalog like any other, so it amends the document in the same turn as the code, and the review shows both. A larger one goes back to the architect: /design, say what the builder found, review, /commit, then /code --clear --implement again. The revising turn is a design turn after the last handoff, so the revised document is found without naming it.

/diff marks design turns [design] and builds [builds <path> at <commit>], and /diff <path> shows the turns that built a design and what they changed.