# Egendefinerte kommandoer og handlinger

I cmux.json lærer du cmux dine egne rutiner: skallkommandoer du kjører ofte, arbeidsområder som åpnes med et forhåndsinnstilt oppsett av terminaler og nettlesere, og handlinger du kan knytte til snarveier, knapper i fanelinjen og kommandopaletten. Legg en fil i .cmux/cmux.json i et prosjekt, i ~/.config/cmux/cmux.json for alle prosjekter, eller begge steder.

## Hvor cmux leser cmux.json

Oppføringer kan komme fra en prosjektfil, en brukerfil eller begge. For prosjektfiler starter cmux i gjeldende katalog og sjekker også hver overordnet katalog over den.

-   **Prosjekt:** `./.cmux/cmux.json` (finnes ved å søke oppover fra arbeidskatalogen; går foran brukerfilen)
-   **Lokal reserve:** `./cmux.json` (støttes fortsatt for eksisterende repoer)
-   **Brukernivå:** `~/.config/cmux/cmux.json` (delt av alle prosjekter; gir det en prosjektfil lar være udefinert)

Lokale handlinger og kommandoer overstyrer globale oppføringer med samme ID eller navn.

Rediger cmux.json, og trykk deretter Cmd+Shift+, eller kjør cmux reload-config for å bruke endringene.

Hvis en prosjektkonfigurasjon eller global konfigurasjon har en skjemafeil, faller cmux tilbake til neste gyldige konfigurasjon og viser raden **cmux.json Schema Error** i Command Palette. Velg den for å åpne konfigurasjonsfilen.

## Skallkommandoer

Den minste oppføringen er et navn pluss en command-streng. Når du velger den i kommandopaletten, skrives strengen inn i terminalen som har fokus, og kjøres.

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

### Felter for skallkommandoer

-   `name`: Påkrevd etikett som ikke kan være tom, og som du velger i kommandopaletten
-   `command`: Skallteksten som cmux skriver inn i den aktive terminalen og kjører
-   `description`: Valgfri sekundær tekst som vises ved siden av oppføringen
-   `keywords`: Flere ord som skal treffe denne oppføringen når du søker i kommandopaletten
-   `confirm`: Sett til true for å få en bekreftelsesforespørsel hver gang før den kjører

En skallkommando kjøres der den aktive terminalen tilfeldigvis befinner seg. Når kommandoen trenger et forutsigbart utgangspunkt, start den med `cd "$(git rev-parse --show-toplevel)" &&` for å gå til toppen av Git-repositoriet, eller med `cd /some/folder &&` for å låse den til en fast mappe.

## Kommandoer som åpner et arbeidsområde

Gi en kommando et workspace-objekt i stedet for en command-streng, så åpner den et nytt arbeidsområde i stedet, ordnet som et tre av delte paneler med terminaler og nettlesere. En oppføring må ha nøyaktig ett av de to.

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

### Felter i et workspace-objekt

