<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Debugging on RockB</title><link>https://baeseokjae.github.io/tags/debugging/</link><description>Recent content in Debugging on RockB</description><image><title>RockB</title><url>https://baeseokjae.github.io/images/og-default.png</url><link>https://baeseokjae.github.io/images/og-default.png</link></image><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 04 Jul 2026 04:00:00 +0000</lastBuildDate><atom:link href="https://baeseokjae.github.io/tags/debugging/index.xml" rel="self" type="application/rss+xml"/><item><title>Coding Agent Debug Logs Guide 2026: Claude Code, Codex, GitHub MCP, and Playwright MCP</title><link>https://baeseokjae.github.io/posts/coding-agent-debug-logs-guide-2026/</link><pubDate>Sat, 04 Jul 2026 04:00:00 +0000</pubDate><guid>https://baeseokjae.github.io/posts/coding-agent-debug-logs-guide-2026/</guid><description>Complete guide to debugging AI coding agents in 2026: Claude Code /doctor and heapdump, Codex CLI log_dir and TOML config, GitHub MCP error types, and Playwright MCP tracing tools.</description><content:encoded><![CDATA[<p>AI coding agents ship code faster than ever, but when they break, the debugging experience is nothing like a traditional stack trace. You don&rsquo;t get a line number and a segfault — you get a silent hang, a garbled terminal, a 529 from the API, or an MCP server that just won&rsquo;t connect. After spending the last year running Claude Code, Codex CLI, GitHub MCP Server, and Playwright MCP in production pipelines, I&rsquo;ve collected the debug patterns that actually work. Here&rsquo;s the field guide I wish I&rsquo;d had.</p>
<h2 id="claude-code-the-most-debuggable-agent-if-you-know-where-to-look">Claude Code: The Most Debuggable Agent, If You Know Where to Look</h2>
<p>Claude Code has the richest debug tooling of any coding agent in 2026 — I covered its overall capabilities in the <a href="/posts/ai-coding-agent-capability-matrix-2026/">AI Coding Agent Capability Matrix 2026</a> — but most of it is hidden behind slash commands you&rsquo;d never discover unless someone told you.</p>
<h3 id="the-doctor-command--your-first-stop">The /doctor Command — Your First Stop</h3>
<p>Before you dig into logs, run <code>/doctor</code> inside Claude Code or <code>claude doctor</code> from the shell. It runs an automated health check covering installation integrity, settings validity, MCP server connectivity, and context usage statistics. I&rsquo;ve seen it catch a stale Node.js version that was silently breaking MCP tool calls — something that would have taken me an hour to trace manually.</p>
<p>When Claude Code feels sluggish or behaves oddly, <code>/doctor</code> is the fastest triage tool. It reports back in under five seconds and flags issues with severity levels.</p>
<h3 id="heapdump-for-memory-mysteries">/heapdump for Memory Mysteries</h3>
<p>If Claude Code is eating RAM and you don&rsquo;t know why, run <code>/heapdump</code>. It writes a JavaScript heap snapshot to <code>~/Desktop/</code> (or your home directory on Linux) as a <code>.heapsnapshot</code> file. Open that in Chrome DevTools → Memory → Load, and you can inspect object allocations, retained sizes, and closure chains. I used this to discover a plugin that was holding a reference to the entire file tree in memory — 1.2 GB of retained objects from a 50 MB project.</p>
<h3 id="safe-mode-and-compaction">Safe Mode and Compaction</h3>
<p>When performance degrades mid-session, two commands save the day:</p>
<ul>
<li><strong><code>claude --safe-mode</code></strong> — launches Claude Code with zero customizations: no plugins, no MCP servers, no hooks. If the problem disappears, one of your customizations is the culprit. Binary search your MCP servers from there.</li>
<li><strong><code>/compact</code></strong> — reduces context size by summarizing older conversation turns. I run <code>/compact keep only the plan and the diff</code> every 30-40 turns in a long session. Without it, auto-compaction kicks in and starts thrashing, which actually makes things worse.</li>
</ul>
<h3 id="session-recovery">Session Recovery</h3>
<p>Crashes happen. <code>claude --resume</code> in the same directory picks up your previous session. If the session file is corrupted, <code>/clear</code> starts fresh without losing your CLAUDE.md project config. And <code>/feedback</code> sends debug logs directly to Anthropic — use it when you hit something that feels like a real bug. For sharing session outputs, check out the <a href="/posts/claude-code-artifacts-guide-2026-live-shareable-previews-from-ai-coding-sessions/">Claude Code Artifacts guide</a> for live previews.</p>
<h3 id="common-claude-code-issues-ive-hit">Common Claude Code Issues I&rsquo;ve Hit</h3>
<table>
  <thead>
      <tr>
          <th>Symptom</th>
          <th>Likely Cause</th>
          <th>Fix</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>High CPU, fan spinning</td>
          <td>Context too large</td>
          <td><code>/compact</code> or <code>/clear</code>, restart</td>
      </tr>
      <tr>
          <td>Garbled terminal text</td>
          <td>GPU acceleration in editor</td>
          <td><code>terminal.integrated.gpuAcceleration: off</code></td>
      </tr>
      <tr>
          <td>Slow search on WSL</td>
          <td>Missing ripgrep</td>
          <td>Install ripgrep, set <code>USE_BUILTIN_RIPGREP=0</code></td>
      </tr>
      <tr>
          <td>529 Overloaded</td>
          <td>API capacity</td>
          <td>Wait 30s, retry. Use off-peak hours</td>
      </tr>
      <tr>
          <td>MCP servers not loading</td>
          <td>Config syntax error</td>
          <td><code>claude --safe-mode</code> to isolate</td>
      </tr>
  </tbody>
