Comandi e azioni personalizzati
In cmux.json insegni a cmux le tue abitudini: comandi shell frequenti, workspace con terminali e browser già disposti e azioni personalizzate. Puoi associare queste azioni a scorciatoie, a pulsanti della barra dei tab e alla Command Palette. Mettine uno in .cmux/cmux.json dentro un progetto, in ~/.config/cmux/cmux.json per tutti i progetti, oppure in entrambi.
Dove cmux legge cmux.json
Le voci possono arrivare da un file di progetto, da un file a livello utente o da entrambi. Per i file di progetto, cmux parte dalla directory corrente e controlla anche ogni directory superiore.
- Progetto:
./.cmux/cmux.json(trovato cercando verso l’alto a partire dalla directory di lavoro; ha la precedenza sul file a livello utente) - Fallback locale:
./cmux.json(ancora supportato per i repository esistenti) - Livello utente:
~/.config/cmux/cmux.json(condiviso da tutti i progetti; fornisce tutto ciò che un file di progetto lascia indefinito)
Modifica cmux.json, quindi premi Cmd+Shift+, oppure esegui cmux reload-config per applicare le modifiche.
Comandi shell
La voce più semplice è un nome più una stringa command. Selezionandola nella Command Palette, quella stringa viene digitata nel terminale che ha il focus ed eseguita.
{
"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
}
]
}Campi di un comando shell
name: Etichetta obbligatoria e non vuota che scegli nella Command Palettecommand: Il testo shell che cmux digita nel terminale attivo ed eseguedescription: Testo secondario facoltativo mostrato accanto alla vocekeywords: Altre parole che devono corrispondere a questa voce quando cerchi nella Command Paletteconfirm: Impostalo a true per ricevere una richiesta di conferma prima di ogni esecuzione
Un comando shell viene eseguito ovunque si trovi in quel momento il terminale attivo. Se il comando ha bisogno di un punto di partenza prevedibile, inizialo con cd "$(git rev-parse --show-toplevel)" && per spostarti alla radice del repository Git, oppure con cd /some/folder && per vincolarlo a una cartella fissa.
Comandi che aprono un workspace
Se dai a un comando un oggetto workspace al posto di una stringa command, aprirà invece un nuovo workspace, organizzato come un albero di pannelli divisi con terminali e browser. Ogni voce deve avere esattamente uno dei due.
{
"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"
}
]
}
}
]
}
}
}
]
}Campi di un oggetto workspace
name: Titolo del workspace; se manca, si usa il nome del comandocwd: Directory di base del workspace; il cwd di ogni tab viene risolto rispetto a essalayout: Il nodo radice dell’albero di layout descritto più avanticolor: Colore nella barra laterale, come esadecimale #RRGGBB o nome di un colore del workspaceenv: Environment variables inherited by every shell in the workspacesetup: Bootstrap command sent to the workspace's first terminal before that terminal's own command
Quando il workspace è già aperto
Imposta restart nel comando per decidere cosa succede se esiste già un workspace con lo stesso nome:
"new": Crea un nuovo workspace (predefinito)"confirm": Chiedi prima, poi sostituiscilo se confermi"recreate": Sostituiscilo subito, senza chiedere"ignore": Passa al workspace esistente
Descrivere un layout
Un layout è un albero. Ogni nodo interno divide la propria area in due e ogni foglia è un pannello che contiene tab.
Nodi split
Uno split divide la propria area in due parti:
direction:"horizontal"o"vertical"children: Un array di esattamente due nodi, ciascuno dei quali è un altro split o un pannellosplit: Posizione del divisore, come frazione dell’area. Il valore predefinito è 0.5; i valori al di fuori dell’intervallo da 0.1 a 0.9 vengono limitati
Nodi pannello
Un pannello è una foglia dell’albero. Il suo array surfaces elenca i tab con cui si apre e deve contenere almeno una voce.
Superfici
Ogni voce nell’array surfaces di un pannello apre un tab, che è un terminale oppure un browser:
type:"terminal"o"browser"name: Titolo del tab da mostrare al posto di quello predefinitofocus: Impostalo a true per dare il focus della tastiera a questo tab una volta costruito il layoutcommand: Solo terminali: testo shell da eseguire appena il terminale si apreurl: Solo browser: la pagina da caricarecwd: Directory iniziale di questo tab, risolta con le regole qui sottoenv: Un oggetto con nomi e valori di variabili d’ambiente aggiuntive
Come vengono risolti i valori di cwd
~/path: risolto all’interno della tua cartella Inizio- Un percorso che inizia con /: usato così com’è
./subdir: aggiunto in coda alla directory del workspace.o non impostato: eredita la directory del workspace
Struttura del file
actions, shortcut o ui.surfaceTabBar.buttons.commands continua a definire comandi shell riutilizzabili e layout di workspace. Le build nightly aggiungono un registro actions. Le azioni sono gli ID pubblici condivisi dalla barra delle schede di superficie, da Command Palette e dalle scorciatoie a livello di azione.
{
"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"
}
]
}
}
}
}
]
}Registro azioni nightly
actions associa ID stabili a comportamenti eseguibili. Usa gli ID integrati cmux.newTerminal, cmux.newBrowser, cmux.splitRight e cmux.splitDown per sovrascrivere i valori predefiniti. Usa ID personali per gli strumenti specifici del progetto.
palette è true per impostazione predefinita. Impostalo su false per nascondere un’azione da Command Palette mantenendola disponibile nella barra delle schede di superficie o tramite una scorciatoia. shortcut usa la stessa sintassi delle scorciatoie delle impostazioni, ad esempio cmd+shift+c o ["cmd+k", "cmd+c"].
ui.surfaceTabBar.buttons sostituisce l’elenco predefinito dei pulsanti quando è presente. Ometti un ID integrato per nasconderlo. Le icone usano sempre una forma oggetto: { "type": "symbol", "name": "play.circle" }, { "type": "emoji", "value": "🧪", "scale": 0.9 } oppure { "type": "image", "path": "./icons/codex.svg" }. I percorsi delle immagini sono relativi al file di configurazione. Il scale delle emoji è facoltativo e il valore predefinito è 1. Sono supportati SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO e ICNS.
Ogni voce pulsante può essere una stringa ID di azione o un oggetto pulsante. Usa un oggetto pulsante quando vuoi la stessa azione con un’etichetta di superficie, un’icona o un tooltip diverso. Il titolo risolto del pulsante viene usato anche come titolo della richiesta di attendibilità.
Inserisci eventuali flag di approvazione o permesso direttamente nella stringa del comando che vuoi davvero eseguire. Il target predefinito dell’azione è newTabInCurrentPane, quindi lo schema comune è aprire una nuova scheda terminale nel pannello corrente e avviare lì Codex, Claude Code o OpenCode.
Azioni personalizzate e Command Palette
Una voce actions è l’elemento riutilizzabile che cmux esegue. Usa le azioni quando lo stesso comportamento deve essere disponibile da Command Palette, dalla barra delle schede di superficie, dalle scorciatoie o dal menu del pulsante più. Mantieni commands per comandi shell riutilizzabili e layout degli spazi di lavoro. Imposta palette su false quando un’azione deve restare fuori da Command Palette.
Tipi di azione
"command": Esegue testo shell in un terminale. Usa target per scegliere il terminale corrente o una nuova scheda nel pannello corrente."agent": Avvia un agente di programmazione supportato. Oggi supporta codex e claude, con argomenti opzionali."builtin": Crea un alias per un’azione cmux integrata come cmux.newTerminal, cmux.newBrowser, cmux.splitRight o cmux.splitDown. Azioni integrate di copia: cmux.copyWorkingDirectory copia la directory di lavoro del terminale, cmux.copyProjectRoot copia la radice del suo repository git (o la directory di lavoro al di fuori di un repository) e cmux.copyScreen copia lo schermo visibile. In un workspace SSH, cloud o tmux remoto, cmux.copyProjectRoot copia la directory di lavoro remota, perché cmux non può individuare il repository git sull'altro host."workspaceCommand": Esegue una definizione di spazio di lavoro con nome da commands. Usalo per layout multipannello, directory di lavoro personalizzate e comandi di avvio."workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically."setting": Modifica un’impostazione nel tuo cmux.json globale, ad esempio per alternare un’impostazione true/false o scorrere un elenco di valori. Vedi Azioni sulle impostazioni più sotto."settingPreset": Applica in un solo passaggio un gruppo di impostazioni con nome definito in settingPresets.
Campi dell’azione
title: Titolo della riga in Command Palette, etichetta del pulsante, titolo della voce di menu e titolo della richiesta di attendibilità, salvo override di una voce.subtitle/description: Testo secondario in Command Palette. description è accettato come alias di subtitle.keywords: Termini di ricerca aggiuntivi per Command Palette.palette: Il valore predefinito è true per le azioni personalizzate. Imposta false per nascondere l’azione da Command Palette mantenendola richiamabile altrove.shortcut: Scorciatoia opzionale dell’azione, con la stessa sintassi a tasto singolo o accordo in due passaggi delle scorciatoie delle impostazioni.target: Solo per azioni command e agent. Usa currentTerminal o newTabInCurrentPane.confirm: Chiede conferma prima di eseguire l’azione.newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.
Comportamento di Command Palette
Command Palette legge il registro delle azioni risolto. Gli ID delle azioni personalizzate vengono aggiunti come righe quando palette non è false. I vecchi commands vengono aggiunti automaticamente come righe personalizzate, a meno che esista già un’azione con lo stesso ID generato. I comandi integrati mantengono le etichette normali, ma sostituire un ID integrato come cmux.newTerminal cambia il comportamento dietro quel punto di ingresso condiviso.
Azioni sulle impostazioni
Un’azione sulle impostazioni indica il path di un’impostazione ed esattamente uno tra set (scrive un valore), toggle: true (inverte un’impostazione true/false), cycle (passa al valore successivo di un elenco, tornando al primo dopo l’ultimo) o unset: true (rimuove la chiave da cmux.json, così si applica il valore della finestra Impostazioni o quello predefinito). toggle e cycle partono dal valore che cmux sta usando, anche se lo hai impostato nella finestra Impostazioni. Un’azione settingPreset applica una voce di settingPresets, un cmux.json parziale i cui oggetti annidati vengono uniti chiave per chiave. cmux verifica ogni modifica rispetto allo schema prima di salvarla, mantiene i tuoi commenti e le altre chiavi e la applica subito. Le azioni sulle impostazioni e i preset vengono eseguiti solo dal tuo cmux.json globale e dai pacchetti a cui fa riferimento; le configurazioni di progetto non possono dichiararli.
{
"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 }
}
}
}Le stesse modifiche funzionano anche da terminale: cmux config set terminal.scrollSpeed 1.4, cmux config toggle fileEditor.wordWrap e cmux config preset sidebar.quiet.
Con confirm: true, cmux chiede conferma prima di salvare e mostra il comando cmux config equivalente. I percorsi vengono divisi a ogni ".", quindi una chiave che contiene a sua volta "." (come una voce workspaceGroups.byCwd per ~/src/app.web) non si può modificare in questo modo. Modificala direttamente in cmux.json.
Azioni personalizzate del pulsante più
Usa ui.newWorkspace.action per sovrascrivere ciò che fa il pulsante più. Usa ui.newWorkspace.contextMenu (o l’alias rightClick) per definire il menu ordinato del clic destro. Le voci di menu possono essere ID di azione, oggetti azione o { "type": "separator" }. Se non impostato, il menu elenca cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L), ciascuno con la scorciatoia corrente. Le voci cloud appaiono solo quando Cloud Machines è abilitato. New Cloud Workspace usa la macchina dell’ultimo spazio di lavoro Cloud selezionato, poi la prima nella barra laterale destra; se non c’è una macchina utilizzabile, apre 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
}
]
}
}
]
}
}
}
]
}Questo esempio fa sì che il normale clic sul più esegua l’azione worktree-agents. Il comando dello spazio di lavoro da commands usa un terminale di configurazione visibile per creare prima il worktree Git. Codex e Claude partono contemporaneamente, attendono il file di stato specifico dello spazio di lavoro, quindi entrano nella directory creata prima di 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.
Esempio completo
{
"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"
}
]
}