
Debug Mode
- 12 installs
- 4 repo stars
- Updated June 2, 2026
- adjfks/corner-skills
debug-mode is a Claude Code skill that runs a Cursor-style, hypothesis-driven interactive debug workflow using runtime instrumentation and log verification.
About
debug-mode is a Cursor-style interactive debugging workflow that is hypothesis-driven and verified through runtime instrumentation. A developer invokes it with /debug-mode for hard-to-locate bugs, front-end/back-end mismatches, and race or async state issues. It stands up a local log-collection server, adds region-marked instrumentation, has the user reproduce the bug, then diagnoses root cause from the collected logs before fixing and cleaning up. Documentation is in Chinese.
- Cursor-style interactive debug mode with runtime instrumentation
- Hypothesis-driven: log, ask user to reproduce, then diagnose from logs
- Ships a local log-collection server and phased workflow
Debug Mode by the numbers
- 12 all-time installs (skills.sh)
- Ranked #414 of 596 Debugging skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
debug-mode capabilities & compatibility
- Capabilities
- interactive debugging · runtime instrumentation · root cause analysis · log analysis
- Use cases
- debugging
- Pricing
- Free
What debug-mode says it does
你已进入 **Debug Mode**。不要直接改业务逻辑猜修复;按阶段顺序执行,并在要求用户复现后 **停止等待**。
不要对简单 typo 或明显堆栈错误主动启用。
npx skills add https://github.com/adjfks/corner-skills --skill debug-modeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 12 |
|---|---|
| repo stars | ★ 4 |
| Last updated | June 2, 2026 |
| Repository | adjfks/corner-skills ↗ |
What it does
Diagnose hard bugs by instrumenting code, collecting runtime logs after user reproduction, then fixing from evidence.
Who is it for?
Hard-to-locate bugs, front-end/back-end behavior mismatches, and race, async, or state issues.
Skip if: Simple typos or obvious stack-trace errors, where the skill should not be auto-invoked.
When should I use this skill?
A user enters /debug-mode or mentions runtime instrumentation, hypothesis verification, .claude/debug.log, or reproduce-then-analyze.
What you get
A root-cause diagnosis backed by instrumented logs, then a verified fix with instrumentation cleaned up.
- local debug log-collection server
- region-marked instrumentation
- evidence-backed root-cause diagnosis
By the numbers
- 7 phases (Phase 0 through Phase 6)
- default debug server port 3847
- requires at least 2 verifiable hypotheses
Files
Debug Mode(与 Cursor 一致)
你已进入 Debug Mode。不要直接改业务逻辑猜修复;按阶段顺序执行,并在要求用户复现后 停止等待。
进入方式
- 用户在 Claude Code 输入:
/debug-mode(可选附带 bug 描述) - 仅用户显式进入;不要在没有请求时自动进入本模式
架构概览
flowchart LR
subgraph local["本机"]
S["debug-server.js<br/>:3847"]
L[".claude/debug.log"]
end
subgraph app["项目代码 #region DEBUG"]
BE["后端: fetch 或 appendFile"]
FE["浏览器: fetch POST"]
end
FE -->|POST /debug| S
BE -->|POST /debug 或写文件| S
BE --> L
S --> L
CC["Claude Code"] -->|读/清空日志| L---
Phase 0:启动日志收集 API(每次 debug 会话一次)
从本 skill 目录定位脚本(安装后通常在 ~/.claude/skills/debug-mode/scripts/ 或项目内 .claude/skills/debug-mode/scripts/):
# SKILL_SCRIPTS = 本 skill 的 scripts 目录绝对路径
# PROJECT_ROOT = 当前调试的项目根目录(从用户打开的文件路径推断,写死在后续插桩里)
bash "${SKILL_SCRIPTS}/start-server.sh" "${PROJECT_ROOT}" 3847验证:
curl -sf http://127.0.0.1:3847/health- 默认端口 3847(
DEBUG_SERVER_PORT可覆盖) - 日志文件:`{PROJECT_ROOT}/.claude/debug.log`
- 远程/只读文件系统:日志可改用 `/tmp/.claude/debug.log`,并在插桩里写死该路径
结束调试后停止服务:
bash "${SKILL_SCRIPTS}/stop-server.sh" "${PROJECT_ROOT}"更详细的语言片段见:references/instrumentation.md(需要插桩时再读)。
---
Phase 1:理解 Bug
若用户未说明,询问:
- 期望行为 vs 实际行为
- 复现步骤、错误信息、环境(dev/prod、浏览器、分支)
阅读相关源码,理清调用链与数据流。
---
Phase 2:生成假设
输出 可验证的假设 列表(至少 2 条,含非显而易见原因):
基于分析,假设如下:
1. **[标题]** — [可能原因]
2. **[标题]** — ...
3. ...---
Phase 3:插桩
日志目标
- 主文件:
{PROJECT_ROOT}/.claude/debug.log(NDJSON) - 浏览器 / 可发 HTTP 的运行时:POST
http://127.0.0.1:3847/debug - 服务端也可 直接 append 同一日志文件(见
references/instrumentation.md)
project_root 规则(与 Cursor 相同)
PROJECT_ROOT 在插桩里必须是写死的绝对路径字符串(从对话中的文件路径推断)。
禁止在插桩代码里使用:import.meta.dir、__dirname、process.cwd()、Deno.cwd()、path.resolve() 等运行时解析。
例外:远程 CI / 本地不可写 → 使用 /tmp/.claude/debug.log。
Region 标记
所有插桩必须包在 region 内,便于一次性删除:
// #region DEBUG
...instrumentation...
// #endregion DEBUG(Python/HTML/Go 等见 references/instrumentation.md)
日志规则
- 禁止
console.log、print、写 stderr/stdout 作为调试输出 - 每条日志带假设编号:
[DEBUG H1]、[DEBUG H2]… - 记录:变量值、分支、时序、关键决策点;保持最小必要集
- 每次让用户复现前:清空日志
bash "${SKILL_SCRIPTS}/clear-log.sh" "${PROJECT_ROOT}" 3847插桩完成后告知用户如何复现,然后 STOP 并等待(不要继续分析或改修复逻辑)。
---
Phase 4:分析日志并诊断
用户确认已复现后:
1. 先看日志体量:wc -l 或 ls -lh;过大则用 tail / grep '\[DEBUG H' 2. 将日志行映射到假设:证实 / 排除 3. 输出诊断(带证据):
## 诊断
**根因**:[有日志依据的结论]
**证据**:
- [H1] 排除 — …
- [H2] 证实 — [引用日志字段/行]若证据不足:提出新假设 → 追加插桩 → 清空日志 → 再请用户复现。
---
Phase 5:修复
- 实施修复,保留
#region DEBUG插桩 - 再次
clear-log.sh,请用户验证修复是否生效,然后 STOP 等待
---
Phase 6:验证与清理
若已修复:
1. 用 Grep 查找 #region DEBUG,删除所有 region 及其中代码 2. 删除 .claude/debug.log(及可选 .claude/debug-server.out) 3. stop-server.sh 4. 简短总结根因与修复
若未修复:
- 读取新日志,询问用户观察到的现象,回到 Phase 2 迭代
---
硬性规则(与 Cursor Debug Mode 对齐)
| 规则 | 说明 |
|---|---|
| 不跳阶段 | 即使“看起来知道答案”也要插桩 + 日志验证 |
| 不提前删插桩 | 用户确认修复前保留 #region DEBUG |
| 不用 stdout 调试 | 只写 .claude/debug.log 或 POST /debug |
| 每次复现前清空日志 | clear-log.sh 或 > .claude/debug.log |
| 必须 region 包裹 | 方便清理 |
| 复现后等待用户 | 不要连续自动推进 |
---
API 速查
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /health | 服务与日志路径探活 |
| POST | /debug | 写入一条 NDJSON(body: hypothesis, message, data, location) |
| POST | /clear | 清空日志文件 |
POST /debug 示例 body:
{
"hypothesis": "H1",
"message": "cart total before tax",
"data": { "subtotal": 99.5, "items": 3 },
"location": "src/cart.ts:88"
}---
安装到 Claude Code
将本目录复制到个人或项目 skills 路径之一:
# 个人(全局)
cp -r skills/debug-mode ~/.claude/skills/debug-mode
# 或项目内
mkdir -p .claude/skills && cp -r /path/to/corner-skills/skills/debug-mode .claude/skills/重启 Claude Code 后使用 /debug-mode。
{
"skill_name": "debug-mode",
"evals": [
{
"id": 1,
"prompt": "/debug-mode 我的 React 页面点击提交后列表不刷新,Network 里接口 200 但 UI 没变。项目在 /Users/me/app,请按 debug 流程来。",
"expected_output": "启动 debug-server、列出假设、在相关组件/请求处添加 #region DEBUG 插桩(fetch 到 3847),清空日志后请用户复现并停止等待。",
"files": []
},
{
"id": 2,
"prompt": "我已经按你说的复现了,debug.log 在 /Users/me/app/.claude/debug.log,请分析。",
"expected_output": "读取/过滤 debug.log,映射 H1/H2 假设,给出带证据的诊断;若不足则提出新假设而非直接猜修复。",
"files": []
}
]
}
debug-mode
在 Claude Code 里复刻 Cursor Debug Mode 的交互式调试流程:先列假设 → 在代码里插桩 → 你本地复现 → 读运行时日志验证 → 再修复,避免「凭感觉改代码」。
适用场景
- 接口返回正常但 UI / 状态不对
- 异步、竞态、闭包陈旧等难以从堆栈直接看出的问题
- 需要对比「某条代码路径有没有走到、变量当时是什么」
不太适合:明显的拼写错误、一眼能看懂的堆栈行号、改一行就能修好的 typo。
前置条件
- Claude Code(支持 Skills / 斜杠命令)
- 本机已安装 Node.js(用于跑日志收集服务,无额外 npm 依赖)
安装
任选一种方式,把本目录放到 Claude Code 的 skills 路径下即可:
# 全局:所有项目可用
cp -r skills/debug-mode ~/.claude/skills/debug-mode
# 仅当前仓库
mkdir -p .claude/skills
cp -r /path/to/corner-skills/skills/debug-mode .claude/skills/安装后重启 Claude Code,在输入框输入 / 应能看到 `debug-mode`。
Skill 配置了disable-model-invocation: true:只有你用/debug-mode进入,Claude 不会自动开启,避免普通对话里误插桩。
快速开始
1. 进入 Debug Mode
在 Claude Code 中输入:
/debug-mode 点击提交后列表不刷新,Network 里接口 200也可以先 /debug-mode,再在后续消息里补充复现步骤。
2. 配合 Agent 完成一轮调试
Agent 会按阶段推进,你需要在中间手动复现 bug(和 Cursor 一样):
| 阶段 | 你会看到什么 | 你需要做什么 |
|---|---|---|
| 理解 + 假设 | 列出 H1、H2… 可能原因 | 补充期望/实际行为、复现步骤(若没说清) |
| 插桩 | 代码里出现 #region DEBUG 块 | 按提示操作页面 / 调 API 复现一次 |
| 分析 | 根据 .claude/debug.log 给出诊断 | 回复「已复现」或粘贴现象 |
| 修复 + 验证 | 改业务代码,暂时保留插桩 | 再复现一次,确认问题消失 |
| 清理 | 删除所有 #region DEBUG、停掉日志服务 | 一般不用动手 |
3. 结束后
项目下可能产生(建议加入 .gitignore):
.claude/debug.log # NDJSON 运行时日志
.claude/debug-server.pid # 日志服务进程信息
.claude/debug-server.out # 服务 stdout(可选)---
工作原理
本 skill 会在本机启动一个轻量 HTTP 服务,把前端/后端的调试信息汇总到同一个日志文件,供 Claude 读取分析。
flowchart LR
subgraph local["本机"]
S["debug-server :3847"]
L[".claude/debug.log"]
end
subgraph code["你的项目 #region DEBUG"]
FE["浏览器 fetch"]
BE["后端 fetch / 写文件"]
end
FE -->|POST /debug| S
BE --> S
BE --> L
S --> L
CC["Claude Code"] -->|读日志| L- 默认端口:
3847(环境变量DEBUG_SERVER_PORT可改) - 日志路径:
{项目根}/.claude/debug.log - 插桩约定:必须用
// #region DEBUG…// #endregion DEBUG包裹,修复后一次性删掉 - 不要用
console.log/print做调试输出(会污染终端,且与 Cursor 规则不一致)
各语言插桩示例见:references/instrumentation.md。
---
手动操作脚本(可选)
Agent 通常会代你执行;你也可以自己在项目根目录操作:
SKILL=~/.claude/skills/debug-mode/scripts # 按实际安装路径修改
PROJECT=$(pwd)
# 启动日志服务
bash "$SKILL/start-server.sh" "$PROJECT" 3847
# 探活
curl http://127.0.0.1:3847/health
# 清空日志(每次复现前)
bash "$SKILL/clear-log.sh" "$PROJECT" 3847
# 停止服务
bash "$SKILL/stop-server.sh" "$PROJECT"手动发一条测试日志
curl -X POST http://127.0.0.1:3847/debug \
-H 'Content-Type: application/json' \
-d '{"hypothesis":"H1","message":"smoke test","data":{"ok":true}}'
cat .claude/debug.logHTTP API
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /health | 检查服务是否正常、日志文件路径 |
POST | /debug | 写入一条日志(JSON body) |
POST | /clear | 清空日志文件 |
POST /debug 常用字段:
| 字段 | 说明 |
|---|---|
hypothesis | 假设编号,如 H1 或 1 |
message | 简短描述 |
data | 任意 JSON,记录变量快照 |
location | 可选,如 src/App.tsx:42 |
---
目录说明
debug-mode/
├── README.md # 本文件(给人看)
├── SKILL.md # Agent 执行的完整流程(给 Claude 看)
├── scripts/
│ ├── debug-server.js # 日志收集 API
│ ├── start-server.sh
│ ├── stop-server.sh
│ └── clear-log.sh
├── references/
│ └── instrumentation.md # 前后端插桩代码片段
└── evals/
└── evals.json # skill 评测用例(可选)---
常见问题
Q:`/debug-mode` 找不到? 确认目录名为 debug-mode,且位于 ~/.claude/skills/ 或项目 .claude/skills/ 下,然后重启 Claude Code。
Q:浏览器插桩没有日志? 先 curl http://127.0.0.1:3847/health 确认服务在跑;确认插桩 URL 端口与启动时一致(默认 3847)。
Q:日志文件在哪? 一般在项目根目录 .claude/debug.log。远程或只读环境可改用 /tmp/.claude/debug.log(需在插桩里写死绝对路径)。
Q:和 Cursor IDE 内置 Debug Mode 的关系? 流程与规则对齐(假设 → 插桩 → 复现 → 读日志 → 修复 → 清理);本 skill 通过本地 HTTP + 统一日志文件在 Claude Code 中实现同样协作方式。
Q:调试完忘记停服务?
bash ~/.claude/skills/debug-mode/scripts/stop-server.sh "$(pwd)"---
相关链接
- Claude Code Skills 文档:<https://code.claude.com/docs/en/skills>
- 更细的插桩示例:references/instrumentation.md
插桩参考(前后端)
默认日志 API:http://127.0.0.1:3847(可用 DEBUG_SERVER_PORT 改端口)
统一日志文件:{project_root}/.claude/debug.log(NDJSON,一行一条)
禁止 console.log / print / stdout 作为调试输出;一律走文件追加或 HTTP POST。
---
浏览器(React / Vue / 原生 JS)
在 #region DEBUG 内使用(DEBUG_PORT 与启动脚本一致):
// #region DEBUG
const __DBG = (h, msg, data) =>
fetch(`http://127.0.0.1:3847/debug`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
hypothesis: h,
message: msg,
data,
location: "ComponentName.tsx:42",
}),
}).catch(() => {});
// #endregion DEBUG调用示例:__DBG("H1", "after fetch", { items: list.length });
---
Node / Bun / Deno(服务端)
方式 A — HTTP(与浏览器相同,需 debug-server 已启动)
// #region DEBUG
fetch("http://127.0.0.1:3847/debug", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
hypothesis: "H2",
message: "handler entry",
data: { userId },
location: "routes/user.ts:18",
}),
}).catch(() => {});
// #endregion DEBUG方式 B — 直接写日志文件(无需 HTTP,适合 CLI / 无浏览器环境)
LOG_PATH 必须是写死的绝对路径(从对话中的项目路径推断,禁止 process.cwd() / __dirname 动态解析):
// #region DEBUG
import fs from "fs";
const LOG_PATH = "/ABS/PATH/TO/project/.claude/debug.log";
fs.appendFileSync(
LOG_PATH,
JSON.stringify({
ts: new Date().toISOString(),
hypothesis: "H2",
message: "[DEBUG H2] handler entry",
data: { userId },
location: "routes/user.ts:18",
}) + "\n"
);
// #endregion DEBUG---
Python
# #region DEBUG
import json, urllib.request
def _dbg(h, msg, data=None, loc=""):
urllib.request.urlopen(
urllib.request.Request(
"http://127.0.0.1:3847/debug",
data=json.dumps({"hypothesis": h, "message": msg, "data": data, "location": loc}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
),
timeout=0.5,
)
# #endregion DEBUG或文件追加(绝对路径写死):
# #region DEBUG
LOG_PATH = "/ABS/PATH/TO/project/.claude/debug.log"
with open(LOG_PATH, "a") as f:
f.write(json.dumps({"hypothesis": "H1", "message": "[DEBUG H1] step", "data": x}) + "\n")
# #endregion DEBUG---
Go
// #region DEBUG
func dbgLog(h, msg string, data any) {
b, _ := json.Marshal(map[string]any{"hypothesis": h, "message": msg, "data": data})
http.Post("http://127.0.0.1:3847/debug", "application/json", bytes.NewReader(b))
}
// #endregion DEBUG---
Region 标记对照
| 语言 | 开始 | 结束 |
|---|---|---|
| JS/TS/Go/Rust/C | // #region DEBUG | // #endregion DEBUG |
| Python/Ruby/Shell | # #region DEBUG | # #endregion DEBUG |
| HTML/Vue/Svelte | <!-- #region DEBUG --> | <!-- #endregion DEBUG --> |
日志消息格式:[DEBUG H1]、[DEBUG H2] … 与假设编号对应。
#!/usr/bin/env bash
# Clear .claude/debug.log (and optionally via HTTP if server is up).
set -euo pipefail
PROJECT_ROOT="${1:-$(pwd)}"
PORT="${2:-${DEBUG_SERVER_PORT:-3847}}"
LOG_FILE="${PROJECT_ROOT}/.claude/debug.log"
mkdir -p "${PROJECT_ROOT}/.claude"
: > "${LOG_FILE}"
if curl -sf -X POST "http://127.0.0.1:${PORT}/clear" >/dev/null 2>&1; then
echo "cleared via API and local file: ${LOG_FILE}"
else
echo "cleared local file: ${LOG_FILE}"
fi
#!/usr/bin/env node
/**
* Local debug log collector for debug-mode skill.
* Accepts POST /debug from browser & server runtimes; appends NDJSON to .claude/debug.log
*
* Usage:
* node debug-server.js [port] [projectRoot]
* DEBUG_SERVER_PORT=3847 DEBUG_PROJECT_ROOT=/path/to/proj node debug-server.js
*/
const http = require("http");
const fs = require("fs");
const path = require("path");
const PORT = parseInt(
process.argv[2] || process.env.DEBUG_SERVER_PORT || "3847",
10
);
const PROJECT_ROOT = path.resolve(
process.argv[3] || process.env.DEBUG_PROJECT_ROOT || process.cwd()
);
const LOG_DIR = path.join(PROJECT_ROOT, ".claude");
const LOG_FILE = path.join(LOG_DIR, "debug.log");
const PID_FILE = path.join(LOG_DIR, "debug-server.pid");
const DEFAULT_PORT = 3847;
function ensureLogDir() {
fs.mkdirSync(LOG_DIR, { recursive: true });
}
function appendLog(entry) {
ensureLogDir();
const line =
typeof entry === "string" ? entry : JSON.stringify(entry);
const normalized = line.endsWith("\n") ? line : `${line}\n`;
fs.appendFileSync(LOG_FILE, normalized, "utf8");
}
function clearLog() {
ensureLogDir();
fs.writeFileSync(LOG_FILE, "", "utf8");
}
function readBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on("data", (c) => chunks.push(c));
req.on("end", () => {
try {
const raw = Buffer.concat(chunks).toString("utf8");
resolve(raw ? JSON.parse(raw) : {});
} catch (e) {
reject(e);
}
});
req.on("error", reject);
});
}
function send(res, status, body) {
const payload = typeof body === "string" ? body : JSON.stringify(body);
res.writeHead(status, {
"Content-Type": "application/json; charset=utf-8",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
});
res.end(payload);
}
function corsPreflight(res) {
res.writeHead(204, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Max-Age": "86400",
});
res.end();
}
const server = http.createServer(async (req, res) => {
const url = new URL(req.url || "/", `http://127.0.0.1:${PORT}`);
if (req.method === "OPTIONS") {
corsPreflight(res);
return;
}
try {
if (req.method === "GET" && url.pathname === "/health") {
send(res, 200, {
ok: true,
port: PORT,
projectRoot: PROJECT_ROOT,
logFile: LOG_FILE,
pid: process.pid,
});
return;
}
if (req.method === "POST" && url.pathname === "/clear") {
clearLog();
send(res, 200, { ok: true, cleared: LOG_FILE });
return;
}
if (req.method === "POST" && url.pathname === "/debug") {
const body = await readBody(req);
const ts = body.ts || new Date().toISOString();
const hypothesis = body.hypothesis || body.h || "";
const message = body.message || body.msg || "";
const hTag =
hypothesis && !String(hypothesis).startsWith("H")
? `H${hypothesis}`
: hypothesis;
const prefix = hTag ? `[DEBUG ${hTag}]` : "[DEBUG]";
const line = {
ts,
hypothesis: hTag || null,
message: message ? `${prefix} ${message}` : prefix,
data: body.data ?? body.payload ?? null,
location: body.location || body.loc || null,
sessionId: body.sessionId || null,
runId: body.runId || null,
};
appendLog(line);
send(res, 200, { ok: true });
return;
}
send(res, 404, { ok: false, error: "not_found" });
} catch (err) {
send(res, 400, { ok: false, error: String(err.message || err) });
}
});
function writePidFile() {
ensureLogDir();
fs.writeFileSync(
PID_FILE,
JSON.stringify({ pid: process.pid, port: PORT, projectRoot: PROJECT_ROOT }),
"utf8"
);
}
function removePidFile() {
try {
fs.unlinkSync(PID_FILE);
} catch {
/* ignore */
}
}
server.listen(PORT, "127.0.0.1", () => {
writePidFile();
// eslint-disable-next-line no-console
console.log(
JSON.stringify({
event: "debug-server-started",
port: PORT,
projectRoot: PROJECT_ROOT,
logFile: LOG_FILE,
health: `http://127.0.0.1:${PORT}/health`,
})
);
});
function shutdown() {
removePidFile();
server.close(() => process.exit(0));
}
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
module.exports = { PORT: DEFAULT_PORT, LOG_FILE, appendLog, clearLog };
#!/usr/bin/env bash
# Start debug log collector in background for the current project.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${1:-$(pwd)}"
PORT="${2:-${DEBUG_SERVER_PORT:-3847}}"
LOG_DIR="${PROJECT_ROOT}/.claude"
PID_FILE="${LOG_DIR}/debug-server.pid"
mkdir -p "${LOG_DIR}"
if [[ -f "${PID_FILE}" ]]; then
existing_pid="$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('${PID_FILE}','utf8')).pid)}catch{}" 2>/dev/null || true)"
if [[ -n "${existing_pid}" ]] && kill -0 "${existing_pid}" 2>/dev/null; then
echo "debug-server already running (pid=${existing_pid}, port=${PORT})"
curl -sf "http://127.0.0.1:${PORT}/health" || true
exit 0
fi
fi
nohup node "${SCRIPT_DIR}/debug-server.js" "${PORT}" "${PROJECT_ROOT}" \
> "${LOG_DIR}/debug-server.out" 2>&1 &
sleep 0.3
curl -sf "http://127.0.0.1:${PORT}/health" && echo ""
#!/usr/bin/env bash
# Stop debug log collector for a project.
set -euo pipefail
PROJECT_ROOT="${1:-$(pwd)}"
PID_FILE="${PROJECT_ROOT}/.claude/debug-server.pid"
if [[ ! -f "${PID_FILE}" ]]; then
echo "no debug-server pid file at ${PID_FILE}"
exit 0
fi
pid="$(node -e "console.log(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8')).pid)" "${PID_FILE}" 2>/dev/null || true)"
if [[ -z "${pid}" ]]; then
rm -f "${PID_FILE}"
exit 0
fi
if kill -0 "${pid}" 2>/dev/null; then
kill "${pid}" 2>/dev/null || true
sleep 0.2
fi
rm -f "${PID_FILE}"
echo "stopped debug-server (pid=${pid})"
Related skills
FAQ
How is it invoked?
The user runs /debug-mode in Claude Code; it does not auto-enter without an explicit request.
Where do debug logs go?
To {PROJECT_ROOT}/.claude/debug.log as NDJSON, or POST to a local server on port 3847; on read-only filesystems it uses /tmp/.claude/debug.log.