</table>
<h2 id="codex-cli-toml-config-and-the-hidden-tui-log">Codex CLI: TOML Config and the Hidden TUI Log</h2>
<p>Codex CLI takes a different approach. Where Claude Code has slash commands, Codex has a configuration file and a log directory.</p>
<h3 id="finding-the-logs">Finding the Logs</h3>
<p>Codex writes logs to <code>$CODEX_HOME/log</code> by default. Setting <code>CODEX_HOME</code> explicitly also enables the opt-in plaintext TUI log (<code>codex-tui.log</code>), which is invaluable for debugging startup issues. If Codex CLI fails to launch or crashes immediately, check that file first — it captures what happened before the TUI even started.</p>
<p>The config lives at <code>~/.codex/config.toml</code> in TOML format. Here&rsquo;s a debug-oriented config I use:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[<span style="color:#a6e22e">logging</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">log_dir</span> = <span style="color:#e6db74">&#34;/home/me/.codex/logs&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">level</span> = <span style="color:#e6db74">&#34;debug&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">mcp_servers</span>.<span style="color:#a6e22e">github</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">command</span> = <span style="color:#e6db74">&#34;npx&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">args</span> = [<span style="color:#e6db74">&#34;-y&#34;</span>, <span style="color:#e6db74">&#34;@github/github-mcp-server&#34;</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">env</span> = { <span style="color:#a6e22e">GITHUB_PERSONAL_ACCESS_TOKEN</span> = <span style="color:#e6db74">&#34;${GITHUB_TOKEN}&#34;</span> }
</span></span></code></pre></div><h3 id="authentication-debugging">Authentication Debugging</h3>
<p>Codex CLI caches login details in a plaintext file at <code>~/.codex/auth.json</code>. Tokens refresh automatically during use, but if you&rsquo;re getting auth errors, check:</p>
<ol>
<li><strong>MFA requirements</strong> — Email/password login requires MFA. Social login (Google, Microsoft, Apple) doesn&rsquo;t.</li>
<li><strong>Forced login method</strong> — Set <code>forced_login_method = &quot;chatgpt&quot;</code> or <code>&quot;api_key&quot;</code> in config.toml to enforce one auth path.</li>
<li><strong>Bearer token env var</strong> — For MCP HTTP servers, use <code>bearer_token_env_var</code> in the MCP server config to source tokens from environment variables rather than hardcoding.</li>
</ol>
<h3 id="mcp-oauth-gotcha">MCP OAuth Gotcha</h3>
<p>Codex CLI supports MCP OAuth with an optional fixed port for the callback server. If you&rsquo;re running in a devbox or behind ingress, set the base callback URL override. Without it, the OAuth redirect URL defaults to localhost and breaks in proxied environments.</p>
<h2 id="github-mcp-server-structured-error-types">GitHub MCP Server: Structured Error Types</h2>
<p>The GitHub MCP Server handles errors differently from the coding agents — it uses typed error objects that bubble through the MCP framework.</p>
<h3 id="error-types-youll-encounter">Error Types You&rsquo;ll Encounter</h3>
<p>The server defines two custom error types:</p>
<ul>
<li><strong><code>GitHubAPIError</code></strong> — for REST API errors. Contains <code>Message</code>, <code>Response</code> (the full <code>*github.Response</code> object), and <code>Err</code> fields. When a tool call fails with a 404 or 403, this is what you get.</li>
<li><strong><code>GitHubGraphQLError</code></strong> — for GraphQL API errors. Contains <code>Message</code> and <code>Err</code> fields. GraphQL errors are trickier because the HTTP status is 200 even when the query fails — you have to inspect the error body.</li>
</ul>
<p>Both types are stored in Go context via <code>errors.ContextWithGitHubErrors(ctx)</code> and retrieved with <code>errors.GetGitHubAPIErrors(ctx)</code> / <code>errors.GetGitHubGraphQLErrors(ctx)</code>. If you&rsquo;re building a custom MCP host, this middleware pattern lets you inspect all errors from a session in one place.</p>
<h3 id="authentication-options">Authentication Options</h3>
<p>The GitHub MCP Server supports three auth methods:</p>
<ol>
<li><strong>OAuth (browser-based)</strong> — Token lives in memory only. Best for local development.</li>
<li><strong>Personal Access Token</strong> — Set <code>GITHUB_PERSONAL_ACCESS_TOKEN</code> env var. Minimum scopes: <code>repo</code>, <code>read:packages</code>, <code>read:org</code>. Store in <code>.env</code>, never commit.</li>
<li><strong>GitHub App</strong> — For GitHub Enterprise Server (GHES/ghe.com). Use <code>--gh-host https://your-subdomain.ghe.com</code>.</li>
</ol>
<p>For enterprise setups, the <code>--gh-host</code> flag is required with the <code>https://</code> prefix. I&rsquo;ve seen teams waste hours debugging &ldquo;not found&rdquo; errors only to realize the host flag was missing.</p>
<h3 id="insiders-mode">Insiders Mode</h3>
<p>Add <code>/insiders</code> to the URL path or set the <code>X-MCP-Insiders</code> header for early access to new features. Useful for testing, but don&rsquo;t rely on it in production — insiders features can change without notice.</p>
<h2 id="playwright-mcp-browser-level-debugging">Playwright MCP: Browser-Level Debugging</h2>
<p>Playwright MCP is unique among these tools because it controls a real browser — similar to how <a href="/posts/github-copilot-browser-tools-guide-2026/">GitHub Copilot&rsquo;s browser tools</a> work in VS Code, but with more granular control. Its debug features are built around browser instrumentation rather than log files.</p>
<h3 id="console-level-filtering">Console Level Filtering</h3>
<p>Set the console output level with <code>--console-level &lt;level&gt;</code> or <code>PLAYWRIGHT_MCP_CONSOLE_LEVEL</code> env var. Values: <code>error</code>, <code>warning</code>, <code>info</code>, <code>debug</code>. Each level includes all more severe levels. I keep mine at <code>info</code> during development and bump to <code>debug</code> when a page interaction silently fails.</p>
<h3 id="output-modes">Output Modes</h3>
<p><code>--output-mode &lt;mode&gt;</code> controls where Playwright MCP writes its output. Two options:</p>
<ul>
<li><strong><code>stdout</code></strong> (default) — Output goes to standard out. Good for local development.</li>
<li><strong><code>file</code></strong> — Writes to <code>--output-dir &lt;path&gt;</code>. Essential for CI/CD pipelines where stdout is ephemeral.</li>
</ul>
<p>Set <code>--output-max-size &lt;bytes&gt;</code> to control when old output files get evicted. I use 50 MB for long-running test suites.</p>
<h3 id="browser-tracing-and-step-debugging">Browser Tracing and Step Debugging</h3>
<p>This is where Playwright MCP shines:</p>
<ul>
<li><strong><code>browser_start_tracing</code> / <code>browser_stop_tracing</code></strong> — Records a full browser trace (network requests, console logs, DOM mutations). Open the trace file in <code>https://trace.playwright.dev</code> for a frame-by-frame replay of what the browser did.</li>
<li><strong><code>browser_pause</code> / <code>browser_resume</code></strong> — Pauses and resumes execution. <code>browser_resume</code> with <code>step=true</code> pauses before the next action, giving you frame-by-frame control.</li>
<li><strong><code>browser_set_debugger</code></strong> — Pauses at a specific <code>&lt;file&gt;:&lt;line&gt;</code> location. Think of it as a breakpoint for browser automation.</li>
</ul>
<p>I use tracing when a Playwright MCP test passes locally but fails in CI. The trace replay shows exactly where the page state diverged — usually a timing issue or a missing network response.</p>
<h3 id="headless-vs-headed">Headless vs. Headed</h3>
<p>Playwright MCP runs <strong>headed by default</strong> (you see the browser window). For CI or headless servers, pass <code>--headless</code>. In containerized environments, you may also need <code>--no-sandbox</code> and <code>--ignore-https-errors</code> depending on your setup.</p>
<h3 id="persistent-profiles">Persistent Profiles</h3>
<p>Session data (cookies, localStorage, IndexedDB) is stored at a platform-specific location by default. Override with <code>--user-data-dir</code> to share sessions across runs. For security-sensitive tasks, use <code>--isolated</code> to keep the profile in memory only — nothing touches disk.</p>
<h2 id="cross-tool-debug-patterns">Cross-Tool Debug Patterns</h2>
<p>After debugging all four tools in anger, here are the patterns that apply across the board:</p>
<h3 id="1-environment-variables-are-your-first-log">1. Environment Variables Are Your First Log</h3>
<p>Every tool in this guide respects environment variables for debug configuration. Before you open a log file, check that your env vars are set correctly. A typo in <code>PLAYWRIGHT_MCP_CONSOLE_LEVEL</code> or a missing <code>GITHUB_PERSONAL_ACCESS_TOKEN</code> will fail silently.</p>
<h3 id="2-mcp-server-health-check">2. MCP Server Health Check</h3>
<p>When an MCP server won&rsquo;t connect, the problem is almost always one of three things:</p>
<ul>
<li><strong>Port conflict</strong> — Another process is using the port. <code>lsof -i :&lt;port&gt;</code> to check.</li>
<li><strong>Auth mismatch</strong> — The token or OAuth session expired. Re-authenticate.</li>
<li><strong>Path issue</strong> — The <code>command</code> in your MCP config isn&rsquo;t on the agent&rsquo;s PATH. Use absolute paths in MCP server configs.</li>
</ul>
<h3 id="3-session-persistence-is-fragile">3. Session Persistence Is Fragile</h3>
<p>Both Claude Code (<code>--resume</code>) and Codex CLI (auth cache) support session persistence, but neither is bulletproof. If you&rsquo;re running long-lived agent sessions, build checkpointing into your workflow — commit frequently, save intermediate results, and don&rsquo;t trust session files as your only state.</p>
<h2 id="which-debug-approach-fits-your-workflow">Which Debug Approach Fits Your Workflow?</h2>
<ul>
<li><strong>Claude Code</strong> — Best debug tooling overall. Use <code>/doctor</code> for triage, <code>/heapdump</code> for memory issues, and <code>/compact</code> for context management. If you&rsquo;re running Claude Code daily, learn these commands.</li>
<li><strong>Codex CLI</strong> — Best for config-driven debugging. The TOML config and log directory give you fine-grained control. Use when you need to debug MCP server connections or auth flows.</li>
<li><strong>GitHub MCP Server</strong> — Best for API-level debugging. The typed error objects and context middleware make it the most engineer-friendly MCP server to troubleshoot. Use when you&rsquo;re building custom MCP hosts.</li>
<li><strong>Playwright MCP</strong> — Best for browser-level debugging. Tracing and step debugging are unmatched for diagnosing flaky browser automation. Use when your tests pass locally but fail in CI.</li>
</ul>
<p>The reality is that most teams will use all four. Claude Code or Codex CLI as the primary coding agent, GitHub MCP for repository operations, and Playwright MCP for browser testing. Knowing the debug patterns for each one — before they break — is what separates a smooth workflow from a frustrating afternoon of staring at a silent terminal.</p>
<h2 id="faq">FAQ</h2>
<h3 id="how-do-i-enable-verbose-logging-in-claude-code">How do I enable verbose logging in Claude Code?</h3>
<p>Claude Code doesn&rsquo;t have a traditional verbose log flag. Instead, use <code>/doctor</code> for a health check, <code>/compact</code> to inspect context usage, and <code>claude --safe-mode</code> to isolate whether a plugin or MCP server is causing issues. For memory profiling, <code>/heapdump</code> writes a Chrome-compatible heap snapshot. If you need raw output, run <code>claude --verbose</code> from the shell — it prints more detail about tool calls and API requests.</p>
<h3 id="codex-cli-logs-are-empty--whats-wrong">Codex CLI logs are empty — what&rsquo;s wrong?</h3>
<p>If <code>$CODEX_HOME/log</code> is empty, you probably haven&rsquo;t set <code>CODEX_HOME</code> explicitly. Codex only writes the plaintext TUI log (<code>codex-tui.log</code>) when <code>CODEX_HOME</code> is set as an environment variable. Without it, logs go to a default location that may not be obvious. Set <code>CODEX_HOME=/home/you/.codex</code> in your shell profile, then restart Codex. Also check that your <code>config.toml</code> has a <code>[logging]</code> section with <code>level = &quot;debug&quot;</code>.</p>
<h3 id="why-does-my-github-mcp-server-return-404-for-repos-i-can-access">Why does my GitHub MCP server return 404 for repos I can access?</h3>
<p>This is almost always an authentication issue, not a missing repo. If you&rsquo;re using a Personal Access Token, verify it has the <code>repo</code> scope. If you&rsquo;re using OAuth, the token may have expired — re-authenticate. For GitHub Enterprise Server, the <code>--gh-host</code> flag must include the <code>https://</code> prefix (e.g., <code>--gh-host https://git.yourcompany.com</code>). Without it, the server defaults to github.com and can&rsquo;t find your enterprise repos.</p>
<h3 id="playwright-mcp-tests-pass-locally-but-fail-in-ci--how-do-i-debug-this">Playwright MCP tests pass locally but fail in CI — how do I debug this?</h3>
<p>Use browser tracing. Add <code>browser_start_tracing</code> before the failing interaction and <code>browser_stop_tracing</code> after it. Open the trace file in <a href="https://trace.playwright.dev">trace.playwright.dev</a> for a frame-by-frame replay. The most common CI-specific issues are: headed mode not available (pass <code>--headless</code>), sandbox restrictions (pass <code>--no-sandbox</code> in containers), and missing environment variables like <code>PLAYWRIGHT_MCP_CONSOLE_LEVEL</code>. Also check that <code>--output-mode file</code> is set so logs persist after the CI job ends.</p>
<h3 id="can-i-use-claude-code-and-codex-cli-together-in-the-same-project">Can I use Claude Code and Codex CLI together in the same project?</h3>
<p>Yes, but with caveats. Both tools respect <code>CLAUDE.md</code> / project config files, but they use different formats — Claude Code uses Markdown-based CLAUDE.md, while Codex uses TOML-based <code>config.toml</code> and <code>requirements.toml</code>. They won&rsquo;t interfere with each other, but you&rsquo;ll need to maintain two config files. I run Claude Code for architecture and planning work, then switch to Codex CLI for tasks where I want the ChatGPT subscription&rsquo;s model access. The MCP server configs are shared — both tools read the same MCP server binaries, so you only configure GitHub MCP or Playwright MCP once.</p>
]]></content:encoded></item></channel></rss>