Comandos y acciones personalizados
En cmux.json usted enseña a cmux sus rutinas: comandos de shell frecuentes, workspaces con terminales y navegadores ya dispuestos, y acciones propias. Puede asignar esas acciones a atajos, a botones de la barra de pestañas y a la Command Palette. Coloque un archivo en .cmux/cmux.json dentro de un proyecto, en ~/.config/cmux/cmux.json para todos los proyectos, o en ambos lugares.
Dónde lee cmux el archivo cmux.json
Las entradas pueden venir de un archivo de proyecto, de un archivo de usuario o de ambos. Para los archivos de proyecto, cmux empieza en el directorio actual y también revisa cada directorio superior.
- Proyecto:
./.cmux/cmux.json(se encuentra buscando hacia arriba desde el directorio de trabajo; tiene prioridad sobre el archivo de usuario) - Local de respaldo:
./cmux.json(sigue siendo compatible con repos existentes) - De usuario:
~/.config/cmux/cmux.json(compartido por todos los proyectos; aporta todo lo que un archivo de proyecto deja sin definir)
Edita cmux.json y luego presiona Cmd+Shift+, o ejecuta cmux reload-config para aplicar los cambios.
Comandos de shell
La entrada más sencilla es un nombre más una cadena command. Al elegirla en la Command Palette, esa cadena se escribe en el terminal que tiene el foco y se ejecuta.
{
"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
}
]
}Campos de un comando de shell
name: Etiqueta obligatoria y no vacía que usted elige en la Command Palettecommand: El texto de shell que cmux escribe en el terminal enfocado y ejecutadescription: Texto secundario opcional que se muestra junto a la entradakeywords: Palabras adicionales que deben coincidir con esta entrada al buscar en la Command Paletteconfirm: Establézcalo en true para recibir una solicitud de confirmación antes de cada ejecución
Un comando de shell se ejecuta dondequiera que esté en ese momento el terminal enfocado. Si el comando necesita un punto de partida predecible, empiécelo con cd "$(git rev-parse --show-toplevel)" && para ir a la raíz del repositorio Git, o con cd /some/folder && para fijarlo a una carpeta concreta.
Comandos que abren un workspace
Si le da a un comando un objeto workspace en lugar de una cadena command, abrirá un nuevo workspace, organizado como un árbol de paneles divididos con terminales y navegadores. Cada entrada necesita exactamente uno de los dos.
{
"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"
}
]
}
}
]
}
}
}
]
}Campos de un objeto workspace
name: Título del workspace; si falta, se usa el nombre del comandocwd: Directorio base del workspace; el cwd de cada pestaña se resuelve respecto a éllayout: El nodo raíz del árbol de disposición descrito a continuacióncolor: Color en la barra lateral, como hexadecimal #RRGGBB o nombre de un color de 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
Cuando el workspace ya está abierto
Defina restart en el comando para decidir qué ocurre si ya existe un workspace con el mismo nombre:
"new": Crear un workspace nuevo (por defecto)"confirm": Preguntar primero y reemplazarlo si usted acepta"recreate": Reemplazarlo de inmediato, sin preguntar"ignore": Cambiar al workspace existente
Describir una disposición
Una disposición es un árbol. Cada nodo interno divide su área en dos y cada hoja es un panel que contiene pestañas.
Nodos de división
Una división reparte su área en dos partes:
direction:"horizontal"o"vertical"children: Un array de exactamente dos nodos, cada uno de los cuales es otra división o un panelsplit: Dónde se sitúa el separador, como fracción del área. El valor predeterminado es 0.5; los valores fuera del rango de 0.1 a 0.9 se ajustan a esos límites
Nodos de panel
Un panel es una hoja del árbol. Su array surfaces enumera las pestañas con las que se abre y debe contener al menos una entrada.
Superficies
Cada entrada del array surfaces de un panel abre una pestaña, que es un terminal o un navegador:
type:"terminal"o"browser"name: Título de pestaña que se muestra en lugar del predeterminadofocus: Establézcalo en true para dar el foco del teclado a esta pestaña una vez construida la disposicióncommand: Solo terminales: texto de shell que se ejecuta en cuanto se abre el terminalurl: Solo navegadores: la página que se cargacwd: Directorio inicial de esta pestaña, resuelto con las reglas de abajoenv: Un objeto con nombres y valores de variables de entorno adicionales
Cómo se resuelven los valores de cwd
~/path: se resuelve dentro de su carpeta de inicio- Una ruta que empieza por /: se toma tal cual
./subdir: se añade al directorio del workspace.o sin definir: hereda el directorio del workspace
Estructura del archivo
actions, shortcut o ui.surfaceTabBar.buttons.commands sigue definiendo comandos de shell reutilizables y diseños de espacios de trabajo. Las versiones nightly añaden un registro actions. Las acciones son los ID públicos compartidos por la barra de pestañas de superficie, Command Palette y los atajos de nivel de acción.
{
"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 de acciones nightly
actions asigna ID estables a comportamientos ejecutables. Usa los ID integrados cmux.newTerminal, cmux.newBrowser, cmux.splitRight y cmux.splitDown para sobrescribir los valores predeterminados. Usa tus propios ID para herramientas específicas del proyecto.
palette usa true de forma predeterminada. Cámbialo a false para ocultar una acción de Command Palette sin dejar de permitir su uso desde la barra de pestañas de superficie o un atajo. shortcut usa la misma sintaxis que los atajos de configuración, por ejemplo cmd+shift+c o ["cmd+k", "cmd+c"].
ui.surfaceTabBar.buttons reemplaza la lista predeterminada de botones cuando está presente. Omite un ID integrado para ocultarlo. Los iconos siempre usan forma de objeto: { "type": "symbol", "name": "play.circle" }, { "type": "emoji", "value": "🧪", "scale": 0.9 } o { "type": "image", "path": "./icons/codex.svg" }. Las rutas de imagen son relativas al archivo de configuración. El scale de emoji es opcional y usa 1 de forma predeterminada. Se admiten SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO e ICNS.
Cada entrada de botón puede ser una cadena con un ID de acción o un objeto de botón. Usa un objeto de botón cuando quieras la misma acción con otra etiqueta de superficie, icono o tooltip. El título resuelto del botón también se usa como título de la solicitud de confianza.
Coloca cualquier flag de aprobación o permiso directamente en la cadena de comando que quieras ejecutar. El destino predeterminado de la acción es newTabInCurrentPane, por lo que el patrón común es abrir una nueva pestaña de terminal en el panel actual e iniciar allí Codex, Claude Code u OpenCode.
Acciones personalizadas y Command Palette
Una entrada actions es lo reutilizable que ejecuta cmux. Usa acciones cuando el mismo comportamiento deba estar disponible desde Command Palette, la barra de pestañas de superficie, los atajos o el menú del botón más. Mantén commands para comandos de shell reutilizables y diseños de espacios de trabajo. Define palette como false cuando una acción no deba aparecer en Command Palette.
Tipos de acción
"command": Ejecuta texto de shell en una terminal. Usa target para elegir la terminal actual o una pestaña nueva en el panel actual."agent": Inicia un agente de programación compatible. Hoy admite codex y claude, con argumentos opcionales."builtin": Crea un alias para una acción integrada de cmux como cmux.newTerminal, cmux.newBrowser, cmux.splitRight o cmux.splitDown. Acciones integradas de copia: cmux.copyWorkingDirectory copia el directorio de trabajo del terminal, cmux.copyProjectRoot copia la raíz de su repositorio git (o el directorio de trabajo fuera de uno) y cmux.copyScreen copia la pantalla visible. En un espacio de trabajo SSH, en la nube o de tmux remoto, cmux.copyProjectRoot copia el directorio de trabajo remoto, porque cmux no puede consultar el repositorio git del otro host."workspaceCommand": Ejecuta una definición de espacio de trabajo con nombre desde commands. Úsalo para diseños multipanel, directorios de trabajo personalizados y comandos de inicio."workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically."setting": Cambia un ajuste de tu cmux.json global, por ejemplo para alternar un ajuste true/false o recorrer una lista de valores. Consulta Acciones de ajustes más abajo."settingPreset": Aplica de una vez un grupo de ajustes con nombre definido en settingPresets.
Campos de acción
title: Título de la fila en Command Palette, etiqueta del botón, título del elemento de menú y título del aviso de confianza, salvo que una entrada lo reemplace.subtitle/description: Texto secundario en Command Palette. description se acepta como alias de subtitle.keywords: Términos de búsqueda adicionales para Command Palette.palette: El valor predeterminado es true para acciones personalizadas. Define false para ocultar la acción de Command Palette y mantenerla invocable desde otros lugares.shortcut: Atajo opcional de acción, con la misma sintaxis de una tecla o acorde de dos pasos que los atajos de configuración.target: Solo para acciones command y agent. Usa currentTerminal o newTabInCurrentPane.confirm: Pide confirmación antes de ejecutar la acción.newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.
Comportamiento de Command Palette
Command Palette lee el registro de acciones resuelto. Los ID de acciones personalizadas se agregan como filas cuando palette no es false. Los commands heredados se agregan automáticamente como filas personalizadas, salvo que ya exista una acción con el mismo ID generado. Los comandos integrados conservan sus etiquetas normales, pero reemplazar un ID integrado como cmux.newTerminal cambia el comportamiento detrás de esa entrada compartida.
Acciones de ajustes
Una acción de ajuste indica la path de un ajuste y exactamente uno de set (escribe un valor), toggle: true (alterna un ajuste true/false), cycle (pasa al siguiente valor de una lista y vuelve al primero después del último) o unset: true (elimina la clave de cmux.json para que se aplique el valor de la ventana Configuración o el predeterminado). toggle y cycle parten del valor que cmux está usando, incluido uno que hayas definido en la ventana Configuración. Una acción settingPreset aplica una entrada de settingPresets, un cmux.json parcial cuyos objetos anidados se combinan clave por clave. cmux valida cada cambio con el esquema antes de guardarlo, conserva tus comentarios y las demás claves, y lo aplica de inmediato. Las acciones de ajustes y los presets solo se ejecutan desde tu cmux.json global y los paquetes a los que hace referencia; las configuraciones de proyecto no pueden declararlos.
{
"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 }
}
}
}Los mismos cambios funcionan desde una terminal: cmux config set terminal.scrollSpeed 1.4, cmux config toggle fileEditor.wordWrap y cmux config preset sidebar.quiet.
Con confirm: true, cmux pregunta antes de guardar y muestra el comando cmux config equivalente. Las rutas se dividen en cada ".", así que una clave que contiene "." (como una entrada de workspaceGroups.byCwd para ~/src/app.web) no se puede cambiar de esta forma. Edítala directamente en cmux.json.
Acciones personalizadas del botón de suma
Usa ui.newWorkspace.action para sobrescribir lo que hace el botón de suma. Usa ui.newWorkspace.contextMenu (o el alias rightClick) para definir el menú ordenado del clic derecho. Las entradas del menú pueden ser ID de acción, objetos de acción o { "type": "separator" }. Si no se configura, el menú muestra cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L), cada uno con su atajo actual. Las opciones de la nube solo aparecen si Cloud Machines está habilitado. New Cloud Workspace usa la máquina del espacio de trabajo Cloud seleccionado más recientemente y después la primera de la barra lateral derecha; si no hay una máquina utilizable, abre 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
}
]
}
}
]
}
}
}
]
}Este ejemplo hace que el clic normal en el botón más ejecute la acción worktree-agents. El comando de espacio de trabajo de commands usa una terminal de preparación visible para crear primero el worktree de Git. Codex y Claude se inician al mismo tiempo, esperan el archivo de estado específico del espacio de trabajo y luego entran en el directorio creado antes de 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.
Ejemplo 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"
}
]
}