# ពាក្យបញ្ជា និង Action ផ្ទាល់ខ្លួន

cmux.json គឺជាកន្លែងដែលអ្នកបង្រៀន cmux នូវទម្លាប់ការងារផ្ទាល់ខ្លួនរបស់អ្នក៖ ពាក្យបញ្ជា shell ដែលអ្នករត់ញឹកញាប់ workspace ដែលបើកជាមួយការរៀបចំទែមីណល និង browser ជាមុន និង action ដែលអ្នកអាចភ្ជាប់ទៅ shortcut ប៊ូតុងលើ tab bar និង Command Palette។ ដាក់វានៅ .cmux/cmux.json ក្នុង project មួយ នៅ ~/.config/cmux/cmux.json សម្រាប់គ្រប់ project ឬទាំងពីរ។

## កន្លែងដែល cmux អាន cmux.json

ធាតុអាចមកពីឯកសារ project ឯកសារសម្រាប់អ្នកប្រើទាំងមូល ឬទាំងពីរ។ សម្រាប់ឯកសារ project, cmux ចាប់ផ្ដើមពីថតបច្ចុប្បន្ន ហើយពិនិត្យថតមេនីមួយៗនៅខាងលើវាផងដែរ។

-   **Project៖** `./.cmux/cmux.json` (រកឃើញដោយស្វែងរកឡើងលើពីថតការងារ; មានអាទិភាពលើឯកសារសម្រាប់អ្នកប្រើទាំងមូល)
-   **Local fallback:** `./cmux.json` (នៅតែគាំទ្រសម្រាប់ repos ដែលមានស្រាប់)
-   **សម្រាប់អ្នកប្រើទាំងមូល៖** `~/.config/cmux/cmux.json` (ប្រើរួមគ្នាដោយគ្រប់ project; ផ្ដល់អ្វីដែលឯកសារ project មិនបានកំណត់)

Actions និង commands ក្នុង local នឹង override entries global ដែលមាន ID ឬ name ដូចគ្នា។

កែ cmux.json បន្ទាប់មកចុច Cmd+Shift+, ឬរត់ cmux reload-config ដើម្បីអនុវត្តការផ្លាស់ប្តូរ។

បើ config របស់ project ឬ global មាន schema error, cmux នឹងត្រឡប់ទៅ config ដែលត្រឹមត្រូវបន្ទាប់ ហើយបង្ហាញ row **cmux.json Schema Error** នៅក្នុង Command Palette។ ជ្រើសវា ដើម្បីបើកឯកសារ config។

## ពាក្យបញ្ជា shell

ធាតុតូចបំផុតគឺមានតែឈ្មោះ និង string ពាក្យបញ្ជា។ ពេលជ្រើសវាក្នុង Command Palette, string នោះត្រូវបានវាយបញ្ចូលក្នុងទែមីណលដែលកំពុងផ្ដោត ហើយដំណើរការ។

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

ផ្ដល់ object workspace ដល់ពាក្យបញ្ជាជំនួសឱ្យ string ពាក្យបញ្ជា ហើយវានឹងបើក workspace ថ្មីជំនួសវិញ ដែលរៀបចំជាដើមឈើនៃ pane ដែលបានបំបែក ផ្ទុកទែមីណល និង browser។ ធាតុមួយត្រូវការមួយគត់ក្នុងចំណោមពីរនេះ។

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"
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}
```

### វាលនៃ object workspace

-   `name`: ចំណងជើងសម្រាប់ workspace; ប្រើឈ្មោះពាក្យបញ្ជាប្រសិនបើមិនបានកំណត់
-   `cwd`: ថតមូលដ្ឋានសម្រាប់ workspace; cwd របស់ tab នីមួយៗត្រូវបានដោះស្រាយផ្អែកលើវា
-   `layout`: root node នៃដើមឈើ layout ដែលបានពិពណ៌នាខាងក្រោម
-   `color`: ពណ៌ក្នុងរបារចំហៀង ជាលេខ hex #RRGGBB ឬឈ្មោះពណ៌ workspace
-   `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

### ពេល workspace បើករួចហើយ

កំណត់ restart លើពាក្យបញ្ជា ដើម្បីសម្រេចថាតើត្រូវធ្វើអ្វី ប្រសិនបើ workspace ដែលមានឈ្មោះដូចគ្នាមានរួចហើយ៖

