Sessions
Read this when you resume or fork a conversation, navigate history, or want to know how compaction works. Model/provider questions → providers.md.
Where sessions live
Sessions are append-only JSONL message trees saved under ~/.ink/sessions/,
organized by working directory. Every turn — user messages, assistant
messages, tool calls and results, model changes, compaction checkpoints — is
preserved on disk; nothing is ever rewritten.
ink -c # continue the most recent session in this directory
ink -r # ink sessions lists them; -r <id> resumes (prefix ok)
ink --no-session # ephemeral run; nothing persisted
In the REPL: /sessions lists, /resume <id> switches (history replays on
screen), /new starts a fresh session (the old one stays on disk), /name <name> names the session for the picker, /status shows session, model,
context, and trust at a glance. /sessions prune sweeps orphaned child
sessions (subagent transcripts whose parent file no longer exists) after an
interactive confirm. The exit line always shows how to resume:
ink -r <id>.
The tree
Every session's messages form a tree, not a line. Forking or jumping creates a branch; the active branch supplies history for the next model request.
/fork— branch the conversation before an earlier message. Pick one from the filterable user-message list, or/fork <n>. Jumping to a user message puts its text back in the input for re-editing./tree— a visual picker over every turn and branch. Arrows move; Tab cycles the filter (default / no-tools / user-only / labeled-only / all);ffolds a subtree;Llabels the selected entry (labels are searchable bookmarks that survive every filter); typing searches; Enter jumps. ←/→/PgUp/PgDn page; alt+←/→ fold at branch points; ctrl+x copies the selected entry's text; deep rows pan automatically. The picker opens on your current position.- Jumping away from a branch optionally summarizes the branch you left into
the new position's context (a three-way ask: No summary / Summarize /
custom prompt).
INK_BRANCH_SUMMARY=0disables summaries entirely;/settings branchSummary.skipPrompt trueskips the ask (straight to no-summary)./settings treeFilterMode <mode>remembers your default filter. - The readline (non-TUI) shell renders the tree as a numbered list;
/tree <n>jumps to row n.
Compaction
Near the context window, older turns are LLM-summarized into a checkpoint:
subsequent model requests use the summary plus recent turns, while the full
history stays on disk. /compact triggers it manually (optionally with
custom instructions). --no-session also disables auto-compaction;
INK_AUTOCOMPACT=0 or "autoCompact": false in settings turns it off.
INK_CONTEXT_WINDOW overrides the window estimate (default 131072).
Branch summaries (from /tree jumps) are separate: they record an abandoned
branch in one entry. Both preserve the original entries — the tree is never
pruned.
Steering and follow-ups (interactive)
Lines typed while Ink is working are queued, never dropped:
- Enter → a
steer:line, injected into the running turn before the next model call. Default drain modeall: every queued steer joins the next boundary at once. - Alt+Enter → a
follow-up:line, consumed by the same run when the model would otherwise stop. Defaultone-at-a-time: one follow-up per answer, so a queued sequence advances without returning to idle. - Alt+Up / Esc+P pulls every queued line back into the editor (draft preserved); Ctrl+C abort hands them back the same way.
- Modes are settings keys:
/settings steeringModeand/settings followUpMode(all|one-at-a-time).
Terminal notes: WezTerm binds Option+Enter to fullscreen and Alacritty may
send plain Return — map both to \x1b[13;3u, or use Esc+P (dequeue has a
fallback; Alt+Enter does not).
Known limits
- The
/resumepicker's type-to-filter consumes committed text only — IME composition windows emit no keys mid-composition (kitty protocol), so CJK input filters once committed. A pasted block takes its first line.