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

Picking Up Where You Left Off

Every turn is recorded as it happens, so nothing you were in the middle of is lost when you leave, when the terminal closes, or when heph is killed. This chapter is about what you find when you come back.

The conversation is there

heph --continue opens your latest branch conversation, or heph --continue NAME / heph --continue FULL-UUID opens a specific one, with everything that was said on the screen: your prompts, the model's replies with their thinking folded, every tool call with its result, and the line that ended each turn. Your prompt history is there for Up. A half-typed prompt you left in the input is back in it.

The interactive mode is kept too: code, plan, or design, including the class /code returns to and your selected plan/design tool set. A successful mode change is saved immediately, even before you send another prompt. Resume and /switch restore each conversation's mode, model role, and tool catalog. Explicit startup flags (--plan, --design, --review, --quick, or --tools) override the saved choices. Older conversations without saved mode state start in code mode. /new and /fork inherit the active mode. heph exec uses its own class flags and does not change the saved interactive mode.

Resuming by publication branch

If you remember the Git branch rather than the conversation name:

heph --continue-branch heph/auth-refactor

Heph searches the containing checkout, including from a subdirectory or with -C, under the effective data root. The branch must match exactly, including case, against a current reserved publication branch or a recorded past local publication. Merely starting from that branch is not a match. Archived sessions participate; subtask refs do not.

One match resumes directly with the usual history, draft, routing, mode, and pending review. Several matches show a numbered terminal list, newest substantive activity first. Each entry includes its name and full UUID, creation and activity times, mode, tip, base/current branch, publication history, and full cached /summary content with age and coverage. Missing summaries are labelled; stale summaries remain visible with their warning. Choosing makes no provider call and does not refresh summaries.

Enter a session number to resume. Invalid numbers prompt again. Press Enter or type q to cancel; EOF also cancels. There is no default choice, even with -y or --yes-really. Without a controlling terminal, select explicitly with heph --continue FULL-UUID. No matches error without starting a new session; locked selections still error. Selecting a past publication does not change the session's current publication branch. The flag excludes startup prompts, --continue, --fork, --adopt, and subcommands.

Finding a saved session

heph sessions reads saved databases, not just live tmux panes. It selects the current checkout, including from a subdirectory, with archives hidden. These are compatibility changes from the earlier global, archive-inclusive inventory. Use explicit global or archive selectors when needed:

heph sessions --limit 20
heph sessions --summary --limit 20
heph -C /path/to/project sessions
heph sessions --name auth
heph sessions --branch heph/auth --published
heph sessions --json
heph sessions 'auth|login' --uncommitted
heph sessions --all-projects --include-archived
heph sessions show UUID
heph sessions show UUID --diff
heph sessions open UUID

The compact table shows UUID, name, reserved branch, independent work flags, runtime, and last recorded work/publication activity. show and JSON retain full source and shadow paths, base, cached summary freshness, blockers, and publication history. --branch searches base, current, and historical branches. A reserved branch does not prove a commit succeeded; --published requires a recorded success. These are local /commit publications, not remote git push events. Earlier publications are unknown, and older source paths remain unknown until the project is opened again (or supplied with -C for the listing).

Add --summary to see each session's full cached work summary in a SUMMARY column. Missing caches show -, and older caches are marked [stale]. This reads the same cache as /summary without generating or refreshing it, probing Git/runtime, or updating activity. --summary --json includes saved caches as summary objects; the flag conflicts with UUID-only --ids output.

Stopped sessions remain discoverable without a worktree. After removing a checkout or Git worktree, use heph -C /former/worktree sessions with its original root path. The missing path selects that former project's saved sessions, not a surviving parent checkout, and listing does not recreate project state. Relative paths are relative to the current directory. Alternatively, heph sessions --all-projects includes projects with missing source directories; add --include-archived for archives. Inspection migrates existing schemas but creates no worktree and runs no recovery. open UUID uses normal resume when no live pane matches; opening can therefore perform recovery. Unique UUID prefixes require at least six characters.

