คำสั่งและแอ็กชันแบบกำหนดเอง
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(ใช้ร่วมกันทุกโปรเจกต์ และเติมส่วนที่ไฟล์ของโปรเจกต์ไม่ได้กำหนดไว้)
แก้ไข cmux.json แล้วกด Cmd+Shift+, หรือรัน cmux reload-config เพื่อใช้การเปลี่ยนแปลง
คำสั่ง shell
รายการที่เล็กที่สุดมีแค่ชื่อและสตริงคำสั่ง เมื่อเลือกรายการนี้ใน Command Palette สตริงนั้นจะถูกพิมพ์ลงในเทอร์มินัลที่โฟกัสอยู่แล้วรัน
{
"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 Palettecommand: ข้อความ shell ที่ cmux พิมพ์ลงในเทอร์มินัลที่โฟกัสอยู่แล้วรันdescription: ข้อความรองที่ไม่บังคับ ซึ่งแสดงคู่กับรายการkeywords: คำเพิ่มเติมที่ควรจับคู่กับรายการนี้เมื่อค้นหาใน Command Paletteconfirm: ตั้งเป็น true เพื่อให้ถามยืนยันทุกครั้งก่อนรัน
คำสั่ง shell จะรันที่ตำแหน่งที่เทอร์มินัลซึ่งโฟกัสอยู่กำลังอยู่ในขณะนั้น หากคำสั่งต้องการจุดเริ่มต้นที่คาดเดาได้ ให้ขึ้นต้นด้วย cd "$(git rev-parse --show-toplevel)" && เพื่อย้ายไปยังระดับบนสุดของ Git repository หรือขึ้นต้นด้วย cd /some/folder && เพื่อให้เริ่มที่โฟลเดอร์ที่กำหนดไว้ตายตัว
คำสั่งที่เปิดเวิร์กสเปซ
หากให้ออบเจ็กต์ workspace กับคำสั่งแทนสตริงคำสั่ง คำสั่งนั้นจะเปิดเวิร์กสเปซใหม่แทน โดยจัดวางเป็นต้นไม้ของพาเนลที่แบ่งไว้ซึ่งบรรจุเทอร์มินัลและเบราว์เซอร์ แต่ละรายการต้องมีอย่างใดอย่างหนึ่งในสองอย่างนี้เท่านั้น
{
"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 workspacesetup: 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: ต่อท้ายไดเรกทอรีของเวิร์กสเปซ.หรือ ไม่ได้ตั้งค่า: ใช้ไดเรกทอรีของเวิร์กสเปซ
โครงสร้างไฟล์
actions, shortcut หรือ ui.surfaceTabBar.buttonscommands ยังคงใช้กำหนด shell commands และ workspace layouts ที่นำกลับมาใช้ซ้ำได้ Nightly builds เพิ่มรีจิสทรี actions แอ็กชันคือ public IDs ที่ใช้ร่วมกันระหว่างแถบแท็บ surface, Command Palette และ shortcuts ระดับแอ็กชัน
{
"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 ที่นั่น
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 Palettepalette: ค่าเริ่มต้นคือ true สำหรับ custom actions ตั้งเป็น false เพื่อซ่อน action จาก Command Palette แต่ยังเรียกจากที่อื่นได้shortcut: shortcut ของ action แบบเลือกได้ ใช้ syntax แบบ single-stroke หรือ two-stroke chord เหมือน shortcuts ใน settingstarget: สำหรับ command และ agent actions เท่านั้น ใช้ currentTerminal หรือ newTabInCurrentPaneconfirm: ถามยืนยันก่อนรัน actionnewWorkspaceMenu: 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 ของโปรเจกต์ประกาศสิ่งเหล่านี้ไม่ได้
{
"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
{
"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:
{
"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.
ตัวอย่างเต็ม
{
"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"
}
]
}