# Sessions, resume & compaction

> Every conversation is saved to disk as it happens, so you can quit and pick up where you left off, roll back a mistake, or trim a long context. This page covers the journal, resuming, rewinding, and compaction.

Every conversation is saved to disk as it happens, so you can quit and pick up
where you left off, roll back a mistake, or trim a long context. This page
covers the journal, resuming, rewinding, and compaction.

<!-- SOURCE: src/kin/harness/persistence/, src/kin/harness/session/, src/kin/harness/compaction.py, src/kin/harness/snapshots.py, src/kin/harness/loop.py, src/kin/harness/status_file.py, src/kin/harness/term_notify.py, src/kin/tui/cli.py, src/kin/tui/mux.py, src/kin/tui/mux_sessions.py, src/kin/tui/launch_picker.py, src/kin/tui/outpost_watch.py, src/kin/harness/cli/ls.py, src/kin/tui/modals/session_switcher.py, src/kin/tui/modals/outpost_peek.py, src/kin/tui/attention.py, src/kin/tui/commands_mixin.py, src/kin/tui/turn_lifecycle.py, src/kin/tui/app.py -->

## Outcome

Move between live and saved work without losing the current conversation, and
know when to resume, fork, rewind, or compact.

## Fast path

1. Press ++ctrl+l++ or run `/sessions`.
2. Choose a **live** row to switch to its process, a **saved** row to resume,
   or **New session here** for an independent clean conversation.
3. Use `/resume` when you want only this project's saved history.
4. Use `/fork` before exploring a risky conversational branch.
5. Quit with ++ctrl+c++; normal sessions are already journaled as they run,
   and Kin leaves the exact resume command in the terminal.

[![Kin session switcher grouping live, waiting, and saved conversations with a New session action.](/docs-assets/kin/assets/screenshots/session_switcher.svg)](/docs-assets/kin/assets/screenshots/session_switcher.svg)

*The switcher presents the action implied by each state: attach to live work,
inspect waiting work, resume a saved journal, or start cleanly.*

## Alternative entry points

#### At launch


`kin --continue` resumes the newest session for the current project.
`kin --resume <id>` chooses an exact journal.

#### In the TUI


`/sessions` includes live local and Outpost work. `/resume` is the narrower
saved-history picker, and `/resume <id>` switches directly.

#### Background work


`/detach` leaves the issuing terminal while the process keeps running.
Bare `kin` reclaims one unattended session, opens a chooser when several
are available, and `kin ls` lists them all.

## The journal

Beam cards use hybrid persistence: the journal stores the beam/job identity at
a conversation boundary, while Outpost remains the live lifecycle authority.
Cards survive resume, compact, clear, rewind, and fork; their marker is clamped
to a safe user-turn boundary so replay never splits a tool call from its
result. This is intentionally asymmetric with context snapshots: a beam is an
external-world fact worth retaining even when nearby conversation text is
rewritten. Old journals contain no markers and replay exactly as before.

Each session is an append-only JSONL file. The first line is a `meta` record
(provider, model, workdir, created time); every line after it is either a
`message` (one entry of the provider-native history, appended at each turn
boundary) or a `mode` change.

```
~/.kin/projects/<workdir-slug>/<session_id>.jsonl
```

The `<workdir-slug>` is the project's absolute path with separators flattened to
dashes, so every project keeps its own set of sessions. The id looks like
`s_<unix-time>_<hex>`.

Append-only means crash-safe: a torn final line is skipped on load, not fatal,
and each turn appends only its new messages. Provider-native history is stored
verbatim—Chat flat dicts, Responses typed output items (encrypted reasoning
included), or Anthropic content-block lists (thinking signatures included)—so
a resumed session is faithful on the same endpoint and wire. The journal
envelope remains v2; `wire_api` in metadata selects the decoder, while old
journals without it retain their Chat-or-Messages meaning.

The projects root can be relocated. `KIN_HOME` moves all of `~/.kin`; the
`KIN_SESSION_DIR` environment variable or the `session_dir` global setting
points the whole projects tree somewhere else. See
[Environment variables](/docs/kin/reference/environment-variables/) and
[Settings (TOML)](/docs/kin/reference/settings-toml/).

## Resume & continue

