skills/deglacer/SKILL.md
MANDATORY gate BEFORE running jq on any .jsonl under ~/.claude/ or reading past CC sessions. Invoke FIRST when introspecting conversations, searching session history, parsing transcripts, or building tools that read ~/.claude/projects/ data. Provides the CC JSONL schema reference and `deglacer` CLI tool — prevents the 54-attempt fumble pattern where Claudes guess at field names. Triggers on 'what happened last session', 'find when we discussed', 'parse session', 'read conversation', 'session history', 'token usage', 'deglacer'. Do NOT use for live session context (use garde-manger) or git history (use git log). (user)
npx skillsauth add spm1001/trousse deglacerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Deglazing the pan to lift the fond — extracting the good bits from past sessions.
You are working with Claude Code session data. This includes:
~/.claude/projects/ session dataDo NOT guess at the schema. The CC JSONL format has multiple entry types, triple-duty user entries, streaming-duplicated message.ids, and inconsistent field presence across versions. This reference is the source of truth.
git log / git blame for code change historydeglacer is the CC JSONL extraction CLI, installed as a uv tool. Use it instead of raw jq for structured extraction.
# Install (once):
uv tool install ~/Repos/batterie/deglacer
# Use:
deglacer SESSION.jsonl
deglacer SESSION.jsonl # conversation text (human + assistant)
deglacer --summary SESSION.jsonl # human messages only (what was discussed)
deglacer --with-tools SESSION.jsonl # include tool call summaries
deglacer --with-thinking SESSION.jsonl # include thinking blocks
deglacer --last 5 SESSION.jsonl # last 5 turns only
deglacer --json SESSION.jsonl # structured JSON output
deglacer --stats SESSION.jsonl # session statistics (tokens, models, tools)
deglacer --timeline SESSION.jsonl # timestamped turn log
deglacer --find "search term" # search across recent sessions
deglacer --recent # list recent sessions (default 20)
deglacer --recent 10 # list N most recent
deglacer --today # list today's sessions
deglacer --since 2026-03-25 # sessions since a date
deglacer --with-tools --last 10 SESSION.jsonl # recent turns with tools
deglacer --with-tools --with-thinking --json ... # everything, structured
deglacer --summary --last 5 SESSION.jsonl # quick recap of recent turns
Sessions live at:
~/.claude/projects/{encoded-cwd}/{session-uuid}.jsonl
Where {encoded-cwd} replaces / with - in the project path.
Subagent transcripts: {session-uuid}/subagents/agent-{id}.jsonl.
Find recent sessions:
ls -lt ~/.claude/projects/*/*.jsonl | head -20
Find sessions for a project:
ls -lt ~/.claude/projects/-home-modha-Repos-myproject/*.jsonl
Match session to slug/name:
head -1 SESSION.jsonl | jq '{sessionId, slug, version}'
Each line in a .jsonl file is one JSON object. The .type field discriminates.
| Type | Purpose | Has timestamp? |
|------|---------|---------------|
| assistant | Claude's response | Yes |
| user | Human msg / tool result / skill injection | Yes |
| progress | Streaming bash/hook/agent output | Yes |
| system | Turn timing, API errors, slash commands | Yes |
| summary | Context compaction | No |
| queue-operation | Input typed while Claude busy | Yes |
| last-prompt | Records last user text | No |
| custom-title | User-set session name | No |
| agent-name | Session agent name | No |
| file-history-snapshot | File backup state | No |
| pr-link | Created PR reference | Yes |
| saved_hook_context | Persisted hook output | Yes |
uuid string Unique entry ID
parentUuid string? Previous entry (linked list)
sessionId string Session UUID (matches filename)
timestamp string ISO 8601
cwd string Working directory
gitBranch string Current git branch
version string CC version (e.g. "2.1.85")
slug string Human-readable session name
userType string Always "external"
entrypoint string "cli" (absent in v2.0.x)
isSidechain boolean Side conversation flag
{
"type": "assistant",
"message": {
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "claude-opus-4-6",
"content": [/* content blocks */],
"stop_reason": "end_turn" | "tool_use" | null,
"usage": {
"input_tokens": 119,
"cache_creation_input_tokens": 18531,
"cache_read_input_tokens": 36004,
"output_tokens": 500
}
},
"requestId": "req_..."
}
Content block types:
{type: "text", text: "..."} — Claude's text{type: "tool_use", id: "toolu_...", name: "Bash", input: {...}} — tool call{type: "thinking", thinking: "...", signature: "..."} — extended thinkingDRAGON: Multiple entries share the same message.id. CC streams
incremental updates. Merge content blocks by message.id, dedup
tool_use blocks by their id field. deglacer handles this automatically.
DRAGON: stop_reason is null in older sessions (pre-v2.1.79).
The user type serves three purposes. Discriminate with:
| Subtype | How to detect | Content shape |
|---------|--------------|---------------|
| Human message | typeof content === "string", has permissionMode | String |
| Tool result | Has toolUseResult | Array of {type: "tool_result"} |
| Skill/system injection | isMeta: true | Array of {type: "text"} |
Human message:
{
"type": "user",
"message": {"role": "user", "content": "the actual human text"},
"permissionMode": "default",
"promptId": "..."
}
Tool result:
{
"type": "user",
"message": {"role": "user", "content": [
{"type": "tool_result", "tool_use_id": "toolu_...", "content": "output text"}
]},
"toolUseResult": {/* shape varies by tool */},
"sourceToolAssistantUUID": "..."
}
toolUseResult shapes:
| Tool | Keys |
|------|------|
| Bash | stdout, stderr, interrupted, isImage, noOutputExpected |
| Bash (large) | + persistedOutputPath, persistedOutputSize |
| Write/Edit | content, filePath, originalFile, structuredPatch, type |
| Read | file, type |
| Agent | agentId, agentType, content, prompt, status, totalDurationMs, totalTokens, totalToolUseCount, usage |
| Error | Bare string: "User rejected tool use" |
The input_tokens field is ONLY the non-cached portion.
Real input = input_tokens + cache_creation_input_tokens + cache_read_input_tokens.
{"type": "summary", "leafUuid": "...", "summary": "short text"}
No uuid, parentUuid, timestamp, version, or sessionId. Three fields only.
.subtype discriminates:
turn_duration: {durationMs, messageCount}api_error: {error: {status, headers, requestID}, retryInMs, retryAttempt}local_command: {content: "...", level: "info"} — slash commandsQuick schema discovery (do this FIRST, not head | jq .):
jq -r '.type' FILE.jsonl | sort | uniq -c | sort -rn
Extract human messages:
jq -r 'select(.type == "user" and .permissionMode and (.isMeta | not))
| .message.content' FILE.jsonl
Extract assistant text (handles multi-block):
jq -r 'select(.type == "assistant")
| [.message.content[]? | select(.type == "text") | .text]
| select(length > 0) | join("\n")' FILE.jsonl
Extract tool calls:
jq -c 'select(.type == "assistant")
| [.message.content[]? | select(.type == "tool_use")
| {tool: .name, input_keys: (.input | keys)}]
| select(length > 0)' FILE.jsonl
Session timeline:
jq -c 'select(.type == "user" or .type == "assistant")
| {ts: .timestamp, type, model: .message.model?}' FILE.jsonl
Token usage per turn:
jq -c 'select(.type == "assistant") | .message.usage
| {in: (.input_tokens + .cache_creation_input_tokens + .cache_read_input_tokens),
out: .output_tokens}' FILE.jsonl
Find sessions mentioning a term:
# Prefer: deglacer --find "term"
# Raw jq fallback:
for f in ~/.claude/projects/*/*.jsonl; do
if jq -e 'select(.type == "user" and (.message.content | type) == "string"
and (.message.content | test("term"; "i")))' "$f" >/dev/null 2>&1; then
echo "$f"
fi
done
| Don't | Why | Do instead |
|-------|-----|-----------|
| jq -s '.' on JSONL | Slurps entire file into memory as array | Stream line-by-line (default jq behaviour) |
| jq '.[]' on JSONL | JSONL isn't an array | Each line is already a separate object |
| .role at top level | Role is at .message.role, not top-level | Use .type for entry type |
| .type == "message" | No such type | Types: user, assistant, progress, system, etc. |
| .type == "human" | No such type | .type == "user" + check it's not a tool result |
| head -1 \| jq . for discovery | Wastes a turn, first line may be queue-operation | jq -r '.type' \| sort \| uniq -c |
| Assume content is string | Assistant content is always array; user content varies | Check type before accessing |
| 2>/dev/null on everything | Hides real errors | Understand the schema, don't hedge |
| Guess at field names | 39% of jq-on-.claude commands are schema discovery | Read this reference |
tools
Orchestrates cross-machine repo hygiene + GitHub account cleanup via an audit→approve→execute process that prevents accidental deletion. FIRST sweeps every git repo across machines (local + ssh) for uncommitted/unpushed work and true ahead/behind drift, THEN audits GitHub-side — Dependabot alerts traced to unused-direct vs transitive deps, stale forks, orphaned secrets, failing workflows, plugin version-bump gaps. Triggers on 'clean up GitHub', 'audit my repos', 'uncommitted or unpushed changes', 'are my repos in sync', 'push discipline', 'Dependabot trouble', 'unused deps', 'stale forks', 'dependency audit'. Requires gh CLI (+ ssh for remote hosts). (user)
development
Deep clean and structural health check for Claude-maintained codebases. INVOKE BEFORE adding significant complexity, WHEN inheriting an unfamiliar repo, or when something feels off and you can't name it. Three agents — Cracks (architecture), Dustballs (convention drift), Goofs (correctness) — examine in parallel, then synthesise into an honest assessment. Triggers on 'toise', 'deep clean', 'health check', 'should I be worried', 'check this codebase', 'is the architecture sound'. (user)
development
Three-lens code review using parallel subagents: Epimetheus (hindsight — bugs, debt, fragility), Metis (craft — clarity, idiom, fit-for-purpose), Prometheus (foresight — vision, extensibility, future-Claude). Triggers on /titans, /review, 'review this code', 'what did I miss', 'before I ship this'. Use after completing substantial work, before /close. (user)
development
Controls InnerClaude instances on Sprites.dev VMs for testing workflows, install patterns, and Claude-to-Claude interaction. INVOKE BEFORE any 'sprite exec', 'inner Claude', 'test this workflow', 'Claude controlling Claude', or remote VM operations. Documents the critical tmux+pipe-pane pattern that makes OuterClaude/InnerClaude interaction work. Also covers checkpoint/restore and bootstrap. (user)