# Prilagođene komande i akcije

U cmux.json učite cmux vlastitim rutinama: shell komandama koje često pokrećete, radnim prostorima koji se otvaraju s unaprijed postavljenim rasporedom terminala i preglednika, te akcijama koje možete vezati za prečice, dugmad na traci kartica i komandnu paletu. Držite datoteku u .cmux/cmux.json unutar projekta, u ~/.config/cmux/cmux.json za sve projekte ili na oba mjesta.

## Gdje cmux čita cmux.json

Unose može dati projektna datoteka, korisnička datoteka ili obje. Za projektne datoteke cmux počinje od trenutnog direktorija i provjerava i svaki nadređeni direktorij iznad njega.

-   **Projekat:** `./.cmux/cmux.json` (pronalazi se pretragom prema gore od radnog direktorija; ima prednost nad korisničkom datotekom)
-   **Rezervna lokalna:** `./cmux.json` (i dalje je podržano za postojeće repozitorije)
-   **Za cijelog korisnika:** `~/.config/cmux/cmux.json` (zajednička za sve projekte; daje sve što projektna datoteka ostavi nedefinisanim)

Lokalne akcije i komande nadjačavaju globalne unose s istim ID-om ili imenom.

Uredite cmux.json, zatim pritisnite Cmd+Shift+, ili pokrenite cmux reload-config da primijenite promjene.

Ako projektna ili globalna konfiguracija ima grešku u shemi, cmux se vraća na sljedeću važeću konfiguraciju i prikazuje red **cmux.json Schema Error** u Command Palette. Izaberi ga da otvoriš konfiguracijsku datoteku.

## Shell komande

Najmanji unos je ime plus command string. Kada ga odaberete u komandnoj paleti, taj string se upisuje u terminal koji ima fokus i izvršava.

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

### Polja shell komande

-   `name`: Obavezna oznaka koja ne smije biti prazna, a koju birate iz komandne palete
-   `command`: Shell tekst koji cmux upisuje u aktivni terminal i izvršava
-   `description`: Opcionalni sporedni tekst koji se prikazuje uz unos
-   `keywords`: Dodatne riječi po kojima se ovaj unos treba pronaći kada pretražujete komandnu paletu
-   `confirm`: Postavite na true da biste svaki put prije izvršavanja dobili upit za potvrdu

Shell komanda se izvršava tamo gdje se aktivni terminal trenutno nalazi. Kada komandi treba predvidljiva početna tačka, započnite je sa `cd "$(git rev-parse --show-toplevel)" &&` da pređete na vrh Git repozitorija, ili sa `cd /some/folder &&` da je vežete za fiksni direktorij.

## Komande koje otvaraju radni prostor

Ako komandi date workspace objekat umjesto command stringa, ona umjesto toga otvara novi radni prostor, uređen kao stablo podijeljenih panela s terminalima i preglednicima. Unos mora imati tačno jedno od ta dva.

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

### Polja workspace objekta

