# Пользовательские команды и действия

В cmux.json вы обучаете cmux своим собственным привычным действиям: часто выполняемым командам оболочки, рабочим пространствам, которые открываются с заранее заданной раскладкой терминалов и браузеров, и действиям, которые можно назначить на сочетания клавиш, кнопки панели вкладок и палитру команд. Храните файл в .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. Если выбрать её в палитре команд, эта строка будет введена в терминал, находящийся в фокусе, и выполнена.

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`: Текст для оболочки, который cmux вводит в активный терминал и выполняет
-   `description`: Необязательный дополнительный текст, показываемый рядом с записью
-   `keywords`: Дополнительные слова, по которым эта запись должна находиться при поиске в палитре команд
-   `confirm`: Укажите true, чтобы перед каждым запуском появлялся запрос подтверждения

Команда оболочки выполняется там, где в данный момент находится активный терминал. Если команде нужна предсказуемая начальная точка, начните её с `cd "$(git rev-parse --show-toplevel)" &&` чтобы перейти в корень Git-репозитория, или с `cd /some/folder &&` чтобы привязать её к определённой папке.

## Команды, открывающие рабочее пространство

Если вместо строки command передать команде объект 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 прямо в строку команды, которую действительно хотите запустить. Цель действия по умолчанию — `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/ru/docs/custom-commands

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