Niestandardowe polecenia i akcje
W cmux.json uczysz cmux własnych nawyków: częstych poleceń powłoki, workspace'ów z gotowym układem terminali i przeglądarek oraz własnych akcji. Akcje możesz przypisać do skrótów, przycisków paska kart i Command Palette. Umieść plik w .cmux/cmux.json w projekcie, w ~/.config/cmux/cmux.json dla wszystkich projektów albo w obu miejscach.
Skąd cmux wczytuje cmux.json
Wpisy mogą pochodzić z pliku projektu, z pliku użytkownika albo z obu. W przypadku plików projektu cmux zaczyna od bieżącego katalogu i sprawdza też każdy katalog nadrzędny powyżej.
- Projektu:
./.cmux/cmux.json(wyszukiwany w górę od katalogu roboczego; ma pierwszeństwo przed plikiem użytkownika) - Lokalna konfiguracja awaryjna:
./cmux.json(nadal obsługiwana dla istniejących repozytoriów) - Użytkownika:
~/.config/cmux/cmux.json(wspólny dla wszystkich projektów; dostarcza wszystko, czego plik projektu nie definiuje)
Edytuj cmux.json, a następnie naciśnij Cmd+Shift+, albo uruchom cmux reload-config, aby zastosować zmiany.
Polecenia powłoki
Najmniejszy wpis to nazwa i ciąg command. Wybranie go w Command Palette wpisuje ten ciąg do terminala, który ma fokus, i go uruchamia.
{
"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
}
]
}Pola polecenia powłoki
name: Wymagana, niepusta etykieta, którą wybierasz w Command Palettecommand: Tekst powłoki, który cmux wpisuje do aktywnego terminala i uruchamiadescription: Opcjonalny tekst dodatkowy wyświetlany obok wpisukeywords: Dodatkowe słowa, które mają pasować do tego wpisu podczas wyszukiwania w Command Paletteconfirm: Ustaw na true, aby przed każdym uruchomieniem pojawiało się pytanie o potwierdzenie
Polecenie powłoki wykonuje się tam, gdzie akurat znajduje się aktywny terminal. Jeśli polecenie wymaga przewidywalnego punktu startowego, zacznij je od cd "$(git rev-parse --show-toplevel)" && (przejście do katalogu głównego repozytorium Git) lub od cd /some/folder && (przypięcie do stałego folderu).
Polecenia otwierające workspace
Jeśli zamiast ciągu command dasz poleceniu obiekt workspace, otworzy ono nowy workspace, ułożony jako drzewo podzielonych paneli z terminalami i przeglądarkami. Wpis musi mieć dokładnie jedno z tych dwóch pól.
{
"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"
}
]
}
}
]
}
}
}
]
}Pola obiektu workspace
name: Tytuł workspace'u; jeśli go brak, używana jest nazwa poleceniacwd: Katalog bazowy workspace'u; cwd każdej karty jest rozwiązywane względem niegolayout: Węzeł główny drzewa układu opisanego poniżejcolor: Kolor na pasku bocznym jako szesnastkowe #RRGGBB lub nazwa koloru workspace'uenv: Environment variables inherited by every shell in the workspacesetup: Bootstrap command sent to the workspace's first terminal before that terminal's own command
Gdy workspace jest już otwarty
Ustaw restart w poleceniu, aby zdecydować, co się stanie, jeśli workspace o tej samej nazwie już istnieje:
"new": Utwórz nowy workspace (domyślnie)"confirm": Najpierw zapytaj, a po twojej zgodzie zastąp go"recreate": Zastąp go od razu, bez pytania"ignore": Przełącz do istniejącego workspace
Opis układu
Układ jest drzewem. Każdy węzeł wewnętrzny dzieli swój obszar na dwie części, a każdy liść to panel zawierający karty.
Węzły podziału
Podział dzieli swój obszar na dwie części:
direction:"horizontal"lub"vertical"children: Tablica dokładnie dwóch węzłów, z których każdy jest kolejnym podziałem albo panelemsplit: Położenie separatora jako ułamek obszaru. Domyślnie 0.5; wartości spoza zakresu od 0.1 do 0.9 są przycinane do tych granic
Węzły paneli
Panel to liść drzewa. Jego tablica surfaces wymienia karty, z którymi się otwiera, i musi zawierać co najmniej jeden wpis.
Powierzchnie
Każdy wpis w tablicy surfaces panelu otwiera jedną kartę, która jest terminalem albo przeglądarką:
type:"terminal"lub"browser"name: Tytuł karty wyświetlany zamiast domyślnegofocus: Ustaw na true, aby po zbudowaniu układu fokus klawiatury trafił na tę kartęcommand: Tylko terminale: tekst powłoki uruchamiany zaraz po otwarciu terminalaurl: Tylko przeglądarki: strona do załadowaniacwd: Katalog startowy tej karty, rozwiązywany według poniższych regułenv: Obiekt z nazwami i wartościami dodatkowych zmiennych środowiskowych
Jak rozwiązywane są wartości cwd
~/path: rozwiązywana wewnątrz twojego folderu domowego- Ścieżka zaczynająca się od /: używana dosłownie
./subdir: dołączana do katalogu workspace'u.lub nieustawione: dziedziczy katalog workspace'u
Struktura pliku
actions, shortcut lub ui.surfaceTabBar.buttons.commands nadal definiuje wielokrotnego użytku polecenia shell i układy workspace. Buildy nightly dodają rejestr actions. Akcje to publiczne ID współdzielone przez pasek kart powierzchni, Command Palette i skróty na poziomie akcji.
{
"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"
}
]
}
}
}
}
]
}Rejestr akcji nightly
actions mapuje stabilne ID na uruchamialne zachowanie. Użyj wbudowanych ID cmux.newTerminal, cmux.newBrowser, cmux.splitRight i cmux.splitDown, aby nadpisać wartości domyślne. Użyj własnych ID dla narzędzi specyficznych dla projektu.
palette domyślnie ma wartość true. Ustaw false, aby ukryć akcję w Command Palette, ale pozostawić ją dostępną z paska kart powierzchni lub skrótu. shortcut używa tej samej składni co skróty ustawień, na przykład cmd+shift+c albo ["cmd+k", "cmd+c"].
ui.surfaceTabBar.buttons zastępuje domyślną listę przycisków, gdy jest obecne. Pomiń wbudowane ID, aby je ukryć. Ikony zawsze używają kształtu obiektu: { "type": "symbol", "name": "play.circle" }, { "type": "emoji", "value": "🧪", "scale": 0.9 } albo { "type": "image", "path": "./icons/codex.svg" }. Ścieżki obrazów są względne wobec pliku konfiguracji. Emoji scale jest opcjonalne i domyślnie wynosi 1. Obsługiwane są SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO i ICNS.
Każdy wpis przycisku może być ciągiem ID akcji albo obiektem przycisku. Użyj obiektu przycisku, gdy chcesz tę samą akcję z inną etykietą powierzchni, ikoną lub tooltipem. Rozwiązany tytuł przycisku jest też używany jako tytuł prośby o zaufanie.
Umieść wszystkie flagi approval lub permission bezpośrednio w ciągu polecenia, które faktycznie chcesz uruchomić. Domyślnym celem akcji jest newTabInCurrentPane, więc typowy wzorzec to otwarcie nowej karty terminala w bieżącym panelu i uruchomienie tam Codex, Claude Code lub OpenCode.
Akcje niestandardowe i Command Palette
Wpis actions to wielokrotnego użytku działanie uruchamiane przez cmux. Używaj akcji, gdy to samo zachowanie ma być dostępne z Command Palette, paska kart powierzchni, skrótów lub menu przycisku plus. Zachowaj commands dla wielokrotnego użytku poleceń shell i układów obszarów roboczych. Ustaw palette na false, gdy akcja nie powinna pojawiać się w Command Palette.
Typy akcji
"command": Uruchamia tekst shell w terminalu. Użyj target, aby wybrać bieżący terminal albo nową kartę w bieżącym panelu."agent": Uruchamia obsługiwanego agenta programistycznego. Obecnie obsługuje codex i claude, z opcjonalnymi argumentami."builtin": Alias wbudowanej akcji cmux, takiej jak cmux.newTerminal, cmux.newBrowser, cmux.splitRight lub cmux.splitDown. Wbudowane akcje kopiowania: cmux.copyWorkingDirectory kopiuje katalog roboczy terminala, cmux.copyProjectRoot kopiuje katalog główny jego repozytorium git (lub katalog roboczy poza repozytorium), a cmux.copyScreen kopiuje widoczny ekran. W obszarze roboczym SSH, w chmurze lub zdalnym tmux cmux.copyProjectRoot kopiuje zdalny katalog roboczy, ponieważ cmux nie może odnaleźć repozytorium git na drugim hoście."workspaceCommand": Uruchamia nazwaną definicję obszaru roboczego z commands. Używaj do układów wielopanelowych, własnych katalogów roboczych i poleceń startowych."workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically."setting": Zmienia jedno ustawienie w globalnym pliku cmux.json, na przykład przełącza ustawienie true/false albo przechodzi przez listę wartości. Zobacz Akcje ustawień poniżej."settingPreset": Stosuje w jednym kroku nazwaną grupę ustawień z settingPresets.
Pola akcji
title: Tytuł wiersza Command Palette, etykieta przycisku, tytuł elementu menu i tytuł prośby o zaufanie, chyba że wpis go zastępuje.subtitle/description: Tekst pomocniczy w Command Palette. description jest akceptowane jako alias dla subtitle.keywords: Dodatkowe hasła wyszukiwania dla Command Palette.palette: Domyślnie true dla akcji niestandardowych. Ustaw false, aby ukryć akcję w Command Palette, pozostawiając ją dostępną gdzie indziej.shortcut: Opcjonalny skrót akcji, używający tej samej składni pojedynczego skrótu lub dwustopniowego chordu co skróty ustawień.target: Tylko dla akcji command i agent. Użyj currentTerminal albo newTabInCurrentPane.confirm: Pytaj przed uruchomieniem akcji.newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.
Zachowanie Command Palette
Command Palette czyta rozstrzygnięty rejestr akcji. ID akcji niestandardowych są dodawane jako wiersze, gdy palette nie jest false. Starsze commands są automatycznie dodawane jako wiersze niestandardowe, chyba że istnieje już akcja z tym samym wygenerowanym ID. Wbudowane polecenia zachowują zwykłe etykiety, ale zastąpienie wbudowanego ID, takiego jak cmux.newTerminal, zmienia zachowanie wspólnego punktu wejścia.
Akcje ustawień
Akcja ustawienia podaje path ustawienia i dokładnie jedno z: set (zapisuje wartość), toggle: true (przełącza ustawienie true/false), cycle (przechodzi do następnej wartości z listy, a po ostatniej wraca do pierwszej) albo unset: true (usuwa klucz z cmux.json, więc obowiązuje wartość z okna Ustawienia lub wartość domyślna). toggle i cycle zaczynają od wartości, której cmux aktualnie używa, także tej ustawionej w oknie Ustawienia. Akcja settingPreset stosuje wpis z settingPresets, czyli częściowy cmux.json, którego zagnieżdżone obiekty są scalane klucz po kluczu. cmux przed zapisem sprawdza każdą zmianę ze schematem, zachowuje komentarze i pozostałe klucze, a potem od razu stosuje zmianę. Akcje ustawień i presety działają tylko z globalnego cmux.json i pakietów, do których się on odwołuje; konfiguracje projektu nie mogą ich deklarować.
{
"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 }
}
}
}Te same zmiany działają z terminala: cmux config set terminal.scrollSpeed 1.4, cmux config toggle fileEditor.wordWrap i cmux config preset sidebar.quiet.
Z confirm: true cmux pyta przed zapisem i pokazuje odpowiadające polecenie cmux config. Ścieżki są dzielone przy każdym znaku ".", więc klucza, który sam zawiera "." (np. wpisu workspaceGroups.byCwd dla ~/src/app.web), nie da się zmienić w ten sposób. Edytuj go bezpośrednio w cmux.json.
Niestandardowe akcje przycisku plus
Użyj ui.newWorkspace.action, aby nadpisać działanie przycisku plus. Użyj ui.newWorkspace.contextMenu (lub aliasu rightClick), aby zdefiniować uporządkowane menu prawego kliknięcia. Wpisami menu mogą być ID akcji, obiekty akcji albo { "type": "separator" }. Gdy nie ustawiono, menu wyświetla cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L) z bieżącymi skrótami. Pozycje chmurowe pojawiają się tylko po włączeniu Cloud Machines. New Cloud Workspace używa maszyny ostatnio wybranego obszaru Cloud, a następnie pierwszej maszyny na prawym pasku bocznym; jeśli nie ma dostępnej maszyny, otwiera 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
}
]
}
}
]
}
}
}
]
}Ten przykład sprawia, że zwykłe kliknięcie plus uruchamia akcję worktree-agents. Polecenie obszaru roboczego z commands używa widocznego terminala przygotowującego, aby najpierw utworzyć Git worktree. Codex i Claude startują jednocześnie, czekają na plik stanu dla obszaru roboczego, a następnie przechodzą do utworzonego katalogu przed 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.
Pełny przykład
{
"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"
}
]
}