headroom.walls.sh · debug

Debugging with Claude Code

Claude Code can drive a debugging session from stack trace to fixed test — but the pattern matters. Give it the full error, the relevant code, and a way to verify the fix. This page covers the workflows that work, the patterns that waste session budget, and how to keep long debug sessions from hitting the 5h wall.

The basic pattern: error → context → fix → verify

The most effective debug prompt gives Claude Code four things at once:

I'm getting this error when I run the test suite:

TypeError: Cannot read properties of undefined (reading 'userId')
  at verifyToken (src/auth.ts:42:18)
  at middleware (src/middleware.ts:15:5)

Here is src/auth.ts. The verifyToken function is supposed to decode a JWT
and return the user object, but something is wrong with how it handles
expired tokens. Please find and fix the issue.

The pattern: error message + stack trace + relevant file + what you expected. Claude Code can read additional files itself, but starting with the most relevant one saves a round trip.

The test-fix loop

For bugs covered by tests, the most reliable workflow is the automated test-fix loop:

Run the test suite. There are 3 failing tests — all related to the auth module.
Find the root cause of each failure, fix it, and confirm the tests pass.
Don't stop until all 3 pass.

Claude Code will run the tests, read the failures, trace the code, make edits, and re-run tests — looping until the tests pass or it hits a blocker. You don't need to be in the loop for each iteration.

Tip: Give Claude Code permission to run your test command without asking. If you're using Claude Code's permissions config, add your test runner to the allow list so the loop doesn't pause to confirm on each run. See permissions setup.

Sharing logs and stack traces

Long stack traces are better piped in than typed:

npm test 2>&1 | claude "These tests are failing. Find the root cause and fix it."

Or reference a log file directly:

claude "Here is the server log from the crash: @logs/error.log — find the cause and fix it."

The @ prefix tells Claude Code to read the file directly. For very large logs, it's better to grep the relevant section first:

grep -A 20 "FATAL|Error|Exception" logs/error.log | claude "Find the root cause of these errors."

Isolating root causes across files

When a bug spans multiple files, the most effective prompt names the symptom and lets Claude Code do the tracing:

Users are getting a 500 error when they try to reset their password. The reset
email sends successfully (we can see it in SendGrid), but clicking the link
returns a 500. Find why and fix it. The relevant code is in src/auth/, src/routes/,
and src/email/.

Claude Code will read all three directories, trace the request flow, and identify where the failure occurs. It's faster than manually reading through three files yourself and forming a hypothesis.

Narrowing scope when the bug is hard to find

If Claude Code can't find the root cause in one pass, narrow the scope:

We've established the bug is in the token validation step. Here is the exact
function in question and the test that's failing. What is wrong with this
specific function?

Forcing Claude Code to focus on a single function avoids it re-reading the whole codebase on each attempt.

Reproducing before fixing

For subtle bugs, ask Claude Code to reproduce the issue as a failing test first:

Before fixing anything, write a failing test that reproduces this bug. Once
we have a test that reliably fails, then fix the code to make it pass.

This ensures the fix actually addresses the root cause, not just the symptom — and leaves you with a regression test.

Debugging in --print mode (scripted)

For automated debugging pipelines, --print runs Claude Code non-interactively and returns the output:

npm test 2>&1 | claude --print "These tests are failing. Return a JSON object with keys: root_cause (string), affected_files (array), and fix_description (string)."

Useful in CI pipelines that automatically open a debugging session when tests fail.

Claude Code in CI / GitHub Actions

Session budget: debug sessions drain fast

Debugging sessions have a particular pattern: many short tool calls (read file, grep, run test) adding up to a high utilization. A 30-minute debug session can consume 20–30% of the 5h rolling window — more than you'd expect, because each test run and file read counts.

Watch out: automated test loops are the fastest way to drain session budget. Each iteration of read → edit → run test → read output is 4–6 tool calls. 10 iterations = 40–60 tool calls. At moderate complexity, that's 15–25% of a session window.

The 5h window resets 5 hours after the oldest request in the window — not when you started Claude Code. So a morning debug session doesn't fully "free up" until the afternoon.

Know your headroom before a long debug session

Starting a debug session when you're already at 70% utilization means you might hit the limit mid-diagnosis. Headroom shows your Claude Code session (5h) and weekly (7d) usage in the menu bar, color-coded before a hard stop interrupts you.

brew install --cask patwalls/tap/headroom

Direct download · About Headroom · Source on GitHub

Common debug anti-patterns

Giving only the error, not the code

A stack trace without the relevant code forces Claude Code to read the entire file to find the function. Include the function or file in the prompt.

Asking to fix without asking to verify

Always include "run the tests to verify" or "confirm this doesn't break anything else." Without an explicit verify step, Claude Code may stop after making the edit.

Long context with stale files

If you've been debugging in a session for an hour, Claude Code's context includes the original (broken) versions of files it read earlier. If you've made changes, tell it: "the file has changed since you read it — re-read auth.ts before continuing."

Too broad a scope on a subtle bug

For subtle logic bugs, a prompt like "something is wrong with authentication" sends Claude Code on a wide search. Narrow it to the specific function or the specific test case.


5-hour session limit explained
Claude Code agent mode — automated loops
Claude Code in CI / GitHub Actions
Claude Code tips and tricks
Rate limits reference