cmux-custom-sidebar

cmux-custom-sidebar

热门

根据自然语言需求构建自定义 cmux 侧边栏。当用户要求创建自定义侧边栏、展示其工作区/标签页/PR/时钟的侧边栏、随性定制(vibe-coded)侧边栏,或者涉及 ~/.config/cmux/sidebars/ 中文件的任何需求时使用。涵盖编写解释型 SwiftUI 风格文件、开启 Beta 功能开关、选择侧边栏以及通过热重载快速迭代的完整流程。

2.5万Star
2126Fork
更新于 2026/8/2
SKILL.md
只读
名称
cmux-custom-sidebar
描述

根据自然语言需求构建自定义 cmux 侧边栏。当用户要求创建自定义侧边栏、展示其工作区/标签页/PR/时钟的侧边栏、随性定制(vibe-coded)侧边栏,或者涉及 ~/.config/cmux/sidebars/ 中文件的任何需求时使用。涵盖编写解释型 SwiftUI 风格文件、开启 Beta 功能开关、选择侧边栏以及通过热重载快速迭代的完整流程。

cmux 自定义侧边栏

cmux 能在运行时直接解析并渲染轻量级的 SwiftUI 风格文件来生成自定义侧边栏:无需 Xcode、无需构建步骤、无需代码签名。文件在保存时会自动热重载,可以实时绑定 cmux 的动态状态(工作区、标签页、git、PR、时钟),并在点击时触发真实的 cmux 命令。

提出需求的用户描述的是最终效果(例如“帮我做个能显示工作区并且能方便切换的侧边栏”),而不是具体的技术实现。请直接替他们做好技术决策,不要向他们询问 SwiftUI 语法、文件路径或代码细节。

本 Skill 是工作流概要。在编写相对复杂的侧边栏之前,请先阅读完整的编写规范文档(包含所有支持的视图、修饰符、语言特性及数据字段):

cmux docs sidebars
curl -fsSL https://raw.githubusercontent.com/manaflow-ai/cmux/main/docs/custom-sidebars.md

工作流

  1. 开启 Beta 功能(仅需设置一次):设置(Settings)> Beta 功能(Beta features)> 自定义侧边栏(Custom sidebars,配置项 customSidebars.beta.enabled)。如果写好的侧边栏没有出现在选择器中,请优先检查此项。
  2. ~/.config/cmux/sidebars/<name>.swift 创建命名文件。文件名会直接作为菜单上的显示标签;请使用短 kebab-case 格式。该文件是一个独立的 SwiftUI 风格视图表达式(无需 struct、无需 var body,也无需 import 语句)。虽然也支持 .json 变体来放置静态布局,但对于任何动态效果,请首选 .swift
  3. 校验与选中:
    cmux sidebar validate <name>   # 使用真实数据结构进行解析与解释执行校验
    cmux sidebar select <name>
    
    用户也可以右键点击侧边栏切换按钮来进行选择。
  4. 迭代调试。保存文件即可完成原地热重载(也可使用 cmux sidebar reload 强制重载)。在宣布完成前,请确认各项列表展现的是真实数据,且点击操作行为正常。

编写规则

  • 绑定到 workspaces 上下文,而不是硬编码文本,这样侧边栏能始终保持数据同步。
  • 代表可打开项的行,在点击时应运行对应的 cmux(...) 操作。仅展示纯文本的列表通常不是用户想要的。
  • 对于类似工作区的列表,请使用 Reorderable;它直接开箱即用支持持久化的拖拽排序。
  • 保持原生且清爽的视觉样式:标题、分隔线,然后是具体内容。
  • 对长列表进行截断(例如 .prefix(20),在渲染前先过滤/排序)。侧边栏大约每秒重新评估更新一次。
  • 严格在受支持的语法子集中编写。不支持的语法会被平滑跳过而不是直接崩溃,但应当选择最接近的受支持方案,避免交付一个半空白的侧边栏。

快速上手

cat > ~/.config/cmux/sidebars/mine.swift <<'SWIFT'
VStack(alignment: .leading, spacing: 8) {
    Text("My sidebar").font(.title3).bold()
    Text(clock.time).font(.caption).foregroundColor(.secondary)
    Divider()
    Reorderable(workspaces, move: "workspace.reorder") { w in
        Button(action: { cmux("workspace.select", workspace_id: w.id) }) {
            HStack {
                Text(w.selected ? "●" : "○").foregroundColor(w.selected ? "#FF8800" : .secondary)
                Text(w.title)
                Spacer()
            }.padding(4)
        }
    }
}
SWIFT
cmux sidebar validate mine && cmux sidebar select mine

实时数据上下文(只读,刷新频率约 1s)

  • workspaces: idtitleselectedpinnedindexdirectoryports + portCountunreadtabs + tabCount;存在时还包含 descriptioncolorbranch + dirtypr / prs{number, label, url, status, stale, branch})、progress{value, label})、latestMessagelatestPromptlatestAtremote{target, state, connected})。
  • workspaces[i].tabs: idtitlefocusedpinned;可用时还包含 directorybranch + dirtyports
  • clock: {time, hour, minute, second, weekday, epoch}
  • 标量字段: workspaceCountselectedTitleselectedIdunreadTotal

可选字段在缺失时会被忽略;请使用 if let b = w.branch { ... }w.pr != nil ? ... : ... 进行安全防护。

操作指令

按钮或 .onTapGesture 主体通过 cmux("<method>", param: value) 进行调用,分发途径与 CLI 相同。常用方法包括:workspace.select (workspace_id)、surface.focus (surface_id)、workspace.reorder (workspace_id + index)。openURL("https://...") 用于打开外部链接。完整命令接口可查阅:cmux docs api

支持的语法子集

容器组件:Stacks 布局(包括 Lazy 变体)、GroupListSection、Grid 网格、ViewThatFitsScrollViewHSplitView(双列可调大小分栏)。内容组件:TextLabelImage(systemName:)Button(支持 title 和 label 两种形式)、MenuProgressViewGaugeSpacerDivider、几何图形(Shapes)、通过 .background 实现的渐变。修饰符:完整排版样式集、十六进制字符串或 Token 格式的颜色、.padding/.frame/布局、支持任意嵌套视图的 .background/.overlay/.mask/.contextMenu、阴影/边框/透明度/视觉效果、.onTapGesture.help.disabled。语言特性:let、自定义 func 辅助函数、for/ForEachif/else、三元运算符、字符串插值、算术运算、数组方法(filter/map/sorted/prefix)、字符串与数字格式化。

暂不支持的功能(直接按标准 Swift 方式编写即可,系统会平滑降级):@State 以及输入控件(TextFieldToggleSliderPicker)、自定义 struct/View 定义、导航相关(sheet/popover)、AsyncImage。目前暂不支持双向编辑数据绑定;但点击触发 cmux(...) 命令是可以正常工作的。

故障排查

  • 右键选择器中找不到:Beta 功能开关未开启,或者文件未直接放置在 ~/.config/cmux/sidebars/ 目录下。
  • 渲染为空或仅渲染部分:运行 cmux sidebar validate <name>。错误信息会直接在侧边栏中内联显示,并标明出错位置;如果保存的代码有错,屏幕上会保留上一次正常渲染的结果,因此修复后再重新保存即可。
  • 列表行不可点击:将该行包裹在 Button(action: { cmux(...) }) { ... } 中,或添加 .onTapGesture { cmux(...) }
  • 拖拽排序无法持久化:请使用 Reorderable(data, move: "workspace.reorder"),而不是 List/.onMove/.draggable