Comandos personalizados

Defina comandos personalizados e layouts de workspace adicionando um arquivo cmux.json à raiz do seu projeto ou ~/.config/cmux/. Os comandos aparecem na paleta de comandos.

Localizações dos arquivos

O cmux procura configuração em dois lugares:

  • Por projeto: ./.cmux/cmux.json - fica no diretório do seu projeto, tem precedência
  • Local de fallback: ./cmux.json - ainda compatível com repositórios existentes
  • Configuração global: ~/.config/cmux/cmux.json - aplica-se a todos os projetos, preenche comandos não definidos localmente
Ações e comandos locais substituem entradas globais com o mesmo ID ou nome.
O registro de ações é um recurso nightly. Instale o build nightly mais recente antes de usar actions, shortcut ou ui.surfaceTabBar.buttons.
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.
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.

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

Esquema

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": "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": { ... }
    }
  ]
}

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 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

  • "builtin": Cria um alias para uma ação integrada do cmux, como cmux.newTerminal, cmux.newBrowser, cmux.splitRight ou cmux.splitDown.
  • "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.
  • "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.

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.

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

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

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.

Comandos simples

Um comando simples executa um comando shell no terminal atualmente focado:

cmux.json
{
  "commands": [
    {
      "name": "Run Tests",
      "keywords": ["test", "check"],
      "command": "npm test",
      "confirm": true
    }
  ]
}

Campos

  • name: Exibido na paleta de comandos (obrigatório)
  • description: Descrição opcional
  • keywords: Termos de pesquisa extras para a paleta de comandos
  • command: Comando shell para executar no terminal focado
  • confirm: Mostrar um diálogo de confirmação antes de executar

Comandos simples são executados no diretório de trabalho atual do terminal focado. Se seu comando depende de caminhos relativos ao projeto, prefixe com cd "$(git rev-parse --show-toplevel)" && para executar a partir da raiz do repositório, ou cd /your/path && para qualquer diretório específico.

Comandos de workspace

Um comando de workspace cria um novo workspace com um layout personalizado de divisões, terminais e painéis do navegador:

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

Campos de workspace

  • name: Nome da aba do workspace (padrão é o nome do comando)
  • cwd: Diretório de trabalho do workspace
  • color: Cor da aba do workspace
  • layout: Árvore de layout definindo divisões e painéis

Comportamento de reinício

Controla o que acontece quando um workspace com o mesmo nome já existe:

  • "new": Criar um novo workspace (padrão)
  • "ignore": Mudar para o workspace existente
  • "recreate": Fechar e recriar sem perguntar
  • "confirm": Perguntar ao usuário antes de recriar

Árvore de layout

A árvore de layout define como os painéis são organizados usando nós de divisão recursivos:

Nó de divisão

Divide o espaço em dois filhos:

  • direction: "horizontal" ou "vertical"
  • split: Posição do divisor de 0.1 a 0.9 (padrão 0.5)
  • children: Exatamente dois nós filhos (divisão ou painel)

Nó de painel

Um nó folha contendo uma ou mais superfícies (abas dentro do painel).

Definição de superfície

Cada superfície em um painel pode ser um terminal ou um navegador:

  • type: "terminal" ou "browser"
  • name: Título de aba personalizado
  • command: Comando shell para executar automaticamente na criação (apenas terminal)
  • cwd: Diretório de trabalho para esta superfície
  • env: Variáveis de ambiente como pares chave-valor
  • url: URL para abrir (apenas navegador)
  • focus: Focar nesta superfície após a criação

Resolução do diretório de trabalho

  • . ou omitido: diretório de trabalho do workspace
  • ./subdir: relativo ao diretório de trabalho do workspace
  • ~/path: expandido para o diretório home
  • Caminho absoluto: usado como está

Exemplo completo

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