-   `"new"`: បង្កើត workspace ថ្មី (លំនាំដើម)
-   `"confirm"`: សួរជាមុន បន្ទាប់មកជំនួសវា ប្រសិនបើអ្នកយល់ព្រម
-   `"recreate"`: ជំនួសវាភ្លាមៗ ដោយមិនសួរ
-   `"ignore"`: ប្ដូរទៅ workspace ដែលមានស្រាប់

## ការពិពណ៌នា layout

layout គឺជាដើមឈើ (tree)។ node ខាងក្នុងនីមួយៗបំបែកតំបន់របស់វាជាពីរ ហើយ leaf នីមួយៗគឺជា pane ដែលផ្ទុក tab។

### Split node

split មួយបែងចែកតំបន់របស់វាជាពីរផ្នែក៖

-   `direction`: `"horizontal"` ឬ `"vertical"`
-   `children`: array ដែលមាន node ពីរគត់ ដែល node នីមួយៗជា split ផ្សេងទៀត ឬ pane
-   `split`: ទីតាំងរបស់ខ្សែបំបែក ជាប្រភាគនៃតំបន់។ លំនាំដើមគឺ 0.5; តម្លៃនៅក្រៅចន្លោះ 0.1 ដល់ 0.9 ត្រូវបានកាត់ឱ្យនៅក្នុងចន្លោះនោះ

### Pane node

pane គឺជា leaf នៃដើមឈើ។ array surfaces របស់វារាយបញ្ជី tab ដែលវាបើកជាមួយ ហើយត្រូវមានយ៉ាងហោចណាស់ធាតុមួយ។

## Surface

ធាតុនីមួយៗក្នុង array surfaces របស់ pane បើក tab មួយ ដែលជាទែមីណល ឬ browser៖

-   `type`: `"terminal"` ឬ `"browser"`
-   `name`: ចំណងជើង tab ដែលត្រូវបង្ហាញជំនួសចំណងជើងលំនាំដើម
-   `focus`: កំណត់ជា true ដើម្បីដាក់ការផ្ដោតក្ដារចុចលើ tab នេះ នៅពេល layout ត្រូវបានបង្កើតរួច
-   `command`: សម្រាប់ទែមីណលតែប៉ុណ្ណោះ៖ អត្ថបទ shell ដែលត្រូវដំណើរការភ្លាមៗពេលទែមីណលបើក
-   `url`: សម្រាប់ browser តែប៉ុណ្ណោះ៖ ទំព័រដែលត្រូវផ្ទុក
-   `cwd`: ថតចាប់ផ្ដើមសម្រាប់ tab នេះ ដោះស្រាយតាមច្បាប់ខាងក្រោម
-   `env`: object នៃឈ្មោះ និងតម្លៃអថេរបរិស្ថានបន្ថែម

### របៀបដែលតម្លៃ cwd ត្រូវបានដោះស្រាយ

-   `~/path`: ដោះស្រាយនៅក្នុងថត home របស់អ្នក
-   ផ្លូវដែលចាប់ផ្ដើមដោយ /: ប្រើតាមដែលបានសរសេរ
-   `./subdir`: បន្ថែមនៅខាងចុងថតរបស់ workspace
-   `.` ឬ មិនបានកំណត់: ទទួលយកថតរបស់ workspace

## រចនាសម្ព័ន្ធឯកសារ

បញ្ជីចុះឈ្មោះ action គឺជាមុខងារ nightly។ ដំឡើង nightly build ថ្មីបំផុត មុនពេលប្រើ `actions`, `shortcut`, ឬ `ui.surfaceTabBar.buttons`។

