自訂指令

透過在專案根目錄或 ~/.config/cmux/ 中新增 cmux.json 檔案來定義自訂指令和工作區版面配置。指令將顯示於指令面板中。

檔案位置

cmux 在兩個地方尋找設定:

  • 依專案: ./.cmux/cmux.json - 位於專案目錄中,優先採用
  • 本機回退: ./cmux.json - 仍支援現有 repo
  • 全域: ~/.config/cmux/cmux.json - 適用於所有專案,補充本地未定義的指令
本機動作與命令會覆寫具有相同 ID 或名稱的全域項目。
動作註冊表是 nightly 功能。使用 actionsshortcutui.surfaceTabBar.buttons 前,請安裝最新 nightly 建置。
專案本機動作會立即顯示在 surface 分頁列和 Command Palette 中。第一次執行仍會要求信任。信任是依精確的動作 fingerprint 計算,而不是依 repo 計算。專案本機圖片圖示會保持鎖定,直到該動作被信任。
如果專案設定或全域設定有 schema 錯誤,cmux 會退回到下一個有效設定,並在 Command Palette 中顯示 cmux.json Schema Error 列。選取它即可開啟設定檔。

編輯 cmux.json 後,按 Cmd+Shift+, 或執行 cmux reload-config 來套用變更。

設定架構

commands 仍用來定義可重複使用的 shell 命令和 workspace 版面。Nightly 建置會加入 actions 註冊表。動作是 surface 分頁列、Command Palette 和動作層級快捷鍵共用的公開 ID。

cmux.json
{
  "actions": {
    "cmux.newTerminal": {
      "type": "command",
      "title": "Codex",
      "subtitle": "Open Codex in a new terminal tab",
      "command": "codex --dangerously-bypass-approvals-and-sandbox",
      "target": "newTabInCurrentPane",
      "shortcut": "cmd+t",
      "icon": { "type": "image", "path": "./icons/codex.svg" }
    },
    "claude": {
      "type": "command",
      "title": "Claude Code",
      "command": "claude --dangerously-skip-permissions",
      "target": "newTabInCurrentPane",
      "shortcut": "cmd+shift+c",
      "icon": { "type": "image", "path": "./icons/claude.svg" }
    },
    "opencode": {
      "type": "command",
      "title": "OpenCode",
      "command": "opencode",
      "target": "newTabInCurrentPane",
      "palette": false,
      "icon": { "type": "emoji", "value": "🧪", "scale": 0.9 }
    },
    "web-dev": {
      "type": "workspaceCommand",
      "title": "Web Dev",
      "commandName": "Web Dev"
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "cmux.newBrowser",
        "cmux.splitRight",
        "cmux.splitDown",
        "claude"
      ]
    }
  },
  "commands": [
    {
      "name": "Web Dev",
      "keywords": ["dev", "start"],
      "workspace": { ... }
    }
  ]
}

Nightly 動作註冊表

actions 將穩定 ID 對應到可執行的行為。使用內建 ID cmux.newTerminalcmux.newBrowsercmux.splitRightcmux.splitDown 覆寫預設值。專案專用工具可使用自己的 ID。

palette 預設為 true。設為 false 可讓動作不顯示在 Command Palette 中,但仍能從 surface 分頁列或快捷鍵呼叫。shortcut 使用和設定快捷鍵相同的語法,例如 cmd+shift+c["cmd+k", "cmd+c"]

存在 ui.surfaceTabBar.buttons 時,它會取代預設按鈕清單。省略某個內建 ID 即可隱藏它。圖示一律使用物件形式:{ "type": "symbol", "name": "play.circle" }{ "type": "emoji", "value": "🧪", "scale": 0.9 }{ "type": "image", "path": "./icons/codex.svg" }。圖片路徑相對於設定檔。Emoji scale 可省略,預設為 1。支援 SVG、PDF、PNG、JPEG、GIF、TIFF、BMP、HEIC、HEIF、WebP、AVIF、ICO 和 ICNS。

每個按鈕項目可以是動作 ID 字串,也可以是按鈕物件。當你想讓同一個動作使用不同的 surface 標籤、圖示或 tooltip 時,請使用按鈕物件。解析後的按鈕標題也會作為信任提示標題。

請把任何 approval 或 permission flags 直接放進你真正想執行的命令字串中。預設動作目標是 newTabInCurrentPane,所以常見模式是在目前 pane 中開啟新的終端分頁,並在其中啟動 Codex、Claude Code 或 OpenCode。

自訂動作與 Command Palette

actions 項目是 cmux 執行的可重複使用行為。當同一個行為需要從 Command Palette、表面分頁列、快捷鍵或加號按鈕選單觸發時,請使用動作。將 commands 保留給可重複使用的 shell 命令與工作區配置。如果某個動作不應出現在 Command Palette,請將 palette 設為 false。

