Skill v0.2.0
currentAutomated scan100/100name: cdp description: "Live-debug a running Node.js service via Chrome DevTools Protocol. Use this skill whenever the user says 'debug', 'set a breakpoint', 'investigate runtime', 'inspect at runtime', 'why is variable Y wrong', or asks to attach to a running container/process to step through real execution. Works on any Node.js project (NestJS, ts-node, plain Node, compiled to dist/) that has a .vscode/launch.json with an attach config — the skill discovers the inspector port, container name, and source-map setup automatically. The skill is conversational: Claude picks breakpoints from the request context, the user manipulates the system (curl/browser), the breakpoint hits, Claude reports findings, then resumes. Do NOT use this skill for: writing/running unit tests (use jest directly), static code review, log inspection (use docker logs)." version: 0.2.0
CDP Debug Skill
A live debugger for Node.js services. Each project's .vscode/launch.json exposes a Node Inspector port; this skill connects via CDP, sets breakpoints, captures pause events, and lets Claude inspect runtime state — all without leaving the conversation.
When to use
Triggers the user might say:
- "debug
UserService.create" - "set a breakpoint at
user.controller.ts:42" - "I want to see what arrives in
dtowhen I POST" - "investigate why this route returns 500"
- "trace the call when handler X runs"
- "logpoint on this line to see
user.id"
Triggers that should NOT route here (use other tools):
- "run the unit tests" → jest
- "review this code" → code-reviewer agent
- "show me the container logs" →
docker logs - "explain how X works" → just read the code
High-level workflow
- Pick breakpoints. Read the code around the user's target. Choose 1–4 breakpoints at the most informative spots: function entry, before a critical branch, after an external call, near the suspicious return. Keep it tight — too many BPs = noise.
- Verify environment. Run
cdp doctoronce per session if not run recently. It validates Node, the bundled CLI, andsocat/curl --unix-socket. - Start daemon. From the project's CWD, run
cdp startwithrun_in_background: true. Use the Monitor tool to tail the daemon log. - Wait for `connected` event in the log. If the log says the container/inspector port is unreachable, the message includes the exact recovery command (e.g.,
docker start <container>). - Set breakpoints.
cdp bp set <file>:<line>for each chosen point. Accept TS or JS paths — daemon handles source-map translation for compiled projects. - Tell the user to act. Short, specific: "Ready. Trigger the POST /api/users and I'll watch."
- Watch for `paused` events via Monitor. Each event carries a frame summary + locals preview already fitted to the LLM budget (depth 2, ~8KB cap).
- Inspect. Use
cdp eval <expr>(orcdp locals,cdp stack) to dig into specific values. Eval works in both paused (call-frame) and running (Runtime.evaluate) states. - Report findings in the conversation in plain language — what's surprising, what matches expectation, what's the next hypothesis.
- Move forward —
cdp step over/in/out,cdp resume, or set new BPs based on what you saw. - When understood, stop.
cdp stopclears BPs, disconnects, kills the daemon. Always stop before ending the conversation topic.
Thecdpcommand is added to the Bash tool's PATH automatically when this plugin is enabled.
Reference: CLI commands
cdp doctor validate envcdp start [--project <path>] [--reattach] start daemon for current projectcdp stop [--all] clean up daemon(s)cdp status PID alive? attached? FSM state? BPs?cdp ls list all live daemons across projectscdp tail print path of event log file (use with Monitor)cdp bp set <file:line> [--cond <expr>] [--log <expr>]cdp bp listcdp bp rm <id|all>cdp wait [--timeout <sec>] block until next paused event; returns frame+localscdp eval <expr> [--depth <N>] [--frame <N>] evaluate expressioncdp locals [--depth <N>] dump current frame localscdp stack summarized call stackcdp step over | in | outcdp resume
Output format
All commands return JSON to stdout. Daemon events are written to /tmp/claude-debug-<slug>.log (one JSON object per line). Common event shapes:
{"event":"connected","port":9229,"target":{"id":"...","title":"..."}}{"event":"breakpoint-set","id":"bp-1","file":"user.service.ts","line":42}{"event":"paused","reason":"breakpoint","bp":"bp-1","frame":{"function":"UserService.create","file":"user.service.ts","line":42},"locals":{...}}{"event":"resumed"}{"event":"logpoint","bp":"bp-2","value":"user=abc-123","ts":1234567890}{"event":"detached","reason":"stop|crash|idle"}
Eval results:
{"ok":true,"value":{...formatted...}}{"ok":false,"error":"...","state":"running"}
Output budget rules (followed by daemon)
- Default depth: 2 levels of object expansion
- Max 50 properties per object level
- Strings truncated at 200 chars (
...[truncated +N chars]) - Arrays truncated at 10 items (
...(+N more)) - Total payload cap: 8KB per command response
- Circular references shown as
[Circular: <path>] - Mongoose-like documents: prefer
.toObject()if available
Patterns Claude should follow
Choosing breakpoints. Don't carpet-bomb. For "why is X wrong", set BP at the moment X is decided (assignment line, return statement, condition branch), not at every line of the function. For "what payload arrives", BP on the first executable line of the controller method.
Reporting back. When a paused event arrives, summarize it for the user in plain language: "Hit `user.service.ts:42`. `dto.email = '...'`, `existing.id = null`. The create path is taken — looks expected so far." — then suggest the next step.
Logpoints over breakpoints when possible. If the user wants to observe multiple events without pausing the request flow, use cdp bp set --log <expr>. Doesn't pause the process. Useful for high-frequency code paths.
Cleanup discipline. Always call cdp stop when the investigation ends or the user's topic shifts. Orphan daemons hold inspector connections and consume resources. Use cdp ls if you suspect stale ones from a previous session.
Multi-project. If debugging an inter-service call (e.g., service A → service B), start a daemon per project in parallel. Each has its own socket+log+pid by slug.
Failure modes the daemon handles
- Container not running: error includes exact
docker start <container>from tasks.json - Inspector port not listening: error after 5s timeout retrying connection
- Source map missing for compiled project: falls back to BP on parallel
dist/.../foo.jswith the SAME line number. Caveat: TS line ≠ JS line in compiled files (JS adds boilerplate, decorators, etc.). When this happens, the daemon emits asourcemap-fallbackevent with a warning. If a BP doesn't fire when expected, set the BP directly on the.jsfile at the correct line — usedist/src/.../foo.js:Ninstead ofsrc/.../foo.ts:N. - Process restart while attached: WS UUID changes; daemon detects and emits
detachedwith reason; CLI tells user tocdp start --reattach - Unsupported command in current FSM state: rejected with explicit message ("eval requires paused state; current=running")
- Inspector script URL doesn't match BP URL: CDP returns
locations: [](BP pending). The script may not be loaded yet, or the URL pattern is wrong. Checkcdp bp list—locations: 0means pending.
Notes on real-world BP firing
- BP fires only when the actual line of bound
.jsruns. In compiled projects without source maps, the parallel-path fallback uses the same line number, which is approximate. Tip: open the.jsfile underdist/and find the executable line that corresponds to the TS code you want to inspect. - BP setting is async with respect to script loading. If the file isn't loaded yet, BP is "pending" — it'll bind when the script first loads.
- For projects using ts-node directly (
runtime: ts-node),.tspaths work directly because Node's ts-node loader registers.tsURLs with the inspector. No source-map work needed.
Files per session
/tmp/claude-debug-<slug>.sock— IPC/tmp/claude-debug-<slug>.log— structured event stream/tmp/claude-debug-<slug>.daemon.log— daemon stdout/stderr (crash output)/tmp/claude-debug-<slug>.pid— PID file for crash detection/tmp/claude-debug-<slug>.bps.json— persisted BPs for--reattach
When in doubt
Run cdp status to see exactly what the daemon thinks. Run cdp doctor if anything seems off about the environment. Read the event log directly with cat $(cdp tail | jq -r .log).