# Власні команди та дії

cmux.json — це місце, де ви навчаєте cmux своїх власних звичок: команд оболонки, які часто запускаєте, робочих просторів, що відкриваються із заздалегідь розташованими терміналами й браузерами, і дій, які можна прив’язати до скорочень, кнопок панелі вкладок і Command Palette. Тримайте його в .cmux/cmux.json усередині проєкту, у ~/.config/cmux/cmux.json для всіх проєктів або в обох місцях.

## Звідки cmux читає cmux.json

Записи можуть надходити з файлу проєкту, з файлу для всього користувача або з обох. Для файлів проєкту cmux починає з поточного каталогу й також перевіряє кожен батьківський каталог вище.

-   **Проєкт:** `./.cmux/cmux.json` (знаходиться пошуком угору від робочого каталогу; має перевагу над файлом для всього користувача)
-   **Локальний fallback:** `./cmux.json` (і далі підтримується для наявних репозиторіїв)
-   **Для всього користувача:** `~/.config/cmux/cmux.json` (спільний для всіх проєктів; доповнює все, що не визначено у файлі проєкту)

Локальні дії та команди перевизначають глобальні записи з тим самим ID або назвою.

Відредагуйте cmux.json, потім натисніть Cmd+Shift+, або виконайте cmux reload-config, щоб застосувати зміни.

Якщо конфігурація проєкту або глобальна конфігурація має помилку схеми, cmux повертається до наступної чинної конфігурації та показує рядок **cmux.json Schema Error** у Command Palette. Виберіть його, щоб відкрити файл конфігурації.

## Команди оболонки

Найпростіший запис — це назва й рядок команди. Якщо вибрати його в 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
    }
  ]
}
```

### Поля команди оболонки

-   `name`: Обов’язкова непорожня мітка, яку ви вибираєте в Command Palette
-   `command`: Текст оболонки, який cmux вводить у термінал у фокусі та виконує
-   `description`: Необов’язковий додатковий текст, що показується поруч із записом
-   `keywords`: Додаткові слова, за якими цей запис має знаходитися під час пошуку в Command Palette
-   `confirm`: Установіть true, щоб щоразу перед запуском отримувати запит на підтвердження

Команда оболонки виконується там, де саме перебуває термінал у фокусі. Якщо команді потрібна передбачувана початкова точка, почніть її з `cd "$(git rev-parse --show-toplevel)" &&` щоб перейти до кореня Git-репозиторію, або з `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 перелічує вкладки, з якими вона відкривається, і має містити принаймні один запис.

## Поверхні

Кожен запис у масиві surfaces панелі відкриває одну вкладку — термінал або браузер:

-   `type`: `"terminal"` або `"browser"`
-   `name`: Заголовок вкладки, що показується замість типового
-   `focus`: Установіть true, щоб після побудови розкладки клавіатурний фокус опинився на цій вкладці
-   `command`: Лише для терміналів: текст оболонки, який треба виконати одразу після відкриття термінала
-   `url`: Лише для браузерів: сторінка, яку треба завантажити
-   `cwd`: Початковий каталог для цієї вкладки, розв’язується за правилами нижче
-   `env`: Об’єкт із назвами й значеннями додаткових змінних середовища

### Як розв’язуються значення cwd

-   `~/path`: розв’язується всередині вашої домашньої папки
-   Шлях, що починається з /: використовується як є
-   `./subdir`: додається до каталогу робочого простору
-   `.` або не задано: успадковує каталог робочого простору

## Структура файлу

Реєстр дій — це функція nightly. Установіть найновішу nightly-збірку перед використанням `actions`, `shortcut` або `ui.surfaceTabBar.buttons`.