動作類型

  • "builtin": 為內建 cmux 動作建立別名,例如 cmux.newTerminal、cmux.newBrowser、cmux.splitRight 或 cmux.splitDown。
  • "command": 在終端機中執行 shell 文字。使用 target 選擇目前終端機或目前面板中的新分頁。
  • "agent": 啟動支援的程式碼代理。現在支援 codex 與 claude,並可使用選用引數。
  • "workspaceCommand": 執行 commands 中具名的工作區定義。用於多面板配置、自訂工作目錄與啟動命令。

動作欄位

  • title: Command Palette 列標題、表面按鈕標籤、選單項目標題,以及信任提示標題,除非項目另行覆寫。
  • subtitle / description: Command Palette 中的次要文字。description 可作為 subtitle 的別名。
  • keywords: Command Palette 的額外搜尋詞。
  • palette: 自訂動作預設為 true。設為 false 可將動作從 Command Palette 隱藏,同時仍可從其他位置呼叫。
  • shortcut: 選用的動作快捷鍵,使用與設定快捷鍵相同的單鍵或兩段式按鍵序列語法。
  • target: 僅用於 command 與 agent 動作。使用 currentTerminal 或 newTabInCurrentPane。
  • confirm: 執行動作前要求確認。

Command Palette 行為

Command Palette 會讀取解析後的動作登錄。當 palette 不是 false 時,自訂動作 ID 會新增為列。舊的 commands 會自動新增為自訂列,除非已存在相同產生 ID 的動作。內建命令會保留一般的面板標籤,但覆寫像 cmux.newTerminal 這樣的內建 ID 會改變該共用入口背後的行為。

加號按鈕的自訂動作

使用 ui.newWorkspace.action 覆寫加號按鈕的行為。使用 ui.newWorkspace.contextMenu(或別名 rightClick)定義有順序的右鍵選單。選單項目可以是動作 ID、動作物件,或 { "type": "separator" }