A regex matches names and branch data, case-sensitively unless it starts with (?i). Use --match for patterns that look like subcommands. All selectors combine with AND. --uncommitted includes accepted private snapshots and unsnapshotted source files; a clean Git worktree is not proof of publication. --merged requires incorporated publications and no private remainder. --unmerged requires positive absence evidence; failed ancestry after a squash or rebase is unknown, selected with --unknown, not proof of lost work.

--runtime STATE selects the separate runtime dimension. --inactive-for 30d uses recorded work or publication, not resume or inspection time. Explicit --disk-usage counts owned worktree files without following links or claiming shared caches as reclaimable. --ids emits full UUIDs and conflicts with --json. JSON includes sessions and diagnostics; incomplete coverage exits nonzero but preserves successful rows.

Ordinary listing takes the fast metadata path: it opens current schemas read-only, batches inventory reads, and displays labelled cached observations or not-inspected. It does not probe Git or sockets. Use show or work/runtime filters for fresh evidence; they may take longer. Actual draft/name edits also advance substantive activity, while resume, inspection, and summary reads do not. Cached flags never authorize cleanup.

Semantic discovery

heph sessions find 'the OAuth refresh bug' --limit 5
heph sessions find 'the flaky build workaround' --include-archived --json

The default is up to five likely matches on the configured fast tier. Every selected candidate is considered in bounded batches, then finalists are reranked from compact relevance assessments. Only metadata and cached summaries are sent, with missing/stale and truncation markers. No summaries are generated, no source files or transcripts sent, and no tools offered. Returned IDs are checked against candidates. A recommendation is not merge evidence or permission to act.

--max-cost sets a positive finite request cap, default $0.50, checked before the next request including its projected cost. --profile chooses a configured provider profile. Empty input and zero limits fail; an empty candidate set makes no model request. Provider errors and malformed output are explicit, not replaced by lexical guesses. JSON exposes coverage, cuts, explanations, summary freshness, request count, and frozen-rate cost. All requests are charged to a detached audit in an existing project database, without creating a session or changing activity.

Archive, clean, or delete

heph sessions archive UUID
heph sessions clean --merged --inactive-for 30d
heph sessions clean --merged --inactive-for 30d --apply
heph sessions delete UUID --apply

Every action previews by default, even with UUIDs. IDs and selectors cannot be mixed. --apply authorizes that invocation's exact set; freeze a prior preview with IDs in scripts. Global actions need explicit --all-projects. In a terminal, deletion additionally shows history loss and requires typing DELETE.

Archive hides the session and keeps its files and history. Clean removes only its reconstructible owned worktree; opening it later restores retained state. Delete removes the ref and exclusive canonical transcript, tool history, and summary. Shared history, immutable request audits, and frozen charges remain. External publication branches, user-owned linked paths, shared caches, and shared object stores are never independently reclaimed per session. No object garbage collection runs.

Cleaning and deletion require proven merged or untouched empty work, with no live owner, pending review/recovery/base change, draft, unknown state, or inconsistent resource. There is no force option. Application rechecks ownership and eligibility under locks and reports each changed, skipped, or failed target; skips/failures or incomplete coverage exit nonzero.

Retry interrupted maintenance using the same action, exact UUID, and --apply. Deletion receipts support retry after the ref disappears. Pre-commit refusal restores quarantine and releases the resume guard. After the database commits, retry completes only the remaining owned cleanup. Ordinary resume refuses unfinished maintenance rather than silently repairing or racing it.

Adopting a session from another checkout

If a linked Git worktree was removed, its published branches may still exist in the main repository, while heph's session still belongs to the removed path. From the main checkout, adopt the session by full UUID:

heph --adopt 01a11228-9185-70e7-bb6c-73a886e16220
heph -C /path/to/main --adopt FULL-UUID -y

The confirmation shows the old project, whether it still exists, the destination, UUID/name, private storage, saved mode and routing, branch/base/pin, draft size, retained history, and latest publication. The default is no. -y / --yes skips this check and retains its usual Level 2 tool auto-approval after resume. Your restored draft is not submitted automatically. --adopt cannot be combined with a startup prompt, --continue, --fork, or a subcommand.

