Skip to content

How to Debug Claude Code Session Issues and See What Actually Happened

Problem

Claude Code was making edits I didn’t understand. I’d ask it to fix a bug, and somehow three other files got changed. I’d see “Read 3 files” in the output but had zero visibility into which files or what was in them. When Claude seemed to forget something I’d told it earlier in the conversation, I had no way to figure out where the context was lost.

Here’s what a typical session looked like from my perspective:

Claude Code output (what I could see)
I'll help you fix that bug.
Read 3 files
Made 5 edits
Ran tests - all passing

That’s it. No details. No context. Just summaries.

I tried asking Claude what it did:

My attempt to understand
Me: What files did you read?
Claude: I read the relevant files for the bug fix.
Me: Which files specifically?
Claude: The ones related to the authentication module.
Me: Can you list them?
Claude: I read auth.ts, user.ts, and session.ts.

But even then, I couldn’t see what Claude actually saw in those files. Did it read the whole file? Just a portion? What lines? And why did it make those specific edits?

The real problem hit when Claude forgot about a constraint I’d mentioned earlier:

Context loss example
Me (message 5): Make sure to preserve backward compatibility with v1 API
... 20 messages later ...
Me: Why did you change the API response format?
Claude: I optimized it for v2.
Me: I told you to preserve backward compatibility!
Claude: I apologize, I don't see that in my current context...

I had no way to debug this. Did the context get pushed out of the window? Did Claude misunderstand? I was flying blind.

What happened?

I started searching for ways to inspect Claude Code sessions and found a Reddit discussion about a tool called claude-devtools. Users described exactly what I needed:

“Full visibility into what actually happened - every file that was read, every edit with proper inline diff, every bash command that ran”

“You can read the extended thinking blocks alongside tool traces, so you can understand why Claude made certain decisions”

“If you’ve ever been confused about why Claude forgot something mid conversation, this clears it up fast”

This sounded like exactly what I needed. But first, I had to understand where the session data was stored.

Claude Code logs everything to ~/.claude/ in JSONL format. These files exist on my machine already - I just needed a way to make sense of them.

How to solve it?

I installed claude-devtools and opened my session logs:

Installing claude-devtools
# Install globally
npm install -g claude-devtools
# View a specific session
claude-devtools view <session-id>
# List recent sessions
claude-devtools list
# Export session for offline analysis
claude-devtools export <session-id> -o session-analysis.json

When I opened my problematic session, I could finally see everything:

1. Every file read with full content:

