Custom Commands

Define custom commands and workspace layouts by adding a cmux.json file to your project root or ~/.config/cmux/. Commands appear in the command palette.

File locations

cmux looks for configuration in two places:

  • Per-project: ./cmux.jsonlives in your project directory, takes precedence
  • Global: ~/.config/cmux/cmux.jsonapplies to all projects, fills in commands not defined locally
Local commands override global commands with the same name.

Changes are picked up automatically — no restart needed.

Schema

A cmux.json file contains a commands array. Each command is either a simple shell command or a full workspace definition:

cmux.json
{
  "commands": [
    {
      "name": "Start Dev",
      "keywords": ["dev", "start"],
      "workspace": { ... }
    },
    {
      "name": "Run Tests",
      "command": "npm test",
      "confirm": true
    }
  ]
}

Simple commands

A simple command runs a shell command in the currently focused terminal:

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

Fields

  • nameDisplayed in the command palette (required)
  • descriptionOptional description
  • keywordsExtra search terms for the command palette
  • commandShell command to run in the focused terminal
  • confirmShow a confirmation dialog before running

Simple commands run in the focused terminal's current working directory. If your command relies on project-relative paths, prefix it with cd "$(git rev-parse --show-toplevel)" && to run from the repo root, or cd /your/path && for any specific directory.

Workspace commands

A workspace command creates a new workspace with a custom layout of splits, terminals, and browser panes:

cmux.json
{
  "commands": [
    {
      "name": "Dev Environment",
      "keywords": ["dev", "fullstack"],
      "restart": "confirm",
      "workspace": {
        "name": "Dev",
        "cwd": ".",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Frontend",
                    "command": "npm run dev",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Backend",
                    "command": "cargo watch -x run",
                    "cwd": "./server",
                    "env": { "RUST_LOG": "debug" }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  ]
}

Workspace fields

  • nameWorkspace tab name (defaults to command name)
  • cwdWorking directory for the workspace
  • colorWorkspace tab color
  • layoutLayout tree defining splits and panes

Restart behavior

Controls what happens when a workspace with the same name already exists:

  • "ignore"Switch to the existing workspace (default)
  • "recreate"Close and recreate without asking
  • "confirm"Ask the user before recreating

Layout tree

The layout tree defines how panes are arranged using recursive split nodes:

Split node

Divides space into two children:

  • direction"horizontal" or "vertical"
  • splitDivider position from 0.1 to 0.9 (default 0.5)
  • childrenExactly two child nodes (split or pane)

Pane node

A leaf node containing one or more surfaces (tabs within the pane).

Surface definition

Each surface in a pane can be a terminal or a browser:

  • type"terminal" or "browser"
  • nameCustom tab title
  • commandShell command to auto-run on creation (terminal only)
  • cwdWorking directory for this surface
  • envEnvironment variables as key-value pairs
  • urlURL to open (browser only)
  • focusFocus this surface after creation

Working directory resolution

  • . or omittedworkspace working directory
  • ./subdirrelative to workspace working directory
  • ~/pathexpanded to home directory
  • Absolute pathused as-is

Full example

cmux.json
{
  "commands": [
    {
      "name": "Web Dev",
      "description": "Docs site with live preview",
      "keywords": ["web", "docs", "next", "frontend"],
      "restart": "confirm",
      "workspace": {
        "name": "Web Dev",
        "cwd": "./web",
        "color": "#3b82f6",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Next.js",
                    "command": "npm run dev",
                    "focus": true
                  }
                ]
              }
            },
            {
              "direction": "vertical",
              "split": 0.6,
              "children": [
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "browser",
                        "name": "Preview",
                        "url": "http://localhost:3777"
                      }
                    ]
                  }
                },
                {
                  "pane": {
                    "surfaces": [
                      {
                        "type": "terminal",
                        "name": "Shell",
                        "env": { "NODE_ENV": "development" }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    },
    {
      "name": "Debug Log",
      "description": "Tail the debug event log from the running dev app",
      "keywords": ["log", "debug", "tail", "events"],
      "restart": "ignore",
      "workspace": {
        "name": "Debug Log",
        "layout": {
          "direction": "horizontal",
          "split": 0.5,
          "children": [
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Events",
                    "command": "tail -f /tmp/cmux-debug.log",
                    "focus": true
                  }
                ]
              }
            },
            {
              "pane": {
                "surfaces": [
                  {
                    "type": "terminal",
                    "name": "Shell"
                  }
                ]
              }
            }
          ]
        }
      }
    },
    {
      "name": "Setup",
      "description": "Initialize submodules and build dependencies",
      "keywords": ["setup", "init", "install"],
      "command": "./scripts/setup.sh",
      "confirm": true
    },
    {
      "name": "Reload",
      "description": "Build and launch the debug app tagged to the current branch",
      "keywords": ["reload", "build", "run", "launch"],
      "command": "./scripts/reload.sh --tag $(git branch --show-current)"
    },
    {
      "name": "Run Unit Tests",
      "keywords": ["test", "unit"],
      "command": "./scripts/test-unit.sh",
      "confirm": true
    }
  ]
}