Skip to content

Sessions

A session is a continuous sequence of events: a conversation with an AI agent, including tool calls, thinking, and responses. Sessions provide audit trails, enable resumption, and persist as markdown files.

Architecture

Sessions follow Crucible’s “plaintext first” philosophy:

  • Markdown is truth — Each session saves as a markdown file
  • Daemon manages state — the daemon tracks active sessions via RPC
  • Resume anytime — Pick up previous sessions with cru session open

Daemon Integration

Sessions are managed by the daemon (cru daemon serve):

┌─────────────────┐ ┌─────────────────────┐
│ cru chat │◄───────►│ cru daemon serve │
│ │ JSON-RPC│ │
│ TUI/CLI client │ │ SessionManager │
│ │ │ AgentManager │
└─────────────────┘ └─────────────────────┘

RPC Methods:

  • session.create — Start new session
  • session.list — List all sessions
  • session.get — Get session details
  • session.load — Load a persisted session from storage into daemon memory
  • session.pause — Pause a running session
  • session.unpause — Unpause a paused session (programmatic, no TUI)
  • session.resume — Resume a session in the TUI (interactive)
  • session.end — End session
  • session.send_message — Send a message and stream the response
  • session.configure_agent — Configure the agent for a session
  • session.subscribe / session.unsubscribe — Event streaming
  • session.archive — Archive a session (remove from active list)
  • session.unarchive — Restore an archived session to active
  • session.delete — Permanently delete a session

CLI naming vs RPC methods: The daemon RPC methods are session.resume (open in TUI) and session.unpause (reactivate programmatically). The CLI commands use clearer names: cru session open maps to session.resume, and cru session resume maps to session.unpause. The old cru session unpause still works as a deprecated alias. Scripts should use cru session resume; humans picking up a conversation should use cru session open.

Session Storage

Sessions are saved under the daemon’s data root — ~/.crucible/sessions/ by default — not inside a kiln. A session attaches kilns as its knowledge scope; where it is filed is a separate question from what it can read.

~/.crucible/sessions/
├── chat-2026-01-02T1430-a1b2c3/
│ ├── meta.json # kilns, workspace, agent, state
│ ├── session.jsonl # append-only event log
│ └── session.md # human-readable transcript
└── chat-2026-01-21T0900-c3d4e5/

Because transcripts live outside kilns, a kiln can be shared, synced, or committed to git without carrying your conversations with it.

Where your old sessions went

Sessions used to live in {kiln}/.crucible/sessions/. The first daemon start after upgrading moves them to the layout above, and this happens once, automatically, for every kiln the daemon knows about (your config’s kilns and every registered project’s).

Two cases worth knowing:

  • Id collisions. Two kilns could each hold a session with the same id. The first keeps its id; the other is republished as {id}--{8 hex}, derived from the kiln it came from, so it is stable across re-runs. Both survive — nothing is overwritten.
  • Sessions the move could not complete. If a session cannot be relocated (unreadable, or both the id and its disambiguated name are taken) it is left where it is and logged as skipped. It stays on disk in {kiln}/.crucible/sessions/, but cru session list and cru session search read only the new root, so it will not appear until you move it by hand.

Run the daemon with RUST_LOG=info on the first start after upgrading if you want to see the migration report.

Session Log Format

Sessions are readable markdown when exported:

---
session_id: chat-20250102-1430-a1b2
workspace: /home/user/project
model: claude-3-5-sonnet
started: 2025-01-02T14:30:00Z
---
# Chat Session
## User
Find all notes tagged #project and summarize them
## Assistant
I'll search for notes with the project tag.
### Tool Call: search_by_tags
```json
{"tags": ["project"]}

Tool Result

Found 12 notes matching #project.

Let me read through these and create a summary…

User

Tell me more about Project Beta

## CLI Commands
Crucible provides a full set of session subcommands. They split into two groups: **user-facing** commands for everyday use, and **daemon** commands for programmatic session control.
### User-Facing Commands
#### List Sessions
```bash
cru session list

Shows recent sessions with ID, workspace, and timestamp.

Search Sessions

