การปรับแต่งและการดูแลระบบคำสั่งและแอ็กชัน
การปรับแต่งและการดูแลระบบ

คำสั่งและแอ็กชันแบบกำหนดเอง

cmux.json คือที่ที่คุณสอนงานประจำของคุณให้ cmux ได้แก่ คำสั่ง shell ที่รันบ่อย เวิร์กสเปซที่เปิดขึ้นพร้อมเทอร์มินัลและเบราว์เซอร์ที่จัดวางไว้ล่วงหน้า และแอ็กชันที่ผูกกับคีย์ลัด ปุ่มบนแถบแท็บ และ Command Palette ได้ วางไฟล์ไว้ที่ .cmux/cmux.json ภายในโปรเจกต์ ที่ ~/.config/cmux/cmux.json สำหรับทุกโปรเจกต์ หรือทั้งสองที่

ตำแหน่งที่ cmux อ่าน cmux.json

รายการอาจมาจากไฟล์ของโปรเจกต์ ไฟล์ระดับผู้ใช้ หรือทั้งสองอย่าง สำหรับไฟล์ของโปรเจกต์ cmux จะเริ่มที่ไดเรกทอรีปัจจุบันและตรวจสอบไดเรกทอรีแม่แต่ละชั้นที่อยู่เหนือขึ้นไปด้วย

  • โปรเจกต์: ./.cmux/cmux.json (พบได้โดยค้นหาขึ้นไปจากไดเรกทอรีทำงาน และมีลำดับความสำคัญเหนือไฟล์ระดับผู้ใช้)
  • local fallback: ./cmux.json (ยังรองรับสำหรับ repo ที่มีอยู่)
  • ระดับผู้ใช้: ~/.config/cmux/cmux.json (ใช้ร่วมกันทุกโปรเจกต์ และเติมส่วนที่ไฟล์ของโปรเจกต์ไม่ได้กำหนดไว้)
Actions และ commands แบบ local จะแทนที่ entries แบบ global ที่มี ID หรือชื่อเดียวกัน

แก้ไข cmux.json แล้วกด Cmd+Shift+, หรือรัน cmux reload-config เพื่อใช้การเปลี่ยนแปลง

ถ้า config ของโปรเจกต์หรือ global มี schema error, cmux จะ fallback ไปยัง config ที่ถูกต้องถัดไปและแสดงแถว cmux.json Schema Error ใน Command Palette เลือกแถวนั้นเพื่อเปิดไฟล์ config

คำสั่ง shell

รายการที่เล็กที่สุดมีแค่ชื่อและสตริงคำสั่ง เมื่อเลือกรายการนี้ใน Command Palette สตริงนั้นจะถูกพิมพ์ลงในเทอร์มินัลที่โฟกัสอยู่แล้วรัน

cmux.json
{
  "commands": [
    {
      "name": "Format Changed Files",
      "description": "Run the formatter on files that differ from main",
      "keywords": [
        "fmt",
        "prettier",
        "style"
      ],
      "command": "git diff --name-only main -- '*.ts' '*.tsx' | xargs npx prettier --write"
    },
    {
      "name": "Reset Local Database",
      "keywords": [
        "db",
        "wipe"
      ],
      "command": "cd \"$(git rev-parse --show-toplevel)\" && ./scripts/db-reset.sh",
      "confirm": true
    }
  ]
}

ฟิลด์ของคำสั่ง shell

  • name: ป้ายกำกับที่จำเป็นและห้ามว่าง ซึ่งคุณเลือกจาก Command Palette
  • command: ข้อความ shell ที่ cmux พิมพ์ลงในเทอร์มินัลที่โฟกัสอยู่แล้วรัน
  • description: ข้อความรองที่ไม่บังคับ ซึ่งแสดงคู่กับรายการ
  • keywords: คำเพิ่มเติมที่ควรจับคู่กับรายการนี้เมื่อค้นหาใน Command Palette
  • confirm: ตั้งเป็น true เพื่อให้ถามยืนยันทุกครั้งก่อนรัน

