Claude Desktop’s Cowork mode stores every session as a plain JSON file on your local filesystem. There’s no official documentation for the format. No schema spec, no changelog entry, no developer guide. So I reverse-engineered it.
Where the files live
On Windows:
%AppData%\Claude\local-agent-mode-sessions\{org-id}\{user-id}\local_{session-id}.json
Newer installs may use claude-code-sessions instead of local-agent-mode-sessions. The directory was renamed at some point, and both can coexist on the same machine.
Each session is a self-contained JSON file. No binary encoding, no database, no LevelDB. Just files you can open in any text editor.
How I found this
I started by asking Claude Code to find my Cowork chat logs. It initially pointed me at IndexedDB/https_claude.ai_0.indexeddb.leveldb, which is the browser-based claude.ai storage, not Claude Desktop’s session storage. That’s a different product with a different storage model.
What it did find correctly was the Cowork service logs (cowork-service.log, cowork_vm_node.log, and coworkd.log) sitting in the Claude Desktop logs/ directory. These are infrastructure and daemon logs, not chat history. They’re useful for diagnosing startup failures and VM issues, but they don’t contain your conversations.
GitHub issue #24534 confirmed where the actual session data lives and the local_ prefix convention. From there I had Claude Code enumerate and diff all 146 session files on my machine to build a complete field inventory.
The schema (27 fields)
Every session file contains a subset of 27 observed fields. 15 appear in all 146 sessions. The rest are conditional; they only appear when the relevant feature was used during that session.
Always present (146/146 sessions)
| Field | Type | What it is |
|---|---|---|
sessionId | string | local_ + UUID |
processName | string | Auto-generated three-word name (e.g. sweet-cool-newton) |
vmProcessName | string | Always matches processName |
cwd | string | Working directory inside the VM sandbox |
userSelectedFolders | string[] | Host folders you gave the session access to |
createdAt | number | Epoch milliseconds |
lastActivityAt | number | Epoch milliseconds |
model | string | Model ID (e.g. claude-opus-4-6) |
isArchived | boolean | Whether you archived the session |
title | string | Session title (auto-generated or user-set) |
initialMessage | string | Your first message |
systemPrompt | string | The full Cowork system prompt (~42KB) |
egressAllowedDomains | string[] | Outbound network allowlist (["*"] = unrestricted) |
accountName | string | Your display name, in plaintext |
emailAddress | string | Your email address, in plaintext |
Near-universal (134-144/146)
| Field | Frequency | What it is |
|---|---|---|
remoteMcpServersConfig | 144/146 | Full MCP server configs with tool definitions |
enabledMcpTools | 144/146 | "uuid:tool-name": true/false map |
slashCommands | 134/146 | Available slash commands |
cliSessionId | 134/146 | Separate CLI session UUID |
Conditional (3-64/146)
| Field | Frequency | What it is |
|---|---|---|
chromePermissionMode | 64/146 | Browser automation permission level |
chromeAllowedDomains | 64/146 | Domains the browser can access |
mcqAnswers | 61/146 | Your answers to multiple-choice prompts |
fsDetectedFiles | 54/146 | Files detected on the host filesystem |
userApprovedFileAccessPaths | 30/146 | Paths you explicitly approved |
fileDeleteApprovedMounts | 26/146 | Mounts where deletion was approved |
error | 17/146 | Error message if the session failed |
scheduledTaskId | 3/146 | ID for scheduled/recurring tasks |
Surprises
The system prompt is embedded in every session. Each file contains a ~42KB copy of the full Cowork system prompt (ranging from 41,940 to 42,923 characters across versions). Across 146 sessions, that’s nearly 6MB of duplicated prompt text. This is presumably for reproducibility, since each session is a snapshot of the exact instructions Claude was operating under.
PII is stored in plaintext. accountName and emailAddress appear in every session file with no encryption or obfuscation. If you’re backing up your AppData or syncing it to cloud storage, these files go with it.
Browser automation is a first-class feature. 64 of my 146 sessions had chromePermissionMode and chromeAllowedDomains set. The observed permission mode is follow_a_plan, which suggests a structured approval model rather than open browsing.
Error patterns reveal infrastructure. 17 sessions have an error field. The most common failure is RPC error -1: failed to ensure virtiofs mount, a VM filesystem mount failure. Other errors include daemon disconnects, auth 503s, and API 500 internal server errors. These are the kinds of errors users report in GitHub issues but rarely see documented.
Scheduled tasks exist. 3 sessions have a scheduledTaskId, and mine were etsy-daily-metrics and pinterest-evening-post. This confirms Cowork supports recurring automated tasks, a feature that isn’t widely discussed.
What’s NOT in these files
The session JSON contains metadata, configuration, and user decisions, but not the full conversation transcript. There are no message arrays, no assistant responses, no tool call logs. The actual conversation turns appear to live in the VM process state referenced by processName, not in these files.
If you’re looking for the full back-and-forth chat history, these files won’t have it. They’re session manifests, not chat logs.
The schema file
I’ve published a JSON Schema documenting all 27 fields with types, descriptions, and frequency data. It’s based on direct observation, not official documentation, because no official documentation exists.
Why this matters
If you’re building tools on top of Claude Desktop, mining your session history, or just want to understand what’s stored on your machine, this is the reference that doesn’t exist elsewhere. The format is undocumented but stable enough across 146 sessions to be useful.
Just don’t treat it as a contract. Anthropic can change it anytime.