cmux.json
{
  "actions": {
    "worktree-agents": {
      "type": "workspaceCommand",
      "title": "Worktree Agents",
      "commandName": "Worktree Agents",
      "icon": { "type": "symbol", "name": "folder.badge.plus" }
    }
  },
  "ui": {
    "newWorkspace": {
      "action": "worktree-agents",
      "contextMenu": [
        { "action": "worktree-agents", "title": "Worktree Agents" },
        { "type": "separator" },
        { "action": "cmux.newTerminal", "title": "New Terminal" },
        { "action": "cmux.newBrowser", "title": "New Browser" }
      ]
    }
  },
  "commands": [
    {
      "name": "Worktree Agents",
      "description": "Create a fresh Git worktree and start Codex and Claude inside it",
      "workspace": {
        "name": "Worktree Agents",
        "cwd": ".",
        "layout": {
          "direction": "horizontal",
          "split": 0.38,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Worktree",
                    "command": "set -euo pipefail; state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; rm -f \"$state\"; repo=$(git rev-parse --show-toplevel); mkdir -p \"$repo/../worktrees\"; slug=agents-$(date +%Y%m%d-%H%M%S); dir=\"$repo/../worktrees/$slug\"; git -C \"$repo\" worktree add -b \"$slug\" \"$dir\"; printf \"%s\\n\" \"$dir\" > \"$state\"; cd \"$dir\"; exec \"${SHELL:-/bin/zsh}\" -l",
                    "focus": true
                  }
                ]
              }
            },
            {
              "direction": "vertical",
              "split": 0.5,
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Codex",
                        "command": "state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; echo \"Waiting for worktree...\"; while [ ! -s \"$state\" ]; do sleep 0.2; done; dir=$(cat \"$state\"); cd \"$dir\"; exec codex --dangerously-bypass-approvals-and-sandbox"
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Claude",
                        "command": "state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; echo \"Waiting for worktree...\"; while [ ! -s \"$state\" ]; do sleep 0.2; done; dir=$(cat \"$state\"); cd \"$dir\"; exec claude --dangerously-skip-permissions"
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

此範例讓一般加號點擊執行 worktree-agents 動作。來自 commands 的工作區命令會先使用可見的設定終端機建立 Git worktree。Codex 與 Claude 同時啟動,等待該工作區專用的狀態檔,然後在 exec 前進入建立的目錄。

簡單指令

簡單指令會在目前聚焦的終端機中執行 shell 指令:

cmux.json
{
  "commands": [
    {
      "name": "Run Tests",
      "keywords": ["test", "check"],
      "command": "npm test",
      "confirm": true
    }
  ]
}

欄位

  • name: 顯示於指令面板(必填)
  • description: 選填說明
  • keywords: 指令面板的額外搜尋詞
  • command: 在聚焦終端機中執行的 shell 指令
  • confirm: 執行前顯示確認對話框

簡單指令在當前聚焦終端的工作目錄中執行。如果指令依賴於專案相對路徑,請在前面加上 cd "$(git rev-parse --show-toplevel)" && 以從倉庫根目錄執行,或使用 cd /your/path && 指定任意目錄。

工作區指令

工作區指令會建立一個新工作區,具有自訂的分割、終端機和瀏覽器窗格版面配置:

cmux.json
{
  "commands": [
    {
      "name": "Dev Environment",
      "keywords": ["dev", "fullstack"],
      "workspace": {
        "name": "Dev",
        "cwd": ".",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Frontend",
                    "command": "npm run dev",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Backend",
                    "command": "cargo watch -x run",
                    "cwd": "./server",
                    "env": { "RUST_LOG": "debug" }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

工作區欄位

  • name: 工作區索引標籤名稱(預設為指令名稱)
  • cwd: 工作區的工作目錄
  • color: 工作區索引標籤顏色
  • layout: 定義分割和窗格的版面配置樹

重新啟動行為

控制當同名工作區已存在時的行為:

  • "new": 建立新的 workspace(預設)
  • "ignore": 切換至現有 workspace
  • "recreate": 不詢問,直接關閉並重新建立
  • "confirm": 重新建立前詢問使用者

版面配置樹

版面配置樹使用遞迴分割節點定義窗格的排列方式:

分割節點

將空間分割為兩個子節點:

  • direction: "horizontal" "vertical"
  • split: 分割線位置,從 0.1 到 0.9(預設 0.5)
  • children: 恰好兩個子節點(分割或窗格)

窗格節點

包含一個或多個 surface(窗格內索引標籤)的葉節點。

Surface 定義

窗格中的每個 surface 可以是終端機或瀏覽器:

  • type: "terminal" "browser"
  • name: 自訂索引標籤標題
  • command: 建立時自動執行的 shell 指令(僅限終端機)
  • cwd: 此 surface 的工作目錄
  • env: 以鍵值對形式表示的環境變數
  • url: 要開啟的 URL(僅限瀏覽器)
  • focus: 建立後聚焦此 surface

工作目錄解析

  • . 省略: 工作區工作目錄
  • ./subdir: 相對於工作區工作目錄
  • ~/path: 展開至主目錄
  • 絕對路徑: 按原樣使用

完整範例

cmux.json
{
  "actions": {
    "web-dev": { "type": "workspaceCommand", "commandName": "Web Dev" },
    "cmux.newTerminal": {
      "type": "command",
      "title": "Codex",
      "command": "codex --dangerously-bypass-approvals-and-sandbox",
      "target": "newTabInCurrentPane",
      "shortcut": "cmd+t",
      "icon": { "type": "image", "path": "./icons/codex.svg" }
    },
    "claude": {
      "type": "command",
      "title": "Claude Code",
      "command": "claude --dangerously-skip-permissions",
      "target": "newTabInCurrentPane",
      "shortcut": "cmd+shift+c",
      "icon": { "type": "image", "path": "./icons/claude.svg" }
    },
    "start-dev": {
      "type": "command",
      "command": "npm run dev",
      "target": "newTabInCurrentPane",
      "icon": { "type": "symbol", "name": "play.circle" }
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "cmux.newBrowser",
        "cmux.splitRight",
        "cmux.splitDown",
        {
          "action": "claude",
          "title": "Claude Here"
        },
        "start-dev"
      ]
    }
  },
  "commands": [
    {
      "name": "Web Dev",
      "description": "Docs site with live preview",
      "keywords": ["web", "docs", "next", "frontend"],
      "workspace": {
        "name": "Web Dev",
        "cwd": "./web",
        "color": "#3b82f6",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Next.js",
                    "command": "npm run dev",
                    "focus": true
                  }
                ]
              }
            },
            {
              "direction": "vertical",
              "split": 0.6,
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "browser",
                        "name": "Preview",
                        "url": "http://localhost:3777"
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Shell",
                        "env": { "NODE_ENV": "development" }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    },
    {
      "name": "Debug Log",
      "description": "Tail the debug event log from the running dev app",
      "keywords": ["log", "debug", "tail", "events"],
      "workspace": {
        "name": "Debug Log",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Events",
                    "command": "tail -f /tmp/cmux-debug.log",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Shell"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    {
      "name": "Setup",
      "description": "Initialize submodules and build dependencies",
      "keywords": ["setup", "init", "install"],
      "command": "./scripts/setup.sh",
      "confirm": true
    },
    {
      "name": "Reload",
      "description": "Build and launch the debug app tagged to the current branch",
      "keywords": ["reload", "build", "run", "launch"],
      "command": "./scripts/reload.sh --tag $(git branch --show-current)"
    },
    {
      "name": "Run Unit Tests",
      "keywords": ["test", "unit"],
      "command": "./scripts/test-unit.sh",
      "confirm": true
    }
  ]
}