Claude session introspect
Skill biyearly-mesothelioma790/skills/claude-session-introspect
Organize reusable AI agent skills for Claude Code, Codex, and Cursor with focused workflows, scripts, and fast task selection
npx -y skills add biyearly-mesothelioma790/skills --skill claude-session-introspectAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Inspect Claude Code session JSONL files at ~/.claude/projects/ to extract real conversation telemetry: token counts (input/output/cache reads/cache writes), assistant turn counts, human prompt counts, tool-use counts, compaction boundaries, and the contents of compaction summaries. Use this skill when the user asks "how many tokens did this session use", "how many prompts have I sent", "show me the stats for this conversation", "what got compacted", "where are the compaction boundaries", "introspect the session", "do brain surgery on the JSONL", or wants any data point that lives inside the on-disk session log rather than the live context window. Inspired by Tal Raviv's "I wanted to know how compaction works" article.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.0 KB, as published. Nobody here has run it
Claude Session Introspect
Claude Code persists every conversation as a JSONL file on disk. This skill is the recipe for opening one and pulling out the numbers you actually want — token usage, prompt counts, compaction events, tool calls — without guessing.
Where sessions live
~/.claude/projects/<encoded-cwd>/<session-uuid>.jsonl
<encoded-cwd> is the absolute path of the project's working directory with / replaced by - and a leading -. Example: /Users/swyx/Work/foo → -Users-swyx-Work-foo.
Each line is one event. The interesting type values:
| type | what it is |
|---|---|
user | a real user message OR a tool result (distinguished by toolUseResult being non-null) |
assistant | an assistant turn (one model response). message.usage has the token counts. |
system | system messages (mostly compaction-related) |
file-history-snapshot | edited-file snapshots used for undo |
attachment | image/file attachments |
permission-mode | permission mode toggles |
Quick locate: find the current session
# 1. encode current working directory
ENC="-$(pwd | sed 's,/,-,g' | sed 's/^-//')"
# 2. list the project's session files, newest first
ls -t "$HOME/.claude/projects/$ENC/"
# 3. the most recent .jsonl is usually the live one
SESSION="$HOME/.claude/projects/$ENC/$(ls -t "$HOME/.claude/projects/$ENC/" | head -1)"
echo "$SESSION"
If you know the session UUID (Claude Code shows it, and image-cache paths embed it), you can grep all projects:
find ~/.claude/projects -name '<uuid>.jsonl'
The headline stats (one-shot)
The stats.sh script in this skill folder takes a session path and prints token totals, turn counts, prompt counts, tool-use counts, and any compaction events.
bash stats.sh "$SESSION"
If you don't have the script handy, here are the inline jq one-liners.
Token totals across the whole session
jq -s '
[.[] | select(.message.usage)] |
{
assistant_turns: length,
input_tokens: (map(.message.usage.input_tokens // 0) | add),
output_tokens: (map(.message.usage.output_tokens // 0) | add),
cache_read_tokens: (map(.message.usage.cache_read_input_tokens // 0) | add),
cache_create_tokens: (map(.message.usage.cache_creation_input_tokens // 0)| add)
}
' "$SESSION"
input_tokens is the FRESH (non-cached) input. cache_read_tokens is the dominant number on long sessions — it's how much was re-read from prompt cache. cache_create_tokens is what got newly written into the cache. Effective total tokens processed = input + cache_read + cache_create.
Counts by event type
jq -r '.type' "$SESSION" | sort | uniq -c
Real human prompts (excluding tool results and system reminders)
A type:"user" line is a human message only if toolUseResult is null. Even then, the content may be a system-injected reminder, not the human's words.
jq -r '
select(.type == "user" and .toolUseResult == null) |
(.message.content
| if type == "string" then .
else (map(select(.type == "text") | .text) | join("\n"))
end)
' "$SESSION" > /tmp/prompts.txt
# total non-empty user message blocks
grep -cv '^$' /tmp/prompts.txt
# distinct human messages = blocks not starting with <system-reminder> or <command-
awk '
BEGIN { n = 0; cur = "" }
/^$/ { if (cur != "" && cur !~ /^<system-reminder>/ && cur !~ /^<command-/) n++; cur=""; next }
{ if (cur=="") cur=$0 }
END { if (cur != "" && cur !~ /^<system-reminder>/ && cur !~ /^<command-/) n++; print n }
' /tmp/prompts.txt
(Blunt but works. If you want surgical accuracy, parse the content array and skip blocks whose first text element is a <system-reminder> tag.)
Tool calls — how many and which tools
jq -r '
select(.type == "assistant") |
.message.content[]? |
select(.type == "tool_use") |
.name
' "$SESSION" | sort | uniq -c | sort -rn
Compaction boundaries — where, why, and what survived
Compaction inserts a system event with subtype:"compact_boundary" (older builds may use isCompactSummary on the next user message). The summary itself is the next user message, prefixed with "This session is being continued from a previous conversation that ran out of context."
# count compaction events
jq -r 'select(.type=="system" and (.subtype // "") == "compact_boundary") | .timestamp' "$SESSION" | wc -l
# was each one auto or manual?
jq -r '
select(.type == "system" and (.subtype // "") == "compact_boundary") |
{ts: .timestamp, trigger: (.compactMetadata.trigger // "unknown"), preTokens: (.compactMetadata.preCompactTokens // null)}
' "$SESSION"
# read the compaction summaries (the actual contents that survived)
jq -r '
select(.type == "user" and (.isCompactSummary == true or
((.message.content // "") | tostring | test("session is being continued from a previous conversation"))))
| (.message.content | if type == "string" then . else (map(select(.type=="text").text)|join("\n")) end)
' "$SESSION" | less
Per-turn token usage (for spotting blowups)
jq -r '
select(.message.usage) |
[.timestamp,
(.message.usage.input_tokens // 0),
(.message.usage.output_tokens // 0),
(.message.usage.cache_read_input_tokens // 0)]
| @tsv
' "$SESSION" | column -t
This is how you find the one tool result that bloated your context — sort by cache_read ascending across the session and watch for the jump.
Gotchas
type:"user"is overloaded. Tool results are alsotype:"user". Always filter ontoolUseResult == nullto get human turns.input_tokenslooks tiny on long sessions. That's correct — it's the delta sent uncached. Almost everything flows throughcache_read_input_tokens.- The "live" session file isn't always the newest. If multiple Claude Code windows are open in the same project, both write to the same project folder. Disambiguate by UUID — the chat header and image-cache paths both expose it.
- JSONL files grow without bound. A long-running project folder can have hundreds of session files.
ls -t | headis your friend. - Don't edit a live JSONL. Claude Code reads it back on
/resume. If you want to do "brain surgery" (Tal Raviv's term), copy the file out, edit the copy, and useclaude --resume <copied-uuid>from a clean directory.
When to reach for this skill
- "How many tokens has this session burned?"
- "How many prompts have I sent today?"
- "Where did compaction kick in and what got summarized?"
- "Which tool call blew up the context?"
- Building a stats display, leaderboard, or "built with Claude Code" badge that needs real numbers.
- Forensics on a session that went sideways — replaying tool calls in order.
Reference
- Tal Raviv, "I wanted to know how compaction works" — https://www.talraviv.co/p/i-wanted-to-know-how-compaction-works
- Claude Code docs on session storage —
~/.claude/projects/
Gives 0 of the 12 instructions most memory context skills give
Counted across 674 of the 847 authors here whose files we hold, read 2026-08-06
- inform the user when setup is completein 21 of 674, across 6 files
- confirm the draft with the user before writingin 21 of 674, across 6 files
- update the agent skills block in place if it existsin 21 of 674, across 6 files
- present findings to the userin 20 of 674, across 5 files
- write the three docs files from seed templatesin 20 of 674, across 5 files
- ask the user about each decision one at a timein 19 of 674, across 4 files
- edit CLAUDE.md if it existsin 18 of 674, across 3 files
- explore current repo statein 18 of 674, across 3 files
- do not overwrite user edits to surrounding sectionsin 18 of 674, across 3 files
- back up the original file before overwritingin 16 of 674, across 8 files
- keep the memory index under 200 linesin 15 of 674
- Provide actionable steps and verificationin 13 of 674, across 2 files
Said here and by no other author read
- filter type user on toolUseResult null
- run stats.sh with the session path
- use jq to aggregate token totals
- exclude system reminders and commands from prompt counts
- disambiguate live sessions by UUID
- copy the file before editing
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.