คำสั่ง shell จะรันที่ตำแหน่งที่เทอร์มินัลซึ่งโฟกัสอยู่กำลังอยู่ในขณะนั้น หากคำสั่งต้องการจุดเริ่มต้นที่คาดเดาได้ ให้ขึ้นต้นด้วย cd "$(git rev-parse --show-toplevel)" && เพื่อย้ายไปยังระดับบนสุดของ Git repository หรือขึ้นต้นด้วย cd /some/folder && เพื่อให้เริ่มที่โฟลเดอร์ที่กำหนดไว้ตายตัว

คำสั่งที่เปิดเวิร์กสเปซ

หากให้ออบเจ็กต์ workspace กับคำสั่งแทนสตริงคำสั่ง คำสั่งนั้นจะเปิดเวิร์กสเปซใหม่แทน โดยจัดวางเป็นต้นไม้ของพาเนลที่แบ่งไว้ซึ่งบรรจุเทอร์มินัลและเบราว์เซอร์ แต่ละรายการต้องมีอย่างใดอย่างหนึ่งในสองอย่างนี้เท่านั้น

cmux.json
{
  "commands": [
    {
      "name": "API Stack",
      "keywords": [
        "api",
        "server",
        "logs"
      ],
      "restart": "confirm",
      "workspace": {
        "name": "API",
        "cwd": "./services/api",
        "color": "#10b981",
        "env": {
          "PORT": "8080"
        },
        "layout": {
          "direction": "vertical",
          "split": 0.65,
          "children": [
            {
              "direction": "horizontal",
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Server",
                        "command": "go run ./cmd/api",
                        "focus": true
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Worker",
                        "command": "go run ./cmd/worker",
                        "env": {
                          "QUEUE": "default"
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Logs",
                    "cwd": "/var/log",
                    "command": "tail -F system.log"
                  },
                  {
                    "type": "browser",
                    "name": "Health",
                    "url": "http://localhost:8080/healthz"
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

ฟิลด์ของออบเจ็กต์ workspace

  • name: ชื่อของเวิร์กสเปซ หากไม่ได้กำหนดจะใช้ชื่อคำสั่ง
  • cwd: ไดเรกทอรีฐานของเวิร์กสเปซ cwd ของแต่ละแท็บจะแปลงค่าโดยอิงจากไดเรกทอรีนี้
  • layout: โหนดรากของต้นไม้เลย์เอาต์ที่อธิบายไว้ด้านล่าง
  • color: สีในแถบข้าง ระบุเป็นเลขฐานสิบหก #RRGGBB หรือชื่อสีของเวิร์กสเปซ
  • env: Environment variables inherited by every shell in the workspace
  • setup: Bootstrap command sent to the workspace's first terminal before that terminal's own command

เมื่อเวิร์กสเปซเปิดอยู่แล้ว

ตั้งค่า restart ในคำสั่งเพื่อกำหนดว่าจะเกิดอะไรขึ้นหากมีเวิร์กสเปซชื่อเดียวกันอยู่แล้ว:

  • "new": สร้าง workspace ใหม่ (ค่าเริ่มต้น)
  • "confirm": ถามก่อน แล้วแทนที่หากคุณยอมรับ
  • "recreate": แทนที่ทันทีโดยไม่ถาม
  • "ignore": สลับไปยัง workspace ที่มีอยู่

การอธิบายเลย์เอาต์

เลย์เอาต์เป็นโครงสร้างแบบต้นไม้ โหนดภายในทุกโหนดแบ่งพื้นที่ของตัวเองออกเป็นสองส่วน และทุกใบคือพาเนลที่บรรจุแท็บ

โหนดการแบ่ง

การแบ่งจะแยกพื้นที่ของตัวเองออกเป็นสองส่วน:

  • direction: "horizontal" หรือ "vertical"
  • children: อาร์เรย์ที่มีโหนดสองโหนดพอดี แต่ละโหนดเป็นการแบ่งอีกชั้นหรือพาเนล
  • split: ตำแหน่งของเส้นแบ่งเป็นสัดส่วนของพื้นที่ ค่าเริ่มต้นคือ 0.5 และค่าที่อยู่นอกช่วง 0.1 ถึง 0.9 จะถูกบีบให้อยู่ในช่วงนั้น

โหนดพาเนล

พาเนลคือใบของต้นไม้ อาร์เรย์ surfaces ของพาเนลระบุแท็บที่จะเปิดขึ้นมาพร้อมกัน และต้องมีอย่างน้อยหนึ่งรายการ

Surface

แต่ละรายการในอาร์เรย์ surfaces ของพาเนลจะเปิดแท็บหนึ่งแท็บ ซึ่งเป็นเทอร์มินัลหรือเบราว์เซอร์:

  • type: "terminal" หรือ "browser"
  • name: ชื่อแท็บที่จะแสดงแทนค่าเริ่มต้น
  • focus: ตั้งเป็น true เพื่อย้ายโฟกัสคีย์บอร์ดมาที่แท็บนี้เมื่อสร้างเลย์เอาต์เสร็จ
  • command: เฉพาะเทอร์มินัล: ข้อความ shell ที่จะรันทันทีเมื่อเทอร์มินัลเปิดขึ้น
  • url: เฉพาะเบราว์เซอร์: หน้าที่จะโหลด
  • cwd: ไดเรกทอรีเริ่มต้นของแท็บนี้ ซึ่งแปลงค่าตามกฎด้านล่าง
  • env: ออบเจ็กต์ที่มีชื่อและค่าของตัวแปรสภาพแวดล้อมเพิ่มเติม

วิธีแปลงค่า cwd

  • ~/path: แปลงเป็นตำแหน่งภายในโฟลเดอร์ home ของคุณ
  • เส้นทางที่ขึ้นต้นด้วย /: ใช้ตามที่เขียนไว้
  • ./subdir: ต่อท้ายไดเรกทอรีของเวิร์กสเปซ
  • . หรือ ไม่ได้ตั้งค่า: ใช้ไดเรกทอรีของเวิร์กสเปซ

โครงสร้างไฟล์

รีจิสทรีของแอ็กชันเป็นฟีเจอร์ nightly โปรดติดตั้ง nightly build ล่าสุดก่อนใช้ actions, shortcut หรือ ui.surfaceTabBar.buttons

commands ยังคงใช้กำหนด shell commands และ workspace layouts ที่นำกลับมาใช้ซ้ำได้ Nightly builds เพิ่มรีจิสทรี actions แอ็กชันคือ public IDs ที่ใช้ร่วมกันระหว่างแถบแท็บ surface, Command Palette และ shortcuts ระดับแอ็กชัน

cmux.json
{
  "actions": {
    "cmux.newTerminal": {
      "type": "agent",
      "agent": "claude",
      "title": "Claude Code",
      "subtitle": "Start Claude Code in a new tab"
    },
    "lint": {
      "type": "command",
      "title": "Lint",
      "subtitle": "Run the linter in a fresh tab",
      "keywords": [
        "eslint",
        "check"
      ],
      "command": "npm run lint",
      "shortcut": [
        "cmd+k",
        "cmd+l"
      ],
      "icon": {
        "type": "symbol",
        "name": "checkmark.seal"
      }
    },
    "scratch-dir": {
      "type": "command",
      "title": "Scratch Directory",
      "command": "cd \"$(mktemp -d)\"",
      "target": "currentTerminal",
      "palette": false,
      "icon": {
        "type": "emoji",
        "value": "📝",
        "scale": 0.85
      }
    },
    "api-stack": {
      "type": "workspaceCommand",
      "title": "API Stack",
      "commandName": "API Stack"
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "cmux.splitRight",
        "lint",
        {
          "action": "scratch-dir",
          "tooltip": "cd into a new temp folder"
        }
      ]
    }
  },
  "commands": [
    {
      "name": "API Stack",
      "keywords": [
        "api"
      ],
      "workspace": {
        "cwd": "./services/api",
        "layout": {
          "pane": {
            "surfaces": [
              {
                "type": "terminal",
                "name": "Server",
                "command": "go run ./cmd/api"
              }
            ]
          }
        }
      }
    }
  ]
}

รีจิสทรีแอ็กชัน nightly

actions แมป stable IDs เข้ากับ behavior ที่รันได้ ใช้ built-in IDs cmux.newTerminal, cmux.newBrowser, cmux.splitRight และ cmux.splitDown เพื่อ override ค่าเริ่มต้น ใช้ IDs ของคุณเองสำหรับเครื่องมือเฉพาะโปรเจกต์

palette มีค่าเริ่มต้นเป็น true ตั้งเป็น false เพื่อซ่อนแอ็กชันจาก Command Palette แต่ยังให้เรียกจากแถบแท็บ surface หรือ shortcut ได้ shortcut ใช้ syntax เดียวกับ shortcuts ใน settings เช่น cmd+shift+c หรือ ["cmd+k", "cmd+c"]

ui.surfaceTabBar.buttons จะแทนที่รายการปุ่มเริ่มต้นเมื่อมีค่าอยู่ ไม่ใส่ built-in ID เพื่อซ่อนรายการนั้น ไอคอนใช้รูปแบบ object เสมอ: { "type": "symbol", "name": "play.circle" }, { "type": "emoji", "value": "🧪", "scale": 0.9 } หรือ { "type": "image", "path": "./icons/codex.svg" } path ของรูปภาพอ้างอิงจากไฟล์ config ค่า emoji scale เป็น optional และมีค่าเริ่มต้น 1 รองรับ SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO และ ICNS

รายการปุ่มแต่ละรายการอาจเป็น string ของ action ID หรือ button object ใช้ button object เมื่อคุณต้องการแอ็กชันเดียวกันแต่มี surface label, icon หรือ tooltip ต่างกัน ชื่อปุ่มที่ resolve แล้วจะถูกใช้เป็นชื่อของ trust prompt ด้วย

ใส่ approval หรือ permission flags ไว้ใน command string ที่คุณต้องการรันจริงโดยตรง target เริ่มต้นของแอ็กชันคือ newTabInCurrentPane ดังนั้น pattern ทั่วไปคือเปิด terminal tab ใหม่ใน pane ปัจจุบันแล้วเริ่ม Codex, Claude Code หรือ OpenCode ที่นั่น

แอ็กชันเฉพาะโปรเจกต์จะแสดงในแถบแท็บ surface และ Command Palette ทันที การรันครั้งแรกยังคงถามเรื่องความเชื่อถือ ความเชื่อถือผูกกับ fingerprint ของแอ็กชันที่ตรงกันแบบเป๊ะ ไม่ได้ผูกกับ repo ไอคอนรูปภาพเฉพาะโปรเจกต์จะยังถูกล็อกจนกว่าแอ็กชันนั้นจะได้รับความเชื่อถือ

Custom actions และ Command Palette

actions คือรายการที่ cmux ใช้รันซ้ำได้ ใช้ actions เมื่อ behavior เดียวกันควรเรียกได้จาก Command Palette, surface tab bar, shortcuts หรือเมนูของปุ่มบวก เก็บ commands ไว้สำหรับ shell commands และ workspace layouts ที่ใช้ซ้ำได้ ตั้ง palette เป็น false เมื่อไม่ต้องการให้ action แสดงใน Command Palette

ประเภท action

  • "command": รันข้อความ shell ใน terminal ใช้ target เพื่อเลือก terminal ปัจจุบันหรือ tab ใหม่ใน pane ปัจจุบัน
  • "agent": เริ่ม coding agent ที่รองรับ ปัจจุบันรองรับ codex และ claude พร้อม args แบบเลือกได้
  • "builtin": สร้าง alias ให้ built-in cmux action เช่น cmux.newTerminal, cmux.newBrowser, cmux.splitRight หรือ cmux.splitDown การดำเนินการคัดลอกในตัว: cmux.copyWorkingDirectory คัดลอกไดเรกทอรีทำงานของเทอร์มินัล cmux.copyProjectRoot คัดลอกรากของรีโพซิทอรี git (หรือไดเรกทอรีทำงานเมื่ออยู่นอกรีโพซิทอรี) และ cmux.copyScreen คัดลอกหน้าจอที่มองเห็น ในเวิร์กสเปซ SSH คลาวด์ หรือ tmux ระยะไกล cmux.copyProjectRoot จะคัดลอกไดเรกทอรีทำงานระยะไกล เพราะ cmux ค้นหารีโพซิทอรี git บนโฮสต์อื่นไม่ได้
  • "workspaceCommand": รัน workspace definition ที่มีชื่อจาก commands ใช้สำหรับเลย์เอาต์หลาย pane, working directory แบบกำหนดเอง และ startup commands
  • "workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically.
  • "setting": เปลี่ยนการตั้งค่าหนึ่งรายการใน cmux.json แบบ global ของคุณ เช่น สลับการตั้งค่าแบบ true/false หรือวนผ่านรายการค่า ดู Action การตั้งค่า ด้านล่าง
  • "settingPreset": ใช้กลุ่มการตั้งค่าที่มีชื่อจาก settingPresets ในขั้นตอนเดียว

ฟิลด์ของ action

  • title: ชื่อแถวใน Command Palette, label ของปุ่ม, ชื่อ item ในเมนู และชื่อ trust prompt เว้นแต่ entry จะ override ค่าไว้
  • subtitle / description: ข้อความรองใน Command Palette โดย description ใช้เป็น alias ของ subtitle ได้
  • keywords: คำค้นหาเพิ่มเติมสำหรับ Command Palette
  • palette: ค่าเริ่มต้นคือ true สำหรับ custom actions ตั้งเป็น false เพื่อซ่อน action จาก Command Palette แต่ยังเรียกจากที่อื่นได้
  • shortcut: shortcut ของ action แบบเลือกได้ ใช้ syntax แบบ single-stroke หรือ two-stroke chord เหมือน shortcuts ใน settings
  • target: สำหรับ command และ agent actions เท่านั้น ใช้ currentTerminal หรือ newTabInCurrentPane
  • confirm: ถามยืนยันก่อนรัน action
  • newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.

พฤติกรรมของ Command Palette

Command Palette อ่าน action registry ที่ resolve แล้ว Custom action IDs จะถูกเพิ่มเป็นแถวเมื่อ palette ไม่ใช่ false ส่วน commands แบบเดิมจะถูกเพิ่มเป็นแถว custom โดยอัตโนมัติ เว้นแต่มี action ที่ใช้ generated ID เดียวกันอยู่แล้ว Built-in commands ยังใช้ labels ปกติ แต่การ override built-in ID เช่น cmux.newTerminal จะเปลี่ยน behavior หลัง entrypoint ร่วมนั้น

Action การตั้งค่า

action การตั้งค่าระบุ path ของการตั้งค่า และระบุเพียงหนึ่งอย่างจาก set (เขียนค่า), toggle: true (สลับการตั้งค่าแบบ true/false), cycle (ไปยังค่าถัดไปในรายการ และวนกลับไปค่าแรกเมื่อถึงค่าสุดท้าย) หรือ unset: true (ลบ key ออกจาก cmux.json เพื่อให้ใช้ค่าจากหน้าต่างการตั้งค่าหรือค่าเริ่มต้น) toggle และ cycle เริ่มจากค่าที่ cmux ใช้อยู่ รวมถึงค่าที่คุณตั้งไว้ในหน้าต่างการตั้งค่า action settingPreset จะใช้ entry จาก settingPresets ซึ่งเป็น cmux.json บางส่วนที่ object ซ้อนกันจะถูก merge ทีละ key cmux ตรวจสอบการเปลี่ยนแปลงแต่ละรายการกับ schema ก่อนบันทึก เก็บ comment และ key อื่นของคุณไว้ แล้วนำการเปลี่ยนแปลงไปใช้ทันที action การตั้งค่าและ preset ทำงานได้เฉพาะจาก cmux.json แบบ global ของคุณและ pack ที่ไฟล์นั้นอ้างถึงเท่านั้น config ของโปรเจกต์ประกาศสิ่งเหล่านี้ไม่ได้

~/.config/cmux/cmux.json
{
  "actions": {
    "scroll.cycle": {
      "type": "setting",
      "title": "Cycle Scroll Speed",
      "path": "terminal.scrollSpeed",
      "cycle": [1.0, 1.4, 1.8]
    },
    "editor.wrap": {
      "type": "setting",
      "title": "Toggle Editor Word Wrap",
      "path": "fileEditor.wordWrap",
      "toggle": true
    },
    "sidebar.quiet": {
      "type": "settingPreset",
      "title": "Quiet Sidebar",
      "preset": "sidebar.quiet"
    }
  },
  "settingPresets": {
    "sidebar.quiet": {
      "sidebar": { "showPorts": false, "showPullRequests": false, "showLog": false }
    }
  }
}

ทำการเปลี่ยนแปลงเดียวกันจาก terminal ได้เช่นกัน: cmux config set terminal.scrollSpeed 1.4, cmux config toggle fileEditor.wordWrap และ cmux config preset sidebar.quiet

เมื่อใช้ confirm: true cmux จะถามก่อนบันทึกและแสดงคำสั่ง cmux config ที่เทียบเท่า path จะถูกแยกที่ "." ทุกตัว ดังนั้น key ที่มี "." อยู่ในชื่อเอง (เช่น entry workspaceGroups.byCwd สำหรับ ~/src/app.web) จึงเปลี่ยนด้วยวิธีนี้ไม่ได้ ให้แก้ไขใน cmux.json โดยตรง

แอ็กชันกำหนดเองของปุ่มบวก

ใช้ ui.newWorkspace.action เพื่อ override สิ่งที่ปุ่มบวกทำ ใช้ ui.newWorkspace.contextMenu (หรือ alias rightClick) เพื่อกำหนดเมนูคลิกขวาที่เรียงลำดับแล้ว รายการเมนูอาจเป็น action IDs, action objects หรือ { "type": "separator" } หากไม่ได้ตั้งค่า เมนูจะแสดง cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L) พร้อมปุ่มลัดปัจจุบัน รายการคลาวด์จะแสดงเมื่อเปิดใช้งาน Cloud Machines เท่านั้น New Cloud Workspace จะใช้เครื่องของพื้นที่ทำงาน Cloud ที่เลือกครั้งล่าสุด แล้วจึงใช้เครื่องแรกในแถบด้านขวา หากไม่มีเครื่องที่ใช้ได้ จะเปิด New Cloud Machine

cmux.json
{
  "actions": {
    "worktree-agents": {
      "type": "workspaceCommand",
      "title": "Agents in New Worktree",
      "commandName": "Agents in New Worktree",
      "icon": {
        "type": "symbol",
        "name": "arrow.triangle.branch"
      }
    }
  },
  "ui": {
    "newWorkspace": {
      "action": "worktree-agents",
      "contextMenu": [
        "worktree-agents",
        {
          "type": "separator"
        },
        {
          "action": "cmux.newWorkspace",
          "title": "Blank Workspace"
        },
        {
          "action": "cmux.newBrowser",
          "title": "Browser"
        }
      ]
    }
  },
  "commands": [
    {
      "name": "Agents in New Worktree",
      "description": "Branch off a new Git worktree, then run Codex and Claude Code in it side by side",
      "workspace": {
        "name": "Worktree",
        "layout": {
          "direction": "vertical",
          "split": 0.7,
          "children": [
            {
              "direction": "horizontal",
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Codex",
                        "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; echo \"Waiting for the worktree...\"; until [ -s \"$marker\" ]; do sleep 0.25; done; cd \"$(cat \"$marker\")\" && exec codex --yolo"
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Claude",
                        "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; echo \"Waiting for the worktree...\"; until [ -s \"$marker\" ]; do sleep 0.25; done; cd \"$(cat \"$marker\")\" && exec claude --dangerously-skip-permissions"
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Setup",
                    "command": "marker=\"${TMPDIR:-/tmp}/cmux-wt-${CMUX_WORKSPACE_ID:-local}\"; rm -f \"$marker\"; root=$(git rev-parse --show-toplevel) || exit 1; branch=\"wt-$(date +%m%d-%H%M%S)\"; wt=\"$root/../$(basename \"$root\")-$branch\"; git -C \"$root\" worktree add -b \"$branch\" \"$wt\" && printf \"%s\\n\" \"$wt\" > \"$marker\" && cd \"$wt\" && exec \"${SHELL:-/bin/zsh}\" -l",
                    "focus": true
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

ตัวอย่างนี้ทำให้การคลิกปุ่มบวกตามปกติรัน action worktree-agents คำสั่ง workspace จาก commands ใช้ terminal setup ที่มองเห็นได้เพื่อสร้าง Git worktree ก่อน Codex และ Claude เริ่มพร้อมกัน รอไฟล์ state เฉพาะ workspace แล้ว cd เข้า directory ที่สร้างขึ้นก่อน exec

Workspace layouts

A workspace layout is stored as a workspace action, embedding a full workspace definition directly in the action so it needs no separate commands entry. It supports the same workspace fields plus setup, a bootstrap command sent to the first terminal before that terminal's own command:

cmux.json
{
  "actions": {
    "pair-review": {
      "type": "workspace",
      "title": "Pair Review",
      "icon": {
        "type": "symbol",
        "name": "person.2.wave.2"
      },
      "restart": "ignore",
      "newWorkspaceMenu": true,
      "workspace": {
        "name": "Review",
        "cwd": "~/src/app",
        "setup": "git pull --ff-only",
        "layout": {
          "direction": "horizontal",
          "split": 0.55,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Diff",
                    "command": "git log -p -n 5",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Codex",
                    "command": "codex"
                  },
                  {
                    "type": "terminal",
                    "name": "Shell"
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

Workspace layouts appear in the plus-button right-click menu automatically. Set newWorkspaceMenu to false to hide one, or to true on any other action to add it to the menu.

You can also create these without writing JSON: right-click the plus button and choose Save Workspace as Layout to capture the current workspace's splits, directories, running agents, and browser tabs into ~/.config/cmux/cmux.json. They are stored as entries in the actions block. Customize Workspace Layouts opens that file in your editor.

Default for new workspaces

Use the Default for New Workspace submenu to pick which saved workspace layout plain New Workspace should run, or choose None to return to a blank terminal. The save dialog also has a Use as default for new workspaces checkbox. The setting is ui.newWorkspace.action; a project-local .cmux/cmux.json value wins over ~/.config/cmux/cmux.json.

ตัวอย่างเต็ม

cmux.json
{
  "actions": {
    "cmux.newTerminal": {
      "type": "command",
      "title": "Codex",
      "command": "codex --yolo",
      "shortcut": "cmd+t",
      "icon": {
        "type": "image",
        "path": "./icons/codex.svg"
      }
    },
    "review": {
      "type": "agent",
      "agent": "claude",
      "args": "--permission-mode plan",
      "title": "Plan with Claude",
      "shortcut": "cmd+shift+p",
      "icon": {
        "type": "symbol",
        "name": "list.bullet.clipboard"
      }
    },
    "storybook": {
      "type": "workspaceCommand",
      "commandName": "Storybook",
      "newWorkspaceMenu": true
    },
    "typecheck": {
      "type": "command",
      "title": "Typecheck",
      "command": "npx tsc --noEmit",
      "target": "newTabInCurrentPane",
      "confirm": false,
      "icon": {
        "type": "emoji",
        "value": "🔎"
      }
    }
  },
  "ui": {
    "surfaceTabBar": {
      "buttons": [
        "cmux.newTerminal",
        "review",
        {
          "action": "typecheck",
          "title": "tsc"
        },
        "cmux.newBrowser",
        "cmux.splitDown"
      ]
    },
    "newWorkspace": {
      "contextMenu": [
        "storybook",
        {
          "type": "separator"
        },
        "cmux.newTerminal",
        "cmux.newBrowser"
      ]
    }
  },
  "commands": [
    {
      "name": "Storybook",
      "description": "Component explorer with a live preview beside it",
      "keywords": [
        "ui",
        "components",
        "stories"
      ],
      "workspace": {
        "name": "Storybook",
        "cwd": "./packages/ui",
        "color": "#a855f7",
        "layout": {
          "direction": "horizontal",
          "split": 0.4,
          "children": [
            {
              "direction": "vertical",
              "split": 0.5,
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Storybook",
                        "command": "npx storybook dev -p 6006 --no-open",
                        "focus": true
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Tests",
                        "command": "npx vitest --watch",
                        "env": {
                          "CI": "false"
                        }
                      }
                    ]
                  }
                }
              ]
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "browser",
                    "name": "Preview",
                    "url": "http://localhost:6006"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    {
      "name": "Install Dependencies",
      "keywords": [
        "install",
        "deps"
      ],
      "command": "npm ci",
      "confirm": true
    },
    {
      "name": "Open Changelog",
      "keywords": [
        "changes",
        "release"
      ],
      "command": "${EDITOR:-vi} CHANGELOG.md"
    }
  ]
}
หน้านี้มีประโยชน์หรือไม่?
แจ้งปัญหา