cmux-debugging

cmux-debugging

热门

针对 cmux 的调试日志、Debug 菜单、运行时踩坑指南、输入延迟敏感路径、SwiftUI 列表快照边界、macOS 系统版本复现及本地视觉迭代。适用于添加调试探针、排查 UI 与运行时问题、修改终端渲染、标签页/侧边栏列表视图、拖拽 UTType 自定义类型或使用 Debug 菜单等场景。

2.5万Star
2120Fork
更新于 2026/8/1
SKILL.md
只读
名称
cmux-debugging
描述

针对 cmux 的调试日志、Debug 菜单、运行时踩坑指南、输入延迟敏感路径、SwiftUI 列表快照边界、macOS 系统版本复现及本地视觉迭代。适用于添加调试探针、排查 UI 与运行时问题、修改终端渲染、标签页/侧边栏列表视图、拖拽 UTType 自定义类型或使用 Debug 菜单等场景。

cmux 调试指南

调试事件日志(Debug event log)

在统一的 DEBUG 构建日志中添加调试事件埋点(按键、鼠标、焦点、分屏、标签页等)。并不需要给每个新代码路径都打日志,大部分埋点只是为了狗粮测试(dogfooding)阶段调试,合并前要记得清理掉。

tail -f "$(cat /tmp/cmux-last-debug-log-path 2>/dev/null || echo /tmp/cmux-debug.log)"
  • 未指定标签的 Debug 版应用日志输出至 /tmp/cmux-debug.log;带标签的(./scripts/reload.sh --tag <tag>)输出至 /tmp/cmux-debug-<tag>.log
  • reload.sh 会将当前日志路径写入 /tmp/cmux-last-debug-log-path,选中的开发版 CLI 路径写入 /tmp/cmux-last-cli-path,并把 /tmp/cmux-cli$HOME/.local/bin/cmux-dev 指向该 CLI。
  • 具体实现:Packages/macOS/CMUXDebugLog/Sources/CMUXDebugLog/DebugEventLog.swift。App 层垫片:Sources/App/DebugLogging.swift。两者均被 #if DEBUG 包裹,因此所有调用处都必须用 #if DEBUG / #endif 条件编译。
  • cmuxDebugLog("message") 会带上时间戳实时追加内容。底层维护了一个容量为 500 条的环形缓冲区(ring buffer);调用 CMUXDebugLog.DebugEventLog.shared.dump() 可将完整的缓冲区内容 dump 到文件。
  • 按键事件在 AppDelegate.swift(monitor、performKeyEquivalent)中记录;鼠标和 UI 事件则内联在视图中记录(如 ContentViewBrowserPanelView)。
  • 固定的事件前缀:focus.panel, focus.bonsplit, focus.firstResponder, focus.moveFocus, tab.select, tab.close, tab.dragStart, tab.drop, pane.focus, pane.drop, divider.dragStart

Debug 菜单

DEBUG 构建版本会在 macOS 顶部菜单栏显示一个 Debug 菜单。当用户提到“debug menu”或“debug window”时,指的是这个菜单,而不是 defaults write 命令。

Debug > Debug Windows 包含用于调节布局、颜色和行为的面板,按字母顺序排列且没有分隔线。如果要新增面板:创建一个带有 shared 单例的 NSWindowController 子类,在 Sources/cmuxApp.swift 的“Debug Windows”菜单中注册它,并为其配备使用 @AppStorage 绑定(以支持实时修改)的 SwiftUI 视图。

运行时踩坑指南

  • 自定义拖拽 UTType 必须声明在 Resources/Info.plistUTExportedTypeDeclarations 下。
  • 切勿添加应用级别的 display link 或手动运行 ghostty_surface_draw 循环;请依赖 Ghostty 原生的唤醒与渲染机制,以防引起输入延迟。
  • Sources/TerminalWindowPortal.swift 中的 WindowTerminalHostView.hitTest() 在每次事件(包括键盘输入)发生时都会触发。切勿在 isPointerEvent 卫语句(guard)之外添加任何繁重逻辑。
  • Sources/ContentView.swift 中的 TabItemView 采用了 Equatable 结合 .equatable() 的方式,以便在打字时跳过 body 的重新求值。在未同步更新 == 并在调用处保留 .equatable() 的情况下,不要新增任何环境(environment)、store 或 binding 读取。
  • Sources/GhosttyTerminalView.swift 中的 TerminalSurface.forceRefresh() 每次按键都会执行。严禁在其中进行内存分配、文件 I/O 或字符串格式化操作。
  • SurfaceSearchOverlay 必须挂载到 Sources/GhosttyTerminalView.swift 中的 GhosttySurfaceScrollView 上,而不是挂载到 SwiftUI 面板容器上。
  • 处于 LazyVStack / LazyHStack / List / ForEach 边界下方的视图只会接收不可变快照与闭包,绝不能直接接收可观察的 store(observable store)。
  • 在 SwiftUI body 中调用的函数严禁修改状态(state)或计划写入 store(schedule store writes)。
  • Foundation、SwiftUI、AttributeGraph 和 WebKit 的行为实现在 macOS 大版本升级间可能有所变化。在断定用户反馈的问题“无法复现”之前,请务必在反馈者所使用的 macOS 系统版本上进行测试。

详细参考文档