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

Non-interactive Use: heph exec

heph exec runs one turn and exits. It is the same engine as the session, the same worktree, gates, and review, without the screen: for scripts, for a quick question from the shell, for piping something in.

heph exec 'fix the failing test in src/parse.rs'
git diff | heph exec 'review this change and list anything risky'
heph exec --plan 'summarize what this crate does' | less

The prompt is the arguments, joined with spaces. If stdin is not a terminal, whatever is on it is appended to the prompt as context, so git diff | heph exec 'review this' gives the model the diff.

What comes out

The model's final text goes to stdout. Everything else, tool calls as they run, status lines, prompts, the review, goes to stderr, so the text can be piped or captured on its own. --stream echoes the model's text to stderr as it streams too, for watching a long answer arrive.

The last stderr line summarizes the turn:

-- turn 01a0c63e on main: EndTurn, 4 rounds, $0.2140; applied src/parse.rs

It ends with ; skills a, b when the turn activated skills, whether you armed them or the model loaded them.

Skills

--skill NAME activates a skill with the prompt, as /skill does in the session; repeat it for more, and they go in the order given:

heph exec --skill rust-change --plan 'how are errors typed here'

A name that is not discovered, or that [skills] disabled names, ends the run before any turn starts, with exit 1. A skill already active on the conversation --continue names is skipped with a note on stderr, since it is in effect. --skill needs a prompt to go with. When --continue offers a pending review and you leave it undecided, the prompt does not run, and the summary line ends ; not delivered: skills a, b.

Exit codes

CodeMeaning
0The turn ended with nothing left to decide: the model finished, and any change was applied.
2The turn ended short: a call no flag covered, an interrupt, the model's output limit, or changes waiting for review. The reason is on stderr.
1Heph itself failed: bad config, no provider, a database or git error.

With a terminal

Run from a shell, heph exec has a tty even though it has no screen, and uses it: permission prompts, ask_user questions, and the review appear as plain prompts on the terminal, and you answer by typing.

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] promoted
  e  edit the pattern before a or A
  n  deny
  N  deny with reason
>

The review works the same way: the brief, then Enter for hunk-by-hunk prompts (a, r, c, e, s, q) or the configured external tool, which opens on the terminal. Heph reads the tty directly, so this works even when stdout is piped or stdin carries the prompt's context.

Without a terminal

In a cron job, a CI step, or a pipe with no tty, there is no one to ask, and heph fails closed:

  • A Level 2 call (shell, web_fetch) that no flag or config pattern covers is denied. The model is told no one is present, and usually explains what it would have needed. The turn continues.

  • ask_user returns an error telling the model to decide or state its assumption.

  • Changes the model made stay in the worktree, unreviewed, and the turn exits 2 with the conversation to continue on:

    changes await review in the worktree of ref main; run `heph exec --continue
    main` in a terminal to review them, or pass --accept-edits
    
  • SIGINT ends the turn as interrupted.

Three flags widen what runs unasked. They approve tool calls, and nothing else: none of them stands in for review.

FlagApproves
--allow-tools PATTERNCalls matching the pattern, e.g. --allow-tools 'exec(cargo) args(*)'. Repeatable.
--yesEvery Level 2 call.
--yes-reallyLevel 2 and Level 3.
--accept-editsNot a tool flag: applies the turn's changes without review.

--accept-edits is the one to think about. With it, whatever the model changed lands in your tree when the gates pass. It is right for a change you will look at in git diff afterward anyway, and wrong for anything you would want to reject hunk by hunk.

Picking a review up later

A turn that exited 2 with changes waiting can be finished from a terminal:

heph exec --continue main

With --continue and no prompt, heph offers the pending review and exits when it is decided. With a prompt as well, the review comes first and the new turn after. The same review opens in the interactive session:

heph --continue main

See Picking Up Where You Left Off.

The base branch

A conversation starts from a branch you name for it (Branches). The session asks; exec cannot, so a conversation with no base branch needs [git] base_branch in the project's config or --base on the command line:

heph exec --base main 'add a test for the parser'

Without either, the run ends before any turn with a message naming both. Once a conversation has a base branch, --base with another name is refused rather than moving it; /base in a session does that.

The other flags

--continue NAME runs on a conversation other than main. --profile, --tier, --model, --plan, --design, --tools, --review, and --quick mean what they mean in the session (Models and Cost, Plan Turns, Design Turns). --implement PATH builds a committed design in a new conversation, or in the --continue one with its context cleared (Design Turns). --quick runs the turn on the quick tier; it does not yet cap the turn at one round.

The global flags go before the subcommand: heph -C DIR exec ..., heph --data-root DIR exec ....