| Action | How |
|--------|-----|
| Resume a specific session at launch | `kin --resume <id>` |
| Resume the newest session for this project | `kin --continue` |
| Switch sessions mid-run | `/resume` (picker) or `/resume <id>` |

After a clean interactive exit, Kin prints a ready-to-paste command for the
conversation that was active at shutdown:

```console
To continue this session, run:
  kin --resume s_1784570243_deadbe
```

If the session used a `--workdir` other than the shell's current directory,
the command includes that absolute, shell-quoted path. Ephemeral (`--no-save`),
failed-to-save, and empty sessions print no hint because there is no surviving
journal to resume. This is the same on the default background-session path and
with `--no-detach`: Kin waits until the UI and terminal wrapper have both
finished, then prints into the shell-visible terminal.

[Headless runs](/docs/kin/guide/headless/) (`kin -p`) write the same journal, so a cron run
that exited `2` (needs-human) can be picked up interactively with
`kin --resume <id>` — the id is printed on stderr and in the `--output` report.

At launch, resume reuses the saved provider, endpoint, model, and sampling
configuration from the journal's `meta` unless you override a backend flag on
a saved-only conversation.
Secrets are never stored in the journal: Kin reattaches the current
`provider_keys[<id>]` credential only when that provider still describes the
saved endpoint. Older journals without a provider id use a unique endpoint and
auth match, so existing history remains resumable; a changed or ambiguous
custom endpoint is never handed a guessed per-provider key. If the saved
provider doesn't match the backend you launch with, resume fails closed (it
refuses rather than replaying into the wrong wire); it does not silently start
a fresh session. A bare `--resume` (no `--mode` flag and no `KIN_MODE`) also
keeps the session's saved
[permission mode](/docs/kin/guide/modes-and-permissions/) rather than re-applying your
global default, so a `strict`-mode session you resume doesn't silently
reopen in `auto`.

Conversation identity also protects live work. If `--continue` or
`--resume ID` names a conversation already owned by a managed process, Kin
attaches to that process, even if another terminal is already viewing it. If
you also supplied provider/model/sampling/mode or another launch-only
override, Kin refuses: attach without overrides, change configuration
in-session, or `/fork` first. This prevents both ignored flags and two live
writers appending to one journal.

In-session, bare `/resume` opens a picker of this project's sessions (newest
first, with a one-line title, age, turn count, and model); `/resume <id>`
switches directly. The switch is non-destructive — the current session's journal
is left intact on disk — so it needs no confirmation. You can't switch while a
turn or a compaction is running, or while another modal is open.

### Forking

`/fork` branches the current session: it copies the on-disk journal to a
fresh session id — everything after the meta line copied byte-for-byte —
then switches you onto the copy via the exact same path `/resume` uses. The
**fork becomes the live session**; the source is left exactly as it was at
the moment you forked, untouched and resumable with `/resume <old-id>` later.
This is the reversible way to explore a branch without losing the original:
fork, go try something, and if it doesn't pan out, `/resume` back to where
you started.

There's no separate "fork back" verb — a fork is just a session like any
other, and `/resume` already gets you to any session by id. `/fork` refuses
(with a notify) while a turn or a compaction is running, the same as
`/export`.

This human command is distinct from the model tool `fork_agent`. `/fork`
switches the human onto a copied root session. `fork_agent(prompt=…)` leaves
the root session in place and spawns a supervised child with conversation
context through the current user request; see [Subagents](/docs/kin/guide/subagents/).

### Subagent journals are hidden