`commands` នៅតែកំណត់ shell commands និង workspace layouts ដែលអាចប្រើឡើងវិញបាន។ Nightly builds បន្ថែមបញ្ជីចុះឈ្មោះ `actions`។ Actions គឺជា public IDs ដែល surface tab bar, Command Palette និង shortcuts កម្រិត action ប្រើរួមគ្នា។

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"
              }
            ]
          }
        }
      }
    }
  ]
}
```

### បញ្ជីចុះឈ្មោះ action សម្រាប់ nightly

`actions` ភ្ជាប់ stable IDs ទៅនឹង behavior ដែលអាចរត់បាន។ ប្រើ built-in IDs `cmux.newTerminal`, `cmux.newBrowser`, `cmux.splitRight`, និង `cmux.splitDown` ដើម្បី override defaults។ ប្រើ IDs ផ្ទាល់ខ្លួនសម្រាប់ tools របស់ project។

`palette` មានតម្លៃ default ជា `true`។ កំណត់ជា `false` ដើម្បីលាក់ action ពី Command Palette ប៉ុន្តែនៅតែអាចហៅបានពី surface tab bar ឬ shortcut។ `shortcut` ប្រើ syntax ដូច settings shortcuts ដែរ ឧទាហរណ៍ `cmd+shift+c` ឬ `["cmd+k", "cmd+c"]`។

`ui.surfaceTabBar.buttons` នឹងជំនួសបញ្ជី buttons default នៅពេលមាន។ ដក built-in ID ចេញ ដើម្បីលាក់វា។ Icons តែងតែប្រើ object shape: `{ "type": "symbol", "name": "play.circle" }`, `{ "type": "emoji", "value": "🧪", "scale": 0.9 }`, ឬ `{ "type": "image", "path": "./icons/codex.svg" }`។ Image paths គឺ relative ទៅឯកសារ config។ Emoji `scale` គឺ optional ហើយ default ជា `1`។ គាំទ្រ SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO, និង ICNS។

ធាតុ button នីមួយៗអាចជា action ID string ឬ button object។ ប្រើ button object នៅពេលអ្នកចង់បាន action ដូចគ្នា ប៉ុន្តែមាន surface label, icon, ឬ tooltip ផ្សេង។ ចំណងជើង button ដែល resolve រួចក៏ត្រូវបានប្រើជាចំណងជើង trust prompt ផងដែរ។

ដាក់ approval ឬ permission flags ណាមួយដោយផ្ទាល់ក្នុង command string ដែលអ្នកចង់រត់ពិតប្រាកដ។ Action target default គឺ `newTabInCurrentPane` ដូច្នេះ pattern ទូទៅគឺបើក terminal tab ថ្មីក្នុង pane បច្ចុប្បន្ន ហើយចាប់ផ្តើម Codex, Claude Code, ឬ OpenCode នៅទីនោះ។

Actions ដែលនៅក្នុង project នឹងបង្ហាញភ្លាមៗនៅក្នុង surface tab bar និង Command Palette។ ការរត់លើកដំបូងនៅតែសួរឱ្យទុកចិត្ត។ ការទុកចិត្តគឺតាម fingerprint action ដែលត្រូវគ្នាពិតប្រាកដ មិនមែនតាម repo ទេ។ រូបតំណាង image ក្នុង project នឹងនៅតែ lock រហូតដល់ action នោះត្រូវបានទុកចិត្ត។

## Custom actions និង Command Palette

`actions` គឺជាធាតុដែល cmux រត់ឡើងវិញបាន។ ប្រើ actions នៅពេល behavior ដូចគ្នាត្រូវមានពី Command Palette, surface tab bar, shortcuts ឬ menu របស់ plus button។ ទុក `commands` សម្រាប់ shell commands និង workspace layouts ដែលប្រើឡើងវិញ។ ដាក់ `palette` ជា false នៅពេល action មិនគួរបង្ហាញក្នុង Command Palette។

### ប្រភេទ action

-   `"command"`: រត់ shell text ក្នុង 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 ចម្លងថតធ្វើការរបស់ terminal, cmux.copyProjectRoot ចម្លងឫសនៃ git repository របស់វា (ឬថតធ្វើការ នៅពេលនៅក្រៅ repository) ហើយ cmux.copyScreen ចម្លងអេក្រង់ដែលមើលឃើញ។ នៅក្នុង workspace SSH, cloud ឬ tmux ពីចម្ងាយ cmux.copyProjectRoot ចម្លងថតធ្វើការពីចម្ងាយ ព្រោះ cmux មិនអាចរក git repository នៅលើ host ផ្សេងបានទេ។
-   `"workspaceCommand"`: រត់ named workspace definition ពី commands។ ប្រើវាសម្រាប់ multi-pane layouts, working directories ផ្ទាល់ខ្លួន និង 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"`: ប្តូរ setting មួយក្នុង cmux.json global របស់អ្នក ឧទាហរណ៍ បិទ/បើក setting true/false ឬប្តូរទៅតម្លៃបន្ទាប់ក្នុងបញ្ជីតម្លៃ។ មើល Action ការកំណត់ ខាងក្រោម។
-   `"settingPreset"`: អនុវត្តក្រុម settings ដែលមានឈ្មោះពី settingPresets ក្នុងមួយជំហាន។

