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

Lokalne akcje i polecenia zastępują globalne wpisy o tym samym ID lub nazwie.

Edytuj cmux.json, a następnie naciśnij Cmd+Shift+, albo uruchom cmux reload-config, aby zastosować zmiany.

Jeśli konfiguracja projektu lub globalna zawiera błąd schematu, cmux przełącza się na następną poprawną konfigurację i pokazuje w Command Palette wiersz **cmux.json Schema Error**. Wybierz go, aby otworzyć plik konfiguracji.

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

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

### Pola polecenia powłoki

-   `name`: Wymagana, niepusta etykieta, którą wybierasz w Command Palette
-   `command`: Tekst powłoki, który cmux wpisuje do aktywnego terminala i uruchamia
-   `description`: Opcjonalny tekst dodatkowy wyświetlany obok wpisu
-   `keywords`: Dodatkowe słowa, które mają pasować do tego wpisu podczas wyszukiwania w Command Palette
-   `confirm`: 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.

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

### Pola obiektu workspace

-   `name`: Tytuł workspace'u; jeśli go brak, używana jest nazwa polecenia
-   `cwd`: Katalog bazowy workspace'u; cwd każdej karty jest rozwiązywane względem niego
-   `layout`: Węzeł główny drzewa układu opisanego poniżej
-   `color`: Kolor na pasku bocznym jako szesnastkowe #RRGGBB lub nazwa koloru workspace'u
-   `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

### 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 panelem
-   `split`: 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ślnego
-   `focus`: Ustaw na true, aby po zbudowaniu układu fokus klawiatury trafił na tę kartę
-   `command`: Tylko terminale: tekst powłoki uruchamiany zaraz po otwarciu terminala
-   `url`: Tylko przeglądarki: strona do załadowania
-   `cwd`: 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

Rejestr akcji to funkcja nightly. Zainstaluj najnowszy build nightly przed użyciem `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.

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

### 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 lokalne dla projektu od razu pojawiają się na pasku kart powierzchni i w Command Palette. Pierwsze uruchomienie nadal prosi o zaufanie. Zaufanie dotyczy dokładnego fingerprintu akcji, a nie repozytorium. Lokalne dla projektu ikony obrazów pozostają zablokowane, dopóki ta akcja nie zostanie zaufana.

## 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ć.

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

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.

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

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:

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

## Pełny przykład

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

Canonical: https://cmux.com/pl/docs/custom-commands

Documentation index: https://cmux.com/llms.txt
