Пользовательские команды
Определяйте пользовательские команды и макеты рабочего пространства, добавив файл cmux.json в корень вашего проекта или ~/.config/cmux/. Команды отображаются в палитре команд.
Расположение файлов
cmux ищет конфигурацию в двух местах:
- Для проекта:
./.cmux/cmux.json- находится в каталоге проекта, имеет приоритет - Локальный fallback:
./cmux.json- по-прежнему поддерживается для существующих репозиториев - Глобально:
~/.config/cmux/cmux.json- применяется ко всем проектам, дополняет команды, не определённые локально
actions, shortcut или ui.surfaceTabBar.buttons.Измените cmux.json, затем нажмите Cmd+Shift+, или выполните cmux reload-config, чтобы применить изменения.
Схема
commands по-прежнему задаёт переиспользуемые shell-команды и раскладки workspace. Nightly-сборки добавляют реестр actions. Действия — это публичные ID, общие для surface tab bar, Command Palette и сочетаний клавиш уровня действия.
{
"actions": {
"cmux.newTerminal": {
"type": "command",
"title": "Codex",
"subtitle": "Open Codex in a new terminal tab",
"command": "codex --dangerously-bypass-approvals-and-sandbox",
"target": "newTabInCurrentPane",
"shortcut": "cmd+t",
"icon": { "type": "image", "path": "./icons/codex.svg" }
},
"claude": {
"type": "command",
"title": "Claude Code",
"command": "claude --dangerously-skip-permissions",
"target": "newTabInCurrentPane",
"shortcut": "cmd+shift+c",
"icon": { "type": "image", "path": "./icons/claude.svg" }
},
"opencode": {
"type": "command",
"title": "OpenCode",
"command": "opencode",
"target": "newTabInCurrentPane",
"palette": false,
"icon": { "type": "emoji", "value": "🧪", "scale": 0.9 }
},
"web-dev": {
"type": "workspaceCommand",
"title": "Web Dev",
"commandName": "Web Dev"
}
},
"ui": {
"surfaceTabBar": {
"buttons": [
"cmux.newTerminal",
"cmux.newBrowser",
"cmux.splitRight",
"cmux.splitDown",
"claude"
]
}
},
"commands": [
{
"name": "Web Dev",
"keywords": ["dev", "start"],
"workspace": { ... }
}
]
}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.
Типы действий
"builtin": Псевдоним встроенного действия cmux, например cmux.newTerminal, cmux.newBrowser, cmux.splitRight или cmux.splitDown."command": Запускает shell-текст в терминале. Используйте target, чтобы выбрать текущий терминал или новую вкладку в текущей панели."agent": Запускает поддерживаемого кодового агента. Сейчас поддерживаются codex и claude с необязательными аргументами."workspaceCommand": Запускает именованное определение рабочей области из commands. Используйте для многопанельных раскладок, пользовательских рабочих каталогов и стартовых команд.
Поля действия
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: Запрашивать подтверждение перед запуском действия.
Поведение Command Palette
Command Palette читает разрешенный реестр действий. ID пользовательских действий добавляются как строки, когда palette не равен false. Устаревшие commands автоматически добавляются как пользовательские строки, если действие с тем же сгенерированным ID еще не существует. Встроенные команды сохраняют обычные названия в палитре, но переопределение встроенного ID, например cmux.newTerminal, меняет поведение за общей точкой входа.
Пользовательские действия кнопки плюс
Используйте ui.newWorkspace.action, чтобы переопределить действие кнопки плюс. Используйте ui.newWorkspace.contextMenu (или alias rightClick), чтобы задать упорядоченное меню правого клика. Пункты меню могут быть ID действий, объектами действий или { "type": "separator" }.
{
"actions": {
"worktree-agents": {
"type": "workspaceCommand",
"title": "Worktree Agents",
"commandName": "Worktree Agents",
"icon": { "type": "symbol", "name": "folder.badge.plus" }
}
},
"ui": {
"newWorkspace": {
"action": "worktree-agents",
"contextMenu": [
{ "action": "worktree-agents", "title": "Worktree Agents" },
{ "type": "separator" },
{ "action": "cmux.newTerminal", "title": "New Terminal" },
{ "action": "cmux.newBrowser", "title": "New Browser" }
]
}
},
"commands": [
{
"name": "Worktree Agents",
"description": "Create a fresh Git worktree and start Codex and Claude inside it",
"workspace": {
"name": "Worktree Agents",
"cwd": ".",
"layout": {
"direction": "horizontal",
"split": 0.38,
"children": [
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Worktree",
"command": "set -euo pipefail; state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; rm -f \"$state\"; repo=$(git rev-parse --show-toplevel); mkdir -p \"$repo/../worktrees\"; slug=agents-$(date +%Y%m%d-%H%M%S); dir=\"$repo/../worktrees/$slug\"; git -C \"$repo\" worktree add -b \"$slug\" \"$dir\"; printf \"%s\\n\" \"$dir\" > \"$state\"; cd \"$dir\"; exec \"${SHELL:-/bin/zsh}\" -l",
"focus": true
}
]
}
},
{
"direction": "vertical",
"split": 0.5,
"children": [
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Codex",
"command": "state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; echo \"Waiting for worktree...\"; while [ ! -s \"$state\" ]; do sleep 0.2; done; dir=$(cat \"$state\"); cd \"$dir\"; exec codex --dangerously-bypass-approvals-and-sandbox"
}
]
}
},
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Claude",
"command": "state=\"${TMPDIR:-/tmp}/cmux-worktree-${CMUX_WORKSPACE_ID:-manual}.dir\"; echo \"Waiting for worktree...\"; while [ ! -s \"$state\" ]; do sleep 0.2; done; dir=$(cat \"$state\"); cd \"$dir\"; exec claude --dangerously-skip-permissions"
}
]
}
}
]
}
]
}
}
}
]
}В этом примере обычный клик по плюсу запускает действие worktree-agents. Команда рабочей области из commands использует видимый терминал настройки, чтобы сначала создать Git worktree. Codex и Claude запускаются одновременно, ждут файл состояния для этой рабочей области, затем переходят в созданный каталог перед exec.
Простые команды
Простая команда выполняет команду shell в текущем сфокусированном терминале:
{
"commands": [
{
"name": "Run Tests",
"keywords": ["test", "check"],
"command": "npm test",
"confirm": true
}
]
}Поля
name: Отображается в палитре команд (обязательно)description: Необязательное описаниеkeywords: Дополнительные поисковые термины для палитры командcommand: Команда shell для выполнения в сфокусированном терминалеconfirm: Показать диалог подтверждения перед выполнением
Простые команды выполняются в текущей рабочей директории активного терминала. Если команда использует пути относительно проекта, добавьте префикс cd "$(git rev-parse --show-toplevel)" && для запуска из корня репозитория, или cd /your/path && для любой конкретной директории.
Команды рабочего пространства
Команда рабочего пространства создаёт новое рабочее пространство с настраиваемым макетом из разделений, терминалов и панелей браузера:
{
"commands": [
{
"name": "Dev Environment",
"keywords": ["dev", "fullstack"],
"workspace": {
"name": "Dev",
"cwd": ".",
"layout": {
"direction": "horizontal",
"split": 0.5,
"children": [
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Frontend",
"command": "npm run dev",
"focus": true
}
]
}
},
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Backend",
"command": "cargo watch -x run",
"cwd": "./server",
"env": { "RUST_LOG": "debug" }
}
]
}
}
]
}
}
}
]
}Поля рабочего пространства
name: Имя вкладки рабочего пространства (по умолчанию — имя команды)cwd: Рабочий каталог для рабочего пространстваcolor: Цвет вкладки рабочего пространстваlayout: Дерево макета, определяющее разделения и панели
Поведение при перезапуске
Управляет тем, что происходит, когда рабочее пространство с тем же именем уже существует:
"new": Создать новый workspace (по умолчанию)"ignore": Переключиться на существующий workspace"recreate": Закрыть и пересоздать без запроса"confirm": Спросить пользователя перед пересозданием
Дерево макета
Дерево макета определяет расположение панелей с помощью рекурсивных узлов разделения:
Узел разделения
Делит пространство на двух потомков:
direction:"horizontal"или"vertical"split: Положение разделителя от 0.1 до 0.9 (по умолчанию 0.5)children: Ровно два дочерних узла (разделение или панель)
Узел панели
Листовой узел, содержащий одну или несколько поверхностей (вкладки внутри панели).
Определение поверхности
Каждая поверхность в панели может быть терминалом или браузером:
type:"terminal"или"browser"name: Пользовательский заголовок вкладкиcommand: Команда shell для автоматического запуска при создании (только терминал)cwd: Рабочий каталог для этой поверхностиenv: Переменные среды в виде пар ключ-значениеurl: URL для открытия (только браузер)focus: Сфокусироваться на этой поверхности после создания
Определение рабочего каталога
.или опущено: рабочий каталог рабочего пространства./subdir: относительно рабочего каталога рабочего пространства~/path: расширено до домашнего каталога- Абсолютный путь: используется как есть
Полный пример
{
"actions": {
"web-dev": { "type": "workspaceCommand", "commandName": "Web Dev" },
"cmux.newTerminal": {
"type": "command",
"title": "Codex",
"command": "codex --dangerously-bypass-approvals-and-sandbox",
"target": "newTabInCurrentPane",
"shortcut": "cmd+t",
"icon": { "type": "image", "path": "./icons/codex.svg" }
},
"claude": {
"type": "command",
"title": "Claude Code",
"command": "claude --dangerously-skip-permissions",
"target": "newTabInCurrentPane",
"shortcut": "cmd+shift+c",
"icon": { "type": "image", "path": "./icons/claude.svg" }
},
"start-dev": {
"type": "command",
"command": "npm run dev",
"target": "newTabInCurrentPane",
"icon": { "type": "symbol", "name": "play.circle" }
}
},
"ui": {
"surfaceTabBar": {
"buttons": [
"cmux.newTerminal",
"cmux.newBrowser",
"cmux.splitRight",
"cmux.splitDown",
{
"action": "claude",
"title": "Claude Here"
},
"start-dev"
]
}
},
"commands": [
{
"name": "Web Dev",
"description": "Docs site with live preview",
"keywords": ["web", "docs", "next", "frontend"],
"workspace": {
"name": "Web Dev",
"cwd": "./web",
"color": "#3b82f6",
"layout": {
"direction": "horizontal",
"split": 0.5,
"children": [
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Next.js",
"command": "npm run dev",
"focus": true
}
]
}
},
{
"direction": "vertical",
"split": 0.6,
"children": [
{
"pane": {
"surfaces": [
{
"type": "browser",
"name": "Preview",
"url": "http://localhost:3777"
}
]
}
},
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Shell",
"env": { "NODE_ENV": "development" }
}
]
}
}
]
}
]
}
}
},
{
"name": "Debug Log",
"description": "Tail the debug event log from the running dev app",
"keywords": ["log", "debug", "tail", "events"],
"workspace": {
"name": "Debug Log",
"layout": {
"direction": "horizontal",
"split": 0.5,
"children": [
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Events",
"command": "tail -f /tmp/cmux-debug.log",
"focus": true
}
]
}
},
{
"pane": {
"surfaces": [
{
"type": "terminal",
"name": "Shell"
}
]
}
}
]
}
}
},
{
"name": "Setup",
"description": "Initialize submodules and build dependencies",
"keywords": ["setup", "init", "install"],
"command": "./scripts/setup.sh",
"confirm": true
},
{
"name": "Reload",
"description": "Build and launch the debug app tagged to the current branch",
"keywords": ["reload", "build", "run", "launch"],
"command": "./scripts/reload.sh --tag $(git branch --show-current)"
},
{
"name": "Run Unit Tests",
"keywords": ["test", "unit"],
"command": "./scripts/test-unit.sh",
"confirm": true
}
]
}