Agent Skills › Prismer-AI/PrismerCloud › prismer-node-inspect-debugger

prismer-node-inspect-debugger

GitHub

提供 Node.js 程序调试能力,支持通过内置 inspect 或 CDP 协议进行断点、单步执行、堆栈查看及变量评估,适用于测试失败排查和运行时状态分析。

sdk/cloud/catalog/skills/prismer-node-inspect-debugger/SKILL.md Prismer-AI/PrismerCloud

Trigger Scenarios

Node 测试失败需要检查中间状态 进程崩溃或行为异常需深入调试 需要查看闭包内不可达的值 需要捕获 CPU 性能剖析或堆快照

Install

npx skills add Prismer-AI/PrismerCloud --skill prismer-node-inspect-debugger -g -y
More Options

Non-standard path

npx skills add https://github.com/Prismer-AI/PrismerCloud/tree/main/sdk/cloud/catalog/skills/prismer-node-inspect-debugger -g -y

Use without installing

npx skills use Prismer-AI/PrismerCloud@prismer-node-inspect-debugger

指定 Agent (Claude Code)

npx skills add Prismer-AI/PrismerCloud --skill prismer-node-inspect-debugger -a claude-code -g -y

安装 repo 全部 skill

npx skills add Prismer-AI/PrismerCloud --all -g -y

预览 repo 内 skill

npx skills add Prismer-AI/PrismerCloud --list

SKILL.md

Frontmatter
{
    "name": "prismer-node-inspect-debugger",
    "scope": "coding",
    "author": "Hermes Agent",
    "license": "MIT",
    "version": "1.0.0",
    "metadata": {
        "hermes": {
            "tags": [
                "debugging",
                "nodejs",
                "node-inspect",
                "cdp",
                "breakpoints",
                "ui-tui"
            ],
            "related_skills": [
                "systematic-debugging",
                "python-debugpy"
            ]
        },
        "nativeReplaces": [
            "node-inspect-debugger"
        ],
        "requiresExplicitGrant": true
    },
    "platforms": [
        "linux",
        "macos",
        "windows"
    ],
    "description": "Debug Node.js via --inspect + Chrome DevTools Protocol CLI."
}

Prismer execution contract

This is the uniquely named prismer-node-inspect-debugger skill, adapted from Hermes. Use the actual tools exposed by the executing host; examples using terminal, process, delegate_task, vision_analyze or browser_* are not tool registrations. Missing dependencies do not hide this skill. Report command startup, version, account/permissions and task-specific live verification separately. Use task-owned artifact paths and existing user authorization; do not change shared accounts, Runtime/provider configuration, global security settings or unrelated work. See NOTICE.md and LICENSE for resource provenance. Runtime availability and upstream-entry suppression are owned by the integration layer.

Node.js Inspect Debugger

Overview

When console.log isn't enough, drive Node's built-in V8 inspector programmatically from the terminal. You get real breakpoints, step in/over/out, call-stack walking, local/closure scope dumps, and arbitrary expression evaluation in the paused frame.

Two tools, pick one:

  • node inspect — built-in, zero install, CLI REPL. Best for quick poking.
  • ndb / CDP via chrome-remote-interface — scriptable from Node/Python; best when you want to automate many breakpoints, collect state across runs, or debug non-interactively from an agent loop.

Prefer node inspect first. It's always available and the REPL is fast.

When to Use

  • A Node test fails and you need to see intermediate state
  • ui-tui crashes or behaves wrong and you want to inspect React/Ink state pre-render
  • tui_gateway child processes (_SlashWorker, PTY bridge workers) misbehave
  • You need to inspect a value in a closure that console.log can't reach without patching
  • Perf: attach to a running process to capture a CPU profile or heap snapshot

Don't use for: things console.log solves in under a minute. Breakpoint-driven debugging is heavier; use it when the payoff is real.

Quick Reference: node inspect REPL

Launch paused on first line:

node inspect path/to/script.js
# or with tsx
node --inspect-brk $(which tsx) path/to/script.ts

The debug> prompt accepts:

Command Action
c or cont continue
n or next step over
s or step step into
o or out step out
pause pause running code
sb('file.js', 42) set breakpoint at file.js line 42
sb(42) set breakpoint at line 42 of current file
sb('functionName') break when function is called
cb('file.js', 42) clear breakpoint
breakpoints list all breakpoints
bt backtrace (call stack)
list(5) show 5 lines of source around current position
watch('expr') evaluate expr on every pause
watchers show watched expressions
repl drop into REPL in current scope (Ctrl+C to exit REPL)
exec expr evaluate expression once
restart restart script
kill kill the script
.exit quit debugger

In the repl sub-mode: type any JS expression, including access to locals/closure variables. Ctrl+C exits back to debug>.

Attaching to a Running Process

When the process is already running (e.g. a long-lived dev server or the TUI gateway):

# 1. Send SIGUSR1 to enable the inspector on an existing process
kill -SIGUSR1 <pid>
# Node prints: Debugger listening on ws://127.0.0.1:9229/<uuid>

# 2. Attach the debugger CLI
node inspect -p <pid>
# or by URL
node inspect ws://127.0.0.1:9229/<uuid>

To start a process with the inspector from the beginning:

node --inspect script.js           # listen on 127.0.0.1:9229, keep running
node --inspect-brk script.js       # listen AND pause on first line
node --inspect=0.0.0.0:9230 script.js   # custom host:port

For TypeScript via tsx:

node --inspect-brk --import tsx script.ts
# or older tsx
node --inspect-brk -r tsx/cjs script.ts

Programmatic CDP (scripting from terminal)

When you want to automate — set many breakpoints, capture scope state, script a repro — use chrome-remote-interface:

npm i -g chrome-remote-interface        # or project-local
# Start your target:
node --inspect-brk=9229 target.js &

Driver script (save as ~/.hermes/cache/scratch/cdp-debug.js):

const CDP = require('chrome-remote-interface');

(async () => {
  const client = await CDP({ port: 9229 });
  const { Debugger, Runtime } = client;

  Debugger.paused(async ({ callFrames, reason }) => {
    const top = callFrames[0];
    console.log(`PAUSED: ${reason} @ ${top.url}:${top.location.lineNumber + 1}`);

    // Walk scopes for locals
    for (const scope of top.scopeChain) {
      if (scope.type === 'local' || scope.type === 'closure') {
        const { result } = await Runtime.getProperties({
          objectId: scope.object.objectId,
          ownProperties: true,
        });
        for (const p of result) {
          // Only inspect pre-approved non-sensitive fields, never every local.
          if (['status', 'phase'].includes(p.name)) {
            console.log(`  ${scope.type}.${p.name} =`, p.value?.value);
          }
        }
      }
    }

    // Evaluate an expression in the paused frame
    const { result } = await Debugger.evaluateOnCallFrame({
      callFrameId: top.callFrameId,
      expression: 'typeof state',
    });
    console.log('state =', result.value ?? result.description);

    await Debugger.resume();
  });

  await Runtime.enable();
  await Debugger.enable();

  // Set a breakpoint by URL regex + line
  await Debugger.setBreakpointByUrl({
    urlRegex: '.*app\\.tsx$',
    lineNumber: 119,       // 0-indexed
    columnNumber: 0,
  });

  await Runtime.runIfWaitingForDebugger();
})();

Run it:

node ~/.hermes/cache/scratch/cdp-debug.js

Hermes-specific note: chrome-remote-interface is NOT in ui-tui/package.json. Install it to a throwaway location if you don't want to dirty the project:

mkdir -p ~/.hermes/cache/scratch/cdp-tools && cd ~/.hermes/cache/scratch/cdp-tools && npm i chrome-remote-interface
NODE_PATH=~/.hermes/cache/scratch/cdp-tools/node_modules node ~/.hermes/cache/scratch/cdp-debug.js

Debugging Hermes ui-tui

The TUI is built Ink + tsx. Two common scenarios:

Debugging a single Ink component under dev

ui-tui/package.json has npm run dev (tsx --watch). Add --inspect-brk by running tsx directly:

cd <hermes-agent-repo>/ui-tui
npm run build    # produce dist/ once so transpile isn't needed on first load
node --inspect-brk dist/entry.js
# In another terminal:
node inspect -p <node pid>

Then inside debug>:

sb('dist/app.js', 220)     # or wherever the suspect render is
cont

When it pauses, repl → inspect props, state refs, useInput handler values, etc.

Debugging a running hermes --tui

The TUI spawns Node from the Python CLI. Easiest path:

# 1. Launch TUI
hermes --tui &
TUI_PID=$(pgrep -f 'ui-tui/dist/entry' | head -1)

# 2. Enable inspector on that Node PID
kill -SIGUSR1 "$TUI_PID"

# 3. Find the WS URL
curl -s http://127.0.0.1:9229/json/list | jq -r '.[0].webSocketDebuggerUrl'

# 4. Attach
node inspect ws://127.0.0.1:9229/<uuid>

Interacting with the TUI (typing in its window) continues to advance execution; your debugger can pause it on a breakpoint at any sb(...).

Debugging _SlashWorker / PTY child processes

Those 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/) use this skill.

Running Vitest Tests Under the Debugger

cd <hermes-agent-repo>/ui-tui
# Run a single test file paused on entry
node --inspect-brk ./node_modules/vitest/vitest.mjs run --no-file-parallelism src/app/foo.test.tsx

In another terminal: node inspect -p <pid>, then sb('src/app/foo.tsx', 42), cont.

Use --no-file-parallelism (vitest) or --runInBand (jest) so only one worker exists — debugging a pool is painful.

Heap Snapshots & CPU Profiles (Non-interactive)

From the CDP driver above, swap Debugger for HeapProfiler / Profiler:

// CPU profile for 5 seconds
await client.Profiler.enable();
await client.Profiler.start();
await new Promise(r => setTimeout(r, 5000));
const { profile } = await client.Profiler.stop();
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const out = fs.mkdtempSync(path.join(os.tmpdir(), 'prismer-profile-'));
fs.writeFileSync(path.join(out, 'cpu.cpuprofile'), JSON.stringify(profile), {flag: 'wx', mode: 0o600});
console.log(out);
// Attach the returned task-owned profile path; it may contain sensitive data.
// Heap snapshot
await client.HeapProfiler.enable();
const chunks = [];
client.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => chunks.push(chunk));
await client.HeapProfiler.takeHeapSnapshot({ reportProgress: false });
const fs = require('node:fs');
const path = require('node:path');
const out = fs.mkdtempSync(path.join(require('node:os').tmpdir(), 'prismer-heap-'));
fs.writeFileSync(path.join(out, 'heap.heapsnapshot'), chunks.join(''), {flag: 'wx', mode: 0o600});
console.log(out);