### វាល action

-   `title`: ចំណងជើង row ក្នុង Command Palette, label របស់ surface button, title របស់ menu item និង title របស់ trust prompt លុះត្រាតែ entry មួយ override វា។
-   `subtitle` / `description`: អត្ថបទ secondary ក្នុង 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 ដូច settings shortcuts។
-   `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 ត្រូវបន្ថែមជា rows នៅពេល `palette` មិនមែន false។ `commands` ចាស់ៗត្រូវបន្ថែមស្វ័យប្រវត្តិជា custom rows លុះត្រាតែមាន action ដែលមាន generated ID ដូចគ្នារួចហើយ។ Built-in commands រក្សា labels ធម្មតា ប៉ុន្តែការជំនួស built-in ID ដូចជា `cmux.newTerminal` នឹងផ្លាស់ប្តូរ behavior នៅក្រោយ entrypoint រួមនោះ។

### Action ការកំណត់

Action ការកំណត់មួយកំណត់ `path` របស់ setting និងមួយគត់ក្នុងចំណោម `set` (សរសេរតម្លៃ), `toggle: true` (បិទ/បើក setting true/false), `cycle` (ទៅតម្លៃបន្ទាប់ក្នុងបញ្ជី ហើយត្រឡប់ទៅតម្លៃដំបូងវិញក្រោយតម្លៃចុងក្រោយ) ឬ `unset: true` (លុប key ចេញពី cmux.json ដើម្បីឱ្យប្រើតម្លៃពីបង្អួច ការកំណត់ ឬតម្លៃលំនាំដើម)។ toggle និង cycle ចាប់ផ្តើមពីតម្លៃដែល cmux កំពុងប្រើ រួមទាំងតម្លៃដែលអ្នកកំណត់ក្នុងបង្អួច ការកំណត់។ Action settingPreset អនុវត្ត entry មួយពី `settingPresets` ដែលជា cmux.json មួយផ្នែក ហើយ nested objects របស់វាត្រូវ merge តាម key នីមួយៗ។ cmux ពិនិត្យការផ្លាស់ប្តូរនីមួយៗជាមួយ schema មុនរក្សាទុក រក្សា comments និង keys ផ្សេងទៀតរបស់អ្នក ហើយអនុវត្តភ្លាមៗ។ Action ការកំណត់ និង presets រត់បានតែពី cmux.json global របស់អ្នក និង packs ដែលវាយោងទៅប៉ុណ្ណោះ; project configs មិនអាចប្រកាសវាបានទេ។

~/.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 សួរមុនរក្សាទុក ហើយបង្ហាញ command cmux config ដែលស្មើគ្នា។ Paths ត្រូវបំបែកនៅគ្រប់ "." ដូច្នេះ key ដែលមាន "." ក្នុងឈ្មោះខ្លួនឯង (ដូចជា entry `workspaceGroups.byCwd` សម្រាប់ ~/src/app.web) មិនអាចប្តូរតាមវិធីនេះបានទេ។ សូមកែវាដោយផ្ទាល់ក្នុង cmux.json។

## Actions ផ្ទាល់ខ្លួនសម្រាប់ប៊ូតុង plus

ប្រើ `ui.newWorkspace.action` ដើម្បី override អ្វីដែលប៊ូតុង plus ធ្វើ។ ប្រើ `ui.newWorkspace.contextMenu` (ឬ alias `rightClick`) ដើម្បីកំណត់ right-click menu ដែលមានលំដាប់។ Menu entries អាចជា 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 workspace ដែលបានជ្រើសចុងក្រោយ បន្ទាប់មកម៉ាស៊ីនដំបូងក្នុង sidebar ខាងស្ដាំ។ ប្រសិនបើគ្មានម៉ាស៊ីនដែលអាចប្រើបាន នឹងបើក 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
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}
```

ឧទាហរណ៍នេះធ្វើឱ្យការចុច plus ធម្មតារត់ action `worktree-agents`។ Workspace command ពី `commands` ប្រើ setup terminal ដែលមើលឃើញ ដើម្បីបង្កើត Git `worktree` ជាមុន។ Codex និង Claude ចាប់ផ្តើមពេលតែមួយ រង់ចាំ state file សម្រាប់ 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"
    }
  ]
}
```

Canonical: https://cmux.com/km/docs/custom-commands

Documentation index: https://cmux.com/llms.txt
