Sessions
How DorkOS manages Claude conversation sessions and their lifecycle
Sessions
A session is a single conversation with Claude. Every message you send, every tool Claude uses, and every response you receive belongs to a session. Sessions are the central unit of interaction in DorkOS.
Session Lifecycle
Creating a Session
When you start a new conversation, a session is created with:
- A unique ID (UUID) that identifies the session across all clients
- A working directory that tells Claude where to operate on your filesystem
- A permission mode that controls whether tool calls require your approval
You can create sessions through the DorkOS UI, the REST API, or by starting a conversation with the Claude Code CLI directly.
Sending Messages
Each message is delivered to the Claude Agent SDK, which streams back a response. During streaming you receive real-time events:
- Text deltas — Incremental chunks of Claude's response
- Tool calls — Actions Claude wants to take (reading files, running commands, etc.)
- Approval requests — Prompts for you to approve or deny a tool call
- Task updates — Progress on multi-step operations
Session Locking
Only one client can write to a session at a time. When you send a message, DorkOS acquires an exclusive lock on that session using your client ID (sent via the X-Client-Id header). If another client tries to write to the same session, it receives a 409 conflict response with the lock holder's ID and acquisition time.
Locks auto-expire after 5 minutes and are released immediately when the SSE connection closes.
Multiple clients can view the same session simultaneously — only sending messages requires an exclusive lock.
Storage
DorkOS does not maintain a separate session database. All session data lives in JSONL transcript files managed by the Claude Agent SDK. This is the single source of truth.
Transcript Files
Each session has a corresponding file at:
~/.claude/projects/{project-slug}/{session-id}.jsonlThese files contain every interaction as newline-delimited JSON. The TranscriptReader service parses them to extract:
- Session metadata — ID, title (from the first user message), timestamps, permission mode
- Message history — The full conversation including user messages, assistant responses, and tool results
- Session list — Built by scanning the project directory for all
.jsonlfiles
Metadata is computed on every request, so it always reflects the current state of the file.
Cross-Client Visibility
Because sessions are plain files on disk, any client that can read the same filesystem sees the same sessions:
- A session started in the DorkOS web UI appears in the Claude Code CLI
- A session started from the CLI shows up when you open DorkOS
- The Obsidian plugin reads from the same location
Start a task in one tool, pick it up in another.
Session Sync
When multiple clients are open, DorkOS keeps them in sync using a file-watching mechanism.
How Sync Works
- A client subscribes to updates via a persistent SSE connection (
GET /api/sessions/:id/stream) - The server watches the session's JSONL file for changes using a file watcher
- When the file changes — from DorkOS, the CLI, or any other client — the server sends a
sync_updateevent - The client re-fetches message history to display the latest state
Sync events are debounced at 100ms to handle rapid writes efficiently. The server reads only new content using incremental byte-offset tracking, so re-fetches are fast even for long sessions.
Sync Events
| Event | When | Data |
|---|---|---|
sync_connected | On initial SSE connection | { sessionId } |
sync_update | When the transcript file changes | { sessionId, timestamp } |
The message history endpoint supports ETag caching. Clients send If-None-Match headers and
receive 304 responses when nothing has changed, keeping re-fetches efficient.
Session Metadata
| Field | Source |
|---|---|
| ID | UUID from the JSONL filename |
| Title | First user message in the transcript |
| Preview | Beginning of the last assistant message |
| Created | File creation timestamp |
| Updated | File modification timestamp |
| Permission mode | Extracted from the SDK init message |
Working Directories
Each session operates within a working directory that determines where Claude can read and write files. The working directory is:
- Set when the session is created
- Persisted in the URL as the
?dir=query parameter (in standalone mode) - Validated against a configurable boundary to prevent access outside allowed paths
The directory picker in the DorkOS sidebar lets you browse and select a working directory before starting a session.