SKILL.md
唯讀
名稱
cmux-debugging
描述
cmux 的 Debug 紀錄、Debug 選單、執行階段陷阱(runtime pitfalls)、打字延遲敏感路徑、SwiftUI 列表快照邊界、OS 版本重現(repro)以及本地視覺迭代指引。適用於新增 Debug 探針(probes)、診斷 UI 或執行階段問題、修改終端機繪製(terminal rendering)、分頁/側邊欄列表視圖、拖放 UTTypes,或使用 Debug 選單等情境。
cmux Debugging
Debug 事件紀錄
將 Debug 事件埋針(鍵盤、滑鼠、焦點、切分面板、分頁)整合至統一的 DEBUG 建置紀錄中。這並非要求每個新程式碼路徑都必須上記錄;多數探針(probes)僅用於吃狗糧(dogfood)除錯循環,並會在合併(merge)前移除。
tail -f "$(cat /tmp/cmux-last-debug-log-path 2>/dev/null || echo /tmp/cmux-debug.log)"
- 未加上標記(tag)的 Debug 應用程式紀錄會輸出至
/tmp/cmux-debug.log;加上標記的 (./scripts/reload.sh --tag <tag>) 則輸出至/tmp/cmux-debug-<tag>.log。 reload.sh會將目前的 Log 路徑寫入/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 轉接層 (shim):Sources/App/DebugLogging.swift。兩者皆包含#if DEBUG條件編譯,因此所有呼叫處都必須使用#if DEBUG/#endif包覆。 cmuxDebugLog("message")會自動加上時間戳記並即時追加紀錄。底層由 500 筆容量的環形緩衝區(ring buffer)支援;CMUXDebugLog.DebugEventLog.shared.dump()可將完整的緩衝區內容寫入檔案。- 按鍵事件於
AppDelegate.swift中記錄(monitor,performKeyEquivalent);滑鼠/UI 事件則直接內嵌於各視圖中(ContentView,BrowserPanelView)。 - 穩定的事件字首(prefixes):
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 包含用於調整版面配置(layout)、色彩與行為的面板,依字母順序排列且無分隔線。若要新增面板:請建立繼承自 NSWindowController 的子類別並提供 shared 單例(singleton),在 Sources/cmuxApp.swift 的 "Debug Windows" 選單中註冊,並搭配使用 @AppStorage 綁定(bindings)的 SwiftUI 視圖以實現即時變更。
執行階段陷阱
- 自訂的拖放(drag-and-drop)UTTypes 必須在
Resources/Info.plist的UTExportedTypeDeclarations底下宣告。 - 請勿新增應用程式層級的 display link 或手動
ghostty_surface_draw循環;應依賴 Ghostty 的喚醒與繪製器(renderer)機制,以避免打字延遲。 Sources/TerminalWindowPortal.swift中的WindowTerminalHostView.hitTest()會在每次事件(包含鍵盤事件)觸發時執行。請勿在isPointerEvent防護判斷之外添加任何非必要的運算。Sources/ContentView.swift中的TabItemView使用Equatable加上.equatable(),可在打字期間跳過 body 的重新評估。請勿在未更新==且未保持呼叫處使用.equatable()的情況下,隨意新增 environment/store/binding 的讀取。Sources/GhosttyTerminalView.swift中的TerminalSurface.forceRefresh()在每次按鍵時都會執行。嚴禁在此進行記憶體配置(allocations)、檔案 I/O 或格式化操作。SurfaceSearchOverlay必須從Sources/GhosttyTerminalView.swift中的GhosttySurfaceScrollView掛載,而非從 SwiftUI 面板容器掛載。- 在
LazyVStack/LazyHStack/List/ForEach邊界下方的 View,只會接收到不可變的快照(immutable snapshots)與閉包(closures),絕不會收到可觀察的 store(observable store)。 - 從 SwiftUI
body呼叫的函式絕不能變更狀態(mutate state)或排程寫入 store。 - Foundation、SwiftUI、AttributeGraph 與 WebKit 的語意(semantics)在 macOS 大版本升級之間可能發生變化。在宣稱使用者回報的重現(repro)不成立之前,請務必先在回報者所在的 macOS 版本上進行測試。
詳細參考文件
- references/debug-event-log.md:何時新增探針(probes)以及如何命名。
- references/runtime-pitfalls.md:在修改終端機繪製、點擊測試(hit testing)、分頁列、列表虛擬化(list virtualization)、搜尋覆蓋層(search overlay)層級或 OS 版本敏感的程式碼之前,請務必閱讀此文件。