`commands` і далі визначає повторно використовувані shell-команди та розкладки workspace. Nightly-збірки додають реєстр `actions`. Дії — це публічні ID, спільні для surface tab bar, Command Palette та скорочень рівня дії.

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` зіставляє стабільні ID із поведінкою, яку можна запустити. Використовуйте вбудовані ID `cmux.newTerminal`, `cmux.newBrowser`, `cmux.splitRight` і `cmux.splitDown`, щоб перевизначити стандартні дії. Для інструментів проєкту використовуйте власні ID.

`palette` за замовчуванням має значення `true`. Установіть `false`, щоб приховати дію з Command Palette, але залишити її доступною на surface tab bar або через скорочення. `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`, тому звичний шаблон відкриває нову вкладку термінала в поточній панелі й запускає там Codex, Claude Code або OpenCode.

Локальні для проєкту дії одразу з’являються на surface tab bar і в Command Palette. Під час першого запуску все одно з’являється запит довіри. Довіра прив’язана до точного fingerprint дії, а не до репозиторію. Локальні для проєкту іконки-зображення залишаються заблокованими, доки цій дії не буде надано довіру.

## Користувацькі дії та Command Palette

Запис `actions` описує повторно використовувану дію, яку запускає cmux. Використовуйте дії, коли та сама поведінка має бути доступна з Command Palette, панелі вкладок поверхні, скорочень або меню кнопки плюс. Залишайте `commands` для повторно використовуваних shell-команд і розкладок робочих просторів. Установіть `palette` у false, якщо дія не має з’являтися в Command Palette.

### Типи дій

-   `"command"`: Запускає shell-текст у терміналі. Використовуйте target, щоб вибрати поточний термінал або нову вкладку в поточній панелі.
-   `"agent"`: Запускає підтримуваного кодового агента. Наразі підтримуються codex і claude з необов’язковими аргументами.
-   `"builtin"`: Псевдонім для вбудованої дії cmux, наприклад cmux.newTerminal, cmux.newBrowser, cmux.splitRight або cmux.splitDown. Вбудовані дії копіювання: cmux.copyWorkingDirectory копіює робочий каталог термінала, cmux.copyProjectRoot — корінь його git-репозиторію (або робочий каталог поза репозиторієм), а cmux.copyScreen — видимий екран. У робочому просторі SSH, хмари або віддаленого tmux cmux.copyProjectRoot копіює віддалений робочий каталог, бо cmux не може знайти git-репозиторій на іншому хості.
-   `"workspaceCommand"`: Запускає іменоване визначення робочого простору з 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, наприклад перемикає параметр true/false або перебирає список значень. Див. розділ «Дії з параметрами» нижче.
-   `"settingPreset"`: Застосовує іменовану групу параметрів із settingPresets за один крок.

### Поля дії

-   `title`: Заголовок рядка Command Palette, підпис кнопки, заголовок пункту меню та заголовок запиту довіри, якщо запис не перевизначає його.
-   `subtitle` / `description`: Вторинний текст у Command Palette. description приймається як псевдонім subtitle.
-   `keywords`: Додаткові пошукові слова для Command Palette.
-   `palette`: Типово true для користувацьких дій. Установіть false, щоб приховати дію з Command Palette, але залишити її доступною в інших місцях.
-   `shortcut`: Необов’язкове скорочення дії з тією самою одноразовою або двоетапною chord-синтаксою, що й скорочення налаштувань.
-   `target`: Лише для дій command і agent. Використовуйте currentTerminal або newTabInCurrentPane.
-   `confirm`: Запитувати підтвердження перед запуском дії.
-   `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 читає розв’язаний реєстр дій. ID користувацьких дій додаються як рядки, коли `palette` не дорівнює false. Старі `commands` автоматично додаються як користувацькі рядки, якщо дія з тим самим згенерованим ID ще не існує. Вбудовані команди зберігають звичні назви в палітрі, але перевизначення вбудованого ID, як-от `cmux.newTerminal`, змінює поведінку за цією спільною точкою входу.

### Дії з параметрами

Дія з параметром вказує `path` параметра й рівно одне з полів: `set` (записати значення), `toggle: true` (перемкнути параметр true/false), `cycle` (перейти до наступного значення зі списку, а після останнього повернутися до першого) або `unset: true` (видалити ключ із cmux.json, щоб діяло значення з вікна «Параметри» або типове значення). toggle і cycle починають зі значення, яке cmux використовує зараз, зокрема заданого у вікні «Параметри». Дія settingPreset застосовує запис із `settingPresets` — частковий cmux.json, вкладені об’єкти якого об’єднуються за ключами. Перед збереженням cmux перевіряє кожну зміну за схемою, зберігає ваші коментарі та інші ключі й одразу застосовує зміну. Дії з параметрами та пресети працюють лише з вашого глобального cmux.json і пакетів, на які він посилається; конфігурації проєктів не можуть їх оголошувати.

~/.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 }
    }
  }
}
```

Ті самі зміни можна зробити з термінала: `cmux config set terminal.scrollSpeed 1.4`, `cmux config toggle fileEditor.wordWrap` і `cmux config preset sidebar.quiet`.

З `confirm: true` cmux запитує підтвердження перед збереженням і показує відповідну команду cmux config. Шляхи розбиваються за кожним символом ".", тому ключ, який сам містить "." (наприклад, запис `workspaceGroups.byCwd` для ~/src/app.web), так змінити не можна. Відредагуйте його безпосередньо в cmux.json.

## Користувацькі дії кнопки плюс

Використовуйте `ui.newWorkspace.action`, щоб перевизначити дію кнопки плюс. Використовуйте `ui.newWorkspace.contextMenu` (або alias `rightClick`), щоб визначити впорядковане меню правого кліку. Пункти меню можуть бути ID дій, об’єктами дій або `{ "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
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}
```

У цьому прикладі звичайний клік по плюсу запускає дію `worktree-agents`. Команда робочого простору з `commands` використовує видимий термінал налаштування, щоб спочатку створити Git `worktree`. Codex і Claude запускаються одночасно, чекають файл стану для цього робочого простору, а потім переходять у створений каталог перед 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/uk/docs/custom-commands

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