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.