Skip to content

CLI Debugging Workflow

Your CI just went red. The error message is “Cannot read properties of undefined (reading ‘map’)” with a stack trace that touches six files across two services. Your teammate says it was working yesterday. Git blame points at a merge commit with 40 changed files. You could spend the next two hours adding console.log statements. Or you could pipe the error into Claude Code and have a root cause analysis in five minutes.

The developers who debug fastest with Claude Code do not just paste errors and ask for fixes. They use a systematic workflow: give Claude the error with full context, let it trace the execution path through your codebase, verify the diagnosis before applying the fix, and write a test that prevents the regression. This lesson covers that workflow.

  • A workflow for going from error message to root cause in minutes
  • Prompts that give Claude enough context to diagnose real bugs, not just guess
  • The pipe-and-diagnose technique for production errors
  • Headless mode patterns for automated error triage in CI
  1. Give Claude the full error context

    The quality of the diagnosis depends entirely on the quality of the input. A bare error message gets you a guess. A stack trace with context gets you a root cause.

  2. Let Claude trace the execution path

    Claude reads the files in the stack trace, follows imports, checks types, and builds a picture of what went wrong. Do not rush this step — the trace is where the bug is found.

    Trace the request flow from src/routes/orders.ts line 47
    through the service layer and into the database query.
    Show me the data shape at each step. Where does the value
    become undefined?
  3. Verify the diagnosis before applying the fix

    Claude might identify the wrong root cause, especially for intermittent bugs. Before writing any fix, verify.

    You're saying the bug is in the middleware that parses the
    JWT token. Prove it: show me the specific line where the
    undefined value originates, and explain why it only happens
    for users with expired sessions.
  4. Fix the bug and write a regression test

    Fix the bug. Then write a test that reproduces the exact
    scenario that caused it -- expired session token with a
    valid user ID. The test should fail without the fix and
    pass with it.
  5. Check for similar bugs elsewhere

    Search the codebase for other places that use the same
    pattern that caused this bug. Are there other middleware
    functions that assume the token payload is always present?
    List them so I can fix them proactively.

Claude Code’s terminal-native design means you can pipe error output directly into it. This is the fastest path from error to diagnosis.

Terminal window
# Pipe a failing test directly to Claude
npm test -- --run tests/services/order.test.ts 2>&1 | \
claude -p "This test is failing. Read the test file and the \
source code it tests. Diagnose the root cause and fix it."
Terminal window
# Grab recent errors and analyze them
grep "ERROR" /var/log/app/production.log | tail -50 | \
claude -p "Analyze these production errors. Group them by \
root cause. For each group, identify the source file and \
suggest a fix. Prioritize by frequency."
Terminal window
# Pipe CI failure output to Claude
gh run view 12345 --log-failed | \
claude -p "This CI run failed. Identify which test failed, \
read the relevant source code, and explain what broke. \
Check recent commits to see if a specific change caused it."

Race conditions are notoriously hard to debug because they are timing-dependent. Give Claude the full picture.

We have an intermittent test failure in tests/services/payment.test.ts.
It passes 9 out of 10 times. The error is "expected 'processing'
but received 'completed'".
Read the test and the payment service. Look for any async operations
that might resolve in a different order depending on timing.
Check for missing awaits, unhandled promises, or shared mutable state.
Our Node.js service memory grows from 200MB to 1.2GB over 6 hours,
then crashes with OOM. I took heap snapshots at startup and at
the 4-hour mark.
Read our event handler code in src/handlers/ and look for:
1. Event listeners that are added but never removed
2. Arrays or maps that grow without bounds
3. Closures that capture large objects
4. Streams that are opened but never closed
This test passes on my machine but fails in CI. Here's the CI output:
[paste output]
Here's my local Node version: v20.11.0
CI uses: v20.10.0
Read the test file and look for:
1. Environment-dependent code (paths, timezones, locale)
2. Timing-sensitive assertions
3. Missing test fixtures or setup steps
4. Order-dependent tests that assume state from a previous test

When a bug spans multiple parts of the system, use sub-agents to investigate in parallel without filling your main context with irrelevant code.

Use sub-agents to investigate this bug from multiple angles:
1. Trace the request from the API gateway through the auth
middleware to the order service. Find where the user object
loses its organization_id field.
2. Check the database migration history for the organizations
table. Was a column recently renamed or made nullable?
3. Search for all places in the codebase that read
user.organization_id and check if any of them handle
the undefined case.
Report findings so we can pinpoint the root cause.

Each sub-agent runs in its own context, reads as many files as needed, and reports back a focused summary. Your main session stays clean for the actual fix.

For teams that want automated error triage, headless mode turns Claude Code into a debugging pipeline.

Terminal window
# Automated error analysis in CI
claude -p "Analyze the test failures in this output and
categorize them:
1. Flaky tests (timing-dependent, order-dependent)
2. Real bugs (code logic errors)
3. Environment issues (missing config, wrong versions)
For real bugs, identify the root cause file and line number.
For flaky tests, suggest how to make them deterministic.
$(cat test-output.log)" \
--output-format json > debug-report.json

This generates a structured JSON report that your CI pipeline can post as a PR comment or send to Slack.

Claude Code is git-aware. Use this for debugging regressions.

This bug started appearing after last Tuesday's deploy. Run:
git log --oneline --after="2026-02-03" -- src/services/
Then read the diffs for each commit that touched the services
directory. Which commit introduced the change that could cause
"TypeError: Cannot read property 'id' of null" in the order
processing flow?

For deeper investigation:

Run git bisect between the last known good commit (abc123)
and the current HEAD. The test that reproduces the bug is
tests/services/order.test.ts. Find the exact commit that
introduced the regression.

Claude fixes the symptom but not the root cause. This happens when you paste just the error message without context. Always include: the stack trace, when it happens, what changed recently, and how often it occurs. The more context, the more accurate the diagnosis.

The fix breaks something else. Claude fixed the bug but did not check for side effects. After every fix, run the full test suite, not just the test for the bug. Add this to your prompt: “After fixing the bug, run the full test suite and show me any new failures.”

Claude cannot reproduce the bug from the description. Write a failing test first. “Before debugging, write a test that reproduces this exact scenario. Run it to confirm it fails. Then trace the code to find the root cause.” A failing test is the most unambiguous bug report.

Extended thinking helps for complex bugs. For bugs that span many files or involve subtle timing issues, set the effort level to high before debugging. Claude will reason through the problem more carefully before suggesting a fix.

Context fills up during a long debugging session. If you have been reading many files to trace a bug, run /compact Focus on the bug diagnosis and the fix. Drop file contents we already analyzed. Alternatively, if you have a clear diagnosis, start a fresh session with just the diagnosis and let Claude implement the fix from scratch.

Your bug is fixed and a regression test is in place. Now strengthen the rest of your test suite so you catch bugs before they reach production.