[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GGX8JM2AXGPMNVMZG3V2NN":3,"skill-same:01M6GGX8JM2AXGPMNVMZG3V2NN":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":57,"commitSha":58,"skillDirectory":59,"forksCount":60,"repositoryHtmlUrl":61,"repositoryHomepageUrl":6,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":63,"updatedAt":64,"install":65,"resources":78},"01M6GGX8JM2AXGPMNVMZG3V2NN","node-inspect-debugger",null,"Debug Node.js via --inspect + Chrome DevTools Protocol CLI.","zapabob\u002FSkills","zapabob","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F130830376?v=4","01M6DBMYZAGRTFQDSQYW3W764P","峯岸 亮","01M6DBMZ3GKDSJ01NZ9XTZD7JD",2,"MIT","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Farchive\u002Fskill-md-reviewed\u002Fsha256\u002Ff2\u002Ff2f72c0c9e67143effc8cb9871a242309813af72c61b8d62548ae275c86f2d08\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"node inspect debugger","node","debugger","nodejs","via","systematic","commands","cdp","chrome devtools","ui","devtools","macos","protocol","debugging","debug","windows","chrome","linux","python","cli","2026-11-10 10:12:30",false,"---\nname: node-inspect-debugger\ndescription: \"Debug Node.js via --inspect + Chrome DevTools Protocol CLI.\"\nversion: 1.0.0\nauthor: Hermes Agent\nlicense: MIT\nplatforms: [linux, macos, windows]\nmetadata:\n  hermes:\n    tags: [debugging, nodejs, node-inspect, cdp, breakpoints, ui-tui]\n    related_skills: [systematic-debugging, python-debugpy, debugging-hermes-tui-commands]\n---\n\n# Node.js Inspect Debugger\n\n## Overview\n\nWhen `console.log` isn't enough, drive Node's built-in V8 inspector programmatically from the terminal. You get real breakpoints, step in\u002Fover\u002Fout, call-stack walking, local\u002Fclosure scope dumps, and arbitrary expression evaluation in the paused frame.\n\nTwo tools, pick one:\n\n- **`node inspect`** — built-in, zero install, CLI REPL. Best for quick poking.\n- **`ndb` \u002F CDP via `chrome-remote-interface`** — scriptable from Node\u002FPython; best when you want to automate many breakpoints, collect state across runs, or debug non-interactively from an agent loop.\n\n**Prefer `node inspect` first.** It's always available and the REPL is fast.\n\n## When to Use\n\n- A Node test fails and you need to see intermediate state\n- ui-tui crashes or behaves wrong and you want to inspect React\u002FInk state pre-render\n- tui_gateway child processes (`_SlashWorker`, PTY bridge workers) misbehave\n- You need to inspect a value in a closure that `console.log` can't reach without patching\n- Perf: attach to a running process to capture a CPU profile or heap snapshot\n\n**Don't use for:** things `console.log` solves in under a minute. Breakpoint-driven debugging is heavier; use it when the payoff is real.\n\n## Quick Reference: `node inspect` REPL\n\nLaunch paused on first line:\n\n```bash\nnode inspect path\u002Fto\u002Fscript.js\n# or with tsx\nnode --inspect-brk $(which tsx) path\u002Fto\u002Fscript.ts\n```\n\nThe `debug>` prompt accepts:\n\n| Command | Action |\n|---|---|\n| `c` or `cont` | continue |\n| `n` or `next` | step over |\n| `s` or `step` | step into |\n| `o` or `out` | step out |\n| `pause` | pause running code |\n| `sb('file.js', 42)` | set breakpoint at file.js line 42 |\n| `sb(42)` | set breakpoint at line 42 of current file |\n| `sb('functionName')` | break when function is called |\n| `cb('file.js', 42)` | clear breakpoint |\n| `breakpoints` | list all breakpoints |\n| `bt` | backtrace (call stack) |\n| `list(5)` | show 5 lines of source around current position |\n| `watch('expr')` | evaluate expr on every pause |\n| `watchers` | show watched expressions |\n| `repl` | drop into REPL in current scope (Ctrl+C to exit REPL) |\n| `exec expr` | evaluate expression once |\n| `restart` | restart script |\n| `kill` | kill the script |\n| `.exit` | quit debugger |\n\n**In the `repl` sub-mode:** type any JS expression, including access to locals\u002Fclosure variables. `Ctrl+C` exits back to `debug>`.\n\n## Attaching to a Running Process\n\nWhen the process is already running (e.g. a long-lived dev server or the TUI gateway):\n\n```bash\n# 1. Send SIGUSR1 to enable the inspector on an existing process\nkill -SIGUSR1 \u003Cpid>\n# Node prints: Debugger listening on ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n\n# 2. Attach the debugger CLI\nnode inspect -p \u003Cpid>\n# or by URL\nnode inspect ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n```\n\nTo start a process with the inspector from the beginning:\n\n```bash\nnode --inspect script.js           # listen on 127.0.0.1:9229, keep running\nnode --inspect-brk script.js       # listen AND pause on first line\nnode --inspect=0.0.0.0:9230 script.js   # custom host:port\n```\n\nFor TypeScript via tsx:\n\n```bash\nnode --inspect-brk --import tsx script.ts\n# or older tsx\nnode --inspect-brk -r tsx\u002Fcjs script.ts\n```\n\n## Programmatic CDP (scripting from terminal)\n\nWhen you want to automate — set many breakpoints, capture scope state, script a repro — use `chrome-remote-interface`:\n\n```bash\nnpm i -g chrome-remote-interface        # or project-local\n# Start your target:\nnode --inspect-brk=9229 target.js &\n```\n\nDriver script (save as `\u002Ftmp\u002Fcdp-debug.js`):\n\n```javascript\nconst CDP = require('chrome-remote-interface');\n\n(async () => {\n  const client = await CDP({ port: 9229 });\n  const { Debugger, Runtime } = client;\n\n  Debugger.paused(async ({ callFrames, reason }) => {\n    const top = callFrames[0];\n    console.log(`PAUSED: ${reason} @ ${top.url}:${top.location.lineNumber + 1}`);\n\n    \u002F\u002F Walk scopes for locals\n    for (const scope of top.scopeChain) {\n      if (scope.type === 'local' || scope.type === 'closure') {\n        const { result } = await Runtime.getProperties({\n          objectId: scope.object.objectId,\n          ownProperties: true,\n        });\n        for (const p of result) {\n          console.log(`  ${scope.type}.${p.name} =`, p.value?.value ?? p.value?.description);\n        }\n      }\n    }\n\n    \u002F\u002F Evaluate an expression in the paused frame\n    const { result } = await Debugger.evaluateOnCallFrame({\n      callFrameId: top.callFrameId,\n      expression: 'typeof state !== \"undefined\" ? JSON.stringify(state) : \"n\u002Fa\"',\n    });\n    console.log('state =', result.value ?? result.description);\n\n    await Debugger.resume();\n  });\n\n  await Runtime.enable();\n  await Debugger.enable();\n\n  \u002F\u002F Set a breakpoint by URL regex + line\n  await Debugger.setBreakpointByUrl({\n    urlRegex: '.*app\\\\.tsx$',\n    lineNumber: 119,       \u002F\u002F 0-indexed\n    columnNumber: 0,\n  });\n\n  await Runtime.runIfWaitingForDebugger();\n})();\n```\n\nRun it:\n\n```bash\nnode \u002Ftmp\u002Fcdp-debug.js\n```\n\nHermes-specific note: `chrome-remote-interface` is NOT in `ui-tui\u002Fpackage.json`. Install it to a throwaway location if you don't want to dirty the project:\n\n```bash\nmkdir -p \u002Ftmp\u002Fcdp-tools && cd \u002Ftmp\u002Fcdp-tools && npm i chrome-remote-interface\nNODE_PATH=\u002Ftmp\u002Fcdp-tools\u002Fnode_modules node \u002Ftmp\u002Fcdp-debug.js\n```\n\n## Debugging Hermes ui-tui\n\nThe TUI is built Ink + tsx. Two common scenarios:\n\n### Debugging a single Ink component under dev\n\n`ui-tui\u002Fpackage.json` has `npm run dev` (tsx --watch). Add `--inspect-brk` by running tsx directly:\n\n```bash\ncd \u002Fhome\u002Fbb\u002Fhermes-agent\u002Fui-tui\nnpm run build    # produce dist\u002F once so transpile isn't needed on first load\nnode --inspect-brk dist\u002Fentry.js\n# In another terminal:\nnode inspect -p \u003Cnode pid>\n```\n\nThen inside `debug>`:\n\n```\nsb('dist\u002Fapp.js', 220)     # or wherever the suspect render is\ncont\n```\n\nWhen it pauses, `repl` → inspect `props`, state refs, `useInput` handler values, etc.\n\n### Debugging a running `hermes --tui`\n\nThe TUI spawns Node from the Python CLI. Easiest path:\n\n```bash\n# 1. Launch TUI\nhermes --tui &\nTUI_PID=$(pgrep -f 'ui-tui\u002Fdist\u002Fentry' | head -1)\n\n# 2. Enable inspector on that Node PID\nkill -SIGUSR1 \"$TUI_PID\"\n\n# 3. Find the WS URL\ncurl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist | jq -r '.[0].webSocketDebuggerUrl'\n\n# 4. Attach\nnode inspect ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n```\n\nInteracting with the TUI (typing in its window) continues to advance execution; your debugger can pause it on a breakpoint at any `sb(...)`.\n\n### Debugging `_SlashWorker` \u002F PTY child processes\n\nThose are Python, not Node — use the `python-debugpy` skill for them. Only Node portions (Ink UI, tui_gateway client, tsx-run tests under `ui-tui\u002F`) use this skill.\n\n## Running Vitest Tests Under the Debugger\n\n```bash\ncd \u002Fhome\u002Fbb\u002Fhermes-agent\u002Fui-tui\n# Run a single test file paused on entry\nnode --inspect-brk .\u002Fnode_modules\u002Fvitest\u002Fvitest.mjs run --no-file-parallelism src\u002Fapp\u002Ffoo.test.tsx\n```\n\nIn another terminal: `node inspect -p \u003Cpid>`, then `sb('src\u002Fapp\u002Ffoo.tsx', 42)`, `cont`.\n\nUse `--no-file-parallelism` (vitest) or `--runInBand` (jest) so only one worker exists — debugging a pool is painful.\n\n## Heap Snapshots & CPU Profiles (Non-interactive)\n\nFrom the CDP driver above, swap Debugger for `HeapProfiler` \u002F `Profiler`:\n\n```javascript\n\u002F\u002F CPU profile for 5 seconds\nawait client.Profiler.enable();\nawait client.Profiler.start();\nawait new Promise(r => setTimeout(r, 5000));\nconst { profile } = await client.Profiler.stop();\nrequire('fs').writeFileSync('\u002Ftmp\u002Fcpu.cpuprofile', JSON.stringify(profile));\n\u002F\u002F Open \u002Ftmp\u002Fcpu.cpuprofile in Chrome DevTools → Performance tab\n```\n\n```javascript\n\u002F\u002F Heap snapshot\nawait client.HeapProfiler.enable();\nconst chunks = [];\nclient.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => chunks.push(chunk));\nawait client.HeapProfiler.takeHeapSnapshot({ reportProgress: false });\nrequire('fs').writeFileSync('\u002Ftmp\u002Fheap.heapsnapshot', chunks.join(''));\n```\n\n## Common Pitfalls\n\n1. **Wrong line numbers in TS source.** Breakpoints hit the emitted JS, not the `.ts`. Either (a) break in the built `dist\u002F*.js`, or (b) enable sourcemaps (`node --enable-source-maps`) and use `sb('src\u002Fapp.tsx', N)` — but only with CDP clients that follow sourcemaps. `node inspect` CLI does not.\n\n2. **`--inspect` vs `--inspect-brk`.** `--inspect` starts the inspector but doesn't pause; your script races past your first breakpoint if you attach too late. Use `--inspect-brk` when you need to set breakpoints before any code runs.\n\n3. **Port collisions.** Default is `9229`. If multiple Node processes are inspecting, pass `--inspect=0` (random port) and read the actual URL from `\u002Fjson\u002Flist`:\n   ```bash\n   curl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist   # lists all inspectable targets on the host\n   ```\n\n4. **Child processes.** `--inspect` on a parent does NOT inspect its children. Use `NODE_OPTIONS='--inspect-brk' node parent.js` to propagate to every child; be aware they all need unique ports (Node auto-increments when `NODE_OPTIONS='--inspect'` is inherited).\n\n5. **Background kills.** If you `Ctrl+C` out of `node inspect` while the target is paused, the target stays paused. Either `cont` first, or `kill` the target explicitly.\n\n6. **Running `node inspect` through an agent terminal.** It's a PTY-friendly REPL. In Hermes, launch it with `terminal(pty=true)` or `background=true` + `process(action='submit', data='...')`. Non-PTY foreground mode will work for one-shot commands but not for interactive stepping.\n\n7. **Security.** `--inspect=0.0.0.0:9229` exposes arbitrary code execution. Always bind to `127.0.0.1` (the default) unless you have an isolated network.\n\n## Verification Checklist\n\nAfter setting up a debug session, verify:\n\n- [ ] `curl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist` returns exactly the target you expect\n- [ ] First breakpoint actually hits (if it doesn't, you likely missed `--inspect-brk` or attached after execution completed)\n- [ ] Source listing at pause shows the right file (mismatch = sourcemap issue, see pitfall 1)\n- [ ] `exec process.pid` in `repl` returns the PID you meant to attach to\n\n## One-Shot Recipes\n\n**\"Why is this variable undefined at line X?\"**\n```bash\nnode --inspect-brk script.js &\nnode inspect -p $!\n# debug>\nsb('script.js', X)\ncont\n# paused. Now:\nrepl\n> myVariable\n> Object.keys(this)\n```\n\n**\"What's the call path into this function?\"**\n```\ndebug> sb('suspectFn')\ndebug> cont\n# paused on entry\ndebug> bt\n```\n\n**\"This async chain hangs — where?\"**\n```\n# Start with --inspect (no -brk), let it run to the hang, then:\ndebug> pause\ndebug> bt\n# Now you see the stuck frame\n```\n","# Node.js Inspect Debugger\n\n## Overview\n\nWhen `console.log` isn't enough, drive Node's built-in V8 inspector programmatically from the terminal. You get real breakpoints, step in\u002Fover\u002Fout, call-stack walking, local\u002Fclosure scope dumps, and arbitrary expression evaluation in the paused frame.\n\nTwo tools, pick one:\n\n- **`node inspect`** — built-in, zero install, CLI REPL. Best for quick poking.\n- **`ndb` \u002F CDP via `chrome-remote-interface`** — scriptable from Node\u002FPython; best when you want to automate many breakpoints, collect state across runs, or debug non-interactively from an agent loop.\n\n**Prefer `node inspect` first.** It's always available and the REPL is fast.\n\n## When to Use\n\n- A Node test fails and you need to see intermediate state\n- ui-tui crashes or behaves wrong and you want to inspect React\u002FInk state pre-render\n- tui_gateway child processes (`_SlashWorker`, PTY bridge workers) misbehave\n- You need to inspect a value in a closure that `console.log` can't reach without patching\n- Perf: attach to a running process to capture a CPU profile or heap snapshot\n\n**Don't use for:** things `console.log` solves in under a minute. Breakpoint-driven debugging is heavier; use it when the payoff is real.\n\n## Quick Reference: `node inspect` REPL\n\nLaunch paused on first line:\n\n```bash\nnode inspect path\u002Fto\u002Fscript.js\n# or with tsx\nnode --inspect-brk $(which tsx) path\u002Fto\u002Fscript.ts\n```\n\nThe `debug>` prompt accepts:\n\n| Command | Action |\n|---|---|\n| `c` or `cont` | continue |\n| `n` or `next` | step over |\n| `s` or `step` | step into |\n| `o` or `out` | step out |\n| `pause` | pause running code |\n| `sb('file.js', 42)` | set breakpoint at file.js line 42 |\n| `sb(42)` | set breakpoint at line 42 of current file |\n| `sb('functionName')` | break when function is called |\n| `cb('file.js', 42)` | clear breakpoint |\n| `breakpoints` | list all breakpoints |\n| `bt` | backtrace (call stack) |\n| `list(5)` | show 5 lines of source around current position |\n| `watch('expr')` | evaluate expr on every pause |\n| `watchers` | show watched expressions |\n| `repl` | drop into REPL in current scope (Ctrl+C to exit REPL) |\n| `exec expr` | evaluate expression once |\n| `restart` | restart script |\n| `kill` | kill the script |\n| `.exit` | quit debugger |\n\n**In the `repl` sub-mode:** type any JS expression, including access to locals\u002Fclosure variables. `Ctrl+C` exits back to `debug>`.\n\n## Attaching to a Running Process\n\nWhen the process is already running (e.g. a long-lived dev server or the TUI gateway):\n\n```bash\n# 1. Send SIGUSR1 to enable the inspector on an existing process\nkill -SIGUSR1 \u003Cpid>\n# Node prints: Debugger listening on ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n\n# 2. Attach the debugger CLI\nnode inspect -p \u003Cpid>\n# or by URL\nnode inspect ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n```\n\nTo start a process with the inspector from the beginning:\n\n```bash\nnode --inspect script.js           # listen on 127.0.0.1:9229, keep running\nnode --inspect-brk script.js       # listen AND pause on first line\nnode --inspect=0.0.0.0:9230 script.js   # custom host:port\n```\n\nFor TypeScript via tsx:\n\n```bash\nnode --inspect-brk --import tsx script.ts\n# or older tsx\nnode --inspect-brk -r tsx\u002Fcjs script.ts\n```\n\n## Programmatic CDP (scripting from terminal)\n\nWhen you want to automate — set many breakpoints, capture scope state, script a repro — use `chrome-remote-interface`:\n\n```bash\nnpm i -g chrome-remote-interface        # or project-local\n# Start your target:\nnode --inspect-brk=9229 target.js &\n```\n\nDriver script (save as `\u002Ftmp\u002Fcdp-debug.js`):\n\n```javascript\nconst CDP = require('chrome-remote-interface');\n\n(async () => {\n  const client = await CDP({ port: 9229 });\n  const { Debugger, Runtime } = client;\n\n  Debugger.paused(async ({ callFrames, reason }) => {\n    const top = callFrames[0];\n    console.log(`PAUSED: ${reason} @ ${top.url}:${top.location.lineNumber + 1}`);\n\n    \u002F\u002F Walk scopes for locals\n    for (const scope of top.scopeChain) {\n      if (scope.type === 'local' || scope.type === 'closure') {\n        const { result } = await Runtime.getProperties({\n          objectId: scope.object.objectId,\n          ownProperties: true,\n        });\n        for (const p of result) {\n          console.log(`  ${scope.type}.${p.name} =`, p.value?.value ?? p.value?.description);\n        }\n      }\n    }\n\n    \u002F\u002F Evaluate an expression in the paused frame\n    const { result } = await Debugger.evaluateOnCallFrame({\n      callFrameId: top.callFrameId,\n      expression: 'typeof state !== \"undefined\" ? JSON.stringify(state) : \"n\u002Fa\"',\n    });\n    console.log('state =', result.value ?? result.description);\n\n    await Debugger.resume();\n  });\n\n  await Runtime.enable();\n  await Debugger.enable();\n\n  \u002F\u002F Set a breakpoint by URL regex + line\n  await Debugger.setBreakpointByUrl({\n    urlRegex: '.*app\\\\.tsx$',\n    lineNumber: 119,       \u002F\u002F 0-indexed\n    columnNumber: 0,\n  });\n\n  await Runtime.runIfWaitingForDebugger();\n})();\n```\n\nRun it:\n\n```bash\nnode \u002Ftmp\u002Fcdp-debug.js\n```\n\nHermes-specific note: `chrome-remote-interface` is NOT in `ui-tui\u002Fpackage.json`. Install it to a throwaway location if you don't want to dirty the project:\n\n```bash\nmkdir -p \u002Ftmp\u002Fcdp-tools && cd \u002Ftmp\u002Fcdp-tools && npm i chrome-remote-interface\nNODE_PATH=\u002Ftmp\u002Fcdp-tools\u002Fnode_modules node \u002Ftmp\u002Fcdp-debug.js\n```\n\n## Debugging Hermes ui-tui\n\nThe TUI is built Ink + tsx. Two common scenarios:\n\n### Debugging a single Ink component under dev\n\n`ui-tui\u002Fpackage.json` has `npm run dev` (tsx --watch). Add `--inspect-brk` by running tsx directly:\n\n```bash\ncd \u002Fhome\u002Fbb\u002Fhermes-agent\u002Fui-tui\nnpm run build    # produce dist\u002F once so transpile isn't needed on first load\nnode --inspect-brk dist\u002Fentry.js\n# In another terminal:\nnode inspect -p \u003Cnode pid>\n```\n\nThen inside `debug>`:\n\n```\nsb('dist\u002Fapp.js', 220)     # or wherever the suspect render is\ncont\n```\n\nWhen it pauses, `repl` → inspect `props`, state refs, `useInput` handler values, etc.\n\n### Debugging a running `hermes --tui`\n\nThe TUI spawns Node from the Python CLI. Easiest path:\n\n```bash\n# 1. Launch TUI\nhermes --tui &\nTUI_PID=$(pgrep -f 'ui-tui\u002Fdist\u002Fentry' | head -1)\n\n# 2. Enable inspector on that Node PID\nkill -SIGUSR1 \"$TUI_PID\"\n\n# 3. Find the WS URL\ncurl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist | jq -r '.[0].webSocketDebuggerUrl'\n\n# 4. Attach\nnode inspect ws:\u002F\u002F127.0.0.1:9229\u002F\u003Cuuid>\n```\n\nInteracting with the TUI (typing in its window) continues to advance execution; your debugger can pause it on a breakpoint at any `sb(...)`.\n\n### Debugging `_SlashWorker` \u002F PTY child processes\n\nThose are Python, not Node — use the `python-debugpy` skill for them. Only Node portions (Ink UI, tui_gateway client, tsx-run tests under `ui-tui\u002F`) use this skill.\n\n## Running Vitest Tests Under the Debugger\n\n```bash\ncd \u002Fhome\u002Fbb\u002Fhermes-agent\u002Fui-tui\n# Run a single test file paused on entry\nnode --inspect-brk .\u002Fnode_modules\u002Fvitest\u002Fvitest.mjs run --no-file-parallelism src\u002Fapp\u002Ffoo.test.tsx\n```\n\nIn another terminal: `node inspect -p \u003Cpid>`, then `sb('src\u002Fapp\u002Ffoo.tsx', 42)`, `cont`.\n\nUse `--no-file-parallelism` (vitest) or `--runInBand` (jest) so only one worker exists — debugging a pool is painful.\n\n## Heap Snapshots & CPU Profiles (Non-interactive)\n\nFrom the CDP driver above, swap Debugger for `HeapProfiler` \u002F `Profiler`:\n\n```javascript\n\u002F\u002F CPU profile for 5 seconds\nawait client.Profiler.enable();\nawait client.Profiler.start();\nawait new Promise(r => setTimeout(r, 5000));\nconst { profile } = await client.Profiler.stop();\nrequire('fs').writeFileSync('\u002Ftmp\u002Fcpu.cpuprofile', JSON.stringify(profile));\n\u002F\u002F Open \u002Ftmp\u002Fcpu.cpuprofile in Chrome DevTools → Performance tab\n```\n\n```javascript\n\u002F\u002F Heap snapshot\nawait client.HeapProfiler.enable();\nconst chunks = [];\nclient.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => chunks.push(chunk));\nawait client.HeapProfiler.takeHeapSnapshot({ reportProgress: false });\nrequire('fs').writeFileSync('\u002Ftmp\u002Fheap.heapsnapshot', chunks.join(''));\n```\n\n## Common Pitfalls\n\n1. **Wrong line numbers in TS source.** Breakpoints hit the emitted JS, not the `.ts`. Either (a) break in the built `dist\u002F*.js`, or (b) enable sourcemaps (`node --enable-source-maps`) and use `sb('src\u002Fapp.tsx', N)` — but only with CDP clients that follow sourcemaps. `node inspect` CLI does not.\n\n2. **`--inspect` vs `--inspect-brk`.** `--inspect` starts the inspector but doesn't pause; your script races past your first breakpoint if you attach too late. Use `--inspect-brk` when you need to set breakpoints before any code runs.\n\n3. **Port collisions.** Default is `9229`. If multiple Node processes are inspecting, pass `--inspect=0` (random port) and read the actual URL from `\u002Fjson\u002Flist`:\n   ```bash\n   curl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist   # lists all inspectable targets on the host\n   ```\n\n4. **Child processes.** `--inspect` on a parent does NOT inspect its children. Use `NODE_OPTIONS='--inspect-brk' node parent.js` to propagate to every child; be aware they all need unique ports (Node auto-increments when `NODE_OPTIONS='--inspect'` is inherited).\n\n5. **Background kills.** If you `Ctrl+C` out of `node inspect` while the target is paused, the target stays paused. Either `cont` first, or `kill` the target explicitly.\n\n6. **Running `node inspect` through an agent terminal.** It's a PTY-friendly REPL. In Hermes, launch it with `terminal(pty=true)` or `background=true` + `process(action='submit', data='...')`. Non-PTY foreground mode will work for one-shot commands but not for interactive stepping.\n\n7. **Security.** `--inspect=0.0.0.0:9229` exposes arbitrary code execution. Always bind to `127.0.0.1` (the default) unless you have an isolated network.\n\n## Verification Checklist\n\nAfter setting up a debug session, verify:\n\n- [ ] `curl -s http:\u002F\u002F127.0.0.1:9229\u002Fjson\u002Flist` returns exactly the target you expect\n- [ ] First breakpoint actually hits (if it doesn't, you likely missed `--inspect-brk` or attached after execution completed)\n- [ ] Source listing at pause shows the right file (mismatch = sourcemap issue, see pitfall 1)\n- [ ] `exec process.pid` in `repl` returns the PID you meant to attach to\n\n## One-Shot Recipes\n\n**\"Why is this variable undefined at line X?\"**\n```bash\nnode --inspect-brk script.js &\nnode inspect -p $!\n# debug>\nsb('script.js', X)\ncont\n# paused. Now:\nrepl\n> myVariable\n> Object.keys(this)\n```\n\n**\"What's the call path into this function?\"**\n```\ndebug> sb('suspectFn')\ndebug> cont\n# paused on entry\ndebug> bt\n```\n\n**\"This async chain hangs — where?\"**\n```\n# Start with --inspect (no -brk), let it run to the hang, then:\ndebug> pause\ndebug> bt\n# Now you see the stuck frame\n```\n",{"name":5,"author":44,"license":15,"version":45,"metadata":46,"platforms":56,"description":7},"Hermes Agent","1.0.0",{"hermes":47},{"tags":48,"related_skills":52},[32,22,49,26,50,51],"node-inspect","breakpoints","ui-tui",[53,54,55],"systematic-debugging","python-debugpy","debugging-hermes-tui-commands",[36,30,34],"main","0d1434f89f4bc6b07e9d272accd8c1013768820f","archive\u002Fskill-md-reviewed\u002Fsha256\u002Ff2\u002Ff2f72c0c9e67143effc8cb9871a242309813af72c61b8d62548ae275c86f2d08",0,"https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills","https:\u002F\u002Fgithub.com\u002Fzapabob","The Open University of JAPAN　2019-now\r\n\r\nTokyo University of Science　2007-2010","2026-10-26 16:29:01",{"source":8,"skillName":5,"commands":66,"prompt":76,"zipAvailable":77},[67,70,73],{"tool":68,"command":69},"npx","npx skills add zapabob\u002FSkills --skill node-inspect-debugger",{"tool":71,"command":72},"bunx","bunx skills add zapabob\u002FSkills --skill node-inspect-debugger",{"tool":74,"command":75},"pnpm","pnpm dlx skills add zapabob\u002FSkills --skill node-inspect-debugger","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Farchive\u002Fskill-md-reviewed\u002Fsha256\u002Ff2\u002Ff2f72c0c9e67143effc8cb9871a242309813af72c61b8d62548ae275c86f2d08\u002FSKILL.md",true,[],[80,113,148,175,202,219],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":99,"publishedAt":39},"01M6GJTE1GESGGF9K028Y7753E","xurl","X\u002FTwitter via xurl CLI: post, search, DM, media, v2 API.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fxurl\u002Fvariants\u002Fhermes-agent\u002FSKILL.md",[86,91,94],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":92,"categoryName":93,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":95,"categoryName":96,"taxonomyType":97,"taxonomyTypeDesc":98},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[82,100,30,38,101,36,34,102,103,104,105,106,107,108,109,110,57,111,23,112],"openclaw","github","official","search","https","social-media","api","Media","hermes","hermes agent","twitter","social","post",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":130,"publishedAt":39},"01M6GJT8S1PXQ8WPXT1HSNBWH2","writing-plans","Write implementation plans: bite-sized tasks, paths, code.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fwriting-plans\u002Fvariants\u002Fhermes-agent\u002FSKILL.md",[119,122,125,126,127],{"categoryNo":120,"categoryName":121,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":123,"categoryName":124,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":92,"categoryName":93,"taxonomyType":89,"taxonomyTypeDesc":90},{"categoryNo":95,"categoryName":96,"taxonomyType":97,"taxonomyTypeDesc":98},{"categoryNo":128,"categoryName":129,"taxonomyType":97,"taxonomyTypeDesc":98},"01JBSEEDCAT000000000000036","内容创作者",[131,132,133,134,30,135,36,136,34,137,138,139,140,141,142,143,144,145,146,147],"writing","writing plans","plans","design","review","workflow","documentation","tasks","development","code","planning","code-review","subagent","write","superpowers","paths","test-driven-development",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":157,"publishedAt":39},"01M6GJST0H5X7WHBJ3BZK0DVKH","whisper","OpenAI's general-purpose speech recognition model. Supports 99 languages, transcription, translation to English, and language identification. Six model sizes from tiny (39M params) to large (1550M params). Use for speech-to-text, podcast transcription, or multilingual audio processing. Best for robust, multilingual ASR.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fwhisper\u002Fvariants\u002Fhermes-agent-optional\u002FSKILL.md",[154],{"categoryNo":155,"categoryName":156,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000016","图像与多媒体",[150,30,36,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174],"openai","speech","multimodal","Transformers","ASR","Audio","text","model","speech recognition","use","general","multilingual","translation","english","identification","processing","Audio Processing",{"skillNo":176,"name":177,"nameZh":6,"description":178,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":179,"categories":180,"keywords":184,"publishedAt":39},"01M6GJSMRQ8EETZTYMG72P70EA","weights-and-biases","W&B: log ML experiments, sweeps, model registry, dashboards.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fweights-and-biases\u002Fvariants\u002Fhermes-agent\u002FSKILL.md",[181],{"categoryNo":182,"categoryName":183,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000013","分析与可视化",[185,30,186,187,34,188,189,190,191,192,193,165,194,195,196,197,198,199,200,201],"weights and biases","tensorflow","experiments","pytorch","visualization","registry","real-time","tuning","dashboards","experiment","log","time","Experiment Tracking","Model Registry","Hyperparameter Tuning","WandB","Real-Time Visualization",{"skillNo":203,"name":204,"nameZh":6,"description":205,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":206,"categories":207,"keywords":209,"publishedAt":39},"01M6GJS19KDPRY112JTR326S06","watchers","Poll RSS, JSON APIs, and GitHub with watermark dedup.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fwatchers\u002Fvariants\u002Fhermes-agent-optional\u002FSKILL.md",[208],{"categoryNo":92,"categoryName":93,"taxonomyType":89,"taxonomyTypeDesc":90},[204,30,210,101,36,211,212,213,214,215,216,108,109,217,218],"terminal","automation","http","monitoring","cron","json","rss","devops","with",{"skillNo":220,"name":221,"nameZh":6,"description":222,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":223,"categories":224,"keywords":227,"publishedAt":39},"01M6GJRHJD2A6Q830SWF9W48BC","serving-llms-vllm","vLLM: high-throughput LLM serving, OpenAI API, quantization.","https:\u002F\u002Fgithub.com\u002Fzapabob\u002FSkills\u002Fblob\u002Fmain\u002Fregistry\u002Fskills\u002Fvllm\u002Fvariants\u002Fhermes-agent\u002FSKILL.md",[225,226],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},{"categoryNo":95,"categoryName":96,"taxonomyType":97,"taxonomyTypeDesc":98},[228,229,230,36,231,158,232,233,234,161,235,106,236,237,238,239,240,241,242,243],"llms","vLLM","serving llms vllm","research","openai api","tensor","Inference Serving","Production","llm serving","High Throughput","PagedAttention","Continuous Batching","Quantization","Tensor Parallelism","high-throughput","throughput"]