-   `name`: Tittel på arbeidsområdet; faller tilbake til kommandonavnet
-   `cwd`: Grunnkatalog for arbeidsområdet; cwd for hver fane tolkes ut fra den
-   `layout`: Rotnoden i oppsettstreet som er beskrevet nedenfor
-   `color`: Farge i sidefeltet, som #RRGGBB-hex eller navnet på en arbeidsområdefarge
-   `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

### Når arbeidsområdet allerede er åpent

Angi restart på kommandoen for å bestemme hva som skjer hvis et arbeidsområde med samme navn allerede finnes:

-   `"new"`: Opprett et nytt workspace (standard)
-   `"confirm"`: Spør først, og erstatt det deretter hvis du godtar
-   `"recreate"`: Erstatt det med en gang uten å spørre
-   `"ignore"`: Bytt til det eksisterende workspacet

## Beskrive et oppsett

Et oppsett er et tre. Hver indre node deler området sitt i to, og hvert blad er et panel som inneholder faner.

### Delingsnoder

En deling deler området sitt i to deler:

-   `direction`: `"horizontal"` eller `"vertical"`
-   `children`: En array med nøyaktig to noder, der hver er enten en ny deling eller et panel
-   `split`: Hvor skillelinjen står, som en brøkdel av området. Standard er 0.5; verdier utenfor 0.1 til 0.9 begrenses

### Panelnoder

Et panel er et blad i treet. surfaces-arrayen lister fanene panelet åpnes med, og må inneholde minst én oppføring.

## Flater

Hver oppføring i et panels surfaces-array åpner én fane, som enten er en terminal eller en nettleser:

-   `type`: `"terminal"` eller `"browser"`
-   `name`: Fanetittel som vises i stedet for standardtittelen
-   `focus`: Sett til true for å gi denne fanen tastaturfokus når oppsettet er bygget
-   `command`: Bare terminaler: skalltekst som kjøres så snart terminalen åpnes
-   `url`: Bare nettlesere: siden som skal lastes
-   `cwd`: Startkatalog for denne fanen, tolket etter reglene nedenfor
-   `env`: Et objekt med ekstra navn og verdier for miljøvariabler

### Slik tolkes cwd-verdier

-   `~/path`: tolkes innenfor hjemmemappen din
-   En sti som begynner med /: brukes som den er
-   `./subdir`: legges til arbeidsområdets katalog
-   `.` eller ikke angitt: arver arbeidsområdets katalog

## Filstruktur

Handlingsregisteret er en nightly-funksjon. Installer den nyeste nightly-byggingen før du bruker `actions`, `shortcut` eller `ui.surfaceTabBar.buttons`.

`commands` definerer fortsatt gjenbrukbare shellkommandoer og workspace-oppsett. Nightly-bygg legger til et `actions`\-register. Handlinger er de offentlige ID-ene som deles av surface-fanelinjen, Command Palette og handlingssnarveier.

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

`actions` kobler stabile ID-er til kjørbar atferd. Bruk de innebygde ID-ene `cmux.newTerminal`, `cmux.newBrowser`, `cmux.splitRight` og `cmux.splitDown` for å overstyre standardene. Bruk egne ID-er for prosjektspesifikke verktøy.

`palette` er som standard `true`. Sett den til `false` for å skjule en handling fra Command Palette, samtidig som den fortsatt er tilgjengelig i surface-fanelinjen eller via en snarvei. `shortcut` bruker samme syntaks som innstillingssnarveier, for eksempel `cmd+shift+c` eller `["cmd+k", "cmd+c"]`.

`ui.surfaceTabBar.buttons` erstatter standardknapplisten når den finnes. Utelat en innebygd ID for å skjule den. Ikoner bruker alltid objektform: `{ "type": "symbol", "name": "play.circle" }`, `{ "type": "emoji", "value": "🧪", "scale": 0.9 }` eller `{ "type": "image", "path": "./icons/codex.svg" }`. Bildestier er relative til konfigurasjonsfilen. Emoji `scale` er valgfritt og standard er `1`. SVG, PDF, PNG, JPEG, GIF, TIFF, BMP, HEIC, HEIF, WebP, AVIF, ICO og ICNS støttes.

Hver knappeoppføring kan enten være en handlings-ID-streng eller et knappeobjekt. Bruk et knappeobjekt når du vil ha samme handling med en annen surface-etikett, ikon eller tooltip. Den løste knappetittelen brukes også som tittel i tillitsforespørselen.

Legg approval- eller permission-flagg direkte i kommandostrengen du faktisk vil kjøre. Standardmålet for handlingen er `newTabInCurrentPane`, så det vanlige mønsteret er å åpne en ny terminalfane i gjeldende panel og starte Codex, Claude Code eller OpenCode der.

Prosjektlokale handlinger vises umiddelbart i surface-fanelinjen og Command Palette. Første kjøring ber fortsatt om tillit. Tillit gjelder det eksakte handlingsfingeravtrykket, ikke repoet. Prosjektlokale bildeikoner forblir låst til handlingen er godkjent.

## Egendefinerte handlinger og Command Palette

En `actions`\-oppføring er den gjenbrukbare tingen cmux kjører. Bruk handlinger når samme oppførsel skal være tilgjengelig fra Command Palette, overflatefanelinjen, snarveier eller plussknappmenyen. Behold `commands` for gjenbrukbare shell-kommandoer og arbeidsområdeoppsett. Sett `palette` til false når en handling ikke skal vises i Command Palette.

### Handlingstyper

-   `"command"`: Kjører shell-tekst i en terminal. Bruk target for å velge gjeldende terminal eller en ny fane i gjeldende panel.
-   `"agent"`: Starter en støttet kodeagent. I dag støttes codex og claude, med valgfrie argumenter.
-   `"builtin"`: Alias til en innebygd cmux-handling som cmux.newTerminal, cmux.newBrowser, cmux.splitRight eller cmux.splitDown. Innebygde kopihandlinger: cmux.copyWorkingDirectory kopierer terminalens arbeidsmappe, cmux.copyProjectRoot kopierer roten av git-repositoriet (eller arbeidsmappen utenfor et repository), og cmux.copyScreen kopierer den synlige skjermen. I et SSH-, sky- eller eksternt tmux-arbeidsområde kopierer cmux.copyProjectRoot den eksterne arbeidsmappen, fordi cmux ikke kan slå opp git-repositoriet på den andre verten.
-   `"workspaceCommand"`: Kjører en navngitt arbeidsområdedefinisjon fra commands. Bruk dette for flerpane-layouter, egendefinerte arbeidsmapper og oppstartskommandoer.
-   `"workspace"`: Create a workspace from an inline workspace definition, with optional restart behavior. Offered in the new-workspace plus-button menu automatically.
-   `"setting"`: Endrer én innstilling i din globale cmux.json, for eksempel slå en true/false-innstilling av eller på eller bla gjennom en liste med verdier. Se Innstillingshandlinger nedenfor.
-   `"settingPreset"`: Bruker en navngitt gruppe innstillinger fra settingPresets i ett steg.

### Handlingsfelt

-   `title`: Tittel i Command Palette-raden, knappetekst, menypunkttittel og tittel i tillitsdialogen, med mindre en oppføring overstyrer den.
-   `subtitle` / `description`: Sekundærtekst i Command Palette. description godtas som alias for subtitle.
-   `keywords`: Ekstra søkeord for Command Palette.
-   `palette`: Standard er true for egendefinerte handlinger. Sett false for å skjule handlingen fra Command Palette, men fortsatt kunne kalle den andre steder.
-   `shortcut`: Valgfri handlingssnarvei, med samme syntaks for enkelttast eller totrinnsakkord som innstillingssnarveier.
-   `target`: Kun for command- og agent-handlinger. Bruk currentTerminal eller newTabInCurrentPane.
-   `confirm`: Spør før handlingen kjøres.
-   `newWorkspaceMenu`: Set true to offer any action in the new-workspace plus-button menu, or false to hide a workspace action from it.

### Command Palette-oppførsel

Command Palette leser det løste handlingsregisteret. Egendefinerte handlings-ID-er legges til som rader når `palette` ikke er false. Eldre `commands` legges automatisk til som egendefinerte rader med mindre en handling med samme genererte ID allerede finnes. Innebygde kommandoer beholder de vanlige palettetikettene, men overstyring av en innebygd ID som `cmux.newTerminal` endrer oppførselen bak det delte inngangspunktet.

### Innstillingshandlinger

En innstillingshandling angir en `path` til en innstilling og nøyaktig én av `set` (skriv en verdi), `toggle: true` (snu en true/false-innstilling), `cycle` (gå til neste verdi i en liste og start på nytt etter den siste) eller `unset: true` (fjern nøkkelen fra cmux.json, slik at verdien fra Innstillinger-vinduet eller standardverdien gjelder). toggle og cycle starter fra verdien cmux bruker, også en du har satt i Innstillinger-vinduet. En settingPreset-handling bruker en oppføring fra `settingPresets`, en delvis cmux.json der nestede objekter slås sammen nøkkel for nøkkel. cmux kontrollerer hver endring mot skjemaet før lagring, beholder kommentarene dine og andre nøkler og tar i bruk endringen med én gang. Innstillingshandlinger og presets kjører bare fra din globale cmux.json og pakkene den viser til; prosjektkonfigurasjoner kan ikke deklarere dem.

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

De samme endringene fungerer fra en terminal: `cmux config set terminal.scrollSpeed 1.4`, `cmux config toggle fileEditor.wordWrap` og `cmux config preset sidebar.quiet`.

Med `confirm: true` spør cmux før lagring og viser den tilsvarende cmux config-kommandoen. Stier deles ved hvert ".", så en nøkkel som selv inneholder "." (for eksempel en `workspaceGroups.byCwd`\-oppføring for ~/src/app.web), kan ikke endres på denne måten. Rediger den direkte i cmux.json.

## Tilpassede handlinger for plussknappen

Bruk `ui.newWorkspace.action` for å overstyre hva plussknappen gjør. Bruk `ui.newWorkspace.contextMenu` (eller aliaset `rightClick`) for å definere den ordnede høyreklikkmenyen. Menyoppføringer kan være handlings-ID-er, handlingsobjekter eller `{ "type": "separator" }`. Når den ikke er angitt, viser menyen cmux.newWorkspace (⌘N), cmux.newCloudWorkspace (⌘Y), cmux.newCloudMachine (⇧⌘Y), cmux.newTerminal (⌘T), cmux.newBrowser (⇧⌘L), hver med gjeldende snarvei. Skyvalg vises bare når Cloud Machines er aktivert. New Cloud Workspace bruker maskinen til det sist valgte Cloud-arbeidsområdet, deretter den første maskinen i høyre sidefelt; hvis ingen brukbar maskin finnes, åpnes 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
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}
```

Dette eksempelet gjør at et vanlig plussklikk kjører handlingen `worktree-agents`. Arbeidsområdekommandoen fra `commands` bruker en synlig oppsettsterminal til først å opprette Git-`worktree`. Codex og Claude starter samtidig, venter på den arbeidsområdespesifikke tilstandsfilen og går deretter inn i den opprettede mappen før 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`.

## Fullstendig eksempel

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

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