Session Persistence
Kangentic persists every agent session to a local SQLite database. Sessions survive application crashes, system restarts, and intentional suspension. You never lose work.
How Persistence Works
Section titled “How Persistence Works”Every interaction between Kangentic and the agent CLI is stored in real-time:
- Conversation history - The full prompt and response chain
- Session metadata - Start time, status, worktree path, branch name
- Terminal output - Raw terminal data for replay
- Task state - Board position, description, and user notes
Data is written incrementally as the agent works, not just when the session ends. If the application crashes mid-session, the data up to that point is preserved.
Session States
Section titled “Session States”| State | Description |
|---|---|
| Running | Agent is actively working. Session data is being written in real-time. |
| Queued | Waiting for a free slot because the max-concurrent-sessions limit is reached. Promoted to Running automatically (FIFO) when a slot frees up. |
| Suspended | Agent was intentionally paused (by user or system). Full state is preserved for resume. |
| Exited | Agent process terminated (finished, errored, or crashed). Check exit_code for details. |
| Orphaned | Session was running when the application closed unexpectedly. Recoverable on next launch. |
The Agent Monitor shows sessions from every project grouped by these states, as Idle, Active, Paused (suspended plus queued), and Recently finished.
Crash Recovery
Section titled “Crash Recovery”When Kangentic starts, it checks for sessions that were in a “Running” state when the application last closed. These are marked as crashed and can be:
- Resumed - Relaunch the agent with the full conversation context. The agent picks up where it left off.
- Archived - Keep the session data but don’t resume. Useful if the task is no longer relevant.
User-Paused Sessions
Section titled “User-Paused Sessions”Pausing from the header button or its kebab twin also closes the task’s detail window, on the reasoning that pausing means “I am done with this task for now”. The session is only suspended, never killed, so it resumes exactly as before when you reopen the task. This is wired to the pause gesture rather than to the suspended state, so the other routes into suspension leave your windows alone: a board move to a To Do or Done column, the Code Review column, and a restart with auto-resume disabled all suspend without closing anything.
Sessions paused manually by the user (via the pause button in the task detail window or the kebab menu) are remembered across restarts. On relaunch, user-paused sessions remain paused instead of auto-resuming. This respects user intent - if you paused an agent, it will not start back up on its own. Only system-suspended sessions (those suspended by shutdown or column moves) auto-resume. The Agent Monitor lists paused sessions under its Paused group, but its rows carry no pause or resume controls - open the task’s detail window (from the monitor or the board) to resume.
Resuming Sessions
Section titled “Resuming Sessions”When you resume a suspended or crashed session, Kangentic:
- Reads the full conversation history from the database
- Recreates the agent session with the stored native session ID (via each CLI’s native resume flag)
- Reconnects the terminal to the new process
- The agent continues working with full awareness of previous context
The agent sees the same conversation it had before, so it can continue its work without repeating steps or losing context.
When resume is refused
Section titled “When resume is refused”Since v0.36.0, three states have no in-place Resume, each with a message naming the way forward instead of an error:
| Task is | Message |
|---|---|
| In a To Do column | Cannot resume a session for a task in the To Do column |
| In Done | This task is complete. Move it out of Done to continue working on it. |
| Archived in any other column | This task is archived. Restore it to the board to continue working on it. |
The gate is the column’s role, not its auto-spawn setting, so a custom column you have turned auto-spawn off for still offers Resume.
A completed task lives in Done with its worktree deleted and its session suspended. Resuming it in place would recreate that worktree and put a live agent on a task with no board card, burning quota with nothing on screen to notice it. The designed route back is to move the task out of Done, which unarchives it first and then spawns through the normal path. Moving a task out of Done also unarchives it immediately rather than waiting for the spawn to land, and the card shows the restore as in progress rather than as Paused, so a slow worktree rebuild does not read as a stall.
A conversation the agent never wrote
Section titled “A conversation the agent never wrote”Kangentic will not resume a conversation that does not exist. A session that ends before its first turn leaves a resumable-looking record pointing at a transcript the agent CLI never wrote, and re-entering it used to leave you on a bare shell with the agent gone.
That is now detected and the spawn is downgraded to a fresh one. The check is deliberately narrow, and all three conditions must hold: the transcript path is the one the agent itself reported, that same report must independently say the conversation had no turns (no tokens, no cost), and any missing or unreadable evidence leaves the resume exactly as it was. A session that had real turns is never downgraded, even if its transcript has moved.
Resume matrix:
| Agent | Resume | Mechanism |
|---|---|---|
| Claude Code | ✓ | Caller-controlled session ID via --resume for deterministic re-entry |
| Codex CLI | ✓ | codex resume <id> with the CLI-generated rollout ID |
| Gemini CLI | ✓ | --resume <id> against the auto-generated chat session file |
| Cursor CLI | ✓ | agent --resume=<id> using the session ID captured from the init event on Cursor’s stream-JSON output |
| GitHub Copilot CLI | ✓ | Caller-controlled UUID via --resume <uuid> (same semantics as Claude) |
| Grok Build | ✓ | Caller-owned session IDs: --session-id <uuid> on first launch, --resume <uuid> to re-enter (Claude-identical flag semantics) |
| Antigravity CLI | ✓ | agy --conversation <uuid> with the conversation ID captured from hook payloads or the shutdown summary; resumes cross-directory |
| OpenCode | ✓ | Native session IDs (ses_<id>) captured from the plugin’s session.created event |
| Aider | - | Edit-first and relaunched fresh. Prior edits are still on the worktree, but conversation history is not carried over |
| Qwen Code | ✓ | Caller-owned session IDs: --session-id <uuid> on first launch, --resume <uuid> to re-enter (Gemini-style chat session file) |
| Kimi Code | ✓ | Caller-owned session IDs via --session <uuid>; --continue resumes the latest |
| Factory Droid | ✓ | droid --cwd <cwd> --resume <uuid> with the UUID from ~/.factory/sessions/<cwd-slug>/<id>.jsonl |
| Warp (Oz CLI) | - | oz does not expose a session-resume mechanism. Re-entry starts a new session in the preserved worktree |
| Ollama | - | Local single-turn chat: each ollama run is one turn with no CLI-level session resume. Re-entry starts a fresh run in the preserved worktree |
Kangentic preserves terminal scrollback across resume so you still see the prior session’s output.
Isolated Sessions
Section titled “Isolated Sessions”A task normally runs on a single main session - its primary conversation, resumed as the task moves between columns. A column can instead be set to run tasks on an isolated session: a separate, independently-resumable conversation of its own, keyed by that column.
An isolated session does not inherit the main conversation, which suits work that should stay independent of it - a code review column is the canonical example. A task can hold its main session plus one isolated session per isolated column, all sharing the same worktree, so edits made in either are real and persist. Only one agent runs at a time per task.
- Entering an isolated column suspends the main session and resumes (or freshly spawns) the column’s isolated session.
- Leaving an isolated column for a normal column suspends the isolated session and resumes the main session.
- The session tab badges the active track as Isolated or Main so you always know which conversation you’re watching.
Two per-column settings control this, both round-tripped to kangentic.json: Session Target (main or isolated) and Session Spawn Strategy (create_or_resume or always_spawn_new). Isolated columns default to spawning a fresh pass each entry - the reviewer archetype - while a main column resumes for continuity. See Column-Level Settings.
State Machine and Locking
Section titled “State Machine and Locking”Added in v0.15.0. Every session lifecycle transition (spawn, suspend, resume, kill, queue-promote) runs through an atomic state machine with a per-task lock. The lock prevents two transitions from interleaving on the same task, which was the root cause of several pause/resume race conditions before v0.15.0: a rapid drag could trigger a spawn while a prior kill was still cleaning up, leaving a half-alive session. Now a move that arrives while the task is mid-transition is queued until the current transition completes, then either executes or is coalesced with the target state if it became redundant.
The state machine also coordinates with the concurrency queue: if a spawn transition finishes by placing the session in the queue (because the max-concurrent limit is reached), queue promotion runs under the same lock so a later manual suspend doesn’t race with an automatic promotion.
Session History
Section titled “Session History”All completed and archived sessions are kept in the database. You can:
- Browse past sessions from the task card
- View the full conversation and terminal output
- See what files the agent modified
- Re-read the agent’s reasoning and decisions
This creates a searchable history of all agent work done in your project.
Storage
Section titled “Storage”Session data is stored in .kangentic/kangentic.db at the root of your repository. This is a SQLite database that you should add to your .gitignore (Kangentic does this automatically on first run).
Lifetime usage history
Section titled “Lifetime usage history”Per-session token and cost samples are append-only in a separate usage_history table, so the Usage Stats Dashboard’s today, week, month, and all period totals stay accurate even after you delete a task or wipe a session. Deleting a task removes its row from sessions and tasks but leaves the historical samples intact. The dashboard’s saved range lives in usageStatsPeriod (see Configuration Reference).
Next steps
Section titled “Next steps”Next: Activity Detection - how Kangentic knows when a session is idle.
See also:
- Notifications - alerts when sessions need you
- Agent Monitor - every project’s sessions, grouped by these states
- Configuration Reference - session-related config keys
Kangentic is free and open source. A star helps other people find it.
Star on GitHub