File read trace (from DevTools)
[10:30:15] Read: src/auth.ts (lines 1-150)
┌─────────────────────────────────────────────────────┐
│ 1 import { User } from './types'; │
│ 2 import { Session } from './session'; │
│ ... │
│ 45 export async function validateToken(token) { │
│ 46 // Check if token is expired │
│ 47 const session = await Session.findByToken(); │
│ │
└─────────────────────────────────────────────────────┘

No more “Read 3 files” with zero context. I could see exactly what Claude saw.

2. Every edit with inline diffs:

Edit trace (from DevTools)
[10:30:45] Edit: src/auth.ts
function validateToken(token: string) {
return Session.findByToken(token);
}
function validateToken(token: string, options?: ValidateOptions) {
const session = await Session.findByToken(token);
if (options?.skipExpiry) return session;
return session && !session.expired ? session : null;
}

I could see the old code, the new code, and understand exactly what changed.

3. Extended thinking blocks:

Thinking trace (from DevTools)
[10:30:40] Extended Thinking:
The user mentioned backward compatibility with v1 API.
I need to add an optional parameter rather than changing
the existing signature. This way existing callers won't break.
Wait - the user said this 20 messages ago. Let me check
if this is still in context...
[Context check] Message 5 is at position 45/200 in context
window. Still available. I should preserve the v1 behavior.

This was the breakthrough. I could see Claude’s reasoning process - including when it checked whether earlier messages were still in context.

4. All bash commands:

Bash command trace (from DevTools)
[10:31:00] Bash: npm test -- --grep auth
[10:31:02] Result: 12 tests passed, 0 failed
[10:31:03] Bash: git diff src/auth.ts
[10:31:04] Result: +5 lines, -2 lines

Every command, every output, all visible.

The reason

The reason I couldn’t debug before was that Claude Code’s default output is optimized for brevity. It shows summaries, not details. This is fine for normal use but terrible for debugging.

DevTools solves this by reading the raw JSONL session logs that Claude Code already writes to disk. It then presents them in a format optimized for human inspection:

How DevTools accesses your data
┌─────────────────────────────────────────────────────┐
│ ~/.claude/projects/abc123/sessions/2026-03-24.jsonl │
│ (Claude Code writes this automatically) │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ Claude DevTools │
│ - Parses JSONL into structured data │
│ - Indexes for search │
│ - Shows inline diffs │
│ - Displays extended thinking │
│ - Highlights syntax │
└─────────────────────────────────────────────────────┘

The key insight is that the data was always there. Claude Code logs everything. I just couldn’t read it easily.

With DevTools, I can now:

  1. Trace context loss: See exactly when a message falls out of the context window

  2. Understand decisions: Read the thinking blocks to see why Claude made a choice

  3. Verify assumptions: Check if Claude actually read the right files

  4. Audit changes: See every edit with proper diffs, not just “made 5 edits”

  5. Debug errors: Find the exact command that failed and its output

Common mistakes I made

Mistake 1: Trusting summaries without verification

I’d see “Read 3 files” and assume Claude read the right ones. Now I check:

Verifying file reads
[DevTools] Session 2026-03-24:
Files read: auth.ts, user.ts, config.ts
Lines read: auth.ts(1-150), user.ts(45-89), config.ts(full)
Wait - Claude only read lines 45-89 of user.ts? That might explain the bug...

Mistake 2: Assuming Claude “understood” my requirements

I’d give an instruction and move on. Now I check the thinking output:

Checking understanding in thinking blocks
[Extended Thinking]
User wants backward compatibility. I'll add an optional parameter.
But wait - they said v1 API specifically. Let me check what v1 format is...
[Tool: Read] api/v1/types.ts

If I don’t see this verification step in the thinking, I know Claude may have missed it.

Mistake 3: Ignoring session history when debugging

When Claude forget something, I’d just restate it. Now I open DevTools first:

Debugging context loss
[DevTools] Checking message 5 position in context...
Message 5 is at position 180/200
Context window: 200K tokens
Used: 185K tokens
Conclusion: Message 5 is barely in context. Claude might not be
able to retrieve it effectively. I should restate the requirement.

Mistake 4: Not checking the actual edits

I’d see “all tests passing” and assume the changes were correct. Now I review every diff:

Reviewing changes
[DevTools] Showing all edits in session:
Edit 1: auth.ts - Added optional parameter ✓
Edit 2: user.ts - Changed return type (unexpected!)
Edit 3: test.ts - Updated tests for new return type
Wait - why did user.ts change? That wasn't part of my request...

Practical workflow

Here’s how I now debug Claude Code sessions:

Step 1: List sessions to find the right one

Finding the session
claude-devtools list --recent 5
Session list output
Session ID: abc123, Date: 2026-03-24 10:30, Files: 8, Edits: 12
Session ID: def456, Date: 2026-03-23 14:15, Files: 3, Edits: 5
Session ID: ghi789, Date: 2026-03-22 09:00, Files: 15, Edits: 23

Step 2: Open the session and filter by tool

Opening and filtering
claude-devtools view abc123 --filter Edit

This shows only the edits with full diffs.

Step 3: Check extended thinking for decisions

Viewing thinking blocks
claude-devtools view abc123 --show-thinking

I can see why Claude made each decision.

Step 4: Export for detailed analysis

Exporting session
claude-devtools export abc123 -o analysis.json

This gives me a JSON file I can search, grep, or analyze programmatically.

Summary

In this post, I showed how to debug Claude Code sessions using claude-devtools. The key point is that Claude Code already logs everything - you just need the right tool to read those logs.

The main capabilities:

  • Full file content visibility - See exactly what Claude read, not just “Read 3 files”
  • Inline diffs for edits - Understand every change with before/after comparison
  • Extended thinking access - Read Claude’s reasoning for each decision
  • Context window debugging - Find out why earlier messages were forgotten
  • Command tracing - See every bash command and its output

If you use Claude Code heavily and find yourself wondering “why did it do that?” or “what files did it actually read?”, claude-devtools gives you the visibility you need.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments