Your First Turn
This chapter walks one change from prompt to applied file. Everything in it is what you saw on the screen when you tried it; the chapters after explain each piece.
Pick a project with a test suite. From its root:
heph
The screen has three parts: the conversation on top, an input line in the middle, a status bar at the bottom.
message ─────────────────────────────────────────────────────────────────────
>
──────────────────────────────────────────────────────────────────────────────
main | code | 0 tok | $0.00 | opus-5
The conversation starts as <unnamed> and gets a prompt-derived name as soon as
you submit your first prompt. A background title may improve it, but failure
keeps the local name. Each plain heph creates a fresh UUID; heph --continue
resumes the latest branch conversation. The current mode (code, plan, or
design) always appears in muted gray after the conversation and branch.
opus-5 is the model that will answer, from the coding tier.
Ask for something small
Type a prompt and press Enter:
> add a pow(base: i64, exp: u32) -> i64 function to src/lib.rs with one test
Your prompt appears in the conversation under You:, and the status bar changes
to working. The model reads what it needs, silently: the tools that only read
(view, grep, ls, and the rest) run without a word. When it edits, you see
the edit happen:
Adding `pow` after `mul` with the exact signature you gave, plus one test.
ok edit src/lib.rs
The sentence above the edit is the model's rationale. Heph asks the model to state what it is changing and why before every write, and keeps that sentence with the change. You will see it again in review.
A prompt to approve
If the model wants to run a command, it has to ask, because a command reaches outside the private copy heph gave it:
┌ permission ─────────────────────────────────────────────────────────────────┐
│exec in worktree of ref main (mirrors /home/you/project) │
│ │
│cargo test --lib auth │
│ │
│y this call only │
│a this session: exec(cargo) args(*) │
│ = any exec of cargo, any arguments; only cargo is run, and each argument │
│ is passed to it literally, never through a shell │
│A remember: the same, written to project config [permissions] │
│e edit the pattern before a or A │
│n deny │
│N deny with reason │
└──────────────────────────────────────────────────────────────────────────────┘
Read it top to bottom: which tool, where it runs, the exact command, then your
choices. y allows this one call. a allows this call and every future
cargo test ... for the rest of the session. A does that and writes the
pattern to the project's config, so it holds tomorrow too. The line beginning
= is the plain-English meaning of the pattern, generated from it, so you know
what you are agreeing to. Press a.
Gates
If the project has acceptance gates configured, they run now, on what the model changed, before you are asked to look:
-- running acceptance gates
A gate that fails goes back to the model with its output, and the model fixes
it. You only see the change once the gates pass. (A fresh project has no gates;
the Gates chapter shows how to add cargo test as one.)
Review
When the model is done and the gates are green, the review opens:
┌ review ─────────────────────────────────────────────────────────────────────┐
│Review: 01a0c63 on main, round 1 -- 1 file, 2 hunks │
│ │
│src/lib.rs │
│hunk 1 (18-31) edit #8fqrN6 │
│Adding `pow` after `mul` with the exact signature you gave, plus one test. │
│hunk 2 (56-64) edit #8fqrN6 │
│Adding `pow` after `mul` with the exact signature you gave, plus one test. │
│ │
│Enter: review each hunk q: reject all │
└──────────────────────────────────────────────────────────────────────────────┘
This is the brief: every hunk, the tool call that made it, and the reason
the model gave. Press Enter to go through the hunks one at a time:
[1/2] src/lib.rs (+11 -1)
hunk 1 (lines 18-31)
why: Adding `pow` after `mul` with the exact signature you gave, plus one test.
@@ -18,9 +18,14 @@ pub fn mul(a: i32, b: i32) -> Option<i32> {
a.checked_mul(b)
}
+/// Return `base` raised to the power `exp`.
+pub fn pow(base: i64, exp: u32) -> i64 {
+ base.pow(exp)
+}
+
#[cfg(test)]
mod tests {
(a)ccept (r)eject (c)omment (e)dit (s)kip (q)uit
Press a to accept the first hunk. For the second, press c and type a
comment:
comment for the model (Enter sends, Esc cancels):
> make the test check pow(2, 10) == 1024 only
A comment rejects the hunk and tells the model why. When the last hunk is decided, heph keeps what you accepted, sends your comment to the model, and the model takes another round. A second review opens with only the new change in it. Accept it, and the turn ends:
-- turn done, 1 file applied, $0.67
The private worktree now has pow and its test. Nothing you rejected is in it.
Heph prepares the publication candidate, passes its final gates, and offers to
commit the shown message to the conversation's branch in a dedicated dialog.
Choose Yes (y) to publish immediately, Yes, but edit the message (e) to open
your editor first, or No (n) or Esc to keep it private. The publication lock
stays held while you answer and through the editor and commit. Both publication
actions need no further gate pass unless upstream changed. Your checkout stays
untouched unless it has that branch checked out.
What just happened
-
Heph copied your project into a worktree of its own and pointed the model at that.
-
The model read files silently and edited the copy; each edit was committed to heph's private history with the rationale as its message.
-
A shell command stopped to ask you, and your
abecame a session-wide approval. -
Gates ran on the model's changes.
-
You reviewed hunk by hunk; a comment sent the model another round inside the same turn.
-
What you accepted became private conversation state. The commit offer lets you publish it now or later with
/commit; your uncommitted checkout changes were never imported.
Press Ctrl-D to open the exit confirmation, then press it again to leave. The
conversation is saved; the next heph in this directory opens it again with
everything on screen.