Discovery uses the effective data root, including archived sessions. The old checkout need not exist, but its heph database and shadow repository must. Adoption requires shared Git history and refuses live ownership, unfinished turns or apply/synchronization/maintenance, pending launch handoffs, and destination identity/name/branch conflicts. Stop or recover unsafe work first; there is no force option.

The UUID, conversation, saved settings, private snapshots, pending-review roots, staged files, and non-ignored dirty files follow the session. Consumed launch records retain their original input and fork checkpoint, even after later navigation. Worktree links use the destination config and checkout. Other source sessions and shared history stay put. Original private resources, ignored files, request audits, and caches are not deleted. Global accounting counts copied request IDs only once. No publication branch or main checkout file is changed by adoption itself.

After transfer, ordinary resume runs. If interrupted, rerun the same command with the same destination and data root. A durable journal blocks ordinary resume and lifecycle actions until verification and source-ref retirement finish. Do not delete it to bypass recovery. If the session is already in the destination, adoption simply resumes it.

A review you put off

If a turn ended with changes you did not review, because you pressed Esc on the brief or stopped partway through the hunks, or you were in a script with no terminal, or a gate kept failing and you were not there to look, the changes waited in the worktree, and the conversation was marked as waiting. Its snapshot is only what you accepted; nothing undecided is ever taken as accepted.

When you next open it, the review is offered at once, before anything else:

-- ref main has a review waiting from turn 01a0c63e

and the brief opens, for the same round the turn stopped in, with the change staged as it was, or with exactly the hunks you had not reached. Decide it as usual. Within a session, the review comes first too: a prompt you type while it waits opens the review, and the prompt is queued behind it, so its turn starts from what you decided. /review opens it on the spot.

Putting the review off again is allowed, and safe: the next prompt's turn carries the unreviewed work onto its own chain, each hunk still credited to the call that wrote it, and reviews it together with its own work. The work is never quietly absorbed as if accepted.

The same happens from the command line:

heph exec --continue main            # offer the review, exit when decided
heph exec --continue main 'and now...'  # the review, then a new turn

A turn heph was killed under

If heph dies with a turn in flight, from kill -9, a crash, a closed terminal, or two presses of Ctrl-D, the next heph on the project finds the turn and closes it as interrupted by exit: the model's stream is dropped, a tool call left without a result gets one saying so, and the worktree is put back at the last thing the model wrote. If the turn had changed anything, that change is offered for review as above, exactly as if you had pressed Esc while it ran. Gates did not run on it, and run on what you keep.

Two plain heph invocations create distinct UUIDs and worktrees. Resuming a conversation already leased by another process errors. A turn belongs to the process that started it, and another process never mistakes a live turn for an abandoned one.

A failed save or full disk

If a tool result could not be saved, clear enough disk space before continuing. The next request repairs missing call/result pairs even when the failed turn was already closed. Saved results stay intact; only missing ones get an error saying the call may have executed. Heph does not rerun the tool automatically or rewrite the stored conversation. Inspect the current files and external state before retrying a call whose outcome is uncertain.

An apply that was interrupted

The one moment heph writes to your tree is the apply at the end of a review. It journals the merge first: what your files were, what they are meant to become. If it dies partway through writing, the next start finishes the job before any turn begins. For each file, if your tree still has the old content it is written; if it already has the new content it is left; if it has something else, you edited it in the meantime, and your version stands. Your tree is never left half-written, and nothing about the recovery is guesswork.

What is not kept

The permission approvals you gave with a last for the session. Approvals you gave with A are in .heph/config.toml and last. The constraints from a review's rejections last for their turn only; a new turn starts clean.

Where it all is

Everything is under ~/.local/share/heph/, keyed by a hash of the project's path: the database of turns, the shadow git repository, and the worktrees. Deleting a project's entries there forgets its conversations and nothing else; your repository is untouched. See Where Heph Keeps Things.