Tilpasning og administrasjonKommandoer og handlinger
Tilpasning og administrasjon

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