Every retained [subagent](/docs/kin/guide/subagents/) spawned by `task` or `fork_agent` writes its own journal next to
the root session's (same project dir), with the spawning session's id recorded
as `parent_session_id` in its `meta`. These child journals are deliberately
**hidden from every root-session enumeration surface** — `/resume`, `--continue`,
and `/sessions` list only root sessions, so a busy session that spawned a dozen
subagents doesn't drown the picker and `--continue` always resumes the root, not
whichever subagent happened to finish last. An explicit `kin --resume <child-id>`
still loads one (a deliberate act; the id isn't advertised). Subagent
transcripts are read live through the [agent panel](/docs/kin/concepts/agents/)
(`Ctrl+O`) and the `agent_output` tool, not through resume.

### Session titles

Each session's picker row starts with a default title — its first user message.
After a session sits idle for ~120 seconds with no new turn, kin generates a short
(3–6 word) title from the conversation via a one-off bounded model side-call (the
same pattern compaction uses — it doesn't touch your history or the context
meter) and saves it to the journal. The timer resets on every new turn, so an
active session is never interrupted, and a resumed historic session picks up a
title after the same idle gap. The generated title is a `title` record in the
journal — persisted like `mode`, so it survives `/compact`, `/clear`, `/rewind`,
and a `/providers` swap — and is what the `/resume` picker prefers over the raw
first message.

By default the side-call runs on the main model. Assigning the
[`utility` job](/docs/kin/guide/models-and-providers/#the-utility-job-housekeeping-side-calls)
moves it to a lightweight route so a title request can never disturb the main
endpoint's prompt cache; if that route is busy or the call fails, kin simply
keeps the fallback title.

See [Slash commands](/docs/kin/guide/slash-commands/) for the full command list and
[CLI reference](/docs/kin/reference/cli/) for the launch flags.

## Background sessions (detach & reattach)

Resume covers the case where the kin *process* is gone. Background sessions
cover the other one: **the process is fine — you just want to leave.** Close
the terminal window, drop an SSH connection, step away mid-turn — kin keeps
running in the background and you land back in the live conversation later,
mid-turn included. No replay: the process never died.

**On by default when tmux is available** — every interactive launch runs as a
background session. Opt out per launch, per machine, or per project:

| How | What |
|-----|------|
| `kin --no-detach` | this launch only — a plain, non-background run |
| `KIN_DETACH=0` | this shell / machine (env) |
| `detach = false` in `~/.kin/settings.toml` | every launch in this project / globally |
| `kin --detach` | force it ON where you'd opted out |

If tmux is missing or too old, kin runs plainly and silently (no nagging — a
default shouldn't); `kin doctor` reports whether background sessions are
available.

Everything else looks and feels exactly like a normal launch — colors, mouse,
keys, and tab titles all pass through unchanged. The terminal tab title names
the workspace folder and shows a slow dot spinner while kin works; it becomes
a static `● … needs input` when an approval or question is waiting. Reduced-motion
mode keeps the busy title static, and `KIN_ASCII=1` uses line-style frames.

- **Leave:** `/detach`. The terminal returns to your shell with a note that
  the session is still running; any in-flight turn keeps going.
- **Come back:** run bare `kin` in the same folder. With exactly one
  unattended healthy process, you land directly in it. With several, Kin
  opens a launch chooser. With none, it creates a new unique process. A
  one-shot `kin --detach` remains recoverable even if background persistence
  is otherwise opted out. Closing the terminal window or losing SSH is
  equivalent to detaching: the process survives.
- **Start alongside:** `kin --new` forces a fresh conversation and process.
  It still follows your detach setting; `kin --new --detach` forces
  persistence, while `kin --new --no-detach` is fresh but unwrapped.
- **Quit for real:** `/exit` (or `/quit`) works exactly as always — the
  current process ends and its journal remains resumable.

Two terminals can attach to the same session at once — both mirror the same
screen (sized to the most recently active one), which is handy for peeking at
a long run from a second window. Mirroring is explicit: select an
**open in another terminal** row in the launch chooser, select the live row in
`/sessions`, or resume its exact live conversation. `/detach` releases only
the terminal that issued it; if Kin cannot identify that client safely, it
warns and detaches nobody.

### What a launch does

| Launch state | Result |
|---|---|
| Bare `kin`, no unattended session | Create a new unique instance |
| Bare `kin`, exactly one unattended session | Reattach it |
| Bare `kin`, multiple unattended sessions | Open the launch chooser |
| `--new`, `--bg`, `--agent`, or provider/model/sampling/preset/mode/no-save flags | Create a fresh instance |
| `--continue` / `--resume ID` targeting a live conversation | Attach its existing process |
| `--continue` / `--resume ID` targeting saved-only work | Create a managed instance resuming it |
| `--no-detach`, headless mode, or a launch inside your own tmux | Run plainly, without Kin's wrapper |

The launch chooser labels every instance **available**, **open in another
terminal**, or **crashed**, shows its title (or a short identity), state, and
age, and ends with **Start new session**. The newest available row is focused.
Escape cancels the launch. If a selected process vanishes, the board refreshes
instead of guessing.

The fine print:

- **Mechanism & requirement:** background sessions are provided by a managed,
  invisible tmux session (version ≥ 3.2 on `PATH`; ≥ 3.4 recommended —
  `kin doctor` reports what it found). Your own tmux config and server are
  never touched, and nothing tmux-shaped is visible: no status bar, no
  prefix key. If tmux is missing or too old, kin runs plainly and silently
  (the default never nags; an explicit `kin --detach` prints one line). If
  anything ever wedges, the rescue command is `tmux -L kin kill-server`;
  `/exit` from inside always works.
- **Inside your own tmux (or with `kin -p`):** kin never nests multiplexers
  and never wraps a headless run — those launches run exactly as today, and
  your own tmux detach already covers the leave-it-running story.
- `--continue` / `--resume ID` map by live conversation identity, not merely
  by folder. An older live process without that identity must be attached
  with bare `kin` before an exact resume; Kin refuses to risk a duplicate
  journal writer.
- `--workdir`, `--detach`, and `--no-detach` shape location/lifecycle rather
  than model configuration, so they do not make an otherwise bare launch
  non-bare. `--new` conflicts with resume/continue. `--bg` always creates a
  fresh instance and also conflicts with resume/continue.
- **A reboot ends the process** — that's what the journal is for:
  `kin --continue` / `/resume` recover the conversation, as ever.
- **A crash freezes the pane** with the traceback on screen instead of
  vanishing — press `q` to close it. If it is the folder's only managed
  instance, the next launch prints the saved traceback and removes it. If it
  has siblings, it remains an inspectable **crashed** row until you end it or
  ordinary cleanup reaps it.

> **Sessions share the same files**
>
> Independent Kin processes in one workspace have independent screens and
> journals, but they read and edit the exact same working tree. Their file
> changes can conflict. Use separate Git worktrees when you need filesystem
> isolation; Kin does not create worktrees or add edit locks automatically.

## Working across folders

One terminal, N projects: spin up sessions across folders and jump between
them. Everything below builds on the persistent-session mechanism above.

### `/sessions` — the switcher

`/sessions` (or **`ctrl+l`**) opens a browser of every session, grouped:

- **running** — every live instance across *all* folders, including
  independently identifiable siblings in the same folder; the current one first,
  needs-you sessions next (oldest wait first), then working, then idle. Enter
  jumps to one; switching is instant (it moves your terminal, not the
  process). `x` ends a session — an idle one dies immediately, a mid-turn one
  asks first (the conversation stays in `/resume`).
- **this folder — saved** — resumable conversations for the current project
  (the same rows `/resume` shows). If another live instance owns the selected
  journal, Kin switches to its process instead of resuming it in-process. A
  plain unwrapped client refuses that duplicate-writer case.
- **start new session in…** — always includes **New session here**, plus
  known folders; enter creates a fresh background instance and jumps to it.
- **on Outpost** — remote jobs; enter peeks at active work or beams a terminal
  job back. Needs-you jobs are counted in the group header.

Switching only works from a persistent launch (it moves the managed terminal
between sessions); a plain launch shows a one-line note instead. Resuming a
saved conversation works from any launch.

### `kin ls` — list background sessions

When Outpost is configured, `kin ls` adds a separate `on Outpost:` block after
local sessions. `--no-cloud` skips that fetch. An unreachable service is shown
explicitly rather than hidden, and the shell wait is capped at 2.5 seconds.

The `/sessions` switcher likewise has an `on Outpost` group. Active rows open a
read-only job view; terminal rows run `/beam back`. Remote needs-human work
contributes to the same needs-you badge as local sessions and raises one edge
toast. Ambient cloud state refreshes every 45 seconds: one failed poll holds
the badge, while two consecutive failures drop the cloud contribution. See
[Beam work to Outpost](/docs/kin/guide/beam/).

`kin ls` lists every live instance across folders — folder, status
(*working* / *needs you* / *idle* / *crashed*), and age — with a `●` marker on
the ones that need you. When a workspace has siblings, each row also includes
its conversation summary or short identity. It's read-only (it never cleans
anything up). Run it from any shell; with no tmux or no live sessions it just
says "no background sessions".

### `--bg` — start work in the background

`kin --bg "refactor the auth module"` begins the work in a persistent session
**without opening the UI**, then returns you to the shell. Check on it with
bare `kin` in the same folder (directly when it is the only available process,
otherwise through the launch chooser) or `kin ls`. It's scriptable — cron and
shell scripts can fire it (it doesn't need a terminal).
`--bg` needs a prompt and can't combine with `-p` (headless-now vs
background-later are opposite promises), `--continue`, or `--resume`. Every
invocation creates a distinct fresh same-workspace instance; its shell
confirmation names how many siblings are already active.

### Cross-session attention

While you work in one session, a sibling that needs you (an approval, a
question, a plan to review) raises a one-time toast — *"~/other needs your
approval — /sessions to jump"* — using its summary or short identity when
several rows share that workspace. The status bar wears a standing
`● N needs you · /sessions` badge until it's resolved. It works whether or not
your current launch is itself persistent.

### Cleanup

Background sessions are tidied at launch time so zombies don't pile up — the
conversation journals are append-only, so a cleaned-up session loses only its
live process state and stays fully resumable. Two knobs (both in
`~/.kin/settings.toml` or via env), tuned per-project if you like:

| Setting | Env | Default | Meaning |
|---------|-----|---------|---------|
| `session_ttl_days` | `KIN_SESSION_TTL_DAYS` | `7.0` | idle/crashed sessions past this age are cleaned up (`0` = never) |
| `session_cap` | `KIN_SESSION_CAP` | `10` | over this many unattended sessions, the oldest idle ones are cleaned up (`0` = uncapped) |

A **needs-you** session is never cleaned up on age alone — a parked human
decision shouldn't vanish silently. A **mid-turn** session is never cleaned up
by the cap. `kin ls` annotates a session that's near its TTL
(`· cleans up in 2d`).

## Rewind & retry

`/rewind [n] [conversation|files|both]` rolls back the last `n` completed
user turns (default 1) — the conversation, the on-disk files, or both. A
bare `/rewind` or `/rewind <n>` behaves exactly as before: it rolls back
the conversation and repaints the transcript from the truncated history.
The cut is always taken at a real user-turn boundary, so a tool round is
never split. Internal end-of-run memory reflection is canonical model history,
but it is not a human turn and never consumes a rewind count or appears in the
picker. Its memory-only workspace checkpoint is likewise ineligible for
`/rewind files`, so a turn with no workspace edits remains a clean no-op. The
journal is rewritten to match, so a resumed session reflects the rewound state.

- `/rewind files` restores on-disk file state to a checkpoint taken just
  before the rewound turn's first edit — **without touching the
  conversation**. If those turns made no edits (or the workdir isn't a git
  repo, or the [snapshot safety net](#file-snapshots) was off), it's a
  clean no-op: "no file changes to rewind."
- `/rewind both` restores files first, then rolls back the conversation to
  match — only if the file restore succeeds. A failed restore leaves the
  conversation untouched (files-first, so you never lose the record of
  what happened without also getting your files back).

`files` and `both` always ask for confirmation, even for a single turn —
restoring the worktree is destructive, and a protective snapshot of the
CURRENT state is taken automatically before either one runs, so a restore
you didn't mean to do is itself reversible.

`/retry` re-sends the last user message — useful after an error or an interrupt.
It still works after a `/rewind`, because the last user turn is recomputed from
the truncated history.

When the **first model request** in a turn ends in a backend hard-error (the
endpoint was unreachable or rejected the request), the error note is followed
by a focusable **↻ retry** button — click it, or `Tab` to it and press `Enter`.
Unlike `/retry`, this first removes the failed turn from history, so the model
sees exactly one fresh copy of your message (no duplicate). If the failure
lands after tools have already run, Kin shows the error without a retry button:
replaying the whole turn could repeat side effects, and splitting the saved
tool-call/result pair would corrupt provider history. Send a new follow-up to
continue safely. The retry note's guidance distinguishes a *recoverable*
failure (a dead/unreachable endpoint — worth retrying as-is) from a *rejected*
request (a bad api key / model id / base url — fix it first, then retry).

Neither `/rewind` nor `/retry` (nor the retry button) runs while a turn or a
compaction is in flight.

### Double-Esc rewind picker

Press ++escape++ twice within about a second — on an empty composer, with
no modal open, and no turn running — to open a picker instead of typing
`/rewind` by hand: it lists your recent turns (newest first, with a short
preview of each), then asks for a scope (conversation / files / both) once
you pick one. ++up++ / ++down++ navigate, ++enter++ selects, ++escape++
backs out with no action at either stage. The picker dispatches through the
exact same `/rewind <n> <scope>` path described above, so `files`/`both`
still confirm before touching your worktree.

A single ++escape++ keeps its normal meaning everywhere (interrupting a
running turn, closing a menu, exiting cursor mode) — the picker only
appears on a *second* tap while kin is otherwise idle.

## Export

`/export [path]` dumps the current session's saved transcript to a markdown
file — a keepsake, not a second live copy. It reads the ON-DISK journal (the
same one resume/rewind read), so it always reflects what's actually durable,
and renders `## You` / `## Kin` sections with tool calls as fenced blocks and
tool results elided to a one-line summary (a full tool result — a
`read_file` dump, a shell command's stdout — would make the export
unreadable). Bare `/export` writes `kin-export-<session-id>.md` into the
workdir; an explicit path wins, and overwrite is allowed with no confirm
(unlike `/clear`/`/rewind`, this is additive, not destructive). Refuses with
a notify while a turn or a compaction is running. The exported file carries
your conversation verbatim, with no sanitization — it's a file you asked
for, not something rendered back at you.

## File snapshots

In a git workspace, kin takes a lightweight checkpoint of your files
**before** the first edit of every turn — a `git commit-tree` recipe under
`refs/kin-snapshots/`, invisible to your real index, HEAD, or worktree
(it never stages, commits, or moves a branch you'd see in `git status` or
`git log`). This is what `/rewind files`/`/rewind both` restore from. The
checkpoint is taken once per turn (a turn that edits three files gets one
checkpoint, not three), and a session keeps its 20 most recent checkpoints
(older ones are pruned automatically).

The safety net is on by default (`KIN_SNAPSHOTS=0` or `snapshots = false`
in `settings.toml` turns it off) and degrades to a silent no-op outside a
git repo — no checkpoint, no error, `/rewind files` just reports nothing
to restore.

**What it does *not* cover:** a shell command or `run_code` script that
writes a file directly (bypassing kin's own `write_file`/`edit_file`
tools) is invisible to this safety net — the checkpoint only fires on
kin's own EDIT-kind tool calls. For those, `git status`/`git diff` (or
your own snapshot habits) are still the tool.

## Terminal notifications

kin gives your terminal a walk-away signal: a bare bell (`\x07`) always,
plus — on a terminal it recognizes as capable (Ghostty, iTerm2, WezTerm, or
kitty) — an OSC 9 escape sequence that surfaces a native desktop
notification (dock bounce / banner) even when the tab isn't focused.

It fires on two moments:

- **A turn finishes** that ran 15 seconds or longer (a fast turn doesn't
  need a walk-away signal). Pressing esc to interrupt never notifies — you
  were right there.
- **kin needs your input** — an approval prompt, a question, a plan or
  settings-proposal review, or a sandbox-override confirmation.

Repeated notifications are debounced to at most one every 10 seconds. If
your terminal reports focus events, the bell is suppressed while the app is
actually focused (a terminal that never reports focus never goes silent —
kin only suppresses once it has *proven* the terminal tells it who has
focus).

The message text is always one of a fixed set of static strings (`kin —
turn complete`, `kin — needs your input`, …) — it never includes any model
or server output. On by default; `KIN_NOTIFY=0` or `notify = false` in
`settings.toml` turns it off. See [`kin -p`](/docs/kin/guide/headless/#exit-codes-the-contract)
for the headless-run equivalent — the same bell fires to stderr at process
completion when stderr is a real terminal.

## Compaction

As history grows toward the context window, compaction replaces the older
portion with one synthetic summary message and keeps the most recent turns
verbatim. Run it manually with `/compact`; add a focus to bias the summary:

```
/compact the auth refactor and the failing tests
```

The summarizer flattens the old history to plain text and produces a structured
summary (task overview, current state, discoveries, next steps, context to
preserve). The result is a single `<summary>…</summary>` user message followed
by the verbatim recent turns — the cut is taken at a user-turn boundary so no
tool round is split and retained thinking-signature blocks are untouched. After
a compact, the journal is rewritten and the context meter re-baselines.

**Proactive fractional auto-compaction is off by default.** It runs only when
you set `KIN_COMPACT_THRESHOLD` (env) or `compact_threshold` (settings), a
fraction of the window clamped to 0.1–0.98. Hard prompt admission remains on:
Kin reserves the backend's configured `max_tokens` before a countable request,
plus a small framing margin, so a long reasoning response still has room inside
the advertised context window. The effective compact trigger is whichever
comes first: the configured fraction or that hard prompt limit.

Kin checks exact prompt tokens before every model round when the backend can
count them. Ordinary compaction keeps recent turns verbatim and applies to root
and child sessions. At a new-turn boundary, if retaining the configured number
of recent turns still leaves the prompt too large, Kin may summarize only the
history completed before the new input; the live input and its same-turn
reminders remain verbatim. If a completed tool round makes a continuation too
large, Kin may compact that completed history and retry once. It never silently
summarizes an oversized live user input: if the preserved input itself cannot
fit, that request is refused intact with the measured prompt/output split so
you can rewind it or change the cap. The number of recent turns kept verbatim
defaults to 4 and is tunable via `KIN_COMPACT_KEEP_TURNS` /
`compact_keep_turns`.

## Context usage

`/tokens` shows where your context is going. On the Anthropic wire it breaks the
total into system prompt, tool definitions, and history (real counts via the
wire's token counter); on the OpenAI-compat wire, which doesn't expose a counter,
it reports the live metered total only. The component figures are approximate —
each includes per-request framing, so they sum to slightly more than the measured
total. The top bar shows live usage continuously as you work.
Its denominator is the effective prompt budget, and `/tokens` separately shows
the model context, output reservation, hard prompt limit, and earlier
auto-compact trigger when configured. Exact count probes refresh this meter but
do not increment Kin's generated-token spend meter.

## Ephemeral runs

Launch with `--no-save` to run without writing a journal. Nothing is persisted,
so the session can't be resumed, rewound, or listed — useful for a throwaway
question you don't want recorded.

## Suppressing empty sessions

Sessions that never receive a user submission — you launch kin and quit
without typing anything — leave **no** journal file on disk. The journal
+ tasks-DAG sidecar pair is created in memory, but `Session.aclose`
deletes them before tearing down the bg subsystems when the per-session
turn counter is still zero. A resumed session that doesn't get a new
turn keeps its file (its history preceded this launch — there's
something to resume). A mode-only change (`/mode strict` then quit) is
also suppressed — no user submission, nothing worth recording.

`--no-save` / `KIN_NO_SAVE` continue to skip persistence entirely; the
suppression only applies on the default save path.

## Old tool names in old journals

The tool registry keeps dispatch-only aliases for `view_file` → `read_file`,
`view_notebook` → `read_notebook`, and `exit_plan` (the pre-plan-lifecycle
tool) so journals written before these renames still resume — the replay
sees the old name, the alias routes it to the current tool, and the model
on the next turn only ever sees the new names. The aliases are not
advertised to the model; they're a backwards-compat seam only. See
[Tools](/docs/kin/guide/tools/) for the full tool surface.

## Troubleshooting

- **A session is not listed:** saved rows are project-scoped. Check the launch
  workspace; subagent journals and `--no-save` sessions are intentionally
  absent.
- **Switching is refused:** wait for the active turn or compaction to settle
  and close any modal.
- **A resumed provider differs:** saved provider-native history fails closed
  across incompatible wires unless you explicitly choose a supported
  conversion.
- **Context is still crowded after a long run:** use `/compact`; use `/fork`
  first when you want a reversible checkpoint.

## Reference

- [Headless runs](/docs/kin/guide/headless/)
- [Commands](/docs/kin/guide/slash-commands/)
- [Keybindings](/docs/kin/guide/keybindings/)
- [Configuration](/docs/kin/getting-started/configuration/)
