关于 debugging-code
Code Debugging 是面向 Rider 中解决方案的调试器优先运行时根因分析技能,涵盖 .NET 和游戏开发项目。当源码和日志不足以确定运行时值或控制流时,可用于收集证据。
主要功能
- 01调查运行时状态和控制流
- 02设置断点并检查变量值
- 03复现测试和应用场景
- 04复用调试会话并管理断点
- 05要求收集确凿证据后再修复运行时问题
适用场景
- 01确定运行中的程序进入了哪个分支
- 02检查故障调用路径中的变量值
- 03确认执行是否到达指定位置
- 04在 Rider 中调试测试失败
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jetbrains/ skills --skill debugging-code安装后在 Claude Code 中输入/debugging-code确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/tools.mdreference/tools/execute_run_configuration.mdget_run_configurations.mdxdebug_control_session.mdxdebug_evaluate_expression.mdxdebug_get_debugger_status.mdxdebug_get_frame_values.mdxdebug_get_stack.mdxdebug_get_threads.mdxdebug_get_value_by_path.mdxdebug_list_breakpoints.mdxdebug_remove_breakpoint.mdxdebug_run_to_line.mdxdebug_set_breakpoint.mdxdebug_set_variable.mdxdebug_start_debugger_session.md详细介绍
代码调试
以调试器为先,对在 Rider 中打开的解决方案进行运行时根因分析,涵盖 C#、C++、F#、VB、Unreal Engine 及其他 GameDev 项目。
通过 execute_tool(command="<tool> --arg value ...") 调用每个工具。不要直接调用底层句柄。仅在即将调用某个特定工具时阅读 reference/tools.md;不要预先加载整个工具树。
目标
当静态阅读代码不足以回答具体的运行时问题,或需要确认静态分析的思路或结果时,使用调试器证据作答——包括确认执行是否通过断点或跟踪点到达 Agent 选定的代码位置。
何时使用此技能
符合以下任一条件时使用此技能:
- 需要运行时状态或控制流证据(实际值、执行的分支、调用顺序、线程上下文,或执行是否到达选定位置),且无法从源代码或日志中有把握地推断;
- 否则需要阅读许多文件或手动追踪很长的调用链才能找到相关路径;
- 用户明确要求使用调试器(断点、单步执行、检查值、调试器会话)。
如果用户手动启用或提及此技能,应将其视为明确要求在所需工具可用时启动并使用调试器;不要将其简化为概念性讨论。
符合以下任一条件时跳过调试器(改用静态分析或日志检查):
- 源代码或构建输出中可见编译时/语法错误;
- 无需运行代码即可看出原因(拼写错误、重载错误、明显的空接收器、参数数量错误);
- 单文件逻辑错误,且所有状态在源代码层面都清晰可见;
- 失败测试消息或日志已指出出错行和具体值。
消歧
如果代码库领域中包含与调试相关的概念,应明确判断用户是在谈论自己的代码,还是确实要求你启动调试器。不要默认将名为 debug/Debugger 的标识符、功能、标志或日志类别——包括 System.Diagnostics.Debug 或 Debug 构建配置——视为调试器请求。
激活门槛(工具可用性)
仅当当前会话中有可用的调试器 MCP 工具时,才使用此技能。最低必需工具集:
xdebug_set_breakpointxdebug_start_debugger_sessionxdebug_control_sessionxdebug_get_stack- 至少一个值工具:
xdebug_get_frame_values、xdebug_get_value_by_path或xdebug_evaluate_expression get_run_configurations
如果无法使用这套最低必需工具:明确说明阻碍,不要强行执行调试器工作流,并改用最佳替代方案。所有工具的说明见 reference/tools.md。
调试前的初步排查
先进行最少量的静态排查(错误文本、堆栈跟踪、附近的源代码)。出现以下任一情况时开始调试器工作:静态分析后仍有多个合理的运行时假设;需要具体的运行时值或精确控制流才能判断;单步跟踪代码比阅读大量跨文件调用路径更省力;或用户明确要求执行调试器操作。
开始新一轮调试前,先评估能否复用当前相关会话。尽早设置第一个断点,并在更改运行时行为前收集具体证据。
强制运行时证据
对于运行时行为问题,在修改代码之前(当调试器证据可用时),至少收集以下内容:
- 暂停会话中的暂停位置(文件/行号);
- 通过
xdebug_get_stack获取顶部调用路径; - 当问题涉及可达性时,提供执行是否命中明确选定的断点或跟踪点的证据;
- 通过
xdebug_get_frame_values、xdebug_get_value_by_path或xdebug_evaluate_expression获取至少一个具体运行时值。
除非已明确说明存在阻碍,否则在收集这些证据之前,不要断言运行时结论。
复现模式选择
AUTO:Agent 可以直接运行并重新运行场景(运行配置、测试、可执行文件、端点)。使用xdebug_start_debugger_session在调试模式下启动;如果只需获取输出或退出代码,则使用execute_run_configuration进行非调试运行。ASSISTED:复现需要用户独有的操作(UI 流程、身份验证、外部依赖、硬件交互)。HYBRID:先尝试一到两次AUTO,如果未复现故障,再切换到ASSISTED。
如果候选目标是测试,默认使用 AUTO。准备好断点之前,绝不要要求用户复现。
测试任务执行
- 要调试测试,请在测试定义处(
[Fact]/[Test]/[TestMethod]方法或用例)传入--filePath+--line;IDE 会识别测试框架(xUnit、NUnit、MSTest)。对于现有测试运行配置,请使用--configurationName。若要在不调试的情况下运行测试(例如,在设置断点前确认测试会失败),请使用相同的目标参数调用execute_run_configuration。 - 触发后,使用
execute_tool(command="xdebug_get_debugger_status")检查结果状态,并在相关会话中继续操作。 - 除非没有可用的测试运行方式来复现问题,或复现需要用户独有的设置,否则不要要求用户手动重新运行。
参数规范
- 可选参数要么省略/设为 null,要么设为实际值;省略时就直接省略。
- 不要使用
""、"/"、"__omit__"、"."或虚构路径等占位字符串来表示省略的可选参数。 - 将 ID 和路径视为不透明的运行时数据:从工具输出中复制,不要自行构造。
会话绑定
- 准备断点或启动之前,调用
execute_tool(command="xdebug_get_debugger_status")。 - 如果存在相关的活动会话,请在该会话中继续,不要另开会话。
- 获取准确的
sessionId,并在所有会话范围内的调用中重复使用。如果会话停止、超时或消失,请先通过xdebug_get_debugger_status刷新会话信息,再继续使用。 - 暂停位置发生变化后,不要重复使用过时的
frameIndex或path;请从最新的xdebug_get_stack重新读取。
运行配置解析
- 从
get_run_configurations获取configurationName;其supportsDynamicLaunchOverrides决定是否支持--programArguments/--workingDirectory/--envs(参见 reference/tools/get_run_configurations.md)。 - 不要自行构造
dotnet调用,也不要在配置不支持覆盖参数时通过--programArguments传入测试筛选器;应遵循运行配置,仅在能实质性提升可复现性或可观测性时使用启动覆盖参数。
断点归属与规范
- 始终先运行
execute_tool(command="xdebug_list_breakpoints"),并以返回的owner(user/agent)为准。 - 修改任何内容前,先建立基线快照(
breakpointId -> enabled)。 - 通过
execute_tool(command="xdebug_set_breakpoint --breakpointId <id> --enabled false")临时禁用当前路径不需要的owner=user断点;仅在调试器周期结束时恢复一次。 - 避免在迭代期间大范围变更断点。
xdebug_remove_breakpoint默认使用--owner agent;如需全局清理,则依次调用两次:--owner agent,然后--owner user。
断点定位模式
xdebug_set_breakpoint 有两种互斥的定位模式(位置与 breakpointId)——一次调用中切勿混用;在 breakpointId 模式下,传入完整的目标状态,因为提供的字段会成为最终结果。每次调用后,都要确认返回的 lineText 与目标行相符。模式和完整约定见:reference/tools/xdebug_set_breakpoint.md。
库代码与反编译源代码调试
可以在库代码和框架代码中设置断点。read_file 可读取外部源文件,以及程序集的捆绑反编译输出(如果有,还包括通过 SourceLink / PDB 解析出的原始文件)。获取路径的方法:
- 堆栈帧:
xdebug_get_stack会返回file路径,包括外部程序集中的路径——请原样使用返回的路径; - 符号搜索:
search_symbol(q="TypeName", include_external=true)会返回外部 / 库符号路径。
在外部代码中设置断点前,始终使用 read_file(file_path=<path>) 查找准确行号;切勿猜测行号。不要通过插入 Console.WriteLine 来编辑源代码;请改用跟踪点。
选择入口点和第一个断点
首次运行前,明确选择范围最小且可复现的入口点(单个测试、聚焦的运行配置、端点处理程序、命令处理程序),并将第一个断点设在最早能观察到不确定性的可执行行(分支决策、映射边界、状态转换、动态分派、异常构造)。如不确定,最多设置 2 个粗略断点——一个在入口边界,一个在疑似故障边界——运行一次后再缩小范围。
核心工作流
复制此检查清单,并在推进过程中逐项勾选:
Debugger Run Progress:
- [ ] Scope the failure: exact error text, expected vs actual, 2-5 candidate anchors in the runtime path
- [ ] `xdebug_get_debugger_status` → reuse an active relevant session OR plan a new one
- [ ] Pick reproduction mode (AUTO / ASSISTED / HYBRID)
- [ ] Snapshot the breakpoint baseline; disable irrelevant user breakpoints
- [ ] Set initial breakpoints; verify `lineText` for each
- [ ] `xdebug_start_debugger_session ...` OR continue inside the existing session
- [ ] After a fresh start or RESUME: `xdebug_control_session --action WAIT_FOR_PAUSE`
- [ ] At each pause: `xdebug_get_stack` + values / eval (`xdebug_get_frame_values`, `xdebug_get_value_by_path`, `xdebug_evaluate_expression`)
- [ ] Decide next movement (`STEP_OVER` / `STEP_INTO` when evidence is nearby, OR a new breakpoint then `RESUME`)
- [ ] For tracepoints: `xdebug_control_session --action DRAIN_EVENTS`
- [ ] Stop on the first proven incorrect state transition or a stated blocker
- [ ] Wrap-up (cleanup + report)
每一步都要遵循以下规范:
- 没有明确指出预期的下一次暂停位置时,绝不执行
RESUME;每次执行RESUME后,始终执行WAIT_FOR_PAUSE。 - 等待超时:执行
PAUSE,重新检查已启用的断点和预期路径;连续超时 2 次后,停止重试该等待,并扩大断点覆盖范围。 - 没有具体运行时值作为依据时,绝不断言根本原因;在原因得到证实前,不要修改运行时行为。
- 不要止步于下游症状——沿调用帧向上追溯 / 回退到产生该状态的位置;如果需要的位置已经经过,则使用更早的断点重新启动。
- 当某个帧指向外部 / 反编译代码时,使用
read_file读取该代码,并在那里设置更深层的断点;不要跳过。
事件和跟踪点
breakpointErrorsTail/tracepointOutputsTail(xdebug_control_session;参见其参考文档)仅由基于 JVM 的调试器填充。Rider 的调试器并非基于 JVM,因此不要依赖这些字段:先在暂停的帧中使用xdebug_evaluate_expression对--condition进行预检,并从程序的运行 / 控制台输出中确认跟踪点日志。- 如需在不暂停程序的情况下记录跟踪点日志,请使用
execute_tool(command="xdebug_set_breakpoint --filePath <path> --line <n> --isLogMessage true --suspendPolicy NONE")(或--isLogStack true)。
表达式规范
xdebug_evaluate_expression 和 xdebug_set_variable 接受当前帧所用语言(C#、C++、F# 或 VB)的原始表达式——确切输入规则请参阅相应的参考文件。除此约定外:
- 对于
--condition和--expression中的全局/静态符号,优先使用完全限定名称,以避免调试器表达式上下文缺少导入而导致Unresolved reference。 - 路由器使用
ParametersListUtil解析外层的execute_tool(command=...)行。表达式包含双引号时,用单引号包裹外层命令字符串;包含单引号时,用双引号包裹外层字符串;避免混用两种引号而不进行转义。 - 如果程序已暂停,先使用
xdebug_evaluate_expression对有风险的--condition表达式进行预检,再依赖该表达式。
向上检查调用帧并回退
程序在某个帧中停止时,检查更上层的帧,以重建数据来源:确定是谁传入了当前值,以及状态最早在哪个调用帧中变得不正确。如果所需位置已经经过:使用更早的断点(AUTO)重新运行,或设置更早的断点并让用户再次复现(ASSISTED)。如果已经错过所需证据,不要从过晚的位置继续。如果某个帧指向外部代码/反编译代码,使用 read_file 阅读,并在需要时在那里设置断点,以便更深入地追踪数据来源。
证据检查清单
得出结论前,记录:确切的失败消息/正文;异常类型和/或状态码;状态首次偏离预期的位置;具体的错误键/值(以及相关数量);错误数据的来源/出处;以及流水线为何会放过这些数据。
收尾
调试完成后:
- 清理:执行
execute_tool(command="xdebug_remove_breakpoint --owner agent"),将已禁用的用户断点恢复到初始状态;如果不再需要该会话,则执行execute_tool(command="xdebug_control_session --action STOP")。 - 报告:
- 用一句话说明根因;
- 用 3-6 个要点说明因果链;
- 提供包含确切观测值的运行时证据;
- 提供代码引用(绝对路径加行号);
- 如果未进行调试而采用了替代方案,说明确切原因以及仍缺少哪些证据。
- 根据用户目标决定下一步:如果用户只要求诊断,则以报告和建议的后续步骤结束;如果任务意味着需要修改代码,则根据已证实的根因实施修复。
工具参考
有关 13 个 xdebug_* MCP 工具以及 get_run_configurations/execute_run_configuration 的签名和逐参数说明,请参阅 reference/tools.md。