## New Skill: continue-claude-work (v1.1.0) - Recover actionable context from local `.claude` session artifacts - Compact-boundary-aware extraction (reads Claude's own compaction summaries) - Subagent workflow recovery (reports completed vs interrupted subagents) - Session end reason detection (clean exit, interrupted, error cascade, abandoned) - Size-adaptive strategy for small/large sessions - Noise filtering (skips 37-53% of session lines) - Self-session exclusion, stale index fallback, MEMORY.md integration - Bundled Python script (no external dependencies) - Security scan passed, argument-hint added ## Skill Updates - **skill-creator** (v1.5.0): Complete rewrite with evaluation framework - Added agents/ (analyzer, comparator, grader) - Added eval-viewer/ (generate_review.py, viewer.html) - Added scripts/ (run_eval, aggregate_benchmark, improve_description, run_loop) - Added references/schemas.md (eval/benchmark schemas) - Expanded SKILL.md with inline vs fork guidance, progressive disclosure patterns - Enhanced package_skill.py and quick_validate.py - **transcript-fixer** (v1.2.0): CLI improvements and test coverage - Enhanced argument_parser.py and commands.py - Added correction_service.py improvements - Added test_correction_service.py - **tunnel-doctor** (v1.4.0): Quick diagnostic script - Added scripts/quick_diagnose.py - Enhanced SKILL.md with 5-layer conflict model - **pdf-creator** (v1.1.0): Auto DYLD_LIBRARY_PATH + rendering fixes - Auto-detect and set DYLD_LIBRARY_PATH for weasyprint - Fixed list rendering and CSS improvements - **github-contributor** (v1.0.3): Enhanced project evaluation - Added evidence-loop, redaction, and merge-ready PR guidance ## Documentation - Updated marketplace.json (v1.38.0, 42 skills) - Updated CHANGELOG.md with v1.38.0 entry - Updated CLAUDE.md (skill count, marketplace version, #42 description) - Updated README.md (badges, skill section #42, use case, requirements) - Updated README.zh-CN.md (badges, skill section #42, use case, requirements) - Fixed absolute paths in continue-claude-work/references/file_structure.md ## Validation - All skills passed quick_validate.py - continue-claude-work passed security_scan.py - marketplace.json validated (valid JSON) - Cross-checked version consistency across all docs
250 lines
7.5 KiB
Markdown
250 lines
7.5 KiB
Markdown
# Claude Code Local File Structure
|
|
|
|
Ground-truth reference for `~/.claude/` directory layout and JSONL session format.
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
~/.claude/
|
|
projects/ # Per-project session storage (primary)
|
|
<normalized-path>/
|
|
sessions-index.json # Master index of all sessions
|
|
<session-id>.jsonl # Session transcript
|
|
<session-id>/ # Session subdirectory (optional)
|
|
subagents/
|
|
agent-<agent-id>.meta.json # Agent metadata
|
|
agent-<agent-id>.jsonl # Agent transcript
|
|
tool-results/
|
|
toolu_<tool-id>.txt # Large tool outputs
|
|
memory/ # Persistent memory files (MEMORY.md, etc.)
|
|
history.jsonl # Global prompt history (no session IDs)
|
|
tasks/ # Task tracking (per-session lock/highwatermark)
|
|
plans/ # Plan documents (random-name.md)
|
|
debug/ # Per-session debug logs (<session-id>.txt)
|
|
transcripts/ # Global tool operation logs (ses_<id>.jsonl)
|
|
file-history/ # File modification backups
|
|
todos/ # Todo items
|
|
```
|
|
|
|
## Path Normalization
|
|
|
|
Project paths are encoded by replacing `/` with `-`:
|
|
|
|
| Original | Normalized |
|
|
|----------|-----------|
|
|
| `/path/to/project` | `-path-to-project` |
|
|
| `/another/workspace/app` | `-another-workspace-app` |
|
|
|
|
## sessions-index.json Schema
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"entries": [
|
|
{
|
|
"sessionId": "20089b2a-e3dd-48b8-809c-0647128bf3b8",
|
|
"fullPath": "~/.claude/projects/-path-to-project/20089b2a-....jsonl",
|
|
"fileMtime": 1741327503477,
|
|
"firstPrompt": "fix the login bug",
|
|
"summary": "Fixed authentication redirect...",
|
|
"messageCount": 42,
|
|
"created": "2026-03-07T03:25:03.477Z",
|
|
"modified": "2026-03-07T12:21:43.806Z",
|
|
"gitBranch": "main",
|
|
"projectPath": "/path/to/project",
|
|
"isSidechain": false
|
|
}
|
|
],
|
|
"originalPath": "/path/to/project"
|
|
}
|
|
```
|
|
|
|
Key fields for session identification:
|
|
- `sessionId` — UUID v4 format
|
|
- `firstPrompt` — first user message (best for topic matching)
|
|
- `summary` — auto-generated summary of the session
|
|
- `modified` — last activity timestamp (ISO 8601)
|
|
- `gitBranch` — git branch at session time
|
|
- `isSidechain` — `false` for main conversations
|
|
|
|
## Compaction in Session Files
|
|
|
|
Claude Code uses [server-side compaction](https://platform.claude.com/docs/en/build-with-claude/compaction). When context fills up, two consecutive lines appear:
|
|
|
|
### Line 1: compact_boundary marker
|
|
|
|
```json
|
|
{
|
|
"type": "system",
|
|
"subtype": "compact_boundary",
|
|
"parentUuid": null,
|
|
"logicalParentUuid": "prev-uuid",
|
|
"compactMetadata": {
|
|
"trigger": "input_tokens",
|
|
"preTokens": 180000
|
|
}
|
|
}
|
|
```
|
|
|
|
### Line 2: Compact summary (special user message)
|
|
|
|
```json
|
|
{
|
|
"type": "user",
|
|
"isCompactSummary": true,
|
|
"isVisibleInTranscriptOnly": true,
|
|
"message": {
|
|
"role": "user",
|
|
"content": "This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion of the conversation.\n\nAnalysis:\n1. **Initial Request**: User asked to...\n2. **Progress**: Completed X, Y, Z...\n3. **Current state**: Working on..."
|
|
}
|
|
}
|
|
```
|
|
|
|
Key properties:
|
|
- **`isCompactSummary: true`** — most reliable way to identify compact summaries
|
|
- **`isVisibleInTranscriptOnly: true`** — not sent to the API, only stored in the transcript
|
|
- Summary is always a plain string in `.message.content` (not an array)
|
|
- Typically 12K-31K characters (high-density information)
|
|
- A long session may have multiple compact boundaries (4+ is common for 10MB+ sessions)
|
|
- The **last** compact boundary's summary reflects the most recent state
|
|
- Messages after the last boundary are the "hot zone" — they were in Claude's live context
|
|
|
|
### Default compaction prompt (from API docs)
|
|
|
|
> "You have written a partial transcript for the initial task above. Please write a summary of the transcript. The purpose of this summary is to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible and will be replaced with this summary."
|
|
|
|
## Session JSONL Message Types
|
|
|
|
Each `.jsonl` file has one JSON object per line. Common types:
|
|
|
|
### file-history-snapshot (always first line)
|
|
|
|
```json
|
|
{
|
|
"type": "file-history-snapshot",
|
|
"messageId": "uuid",
|
|
"snapshot": { "trackedFileBackups": {}, "timestamp": "..." },
|
|
"isSnapshotUpdate": false
|
|
}
|
|
```
|
|
|
|
### User message
|
|
|
|
```json
|
|
{
|
|
"parentUuid": "prev-uuid or null",
|
|
"isSidechain": false,
|
|
"cwd": "/path/to/project",
|
|
"sessionId": "session-uuid",
|
|
"version": "2.1.71",
|
|
"gitBranch": "main",
|
|
"type": "user",
|
|
"message": {
|
|
"role": "user",
|
|
"content": "fix the login bug"
|
|
},
|
|
"uuid": "msg-uuid",
|
|
"timestamp": "2026-03-07T03:25:03.477Z"
|
|
}
|
|
```
|
|
|
|
**Important**: `.message.content` can be:
|
|
- A **string** for plain text user messages
|
|
- An **array** of content blocks for tool results and multi-part messages:
|
|
```json
|
|
"content": [
|
|
{ "type": "tool_result", "tool_use_id": "toolu_...", "content": "..." },
|
|
{ "type": "text", "text": "now do X" }
|
|
]
|
|
```
|
|
|
|
### Assistant message
|
|
|
|
```json
|
|
{
|
|
"type": "assistant",
|
|
"message": {
|
|
"role": "assistant",
|
|
"model": "claude-opus-4-6",
|
|
"content": [
|
|
{ "type": "thinking", "thinking": "internal reasoning..." },
|
|
{ "type": "text", "text": "visible response text" },
|
|
{ "type": "tool_use", "id": "toolu_...", "name": "Bash", "input": { "command": "..." } }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Content block types in assistant messages:
|
|
- `thinking` — internal reasoning (skip when extracting actionable context)
|
|
- `text` — visible response to user (extract this)
|
|
- `tool_use` — tool invocations (useful for understanding what was done)
|
|
|
|
### Tool result (user message with tool output)
|
|
|
|
```json
|
|
{
|
|
"type": "user",
|
|
"message": {
|
|
"role": "user",
|
|
"content": [
|
|
{ "type": "tool_result", "tool_use_id": "toolu_...", "content": "command output..." }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## history.jsonl Schema
|
|
|
|
Global prompt log. Does NOT contain session IDs — only useful for finding when a prompt was issued and in which project:
|
|
|
|
```json
|
|
{
|
|
"display": "/init ",
|
|
"pastedContents": {},
|
|
"timestamp": 1758996122446,
|
|
"project": "/path/to/project"
|
|
}
|
|
```
|
|
|
|
## Extraction Patterns
|
|
|
|
### List recent sessions for current project
|
|
|
|
```bash
|
|
cat ~/.claude/projects/<normalized-path>/sessions-index.json \
|
|
| jq '.entries | sort_by(.modified) | reverse | .[:5] | .[] | {sessionId, firstPrompt, summary, messageCount, modified, gitBranch}'
|
|
```
|
|
|
|
### Extract user text from session tail
|
|
|
|
Handles both string and array content formats:
|
|
|
|
```bash
|
|
tail -n 200 <session-file>.jsonl \
|
|
| jq -r 'select(.type == "user" and .message.role == "user")
|
|
| .message.content
|
|
| if type == "string" then .
|
|
elif type == "array" then map(select(.type == "text") | .text) | join("\n")
|
|
else empty end' \
|
|
| tail -n 80
|
|
```
|
|
|
|
### Extract assistant text (excluding thinking/tool_use)
|
|
|
|
```bash
|
|
tail -n 200 <session-file>.jsonl \
|
|
| jq -r 'select(.message.role == "assistant")
|
|
| .message.content
|
|
| if type == "array" then map(select(.type == "text") | .text) | join("\n")
|
|
else empty end' \
|
|
| tail -n 120
|
|
```
|
|
|
|
### Find sessions by keyword in firstPrompt
|
|
|
|
```bash
|
|
cat ~/.claude/projects/<normalized-path>/sessions-index.json \
|
|
| jq -r '.entries[] | select(.firstPrompt | test("keyword"; "i")) | "\(.modified) \(.sessionId) \(.firstPrompt)"'
|
|
```
|