Terminal window
cru session search "rust"

Search sessions by title or content.

Show Session Details

Terminal window
cru session show chat-20250102-1430-a1b2

Display details for a specific session, including model, message count, and timestamps.

Open a Session (Interactive TUI)

Terminal window
cru session open chat-20250102-1430-a1b2

Opens the session in the interactive TUI. The conversation history loads and you can continue chatting. This is the command humans use to pick up where they left off.

Export Session

Terminal window
cru session export chat-20250102-1430-a1b2 -o session.md

Export a session to a standalone markdown file.

Cleanup Old Sessions

Terminal window
cru session cleanup # only sessions sharing the invoking kiln
cru session cleanup --all-kilns # every session on this machine

Remove old sessions. Every session on the box lives in one flat root now, so the scope is stated rather than implied: without --all-kilns only sessions that share a kiln with the invoking one are eligible, which is also why --all-kilns is the only way a kiln-less session is ever collected.

cru session reindex is retired — sessions no longer live inside a kiln, so there is no per-kiln session corpus to rebuild.

Daemon Commands

These commands control sessions at the daemon level. They’re designed for scripts, automation, and multi-client workflows rather than interactive use.

Create a Session

Terminal window
cru session create # Basic creation
cru session create --agent researcher # With an agent card
cru session create --acp claude # With an external ACP agent
cru session create --title "Auth refactor" --workspace /path/to/project
ID=$(cru session create -q) # Capture session ID for scripting
cru session create -f json # Structured JSON output

Create a new daemon session. The -q/--quiet flag prints only the session ID, which is handy for capturing in shell variables. Use --title to give the session a human-readable name and --workspace to pin it to a specific project directory.

--agent and --acp name different things and cannot be combined. --agent runs the built-in internal agent with an agent card‘s prompt, model, tool policy and MCP servers layered over your config defaults. --acp instead launches an external agent subprocess by profile name (claude, gemini, codex, cursor, opencode, or anything under [acp.agents.*]). cru agents list shows both. Either way the daemon resolves the name before the session exists, so an unknown one fails without leaving a session behind.

--agent named an ACP profile in earlier versions. It names a card now, so that it agrees with cru agents; passing a profile name to it reports the mismatch and points at --acp.

Pause a Session

Terminal window
cru session pause chat-20250102-1430-a1b2

Pause a running daemon session. The session stays in memory but stops processing.

Resume a Session (Daemon)

Terminal window
cru session resume chat-20250102-1430-a1b2

Reactivate a paused daemon session without opening a TUI. Use this in scripts and automation workflows. For interactive use, prefer cru session open instead. The old cru session unpause still works as a deprecated alias.

End a Session

Terminal window
cru session end chat-20250102-1430-a1b2

End a daemon session. The session is finalized and persisted.

Send a Message

Terminal window
cru session send chat-20250102-1430-a1b2 "Analyze the auth module"
# Or with env var:
CRU_SESSION=chat-20250102-1430-a1b2 cru session send "Analyze the auth module"
# Or pipe from stdin:
echo "Analyze the auth module" | cru session send chat-20250102-1430-a1b2

Send a message to a session and stream the response. Both the session ID and message are positional arguments. If you set CRU_SESSION, you can omit the ID entirely.

Configure Agent

Terminal window
cru session configure chat-20250102-1430-a1b2 -p openai -m gpt-4o

Configure the agent backend for a session: provider, model, and endpoint. For runtime parameter tweaks (model, thinking budget), use cru set instead:

Terminal window
cru set chat-20250102-1430-a1b2 thinkingbudget=high

Load a Session

Terminal window
cru session load chat-20250102-1430-a1b2

Load a persisted session from storage into daemon memory. This doesn’t open a TUI; it just makes the session available for daemon operations like send, pause, or configure.

Scripting Patterns

A full programmatic lifecycle, start to finish:

Terminal window
# Create, configure, use, and tear down a session
ID=$(cru session create -q --title "Code review" --acp claude)
cru session configure "$ID" -p anthropic -m claude-sonnet-4-20250514
cru session send "$ID" "Review the auth module for security issues"
cru session pause "$ID"
# ... later ...
cru session resume "$ID"
cru session send "$ID" "Now check the database layer"
cru session end "$ID"