-   `name`: Naslov radnog prostora; ako nije naveden, koristi se ime komande
-   `cwd`: Osnovni direktorij radnog prostora; cwd svake kartice razrješava se u odnosu na njega
-   `layout`: Korijenski čvor stabla rasporeda opisanog ispod
-   `color`: Boja u bočnoj traci, kao #RRGGBB hex vrijednost ili naziv boje radnog prostora
-   `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

### Kada je radni prostor već otvoren

Postavite restart na komandi da odredite šta se dešava ako radni prostor s istim imenom već postoji:

-   `"new"`: Kreiraj novi radni prostor (zadano)
-   `"confirm"`: Prvo pitaj, a zatim ga zamijeni ako se složite
-   `"recreate"`: Odmah ga zamijeni bez upita
-   `"ignore"`: Prebaci na postojeći radni prostor

## Opisivanje rasporeda

Raspored je stablo. Svaki unutrašnji čvor dijeli svoju površinu na dva dijela, a svaki list je panel koji sadrži kartice.

### Čvorovi podjele

Podjela dijeli svoju površinu na dva dijela:

-   `direction`: `"horizontal"` ili `"vertical"`
-   `children`: Niz od tačno dva čvora, od kojih je svaki nova podjela ili panel
-   `split`: Gdje se nalazi razdjelnik, kao udio površine. Zadano je 0.5; vrijednosti izvan raspona od 0.1 do 0.9 se ograničavaju

### Čvorovi panela

Panel je list stabla. Njegov niz surfaces navodi kartice s kojima se otvara i mora sadržavati barem jedan unos.

## Površine

Svaki unos u nizu surfaces panela otvara jednu karticu, koja je ili terminal ili preglednik:

-   `type`: `"terminal"` ili `"browser"`
-   `name`: Naslov kartice koji se prikazuje umjesto zadanog
-   `focus`: Postavite na true da ova kartica dobije fokus tastature nakon što se raspored izgradi
-   `command`: Samo terminali: shell tekst koji se izvršava čim se terminal otvori
-   `url`: Samo preglednici: stranica koja se učitava
-   `cwd`: Početni direktorij za ovu karticu, razriješen prema pravilima ispod
-   `env`: Objekat s dodatnim imenima i vrijednostima varijabli okruženja

### Kako se razrješavaju cwd vrijednosti

-   `~/path`: razrješava se unutar vašeg početnog direktorija
-   Putanja koja počinje sa /: koristi se doslovno
-   `./subdir`: dodaje se na direktorij radnog prostora
-   `.` ili nije postavljeno: nasljeđuje direktorij radnog prostora

## Struktura datoteke

Registar akcija je nightly funkcija. Instaliraj najnoviji nightly build prije korištenja `actions`, `shortcut` ili `ui.surfaceTabBar.buttons`.

`commands` i dalje definiraju višekratne shell komande i rasporede workspacea. Nightly buildovi dodaju registar `actions`. Akcije su javni ID-jevi koje dijele surface tab bar, Command Palette i prečice na nivou akcije.

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

### Nightly registar akcija

`actions` mapira stabilne ID-jeve na ponašanje koje se može pokrenuti. Koristi ugrađene ID-jeve `cmux.newTerminal`, `cmux.newBrowser`, `cmux.splitRight` i `cmux.splitDown` da zamijeniš zadane vrijednosti. Koristi vlastite ID-jeve za projektne alate.

`palette` je zadano `true`. Postavi na `false` da sakriješ akciju iz Command Palette, ali je ostaviš dostupnom surface tab baru ili prečici. `shortcut` koristi istu sintaksu kao prečice u postavkama, na primjer `cmd+shift+c` ili `["cmd+k", "cmd+c"]`.

`ui.surfaceTabBar.buttons` zamjenjuje zadanu listu dugmadi kada je prisutan. Izostavi ugrađeni ID da ga sakriješ. Ikone uvijek koriste oblik objekta: `{ "type": "symbol", "name": "play.circle" }`, `{ "type": "emoji", "value": "🧪", "scale": 0.9 }` ili `{ "type": "image", "path": "./icons/codex.svg" }`. Putanje slika su relativne prema konfiguracijskoj datoteci. Emoji `scale` je opcionalan i zadano je `1`. Podržani su SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO i ICNS.

Svaki unos dugmeta može biti string ID-ja akcije ili objekat dugmeta. Koristi objekat dugmeta kada želiš istu akciju s drugačijom oznakom na površini, ikonom ili tooltipom. Razriješeni naslov dugmeta koristi se i kao naslov upita za povjerenje.

Stavi sve approval ili permission flagove direktno u string komande koju zaista želiš pokrenuti. Zadani cilj akcije je `newTabInCurrentPane`, pa je čest obrazac otvoriti novi terminalski tab u trenutnom panelu i tamo pokrenuti Codex, Claude Code ili OpenCode.

Akcije lokalne za projekat odmah se pojavljuju u surface tab baru i Command Palette. Prvo pokretanje i dalje traži povjerenje. Povjerenje se veže za tačan fingerprint akcije, a ne za repo. Ikone slika lokalne za projekat ostaju zaključane dok se toj akciji ne ukaže povjerenje.

## Prilagođene akcije i Command Palette

Unos `actions` je ponovo upotrebljiva stvar koju cmux izvršava. Koristite akcije kada isto ponašanje treba biti dostupno iz Command Palette, površinske trake tabova, prečica ili menija plus dugmeta. Zadržite `commands` za ponovo upotrebljive shell komande i rasporede radnih prostora. Postavite `palette` na false kada akcija ne treba biti u Command Palette.

### Tipovi akcija

-   `"command"`: Pokreće shell tekst u terminalu. Koristite target da izaberete trenutni terminal ili novi tab u trenutnom panelu.
-   `"agent"`: Pokreće podržanog programerskog agenta. Trenutno podržava codex i claude, uz opcionalne argumente.
-   `"builtin"`: Alias za ugrađenu cmux akciju kao što su cmux.newTerminal, cmux.newBrowser, cmux.splitRight ili cmux.splitDown. Ugrađene akcije kopiranja: cmux.copyWorkingDirectory kopira radni direktorij terminala, cmux.copyProjectRoot kopira korijen njegovog git repozitorija (ili radni direktorij izvan repozitorija), a cmux.copyScreen kopira vidljivi ekran. U SSH, cloud ili udaljenom tmux radnom prostoru cmux.copyProjectRoot kopira udaljeni radni direktorij, jer cmux ne može pronaći git repozitorij na drugom hostu.
-   `"workspaceCommand"`: Pokreće imenovanu definiciju radnog prostora iz commands. Koristite za rasporede s više panela, prilagođene radne direktorije i početne komande.
-   `"workspace"`: Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically.
-   `"setting"`: Mijenja jednu postavku u vašem globalnom cmux.json, na primjer uključuje ili isključuje true/false postavku ili prolazi kroz listu vrijednosti. Pogledajte Akcije postavki ispod.
-   `"settingPreset"`: Primjenjuje imenovanu grupu postavki iz settingPresets u jednom koraku.

### Polja akcije

-   `title`: Naslov reda u Command Palette, oznaka dugmeta, naslov stavke menija i naslov upita za povjerenje, osim ako ga unos ne nadjača.
-   `subtitle` / `description`: Sekundarni tekst u Command Palette. description se prihvata kao alias za subtitle.
-   `keywords`: Dodatni pojmovi za pretragu u Command Palette.
-   `palette`: Podrazumijevano je true za prilagođene akcije. Postavite false da sakrijete akciju iz Command Palette, a da ostane dostupna drugdje.
-   `shortcut`: Opcionalna prečica akcije, sa istom sintaksom jednog pritiska ili dvostepenog niza kao prečice u postavkama.
-   `target`: Samo za command i agent akcije. Koristite currentTerminal ili newTabInCurrentPane.
-   `confirm`: Zatraži potvrdu prije pokretanja akcije.
-   `newWorkspaceMenu`: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.

### Ponašanje Command Palette

Command Palette čita razriješeni registar akcija. ID-jevi prilagođenih akcija dodaju se kao redovi kada `palette` nije false. Stare `commands` automatski se dodaju kao prilagođeni redovi, osim ako akcija s istim generisanim ID-om već postoji. Ugrađene komande zadržavaju normalne oznake, ali nadjačavanje ugrađenog ID-a kao što je `cmux.newTerminal` mijenja ponašanje iza zajedničke ulazne tačke.

### Akcije postavki

Akcija postavke navodi `path` postavke i tačno jedno od: `set` (upisuje vrijednost), `toggle: true` (prebacuje true/false postavku), `cycle` (prelazi na sljedeću vrijednost u listi, a nakon posljednje kreće ispočetka) ili `unset: true` (uklanja ključ iz cmux.json, pa važi vrijednost iz prozora Postavke ili zadana vrijednost). toggle i cycle polaze od vrijednosti koju cmux trenutno koristi, uključujući onu postavljenu u prozoru Postavke. Akcija settingPreset primjenjuje unos iz `settingPresets`, djelimični cmux.json čiji se ugniježđeni objekti spajaju ključ po ključ. cmux prije spremanja provjerava svaku promjenu prema shemi, zadržava vaše komentare i ostale ključeve i odmah primjenjuje promjenu. Akcije postavki i preseti rade samo iz vašeg globalnog cmux.json i paketa na koje on upućuje; projektne konfiguracije ih ne mogu deklarisati.

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

Iste promjene rade i iz terminala: `cmux config set terminal.scrollSpeed 1.4`, `cmux config toggle fileEditor.wordWrap` i `cmux config preset sidebar.quiet`.

Uz `confirm: true`, cmux pita prije spremanja i prikazuje odgovarajuću cmux config komandu. Putanje se dijele na svakoj ".", pa se ključ koji i sam sadrži "." (npr. unos `workspaceGroups.byCwd` za ~/src/app.web) ne može promijeniti na ovaj način. Uredite ga direktno u cmux.json.

## Prilagođene akcije plus dugmeta

Koristi `ui.newWorkspace.action` da zamijeniš ono što plus dugme radi. Koristi `ui.newWorkspace.contextMenu` (ili alias `rightClick`) da definiraš uređeni meni desnog klika. Stavke menija mogu biti ID-jevi akcija, objekti akcija ili `{ "type": "separator" }`. Kada nije postavljeno, meni prikazuje cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L), sa trenutnim prečicama. Stavke oblaka prikazuju se samo kada je Cloud Machines uključen. New Cloud Workspace koristi mašinu posljednjeg odabranog Cloud workspacea, zatim prvu mašinu na desnoj bočnoj traci; ako nema dostupne mašine, otvara 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
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}
```

Ovaj primjer čini da običan klik na plus pokrene akciju `worktree-agents`. Komanda radnog prostora iz `commands` koristi vidljiv terminal za pripremu da prvo napravi Git `worktree`. Codex i Claude se pokreću istovremeno, čekaju datoteku stanja specifičnu za radni prostor, zatim prelaze u kreirani direktorij prije 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`.

## Potpuni primjer

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/bs/docs/custom-commands

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