Common Pitfalls

  1. Wrong line numbers in TS source. Breakpoints hit the emitted JS, not the .ts. Either (a) break in the built dist/*.js, or (b) enable sourcemaps (node --enable-source-maps) and use sb('src/app.tsx', N) — but only with CDP clients that follow sourcemaps. node inspect CLI does not.

  2. --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.

  3. Port collisions. Use --inspect=127.0.0.1:0 and read the actual WebSocket URL from the child stderr. Query /json/list on THAT port only, verify target PID and URL before attaching; it does not list all host inspector instances.

  4. Child processes. Allocate a distinct/random loopback port to each child. Inherited NODE_OPTIONS does not guarantee automatic port incrementing.

  5. 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.

  6. 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.

  7. Security. Public inspector bindings expose arbitrary code execution. Always bind to 127.0.0.1 (the default) unless you have an isolated network.

Verification Checklist

After setting up a debug session, verify:

  • curl -s http://127.0.0.1:9229/json/list returns exactly the target you expect
  • First breakpoint actually hits (if it doesn't, you likely missed --inspect-brk or attached after execution completed)
  • Source listing at pause shows the right file (mismatch = sourcemap issue, see pitfall 1)
  • exec process.pid in repl returns the PID you meant to attach to

One-Shot Recipes

"Why is this variable undefined at line X?"

node --inspect-brk script.js &
node inspect -p $!
# debug>
sb('script.js', X)
cont
# paused. Now:
repl
> myVariable
> Object.keys(this)

"What's the call path into this function?"

debug> sb('suspectFn')
debug> cont
# paused on entry
debug> bt

"This async chain hangs — where?"

# Start with --inspect (no -brk), let it run to the hang, then:
debug> pause
debug> bt
# Now you see the stuck frame

Version History

  • f4c4a0c Current 2026-10-19 02:40

Same Skill Collection

sdk/apc/skills/bug-reproduce/SKILL.md
sdk/apc/skills/code-review/SKILL.md
sdk/apc/skills/design-review/SKILL.md
sdk/apc/skills/doc-sync/SKILL.md
sdk/apc/skills/env-doctor/SKILL.md
sdk/apc/skills/git-ops/SKILL.md
sdk/apc/skills/impact-trace/SKILL.md
sdk/apc/skills/observability/SKILL.md
sdk/apc/skills/release-db-config-sync/SKILL.md
sdk/apc/skills/release-ota-promote/SKILL.md
sdk/apc/skills/release-preflight/SKILL.md
sdk/apc/skills/release-rollback/SKILL.md
sdk/apc/skills/release-tag/SKILL.md
sdk/apc/skills/releasing-prod/SKILL.md
sdk/apc/skills/releasing-test/SKILL.md
sdk/apc/skills/sdk-release/SKILL.md
sdk/apc/skills/spec-intake/SKILL.md
sdk/apc/skills/test-result-feedback/SKILL.md
sdk/apc/skills/test-runner/SKILL.md
sdk/apc/skills/ui-canvas/SKILL.md
sdk/cloud/catalog/skills/agent-meta/SKILL.md
sdk/cloud/catalog/skills/assets/SKILL.md
sdk/cloud/catalog/skills/browser-use/SKILL.md
sdk/cloud/catalog/skills/canvas-design/SKILL.md
sdk/cloud/catalog/skills/claim-agent-ownership/SKILL.md
sdk/cloud/catalog/skills/codebase-design/SKILL.md
sdk/cloud/catalog/skills/competitor-intelligence/SKILL.md
sdk/cloud/catalog/skills/diagnosing-bugs/SKILL.md
sdk/cloud/catalog/skills/doc-coauthoring/SKILL.md
sdk/cloud/catalog/skills/document-actions/SKILL.md
sdk/cloud/catalog/skills/domain-modeling/SKILL.md
sdk/cloud/catalog/skills/evidence-citations/SKILL.md
sdk/cloud/catalog/skills/frontend-design/SKILL.md
sdk/cloud/catalog/skills/image-generate/SKILL.md
sdk/cloud/catalog/skills/ingest/SKILL.md
sdk/cloud/catalog/skills/internal-comms/SKILL.md
sdk/cloud/catalog/skills/mcp-builder/SKILL.md
sdk/cloud/catalog/skills/meeting-actions/SKILL.md
sdk/cloud/catalog/skills/office-artifacts/SKILL.md
sdk/cloud/catalog/skills/okr/SKILL.md
sdk/cloud/catalog/skills/pkf-svg/SKILL.md
sdk/cloud/catalog/skills/pkf-writing/SKILL.md
sdk/cloud/catalog/skills/prismer-apple-notes/SKILL.md
sdk/cloud/catalog/skills/prismer-apple-reminders/SKILL.md
sdk/cloud/catalog/skills/prismer-ascii-video/SKILL.md
sdk/cloud/catalog/skills/prismer-blocked-page-recovery/SKILL.md
sdk/cloud/catalog/skills/prismer-box/SKILL.md
sdk/cloud/catalog/skills/prismer-codebase-inspection/SKILL.md
sdk/cloud/catalog/skills/prismer-computer-use/SKILL.md
sdk/cloud/catalog/skills/prismer-design-md/SKILL.md

Metadata

Files
0
Version
f4c4a0c
Hash
ab66bff4
Indexed
2026-10-19 02:40

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-31 13:37
浙ICP备14020137号-1