Personalização e AdministraçãoComandos e ações
Personalização e Administração

Comandos e ações personalizados

No cmux.json você ensina ao cmux suas rotinas: comandos de shell frequentes, workspaces com terminais e navegadores já organizados e ações próprias. Você pode associar essas ações a atalhos, a botões da barra de abas e à Command Palette. Mantenha um em .cmux/cmux.json dentro de um projeto, em ~/.config/cmux/cmux.json para todos os projetos, ou nos dois lugares.

Onde o cmux lê o cmux.json

As entradas podem vir de um arquivo de projeto, de um arquivo do usuário ou de ambos. Para arquivos de projeto, o cmux começa no diretório atual e também verifica cada diretório pai acima dele.

  • Projeto: ./.cmux/cmux.json (encontrado buscando para cima a partir do diretório de trabalho; tem prioridade sobre o arquivo do usuário)
  • Local de fallback: ./cmux.json (ainda compatível com repositórios existentes)
  • Do usuário: ~/.config/cmux/cmux.json (compartilhado por todos os projetos; fornece tudo o que um arquivo de projeto deixa indefinido)
Ações e comandos locais substituem entradas globais com o mesmo ID ou nome.

Edite cmux.json e depois pressione Cmd+Shift+, ou execute cmux reload-config para aplicar as alterações.

Se uma configuração de projeto ou global tiver um erro de esquema, o cmux volta para a próxima configuração válida e mostra uma linha cmux.json Schema Error na Command Palette. Selecione-a para abrir o arquivo de configuração.

Comandos de shell

A menor entrada é um nome mais uma string command. Ao escolhê-la na Command Palette, essa string é digitada no terminal que está em foco e executada.

