Sessions, Resume, Handoff, Checkpoints

Overview

eVi keeps a durable record of your conversations and the file changes it makes, so you can pick up where you left off and undo mistakes.

Why you'd use it: nothing is lost when you close the terminal or browser, you can move a conversation between machines, you keep an auditable record of what was said, and you can undo file writes eVi made without reaching for git.

How it works

Transcripts

When the transcripts tool toggle is on (the default), each turn is appended to:

~/.evi/transcripts/<YYYY-MM-DD>/<session_id>.jsonl

Each line is a JSON object for one message (role = user / assistant / tool / system, plus content, a ts timestamp, and — for tool turns — tool_name, or tool_calls on assistant turns). Because writes happen per turn, the on-disk copy is always current as of the last completed turn.

Listing scans the day directories newest-first and summarizes each file: message count, first user message (the injected [ongoing goal: …] prefix is stripped from the summary), and start/end timestamps derived from the ts fields.

Resume is a best-effort reconstruction. eVi rebuilds an in-memory history from the JSONL in order and re-emits user/assistant/tool messages (synthesizing tool_call_ids where the original wasn't logged). It does not restore the backend's KV cache (the next message is a fresh prompt to the model) nor transient flags like an active goal or one-shot plan mode — re-set those if you need them.

In the web UI, a session id arriving via /?session=<id> is revived from disk on first use: if a transcript for that id exists, its history is loaded into a fresh Agent before the next message.

Checkpoints

Every write_file operation records the file's prior state first, under:

~/.evi/checkpoints/journal.jsonl     # one entry per write: {seq, ts, path, op, blob?, size?}
~/.evi/checkpoints/blobs/<sha256>    # prior contents, content-addressed (dedup'd)

The op is one of:

rewind walks entries with seq >= target newest-first, restoring/deleting each, then trims those entries from the journal — so a second rewind continues further back. Checkpointing is best-effort: a checkpoint failure never blocks the actual write.

Setup

Config lives in ~/.evi/config.toml. Transcripts are controlled by the transcripts key under the [tools] section:

[tools]
transcripts = true     # write session JSONL under ~/.evi/transcripts/

Relevant paths:

DataPath
Session transcripts~/.evi/transcripts/<YYYY-MM-DD>/<session_id>.jsonl
Checkpoint journal~/.evi/checkpoints/journal.jsonl
Checkpoint blobs~/.evi/checkpoints/blobs/<sha256>

Usage

CLI — evi sessions

evi sessions list [--days 7] [--limit 20]    # recent sessions, newest first
evi sessions show <session_id>               # print the full transcript
evi sessions export <session_id> [-f md|html|json] [-o PATH]
evi sessions resume <session_id>             # reopen and continue in the SAME file
evi sessions continue                        # resume the most recently active session
evi sessions fork <session_id>               # branch into a NEW session, original intact
evi sessions handoff [session_id]            # print resume cmd + URL for another device
evi sessions title <session_id>              # LLM-generated short title for a session

CLI — evi rewind (checkpoints)

evi rewind --list        # (or -l) list recent file checkpoints with their seq numbers
evi rewind               # undo just the latest write
evi rewind <seq>         # undo all writes with seq >= <seq>

rewind with no seq (or 0) undoes only the most recent write.

REPL slash command

Inside an interactive chat (evi chat), /recent [n] lists recent sessions (read-only; default 8, scans the last 30 days). It prints short ids and reminds you to resume with evi sessions resume <id> after /exit, or via the evi link <id> deep link.

Web UI

Examples

Example 1 — list, peek, resume, and hand off to a laptop

$ evi sessions list --days 14 --limit 5
a1b2c3d4  2026-06-08 21:14   17 msgs  refactor the auth middleware
9f8e7d6c  2026-06-07 09:02    6 msgs  draft a release note for v0.31.0

$ evi sessions show a1b2c3d4 | head            # inspect before reopening

$ evi sessions resume a1b2c3d4
resumed a1b2c3d4 (16 messages restored)
> …continue the conversation here; new turns append to the same file…

To continue it later on another machine:

$ evi sessions handoff a1b2c3d4
handoff a1b2c3d4 (17 messages)
  1. sync this device:   evi sync push
  2. on the other device: evi sync pull, then either
       evi sessions resume a1b2c3d4
       or open http:///?session=a1b2c3d4 in the web UI

Run evi sync push here, evi sync pull on the other device, then either resume command works because the transcript file travels with the sync.

Example 2 — fork a session, export it, then undo a bad file write

Branch a copy so the original stays clean, and save a readable archive:

$ evi sessions fork a1b2c3d4
forked a1b2c3d4 → new session b7c8d9e0 (16 messages copied)

$ evi sessions export a1b2c3d4 --format md --out ~/notes/auth-chat.md
wrote /home/you/notes/auth-chat.md

If eVi made a file edit you want to undo:

$ evi rewind --list
     7 21:40:11 modify /home/you/project/app.py
     8 21:41:02 create /home/you/project/new_helper.py

$ evi rewind 7        # undo seq 7 and everything after it (7 and 8)
✓ deleted (was newly created) — /home/you/project/new_helper.py
✓ restored — /home/you/project/app.py

evi rewind alone would have undone only seq 8; passing 7 rolls back from that point onward.

Example 3 — make sure transcripts are enabled

If evi sessions list says no sessions are found, confirm the toggle:

# ~/.evi/config.toml
[tools]
transcripts = true

Notes / limits

Edit on GitHub ↗