All lifecycle commands accept -f json for structured output, which pairs well with jq:

Terminal window
cru session pause "$ID" -f json | jq .previous_state
cru session list -f json | jq '.sessions[].session_id'
cru session search "auth" -f json | jq '.[].session_id'

Environment Variables

VariablePurpose
CRU_SESSIONDefault session ID for send and cru set when no positional ID is given

Start a New Chat

Terminal window
cru chat # Auto-creates a new session

Running cru chat starts a fresh session. If there’s a recent session for the current workspace, it may auto-resume.

In-TUI Session Management

Resume on Send

When you start cru chat, if there’s a recent session for the current workspace, it auto-resumes. Your first message continues the previous conversation.

Switch Sessions

Use the :session command:

:session list # Show available sessions
:session new # Start fresh session

Session Archiving

Sessions have two states: active and archived. Active sessions appear in session.list by default. Archived sessions are hidden unless you explicitly ask for them.

Active vs Archived

ActiveArchived
Visible in session.listYesOnly with include_archived: true
Can receive messagesYesNo (must unarchive first)
Counts toward “recent sessions”YesNo
Data preservedYesYes
Can be resumedYesYes (after unarchive)

Archiving doesn’t delete anything. It moves the session out of the active view so your session list stays manageable. Unarchive brings it back.

Manual Archive and Unarchive

Use the session.archive and session.unarchive RPC methods. Both require session_id and kiln parameters:

Terminal window
# Archive a session
cru session archive chat-20250102-1430-a1b2
# Unarchive it later
cru session unarchive chat-20250102-1430-a1b2

Deleting Sessions

To permanently remove a session, use session.delete. This cleans up both the daemon state and the agent resources. Requires session_id and kiln parameters:

Terminal window
cru session delete chat-20250102-1430-a1b2

Deletion is irreversible. The session’s JSONL file and any associated daemon state are removed.

Listing Archived Sessions

By default, session.list only returns active sessions. Pass include_archived: true to see everything:

Terminal window
cru session list --all # includes archived sessions

Auto-Archive

The daemon automatically archives stale sessions. A background sweep runs every 30 minutes, checking for sessions that have been inactive (no messages, no subscribers) beyond a configurable threshold.

Default threshold: 72 hours of inactivity.

Configure it in ~/.config/crucible/config.toml:

[server]
auto_archive_hours = 72 # default; set to 0 to disable

The sweep skips sessions that have active subscribers (connected clients). It also re-checks activity timestamps before archiving to avoid race conditions where a session receives new activity between the staleness check and the archive operation.

Auto-archived sessions can be unarchived at any time. No data is lost.

Session Configuration

Session behavior is configured through the [chat] section in ~/.config/crucible/config.toml. The daemon manages session persistence automatically; sessions always save under the daemon data root (~/.crucible/sessions/), never inside a kiln.

[chat]
# Default chat model (can be overridden per session)
# model = "llama3.2"
# Show thinking/reasoning tokens from models that support it
# show_thinking = false

Agent Configuration per Session

Each session tracks agent configuration:

  • Model — LLM model (e.g., claude-3-5-sonnet, gpt-4o)
  • Thinking Budget — Token budget for extended thinking
  • Temperature — Response randomness
  • Tools — Available MCP tools

Change mid-session via :set or :model:

:set model claude-3-5-sonnet
:set thinkingbudget 8000
:model gpt-4o # Opens model picker

Changes persist for the session and sync across connected clients.

Events

Sessions emit events that can be subscribed to via RPC:

EventDescription
stream_startResponse streaming begins
stream_chunkText chunk received
stream_endResponse complete
tool_callTool invocation
tool_resultTool completed
thinkingThinking/reasoning tokens
errorError occurred

Subscribe from external tools:

Terminal window
cru session subscribe <session-id>

See Also

  • chat — Interactive chat command
  • Commands — TUI REPL commands
  • agents — Agent configuration