Пользовательские команды и действия
В cmux.json вы обучаете cmux своим собственным привычным действиям: часто выполняемым командам оболочки, рабочим пространствам, которые открываются с заранее заданной раскладкой терминалов и браузеров, и действиям, которые можно назначить на сочетания клавиш, кнопки панели вкладок и палитру команд. Храните файл в .cmux/cmux.json внутри проекта, в ~/.config/cmux/cmux.json для всех проектов или в обоих местах.
Где cmux ищет cmux.json
Записи могут поступать из файла проекта, из пользовательского файла или из обоих. Файл проекта cmux ищет начиная с текущей директории, а также проверяет каждую родительскую директорию выше неё.
- Проект:
./.cmux/cmux.json(ищется вверх от рабочей директории; имеет приоритет над пользовательским файлом) - Локальный fallback:
./cmux.json(по-прежнему поддерживается для существующих репозиториев) - Пользовательский:
~/.config/cmux/cmux.json(общий для всех проектов; задаёт всё, что не определено в файле проекта)
Измените cmux.json, затем нажмите Cmd+Shift+, или выполните cmux reload-config, чтобы применить изменения.
Команды оболочки
Минимальная запись состоит из имени и строки command. Если выбрать её в палитре команд, эта строка будет введена в терминал, находящийся в фокусе, и выполнена.
{
"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, она откроет новое рабочее пространство, организованное как дерево разделённых панелей с терминалами и браузерами. В записи должно быть ровно одно из этих двух полей.
{
"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 перечисляет вкладки, с которыми она открывается, и должен содержать хотя бы одну запись.
Поверхности
Каждая запись в массиве surfaces панели открывает одну вкладку — терминал или браузер:
type:"terminal"или"browser"name: Заголовок вкладки, показываемый вместо стандартногоfocus: Укажите true, чтобы после построения раскладки фокус клавиатуры оказался на этой вкладкеcommand: Только для терминалов: текст для оболочки, выполняемый сразу после открытия терминалаurl: Только для браузеров: страница для загрузкиcwd: Начальная директория этой вкладки, определяемая по правилам нижеenv: Объект с дополнительными именами и значениями переменных окружения
Как определяются значения cwd
~/path: отсчитывается от вашей домашней папки- Путь, начинающийся с /: используется как есть
./subdir: добавляется к директории рабочего пространства.или не задано: берётся директория рабочего пространства
Структура файла
actions, shortcut или ui.surfaceTabBar.buttons.commands по-прежнему задаёт переиспользуемые shell-команды и раскладки workspace. Nightly-сборки добавляют реестр actions. Действия — это публичные ID, общие для surface tab bar, Command Palette и сочетаний клавиш уровня действия.
{
"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.
Пользовательские действия и 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 и пакетов, на которые он ссылается; конфигурации проектов не могут их объявлять.
{
"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.
{
"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:
{
"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"
}
]
}