cmux.json
{
  "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 comando de shell

  • name: Rótulo obrigatório e não vazio que você escolhe na Command Palette
  • command: O texto de shell que o cmux digita no terminal em foco e executa
  • description: Texto secundário opcional exibido ao lado da entrada
  • keywords: Palavras extras que devem corresponder a esta entrada quando você pesquisa na Command Palette
  • confirm: Defina como true para receber um pedido de confirmação antes de cada execução

Um comando de shell é executado onde quer que o terminal em foco esteja no momento. Quando o comando precisa de um ponto de partida previsível, comece-o com cd "$(git rev-parse --show-toplevel)" && para ir à raiz do repositório Git, ou com cd /some/folder && para fixá-lo em uma pasta específica.

Comandos que abrem um workspace

Dê a um comando um objeto workspace no lugar de uma string command e ele abrirá um novo workspace, organizado como uma árvore de painéis divididos com terminais e navegadores. Cada entrada precisa de exatamente um dos dois.

cmux.json
{
  "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 um objeto workspace

  • name: Título do workspace; na ausência dele, usa o nome do comando
  • cwd: Diretório base do workspace; o cwd de cada aba é resolvido em relação a ele
  • layout: O nó raiz da árvore de layout descrita abaixo
  • color: Cor na barra lateral, em hexadecimal #RRGGBB ou como nome de uma cor de workspace
  • env: Environment variables inherited by every shell in the workspace
  • setup: Bootstrap command sent to the workspace's first terminal before that terminal's own command

Quando o workspace já está aberto

Defina restart no comando para decidir o que acontece se já existir um workspace com o mesmo nome:

  • "new": Criar um novo workspace (padrão)
  • "confirm": Perguntar primeiro e substituí-lo se você concordar
  • "recreate": Substituí-lo imediatamente, sem perguntar
  • "ignore": Mudar para o workspace existente

Descrevendo um layout

Um layout é uma árvore. Cada nó interno divide sua área em duas, e cada folha é um painel que contém abas.

Nós de divisão

Uma divisão separa sua área em duas partes:

  • direction: "horizontal" ou "vertical"
  • children: Um array com exatamente dois nós, cada um sendo outra divisão ou um painel
  • split: Onde fica o divisor, como fração da área. O padrão é 0.5; valores fora do intervalo de 0.1 a 0.9 são ajustados a esses limites

Nós de painel

Um painel é uma folha da árvore. Seu array surfaces lista as abas com que ele abre e precisa conter pelo menos uma entrada.

Superfícies

Cada entrada no array surfaces de um painel abre uma aba, que é um terminal ou um navegador:

  • type: "terminal" ou "browser"
  • name: Título da aba exibido no lugar do padrão
  • focus: Defina como true para dar o foco do teclado a esta aba depois que o layout for montado
  • command: Somente terminais: texto de shell a executar assim que o terminal abrir
  • url: Somente navegadores: a página a carregar
  • cwd: Diretório inicial desta aba, resolvido pelas regras abaixo
  • env: Um objeto com nomes e valores de variáveis de ambiente adicionais

Como os valores de cwd são resolvidos

  • ~/path: resolvido dentro da sua pasta pessoal
  • Um caminho que começa com /: usado literalmente
  • ./subdir: anexado ao diretório do workspace
  • . ou não definido: herda o diretório do workspace

Estrutura do arquivo

O registro de ações é um recurso nightly. Instale o build nightly mais recente antes de usar actions, shortcut ou ui.surfaceTabBar.buttons.

commands ainda define comandos shell reutilizáveis e layouts de workspace. Builds nightly adicionam um registro actions. Ações são os IDs públicos compartilhados pela barra de abas de superfície, Command Palette e atalhos no nível da ação.

cmux.json
{
  "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 ações nightly

actions mapeia IDs estáveis para comportamentos executáveis. Use os IDs integrados cmux.newTerminal, cmux.newBrowser, cmux.splitRight e cmux.splitDown para sobrescrever os padrões. Use seus próprios IDs para ferramentas específicas do projeto.

palette usa true por padrão. Defina como false para ocultar uma ação da Command Palette, mantendo-a disponível na barra de abas de superfície ou por um atalho. shortcut usa a mesma sintaxe dos atalhos de configurações, por exemplo cmd+shift+c ou ["cmd+k", "cmd+c"].

ui.surfaceTabBar.buttons substitui a lista padrão de botões quando está presente. Omita um ID integrado para ocultá-lo. Ícones sempre usam formato de objeto: { "type": "symbol", "name": "play.circle" }, { "type": "emoji", "value": "🧪", "scale": 0.9 } ou { "type": "image", "path": "./icons/codex.svg" }. Caminhos de imagem são relativos ao arquivo de configuração. O scale de emoji é opcional e o padrão é 1. SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO e ICNS são compatíveis.

Cada entrada de botão pode ser uma string de ID de ação ou um objeto de botão. Use um objeto de botão quando quiser a mesma ação com outro rótulo de superfície, ícone ou tooltip. O título resolvido do botão também é usado como título do prompt de confiança.

Coloque qualquer flag de aprovação ou permissão diretamente na string de comando que você realmente quer executar. O destino padrão da ação é newTabInCurrentPane, então o padrão comum é abrir uma nova aba de terminal no painel atual e iniciar Codex, Claude Code ou OpenCode ali.

Ações locais do projeto aparecem imediatamente na barra de abas de superfície e na Command Palette. A primeira execução ainda pede confiança. A confiança vale para a impressão digital exata da ação, não para o repositório. Ícones de imagem locais do projeto ficam bloqueados até que essa ação seja confiável.

Ações personalizadas e Command Palette

Uma entrada actions é a unidade reutilizável que o cmux executa. Use ações quando o mesmo comportamento deve estar disponível na Command Palette, na barra de abas de superfície, em atalhos ou no menu do botão de mais. Mantenha commands para comandos shell reutilizáveis e layouts de workspace. Defina palette como false quando uma ação não deve aparecer na Command Palette.

Tipos de ação

  • "command": Executa texto shell em um terminal. Use target para escolher o terminal atual ou uma nova aba no painel atual.
  • "agent": Inicia um agente de programação compatível. Hoje oferece suporte a codex e claude, com argumentos opcionais.
  • "builtin": Cria um alias para uma ação integrada do cmux, como cmux.newTerminal, cmux.newBrowser, cmux.splitRight ou cmux.splitDown. Ações integradas de cópia: cmux.copyWorkingDirectory copia o diretório de trabalho do terminal, cmux.copyProjectRoot copia a raiz do repositório git (ou o diretório de trabalho fora de um repositório) e cmux.copyScreen copia a tela visível. Em um workspace SSH, na nuvem ou de tmux remoto, cmux.copyProjectRoot copia o diretório de trabalho remoto, porque o cmux não consegue consultar o repositório git no outro host.
  • "workspaceCommand": Executa uma definição de workspace nomeada em commands. Use para layouts com vários painéis, diretórios de trabalho personalizados e comandos de inicialização.
  • "workspace": Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically.
  • "setting": Altera uma configuração no seu cmux.json global, por exemplo para alternar uma configuração true/false ou percorrer uma lista de valores. Veja Ações de configuração abaixo.
  • "settingPreset": Aplica de uma vez um grupo nomeado de configurações definido em settingPresets.

Campos da ação

  • title: Título da linha na Command Palette, rótulo do botão, título do item de menu e título do prompt de confiança, a menos que uma entrada substitua.
  • subtitle / description: Texto secundário na Command Palette. description é aceito como alias de subtitle.
  • keywords: Termos de busca adicionais para a Command Palette.
  • palette: O padrão é true para ações personalizadas. Defina false para ocultar a ação da Command Palette mantendo-a chamável de outros lugares.
  • shortcut: Atalho opcional da ação, usando a mesma sintaxe de tecla única ou acorde de dois passos dos atalhos das configurações.
  • target: Somente para ações command e agent. Use currentTerminal ou newTabInCurrentPane.
  • confirm: Pede confirmação antes de executar a ação.
  • newWorkspaceMenu: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.

Comportamento da Command Palette

A Command Palette lê o registro de ações resolvido. IDs de ações personalizadas são adicionados como linhas quando palette não é false. commands legados são adicionados automaticamente como linhas personalizadas, a menos que uma ação com o mesmo ID gerado já exista. Comandos integrados mantêm seus rótulos normais, mas substituir um ID integrado como cmux.newTerminal altera o comportamento por trás dessa entrada compartilhada.

Ações de configuração

Uma ação de configuração indica o path de uma configuração e exatamente um entre set (grava um valor), toggle: true (alterna uma configuração true/false), cycle (avança para o próximo valor de uma lista, voltando ao primeiro depois do último) ou unset: true (remove a chave do cmux.json, para que valha o valor da janela Configurações ou o padrão). toggle e cycle partem do valor que o cmux está usando, inclusive um definido na janela Configurações. Uma ação settingPreset aplica uma entrada de settingPresets, um cmux.json parcial cujos objetos aninhados são mesclados chave por chave. O cmux valida cada alteração com o esquema antes de salvar, mantém seus comentários e as demais chaves e aplica a alteração na hora. Ações de configuração e presets só rodam a partir do seu cmux.json global e dos pacotes que ele referencia; configurações de projeto não podem declará-los.

~/.config/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 }
    }
  }
}

As mesmas alterações funcionam a partir de um terminal: cmux config set terminal.scrollSpeed 1.4, cmux config toggle fileEditor.wordWrap e cmux config preset sidebar.quiet.

Com confirm: true, o cmux pergunta antes de salvar e mostra o comando cmux config equivalente. Os caminhos são divididos em cada ".", então uma chave que contém "." (como uma entrada de workspaceGroups.byCwd para ~/src/app.web) não pode ser alterada dessa forma. Edite-a diretamente no cmux.json.

Ações personalizadas do botão de mais

Use ui.newWorkspace.action para sobrescrever o que o botão de mais faz. Use ui.newWorkspace.contextMenu (ou o alias rightClick) para definir o menu ordenado do clique direito. Entradas de menu podem ser IDs de ação, objetos de ação ou { "type": "separator" }. Quando não definido, o menu lista cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L), cada um com seu atalho atual. As opções de nuvem aparecem apenas quando Cloud Machines está habilitado. New Cloud Workspace usa a máquina do espaço de trabalho Cloud selecionado mais recentemente e depois a primeira na barra lateral direita; se não houver uma máquina utilizável, abre o New Cloud Machine.

cmux.json
{
  "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 exemplo faz o clique normal no botão de mais executar a ação worktree-agents. O comando de workspace em commands usa um terminal de preparação visível para criar primeiro o worktree do Git. Codex e Claude iniciam ao mesmo tempo, esperam o arquivo de estado específico do workspace e então entram no diretório criado 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:

cmux.json
{
  "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.

Exemplo completo

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"
    }
  ]
}