{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/manaflow-ai/cmux/main/web/data/cmux.schema.json", "title": "cmux.json", "description": "cmux configuration. Global cmux.json supports app settings, shortcuts, actions, custom commands, notification hooks, and workspace layouts. Project-local .cmux/cmux.json supports actions, commands, notification hooks, and UI action wiring.", "type": "object", "additionalProperties": false, "properties": { "$schema": { "type": "string", "format": "uri", "default": "https://raw.githubusercontent.com/manaflow-ai/cmux/main/web/data/cmux.schema.json", "description": "Optional schema URL for editor completion and validation." }, "schemaVersion": { "type": "integer", "minimum": 1, "default": 1, "description": "Schema version for forward-compatible migrations. Newer versions are parsed on a best-effort basis." }, "paneBorderColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "descriptionKey": "schemaDescriptions.paneBorderColor", "description": "Override the cmux pane divider color in split workspaces. This affects cmux pane boundaries, not Ghostty internal splits." }, "activePaneBorderColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "descriptionKey": "schemaDescriptions.activePaneBorderColor", "description": "Optional border color drawn around the focused cmux pane in split workspaces." }, "actions": { "title": "actions", "description": "Action registry used by the surface tab bar, Command Palette, shortcuts, and plus-button menu. Each entry supports type \"builtin\", \"command\", \"agent\" (any CLI agent name, e.g. claude, codex, opencode, or a custom binary, with optional args), \"workspaceCommand\", or \"workspace\" (inline workspace with name/cwd/color/env/setup/layout, plus optional restart). Inline workspace entries are auto-offered in the new-workspace plus-button menu; set newWorkspaceMenu true/false on any action to override. \"Save Workspace as Layout\" in the plus-button menu writes entries here.", "type": "object", "additionalProperties": true }, "ui": { "title": "ui", "description": "UI action wiring, including surface tab bar buttons and plus-button behavior. The plus-button context menu shows ui.newWorkspace.contextMenu (or the default items) followed by actions that opt in via newWorkspaceMenu.", "type": "object", "additionalProperties": true, "properties": { "newWorkspace": { "title": "newWorkspace", "description": "New Workspace button behavior and context-menu wiring.", "type": "object", "additionalProperties": true, "properties": { "action": { "type": "string", "description": "ID of the action run by plain New Workspace. This is the default workspace layout; omit or remove it for None (Blank Terminal). Project-local ui.newWorkspace.action wins over the global value." } } } } }, "commands": { "title": "commands", "description": "Custom shell commands and workspace layout definitions. Workspace definitions support name, cwd, color, env, layout, and setup (a bootstrap command sent to the first terminal before its own command).", "type": "array", "items": { "type": "object", "additionalProperties": true } }, "agentChat": { "title": "agentChat", "description": "Agent Chat GUI server settings. The built-in New agent chat action opens this URL in a browser workspace, probing /healthz first and optionally starting the server with startCommand.", "descriptionKey": "schemaDescriptions.agentChat.description", "type": "object", "additionalProperties": false, "properties": { "url": { "type": "string", "format": "uri", "pattern": "^https?://", "minLength": 1, "default": "http://127.0.0.1:7739", "description": "Base URL for the machine-local Agent Chat GUI server. cmux probes /healthz before opening the workspace.", "descriptionKey": "schemaDescriptions.agentChat.url" }, "startCommand": { "type": "string", "minLength": 1, "description": "Optional shell command to start the Agent Chat server when /healthz is unreachable. cmux runs it detached with the user's SHELL, polls healthz for a short bounded window, then opens the workspace either way.", "descriptionKey": "schemaDescriptions.agentChat.startCommand" }, "keys": { "type": "object", "additionalProperties": false, "description": "Keyboard behavior overrides for the Agent Chat web UI.", "descriptionKey": "schemaDescriptions.agentChat.keys.description", "properties": { "ctrlJ": { "type": "string", "enum": ["newline", "menu"], "default": "newline", "description": "Behavior for Ctrl+J in Agent Chat text fields. Use newline to insert a line break, or menu to move to the next popup item while a menu is open.", "descriptionKey": "schemaDescriptions.agentChat.keys.ctrlJ" } } }, "fonts": { "type": "object", "additionalProperties": false, "description": "Font overrides for the Agent Chat web UI. Omitted values fall back to Ghostty and built-in defaults.", "descriptionKey": "schemaDescriptions.agentChat.fonts.description", "properties": { "sansFamily": { "type": "string", "minLength": 1, "description": "CSS font family used for Agent Chat body and UI text.", "descriptionKey": "schemaDescriptions.agentChat.fonts.sansFamily" }, "bodyFamily": { "type": "string", "minLength": 1, "description": "Alias for sansFamily.", "descriptionKey": "schemaDescriptions.agentChat.fonts.bodyFamily" }, "family": { "type": "string", "minLength": 1, "description": "Alias for sansFamily.", "descriptionKey": "schemaDescriptions.agentChat.fonts.family" }, "baseSize": { "type": "number", "exclusiveMinimum": 0, "description": "Base Agent Chat font size in CSS pixels.", "descriptionKey": "schemaDescriptions.agentChat.fonts.baseSize" }, "bodySize": { "type": "number", "exclusiveMinimum": 0, "description": "Alias for baseSize.", "descriptionKey": "schemaDescriptions.agentChat.fonts.bodySize" }, "monoFamily": { "type": "string", "minLength": 1, "description": "CSS font family used for Agent Chat code and monospace text.", "descriptionKey": "schemaDescriptions.agentChat.fonts.monoFamily" }, "codeFamily": { "type": "string", "minLength": 1, "description": "Alias for monoFamily.", "descriptionKey": "schemaDescriptions.agentChat.fonts.codeFamily" }, "codeSize": { "type": "number", "exclusiveMinimum": 0, "description": "Agent Chat code font size in CSS pixels.", "descriptionKey": "schemaDescriptions.agentChat.fonts.codeSize" }, "monoSize": { "type": "number", "exclusiveMinimum": 0, "description": "Alias for codeSize.", "descriptionKey": "schemaDescriptions.agentChat.fonts.monoSize" }, "codeLineHeight": { "type": "number", "exclusiveMinimum": 0, "description": "Line-height multiplier used for Agent Chat code blocks.", "descriptionKey": "schemaDescriptions.agentChat.fonts.codeLineHeight" } } } } }, "vault": { "title": "vault", "description": "Vault session restore agent registrations. cmux includes Pi by default; use this section to add or override JSONL-backed coding agents without an app update.", "type": "object", "additionalProperties": false, "properties": { "agents": { "type": "array", "description": "Custom coding agents that Vault can detect, list, and resume.", "items": { "type": "object", "additionalProperties": true, "required": ["id", "name", "sessionIdSource", "resumeCommand"], "properties": { "id": { "type": "string", "pattern": "^[A-Za-z0-9._-]+$", "description": "Stable lowercase-ish identifier used in Vault persistence, for example pi." }, "name": { "type": "string", "description": "Display name shown in Vault." }, "iconAssetName": { "type": "string", "description": "Optional asset catalog image name shown for this agent in Vault." }, "detect": { "type": "object", "additionalProperties": false, "description": "Rules for detecting a running agent process inside a cmux terminal.", "properties": { "processName": { "type": "string", "description": "Executable basename to match, for example pi." }, "argvContains": { "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } } ], "description": "Substring or substrings that must appear in the process argv." } } }, "sessionIdSource": { "oneOf": [ { "type": "string", "description": "Use piSessionFile for Pi JSONL discovery, or an argv option such as --session." }, { "type": "object", "additionalProperties": false, "required": ["type"], "properties": { "type": { "type": "string", "enum": ["argvOption", "piSessionFile"] }, "argvOption": { "type": "string", "description": "Option whose following value is the session id, for example --session." } }, "allOf": [ { "if": { "properties": { "type": { "const": "argvOption" } } }, "then": { "required": ["argvOption"] } }, { "if": { "properties": { "type": { "const": "piSessionFile" } } }, "then": { "not": { "required": ["argvOption"] } } } ] } ], "description": "Where cmux reads the native session id for an active process." }, "resumeCommand": { "type": "string", "anyOf": [ { "pattern": "\\{\\{sessionId\\}\\}" }, { "pattern": "\\{\\{sessionPath\\}\\}" } ], "description": "Shell-like argv template used to resume a session. Supported placeholders: {{sessionId}}, {{sessionPath}}, {{executable}}, {{cwd}}, {{sessionDir}}. Must include {{sessionId}} or {{sessionPath}}." }, "forkCommand": { "type": "string", "anyOf": [ { "pattern": "\\{\\{sessionId\\}\\}" }, { "pattern": "\\{\\{sessionPath\\}\\}" } ], "description": "Optional shell-like argv template used to fork (branch) a session into a new copy, for example \"{{executable}} --session {{sessionId}} --fork\". Same placeholders as resumeCommand. Omit when the agent has no fork capability; Fork Conversation stays hidden for it." }, "cwd": { "type": "string", "enum": ["preserve", "ignore"], "default": "preserve", "description": "Whether Vault should cd to the saved working directory before running resumeCommand." }, "sessionDirectory": { "type": "string", "description": "Optional root directory for JSONL session discovery, such as ~/.pi/agent/sessions." } } }, "default": [] } } }, "newWorkspaceCommand": { "type": "string", "description": "Legacy name of a workspace command to run when creating a new workspace. Prefer ui.newWorkspace.action for new configs." }, "workspaceGroups": { "type": "object", "title": "workspaceGroups", "description": "Per-cwd customization for sidebar workspace groups. The anchor workspace's cwd is matched against the keys in `byCwd`; longest-match wins. Keys containing `*` or `?` are matched as fnmatch globs (with `~` expanded); other keys are path prefixes.", "additionalProperties": false, "properties": { "newWorkspacePlacement": { "type": "string", "enum": ["afterCurrent", "top", "end"], "default": "afterCurrent", "description": "Global default for where Cmd-N inside a group, the group header + button, and configured group actions place the new workspace: `afterCurrent` (after the active in-group workspace, falling back to top), `top` (second slot, just after the anchor), or `end` (after the last member).", "descriptionKey": "schemaDescriptions.workspaceGroups.newWorkspacePlacement" }, "byCwd": { "type": "object", "description": "Map of cwd patterns to group customization. Empty when omitted.", "additionalProperties": { "type": "object", "additionalProperties": false, "properties": { "color": { "type": "string", "description": "Hex color (e.g. \"#7A4FD8\") applied as the group header tint when the group itself has no explicit customColor." }, "icon": { "type": "string", "description": "SF Symbol name (e.g. \"folder.fill\", \"ladybug.fill\") for the group header. Falls back to \"folder.fill\" when omitted." }, "contextMenu": { "type": "array", "description": "Items appearing in the right-click menu on the group's + button. Same schema as the global ui.newWorkspace.contextMenu entries.", "items": { "oneOf": [ { "type": "string" }, { "type": "object", "additionalProperties": true } ] } }, "newWorkspacePlacement": { "type": "string", "enum": ["afterCurrent", "top", "end"], "description": "Per-cwd override for where Cmd-N inside the group, the group header + button, and configured group actions place the new workspace: `afterCurrent` (after the active in-group workspace, falling back to top), `top` (second slot, just after the anchor), or `end` (after the last member). Falls back to the global default when omitted.", "descriptionKey": "schemaDescriptions.workspaceGroups.byCwd.newWorkspacePlacement" } } } } } }, "surfaceTabBarButtons": { "title": "surfaceTabBarButtons", "description": "Legacy root-level surface tab bar buttons. Prefer ui.surfaceTabBar.buttons for new configs.", "type": "array", "items": { "oneOf": [ { "type": "string" }, { "type": "object", "additionalProperties": true } ] } }, "app": { "title": "app", "description": "General app preferences from Settings > App.", "type": "object", "additionalProperties": false, "properties": { "language": { "type": "string", "enum": [ "system", "en", "ar", "bs", "zh-Hans", "zh-Hant", "da", "de", "es", "fr", "it", "ja", "ko", "nb", "pl", "pt-BR", "ru", "th", "tr" ], "default": "system", "description": "Preferred app language." }, "appearance": { "type": "string", "enum": ["system", "light", "dark"], "default": "system", "description": "App appearance mode." }, "appIcon": { "type": "string", "enum": ["automatic", "light", "dark"], "default": "automatic", "description": "Dock and app switcher icon style." }, "windowTitleTemplate": { "type": "string", "default": "", "descriptionKey": "schemaDescriptions.app.windowTitleTemplate", "description": "Optional NSWindow title template. Blank preserves cmux's existing default title behavior, including the current-directory fallback. Supported placeholders: {windowId}, {windowToken}, {activeWorkspace}, {activeDirectory}, {defaultTitle}, {appName}." }, "menuBarOnly": { "type": "boolean", "default": false, "description": "Hide the Dock icon and app switcher entry while keeping cmux available from the menu bar." }, "newWorkspacePlacement": { "type": "string", "enum": ["top", "afterCurrent", "end"], "default": "afterCurrent", "description": "Where new workspaces are inserted in the sidebar." }, "forkConversationDefaultDestination": { "type": "string", "enum": ["right", "left", "top", "bottom", "newTab", "newWorkspace"], "default": "right", "descriptionKey": "schemaDescriptions.app.forkConversationDefaultDestination", "description": "Default destination for the tab context menu's primary Fork Conversation action. The submenu still exposes every destination." }, "workspaceInheritWorkingDirectory": { "type": "boolean", "default": true, "description": "When true, new workspaces inherit the current workspace working directory. When false, new workspaces leave the working directory unset so Ghostty's working-directory setting can provide the default." }, "minimalMode": { "type": "boolean", "default": false, "description": "Hide the workspace title bar and move controls into the sidebar." }, "keepWorkspaceOpenWhenClosingLastSurface": { "type": "boolean", "default": false, "description": "When true, closing the last surface keeps the workspace open." }, "focusPaneOnFirstClick": { "type": "boolean", "default": true, "description": "When cmux is inactive, the first click can activate and focus the clicked pane." }, "preferredEditor": { "type": "string", "default": "", "description": "Custom editor command used when Cmd-click file previews are disabled or a file is unsupported. Leave empty to use the default." }, "openSupportedFilesInCmux": { "type": "boolean", "default": true, "description": "When enabled, Cmd-clicking readable local files opens supported previews in cmux, including text, code, PDFs, images, audio, video, and Quick Look files. Preview headers include an Open With menu based on the user's default and compatible macOS apps for that file." }, "openMarkdownInCmuxViewer": { "type": "boolean", "default": true, "description": "When enabled, Cmd-clicking .md/.markdown/.mkd/.mdx files opens the rendered cmux markdown viewer panel (with live reload) instead of the generic file preview." }, "globalFontMagnification": { "type": "integer", "minimum": 50, "maximum": 200, "multipleOf": 10, "default": 100, "descriptionKey": "schemaDescriptions.app.globalFontMagnification", "description": "Scales cmux-owned terminals, tab titles, sidebars, settings, overlays, and app chrome by this percentage. Rendered browser page content is excluded." }, "reorderOnNotification": { "type": "boolean", "default": true, "description": "Move workspaces with new notifications toward the top." }, "iMessageMode": { "type": "boolean", "default": false, "description": "Move a workspace to the top and show the submitted message when sending an agent prompt." }, "sendAnonymousTelemetry": { "type": "boolean", "default": true, "description": "Allow anonymous telemetry." }, "confirmQuit": { "type": "string", "enum": ["always", "dirty-only", "never"], "default": "always", "descriptionKey": "schemaDescriptions.app.confirmQuit", "description": "Control when cmux asks for confirmation before quitting. DEV builds always quit immediately regardless of this setting. Legacy app.warnBeforeQuit is still accepted as a boolean fallback." }, "warnBeforeQuit": { "type": "boolean", "default": true, "descriptionKey": "schemaDescriptions.app.warnBeforeQuit", "description": "Legacy boolean fallback for quit confirmation. Use app.confirmQuit for new configs." }, "warnBeforeClosingTab": { "type": "boolean", "default": true, "description": "Show a confirmation before closing a tab." }, "warnBeforeClosingTabXButton": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.app.warnBeforeClosingTabXButton", "description": "Show a confirmation before closing a tab with the tab close button." }, "hideTabCloseButton": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.app.hideTabCloseButton", "description": "Hide tab close buttons in the pane tab bar." }, "renameSelectsExistingName": { "type": "boolean", "default": true, "description": "Select the current name when opening rename flows." }, "commandPaletteSearchesAllSurfaces": { "type": "boolean", "default": false, "description": "Search every surface in the command palette switcher instead of only the active workspace." } } }, "terminal": { "title": "terminal", "description": "Terminal presentation settings from Settings > Terminal.", "type": "object", "additionalProperties": false, "properties": { "showScrollBar": { "type": "boolean", "default": true, "description": "Show the right-edge terminal scroll bar when scrollback is available. cmux automatically suppresses it for alternate-screen style TUI surfaces." }, "scrollSpeed": { "type": "number", "minimum": 0.25, "maximum": 3.0, "default": 1.0, "descriptionKey": "schemaDescriptions.terminal.scrollSpeed", "description": "Multiplier applied to terminal scroll wheel and trackpad deltas. Higher values scroll faster; lower values scroll slower." }, "sessionContentMaxWidth": { "oneOf": [ { "type": "boolean", "const": false }, { "type": "number", "minimum": 320, "multipleOf": 20 } ], "default": false, "descriptionKey": "schemaDescriptions.terminal.sessionContentMaxWidth", "description": "Optional maximum width, in points, for terminal and built-in agent chat content. Set false to use the full pane width." }, "sessionContentAlignment": { "type": "string", "enum": ["left", "center", "right"], "default": "center", "descriptionKey": "schemaDescriptions.terminal.sessionContentAlignment", "description": "Horizontal placement for terminal and built-in agent chat content when sessionContentMaxWidth is enabled." }, "copyOnSelect": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.terminal.copyOnSelect", "description": "When true, copy selected terminal text to the system clipboard when the selection is committed. When false, cmux does not emit a Ghostty copy-on-select override; Ghostty config and defaults control selection-clipboard behavior." }, "autoResumeAgentSessions": { "type": "boolean", "default": true, "description": "Automatically run agent resume commands for restored terminal sessions when cmux reopens after quit. Set false to restore panes while keeping Claude Code, Codex, OpenCode, and other saved agent sessions idle until you resume them manually." }, "showTextBoxOnNewTerminals": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.terminal.showTextBoxOnNewTerminals", "description": "Show the beta TextBox input by default for newly created workspaces, terminal tabs, and terminal splits." }, "focusTextBoxOnNewTerminals": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.terminal.focusTextBoxOnNewTerminals", "description": "Focus the beta TextBox input by default for newly created workspaces, terminal tabs, and terminal splits. Focusing also shows the TextBox." }, "agentHibernation": { "type": "object", "additionalProperties": false, "description": "Opt-in Agent Hibernation settings. cmux kills idle background agent processes to free RAM and CPU, then resumes them with their saved session when their tab is visited. A terminal is only suspended when it runs a restorable coding agent, the agent lifecycle reports idle, the terminal is off-screen, the live-terminal limit is exceeded, and its output has stayed unchanged for the idle window plus a short confirmation settle window. The placeholder Resume button is a manual fallback.", "properties": { "enabled": { "type": "boolean", "default": false, "description": "Enable Agent Hibernation." }, "idleSeconds": { "type": "integer", "minimum": 5, "maximum": 604800, "default": 5, "description": "Minimum seconds with no terminal output or input before an idle restorable agent terminal can hibernate. A short confirmation settle window (~60s) still applies on top of this before the agent is killed." }, "maxLiveTerminals": { "type": "integer", "minimum": 1, "maximum": 256, "default": 12, "description": "Maximum live restorable agent terminals to keep before cmux hibernates eligible background terminals, oldest first." } } }, "rendererRealization": { "type": "object", "additionalProperties": false, "description": "Reclaim off-screen terminal GPU renderer memory. cmux releases the Metal renderer (IOSurface) of a terminal that has stayed off-screen and idle while keeping its process and terminal state alive, then rebuilds the renderer instantly when the tab is visited again. Non-destructive and on by default.", "properties": { "enabled": { "type": "boolean", "default": true, "description": "Reclaim off-screen terminal renderer memory." }, "idleSeconds": { "type": "integer", "minimum": 5, "maximum": 604800, "default": 30, "description": "Minimum seconds a terminal must stay off-screen before its GPU renderer memory is reclaimed." }, "maxWarmRenderers": { "type": "integer", "minimum": 1, "maximum": 256, "default": 12, "description": "Most recently visible terminals to keep renderer-ready so switching stays instant. Extra off-screen renderers are reclaimed oldest first." } } }, "textBoxMaxLines": { "type": "integer", "minimum": 1, "maximum": 20, "default": 10, "description": "Maximum number of lines the rich terminal TextBox input can grow to before it scrolls." }, "textBoxDefaultSubmitAction": { "type": "string", "default": "text-entry", "description": "Default TextBox submit action ID for new terminal sessions. Use text-entry for plain input or one of the configured action IDs.", "descriptionKey": "schemaDescriptions.terminal.textBoxDefaultSubmitAction" }, "textBoxSubmitActions": { "type": "array", "default": [], "description": "Configurable TextBox submit actions shown on the submit button, Shift-Tab cycle, and right-click menu.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActions", "items": { "type": "object", "additionalProperties": false, "required": ["id", "title", "kind", "systemImage", "backgroundColorHex"], "properties": { "id": { "type": "string", "pattern": "^[A-Za-z0-9._-]+$", "description": "Stable action ID referenced by terminal.textBoxDefaultSubmitAction.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionId" }, "title": { "type": "string", "description": "Menu label for this submit action.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionTitle" }, "kind": { "type": "string", "enum": ["textEntry", "commandTemplate"], "description": "Whether this action submits plain Text Entry or expands a shell command template.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionKind" }, "commandTemplate": { "type": "string", "description": "Shell command template for commandTemplate actions. Include {{prompt}} to shell-quote the prompt into the command.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionCommandTemplate" }, "preservePromptAfterLaunch": { "type": "boolean", "description": "When true, launch commandTemplate without the prompt and keep the prompt in the TextBox for the active agent.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionPreservePromptAfterLaunch" }, "systemImage": { "type": "string", "description": "Fallback SF Symbol name shown on the submit button.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionSystemImage" }, "assetName": { "type": "string", "description": "Optional app asset catalog image name shown on the submit button.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionAssetName" }, "imagePath": { "type": "string", "description": "Optional PNG or image file path shown on the submit button. Tilde is expanded.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionImagePath" }, "backgroundColorHex": { "type": "string", "pattern": "^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$", "description": "Action color metadata as RGB or RGBA hex. The submit button fill stays white and only changes opacity between enabled and disabled states.", "descriptionKey": "schemaDescriptions.terminal.textBoxSubmitActionBackgroundColorHex" } }, "allOf": [ { "if": { "required": ["kind"], "properties": { "kind": { "const": "commandTemplate" } } }, "then": { "required": ["commandTemplate"], "anyOf": [ { "properties": { "commandTemplate": { "type": "string", "pattern": "\\{\\{prompt\\}\\}" } } }, { "required": ["preservePromptAfterLaunch"], "properties": { "preservePromptAfterLaunch": { "const": true } } } ] } } ] } }, "resumeCommands": { "type": "array", "default": [], "description": "Signed command-prefix approvals for restoring non-agent terminal surfaces. cmux writes this list when you approve a surface resume command.", "items": { "type": "object", "additionalProperties": false, "required": ["version", "id", "commandPrefix", "environmentKeys", "policy", "createdAt", "updatedAt", "signature"], "properties": { "version": { "type": "integer", "const": 1 }, "id": { "type": "string" }, "name": { "type": "string" }, "commandPrefix": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "Shell argv prefix that must match the saved resume command." }, "cwd": { "type": "string", "description": "Optional working directory that must match the saved resume command." }, "environment": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Optional non-sensitive environment values that must match the saved resume command." }, "environmentKeys": { "type": "array", "items": { "type": "string" } }, "source": { "type": "string" }, "policy": { "type": "string", "enum": ["manual", "prompt", "auto"] }, "createdAt": { "type": "number" }, "updatedAt": { "type": "number" }, "lastUsedAt": { "type": "number" }, "signature": { "type": "string", "description": "HMAC signature for the record. Changing signed fields invalidates the approval." } } } }, "uploadCommands": { "type": "array", "default": [], "description": "Host-scoped rules that replace the built-in scp for terminal file drops and pastes over SSH. When the ssh destination matches a rule, cmux runs that rule's command once per file instead of scp, and inserts the command's stdout at the cursor (verbatim, with control characters stripped); if the command prints nothing, cmux inserts the shell-escaped remote path it chose instead. Per-file outputs are space-joined. First matching enabled rule wins; no match runs the built-in scp unchanged. A non-zero exit, timeout, or cancel inserts nothing.", "items": { "type": "object", "additionalProperties": false, "required": ["command"], "properties": { "hostPattern": { "type": ["string", "null"], "minLength": 1, "description": "fnmatch glob matched against the ssh destination (user@ and IPv6 brackets stripped, lowercased), like a single ssh_config Host pattern. Omit the key or set it to null for a catch-all (a blank string is rejected)." }, "command": { "type": "string", "minLength": 1, "pattern": "\\S", "description": "Shell command run via /bin/sh -c, once per file. It receives the file and endpoint on its environment (CMUX_UPLOAD_LOCAL_PATH, CMUX_UPLOAD_REMOTE_PATH, CMUX_UPLOAD_DESTINATION, CMUX_UPLOAD_PORT, CMUX_UPLOAD_IDENTITY_FILE, CMUX_UPLOAD_SSH_OPTIONS). Its stdout is what cmux inserts at the cursor." }, "enabled": { "type": "boolean", "default": true, "description": "Whether this rule is active. Defaults to true." } } } } } }, "notifications": { "title": "notifications", "description": "Notification behavior from Settings > Notifications.", "type": "object", "additionalProperties": false, "properties": { "dockBadge": { "type": "boolean", "default": true, "description": "Show the unread count in the Dock tile." }, "showInMenuBar": { "type": "boolean", "default": true, "description": "Show the menu bar extra." }, "unreadPaneRing": { "type": "boolean", "default": true, "description": "Highlight panes with unread notifications." }, "paneFlash": { "type": "boolean", "default": true, "description": "Flash the focused pane when requested." }, "suppressOnlyFocusedSurface": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.notifications.suppressOnlyFocusedSurface", "description": "When enabled, a notification banner is auto-withdrawn only when its surface is the exact focused surface. A banner delivered for a non-focused surface in the currently visible workspace stays up until you focus that surface (or click/dismiss it), instead of being retracted when the workspace becomes visible. Off preserves the legacy workspace-visibility withdraw." }, "agentPermissionPrompt": { "type": "boolean", "default": true, "descriptionKey": "schemaDescriptions.notifications.agentPermissionPrompt", "description": "Notify when an agent (e.g. Claude Code) is blocked waiting for your permission to run a tool. On by default, since this is the alert you must act on to unblock the agent." }, "agentTurnComplete": { "type": "string", "enum": ["whenIdle", "always", "never"], "default": "whenIdle", "descriptionKey": "schemaDescriptions.notifications.agentTurnComplete", "description": "When to notify that an agent finished a turn. whenIdle (default) suppresses the notification while the agent still has a running background task or a pending scheduled wakeup, so you are pinged once work truly drains. always notifies on every turn end; never disables it." }, "agentIdleReminder": { "type": "boolean", "default": true, "descriptionKey": "schemaDescriptions.notifications.agentIdleReminder", "description": "Notify when an agent has been idle waiting for your input (about 60s after a turn ends). Suppressed while background work from the last turn is still pending, so a running build or watcher does not trigger a false waiting alert." }, "sound": { "type": "string", "enum": [ "default", "Basso", "Blow", "Bottle", "Frog", "Funk", "Glass", "Hero", "Morse", "Ping", "Pop", "Purr", "Sosumi", "Submarine", "Tink", "custom_file", "none" ], "default": "default", "description": "Notification sound preset." }, "customSoundFilePath": { "type": "string", "default": "", "description": "Local path to the custom notification sound file." }, "command": { "type": "string", "default": "", "description": "Optional shell command to run alongside notification delivery." }, "hooksMode": { "type": "string", "enum": ["append", "replace"], "default": "append", "description": "Controls whether project-local notification hooks append to inherited hooks or replace them." }, "hooks": { "type": "array", "default": [], "description": "Composable shell hooks that receive notification policy JSON on stdin and return updated policy JSON on stdout.", "items": { "type": "object", "additionalProperties": false, "required": ["id", "command"], "properties": { "id": { "type": "string", "minLength": 1, "description": "Stable hook identifier used in logs and failure alerts." }, "command": { "type": "string", "minLength": 1, "pattern": ".*\\S.*", "description": "Shell command run with notification policy JSON on stdin." }, "timeoutSeconds": { "type": "number", "exclusiveMinimum": 0, "default": 20, "description": "Maximum time cmux waits for this hook before falling back to default notification behavior." }, "enabled": { "type": "boolean", "default": true, "description": "Disable this hook without removing it." } } } } } }, "sidebar": { "title": "sidebar", "description": "Sidebar content and metadata visibility from Settings > Sidebar.", "type": "object", "additionalProperties": false, "properties": { "hideAllDetails": { "type": "boolean", "default": false, "description": "Hide all per-workspace detail rows." }, "wrapWorkspaceTitles": { "type": "boolean", "default": false, "description": "Allow workspace titles in the sidebar to wrap to multiple lines instead of truncating after one line." }, "showWorkspaceDescription": { "type": "boolean", "default": true, "description": "Show custom workspace descriptions in the sidebar." }, "beta": { "type": "object", "additionalProperties": false, "description": "Experimental sidebar features.", "properties": { "workspaceTodos": { "type": "object", "additionalProperties": false, "description": "Workspace todos checklist presentation.", "properties": { "checklistStyle": { "type": "string", "enum": ["popover", "inline"], "default": "popover", "description": "How a row's checklist opens from its summary line: an anchored popover or inline expansion." } } } } }, "branchLayout": { "type": "string", "enum": ["vertical", "inline"], "default": "vertical", "description": "Show git branch details stacked vertically or inline." }, "showNotificationMessage": { "type": "boolean", "default": true, "description": "Show the latest notification text in the sidebar." }, "notificationMessageLineLimit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 12, "description": "Maximum lines shown for the latest notification below each workspace title.", "descriptionKey": "schemaDescriptions.sidebar.notificationMessageLineLimit" }, "showBranchDirectory": { "type": "boolean", "default": true, "description": "Show the workspace working directory." }, "showPullRequests": { "type": "boolean", "default": true, "description": "Show pull request metadata in the sidebar." }, "watchGitStatus": { "type": "boolean", "default": true, "description": "Watch repository files for sidebar branch and pull request metadata without polling git." }, "makePullRequestsClickable": { "type": "boolean", "default": true, "description": "Allow sidebar pull request metadata to open links when clicked." }, "openPullRequestLinksInCmuxBrowser": { "type": "boolean", "default": true, "description": "Open sidebar pull request links in the embedded cmux browser." }, "openPortLinksInCmuxBrowser": { "type": "boolean", "default": true, "description": "Open sidebar port links in the embedded cmux browser." }, "showSSH": { "type": "boolean", "default": true, "description": "Show SSH connection details." }, "showPorts": { "type": "boolean", "default": true, "description": "Show listening ports." }, "showLog": { "type": "boolean", "default": true, "description": "Show recent log snippets." }, "showProgress": { "type": "boolean", "default": true, "description": "Show progress indicators." }, "showAgentActivity": { "type": "boolean", "default": true, "description": "Show the loading spinner on workspaces with running coding agents or active loaders." }, "loadingSpinnerPosition": { "type": "string", "enum": ["leading", "trailing"], "default": "leading", "description": "Which side of the workspace row the loading spinner appears on: leading (left, sharing the unread-badge slot) or trailing (right)." }, "notificationBadgePosition": { "type": "string", "enum": ["leading", "trailing"], "default": "leading", "description": "Which side of the workspace row the unread notification badge appears on: leading (left) or trailing (right)." }, "showCustomMetadata": { "type": "boolean", "default": true, "description": "Show custom metadata pills." }, "rightMaxWidth": { "type": "number", "exclusiveMinimum": 0, "descriptionKey": "schemaDescriptions.sidebar.rightMaxWidth", "description": "Maximum width in points for the right sidebar. When omitted, the built-in dynamic cap applies." } } }, "workspaceColors": { "title": "workspaceColors", "description": "Workspace tab and badge colors from Settings > Workspace Colors.", "type": "object", "additionalProperties": false, "properties": { "indicatorStyle": { "type": "string", "enum": [ "leftRail", "solidFill", "rail", "border", "wash", "lift", "typography", "washRail", "blueWashColorRail" ], "default": "leftRail", "description": "Active workspace indicator style. Legacy aliases are accepted and normalized." }, "selectionColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "description": "Override the selected workspace background color." }, "notificationBadgeColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "description": "Override the unread notification badge color." }, "colors": { "type": "object", "description": "Full named workspace color palette. Include built-in entries you want to keep, remove keys to remove colors, and add more named entries to extend the picker.", "default": { "Red": "#C0392B", "Crimson": "#922B21", "Orange": "#A04000", "Amber": "#7D6608", "Olive": "#4A5C18", "Green": "#196F3D", "Teal": "#006B6B", "Aqua": "#0E6B8C", "Blue": "#1565C0", "Navy": "#1A5276", "Indigo": "#283593", "Purple": "#6A1B9A", "Magenta": "#AD1457", "Rose": "#880E4F", "Brown": "#7B3F00", "Charcoal": "#3E4B5E" }, "additionalProperties": { "$ref": "#/$defs/colorHex" } }, "paletteOverrides": { "type": "object", "description": "Legacy workspace color overrides for built-in palette names. Prefer workspaceColors.colors for new configs.", "default": {}, "deprecated": true, "additionalProperties": { "$ref": "#/$defs/colorHex" } }, "customColors": { "type": "array", "description": "Legacy list of custom workspace colors. Prefer workspaceColors.colors for new configs.", "default": [], "deprecated": true, "items": { "$ref": "#/$defs/colorHex" } } } }, "sidebarAppearance": { "title": "sidebarAppearance", "description": "Sidebar tint settings from Settings > Sidebar Appearance.", "type": "object", "additionalProperties": false, "properties": { "matchTerminalBackground": { "type": "boolean", "default": false, "description": "Use the terminal background instead of the sidebar tint." }, "tintColor": { "$ref": "#/$defs/colorHex", "default": "#000000", "description": "Base sidebar tint color used when light/dark overrides are not set." }, "lightModeTintColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "description": "Sidebar tint override for light appearance." }, "darkModeTintColor": { "$ref": "#/$defs/colorHexOrNull", "default": null, "description": "Sidebar tint override for dark appearance." }, "tintOpacity": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.03, "description": "Sidebar tint opacity from 0 to 1. Note: this only controls the sidebar tint, not terminal/window transparency. For terminal background transparency or blur, set `background-opacity` and `background-blur` in `~/.config/ghostty/config` and run `cmux reload-config`." } } }, "automation": { "title": "automation", "description": "Socket control and automation settings from Settings > Automation.", "type": "object", "additionalProperties": false, "properties": { "socketControlMode": { "type": "string", "enum": [ "off", "cmuxOnly", "automation", "password", "allowAll", "openAccess", "fullOpenAccess", "notifications", "full" ], "default": "cmuxOnly", "description": "Socket control mode. Legacy aliases are accepted and normalized." }, "socketPassword": { "oneOf": [ { "type": "string" }, { "type": "null" } ], "default": "", "description": "Password for password-mode socket access. Use null or an empty string to clear it." }, "claudeCodeIntegration": { "type": "boolean", "default": true, "description": "Enable cmux integration hooks for Claude Code." }, "claudeBinaryPath": { "type": "string", "default": "", "description": "Custom path to the claude binary." }, "workspaceAutoNaming": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.automation.workspaceAutoNaming", "description": "Opt-in AI auto-naming of workspaces and tabs from agent conversation content. When enabled, cmux summarizes supported agent sessions into short titles using each agent's own binary; manual renames always win." }, "autoNamingAgent": { "type": "string", "default": "auto", "descriptionKey": "schemaDescriptions.automation.autoNamingAgent", "description": "Which agent generates auto-names for every session. \"auto\" (default) names each session with its own agent; any agent slug (claude, codex, grok, opencode, pi, omp, …) overrides naming for all sessions, even other agents' sessions. Undriveable or uninstalled agents fall back to the session's own agent, so naming never breaks." }, "ripgrepBinaryPath": { "type": "string", "default": "", "description": "Custom path to the ripgrep (rg) binary used by project search." }, "suppressSubagentNotifications": { "type": "boolean", "default": true, "descriptionKey": "schemaDescriptions.automation.suppressSubagentNotifications", "description": "Suppress visible completion notifications and status mutations from nested Codex or Claude child agents while keeping their events in Feed telemetry." }, "ampIntegration": { "type": "boolean", "default": true, "descriptionKey": "schemaDescriptions.automation.ampIntegration", "description": "Enable cmux integration hooks for Amp. When disabled, the bundled plugin stays inactive without needing to be removed." }, "cursorIntegration": { "type": "boolean", "default": true, "description": "Enable cmux integration hooks for Cursor." }, "geminiIntegration": { "type": "boolean", "default": true, "description": "Enable cmux integration hooks for Gemini." }, "kiroIntegration": { "type": "boolean", "default": true, "description": "Enable cmux integration hooks for Kiro CLI." }, "kiroNotificationLevel": { "type": "string", "enum": [ "minimal", "standard", "verbose" ], "default": "standard", "description": "Controls how many Kiro tool events appear in Feed." }, "portBase": { "type": "integer", "minimum": 1, "default": 9100, "description": "Starting value for workspace CMUX_PORT assignments." }, "portRange": { "type": "integer", "minimum": 1, "default": 10, "description": "Number of ports reserved per workspace." } } }, "browser": { "title": "browser", "description": "Embedded browser settings from Settings > Browser.", "type": "object", "additionalProperties": false, "properties": { "defaultSearchEngine": { "type": "string", "enum": ["google", "duckduckgo", "bing", "kagi", "startpage", "brave", "perplexity", "exa", "yahoo", "ecosia", "qwant", "mojeek", "wikipedia", "github", "baidu", "yandex", "custom"], "default": "google", "descriptionKey": "schemaDescriptions.browser.defaultSearchEngine", "description": "Default search engine for non-URL browser address bar queries. Use custom with customSearchEngineURLTemplate for arbitrary providers." }, "customSearchEngineName": { "type": "string", "default": "", "descriptionKey": "schemaDescriptions.browser.customSearchEngineName", "description": "Display name used when defaultSearchEngine is custom." }, "customSearchEngineURLTemplate": { "type": "string", "default": "https://www.google.com/search?q={query}", "descriptionKey": "schemaDescriptions.browser.customSearchEngineURLTemplate", "description": "Search URL used when defaultSearchEngine is custom. Include {query} or %s for the encoded query. If omitted, cmux appends q= to the URL." }, "showSearchSuggestions": { "type": "boolean", "default": true, "description": "Show omnibar search suggestions." }, "theme": { "type": "string", "enum": ["system", "light", "dark"], "default": "system", "description": "Embedded browser theme." }, "discardHiddenWebViews": { "type": "boolean", "default": true, "description": "Allow hidden browser tabs to release page memory and restore when shown again." }, "hiddenWebViewDiscardDelaySeconds": { "type": "number", "minimum": 0, "maximum": 3600, "default": 300, "description": "Seconds a browser tab must stay hidden before cmux frees its page memory." }, "askWhereToSaveDownloads": { "type": "boolean", "default": false, "descriptionKey": "schemaDescriptions.browser.askWhereToSaveDownloads", "description": "Show a save panel for browser downloads instead of saving directly to Downloads." }, "openTerminalLinksInCmuxBrowser": { "type": "boolean", "default": true, "description": "Open clicked terminal links in the embedded browser." }, "interceptTerminalOpenCommandInCmuxBrowser": { "type": "boolean", "default": true, "description": "Intercept terminal open http(s) commands and route them through the embedded browser." }, "hostsToOpenInEmbeddedBrowser": { "type": "array", "items": { "type": "string" }, "default": [], "description": "Allowlist of hosts that should stay inside the embedded browser." }, "urlsToAlwaysOpenExternally": { "type": "array", "items": { "type": "string" }, "default": [], "description": "Rules that always open matching URLs in the system browser." }, "insecureHttpHostsAllowedInEmbeddedBrowser": { "type": "array", "items": { "type": "string" }, "default": [ "localhost", "*.localhost", "127.0.0.1", "::1", "0.0.0.0", "*.localtest.me" ], "description": "HTTP hosts allowed in the embedded browser without a warning prompt." }, "showImportHintOnBlankTabs": { "type": "boolean", "default": true, "description": "Show the browser import hint on blank tabs." }, "reactGrabVersion": { "type": "string", "default": "0.1.29", "description": "Pinned react-grab version for the browser toolbar helper." } } }, "mobile": { "title": "mobile", "description": "Mac-side settings for cmux on iOS.", "type": "object", "additionalProperties": false, "properties": { "artifactFolderAccess": { "type": "string", "enum": ["subtree", "oneLevel"], "default": "subtree", "description": "Controls whether a referenced or terminal-visible directory authorizes its full canonical subtree or only immediate children." } } }, "markdown": { "title": "markdown", "description": "Built-in markdown viewer settings.", "type": "object", "additionalProperties": false, "properties": { "fontSize": { "type": "integer", "minimum": 8, "maximum": 96, "default": 15, "description": "Default body font size, in points, for newly opened markdown viewers. Zoom a viewer live with Cmd-+ / Cmd-- / Cmd-0.", "descriptionKey": "schemaDescriptions.markdown.fontSize" }, "fontFamily": { "type": "string", "default": "", "description": "Default body font family for newly opened markdown viewers. Leave empty for the system markdown font stack.", "descriptionKey": "schemaDescriptions.markdown.fontFamily" }, "maxWidth": { "type": "integer", "minimum": 320, "maximum": 2400, "default": 980, "description": "Default maximum reading column width, in CSS pixels, for newly opened markdown viewers.", "descriptionKey": "schemaDescriptions.markdown.maxWidth" } } }, "canvas": { "title": "canvas", "description": "Freeform canvas workspace layout settings.", "type": "object", "additionalProperties": false, "properties": { "paneGap": { "type": "integer", "minimum": 0, "maximum": 64, "default": 16, "description": "Spacing between panes in the canvas layout, in points. Snapping, tidy, and new-pane placement all use this one gap.", "descriptionKey": "schemaDescriptions.canvas.paneGap" }, "snappingEnabled": { "type": "boolean", "default": true, "description": "Snap pane drags and resizes to neighbor edges and the pane gap. Hold Command to suspend snapping for one gesture.", "descriptionKey": "schemaDescriptions.canvas.snappingEnabled" } } }, "fileEditor": { "title": "fileEditor", "description": "Built-in plain-text file editor settings.", "type": "object", "additionalProperties": false, "properties": { "wordWrap": { "type": "boolean", "default": false, "description": "Wrap long lines at the editor's right edge instead of scrolling horizontally.", "descriptionKey": "schemaDescriptions.fileEditor.wordWrap" } } }, "fileExplorer": { "title": "fileExplorer", "description": "Right-sidebar file explorer (file tree) settings.", "descriptionKey": "schemaDescriptions.fileExplorer.description", "type": "object", "additionalProperties": false, "properties": { "doubleClickAction": { "type": "string", "enum": ["preview", "defaultEditor", "preferredEditor"], "default": "preview", "description": "What double-clicking (or pressing Return on a search result for) a file in the file explorer does. `preview` opens the built-in cmux file preview (the default and historical behavior). `defaultEditor` opens with the macOS default app for the file type. `preferredEditor` opens with the `app.preferredEditor` command, falling back to the default app when none is set. Only applies to files; directories always expand/collapse, and non-local (remote) file explorers always open the cmux preview.", "descriptionKey": "schemaDescriptions.fileExplorer.doubleClickAction" } } }, "diffViewer": { "title": "diffViewer", "description": "Built-in diff viewer settings.", "type": "object", "additionalProperties": false, "properties": { "defaultLayout": { "type": "string", "enum": ["unified", "split"], "default": "unified", "description": "Default layout for newly opened diff viewers. The toolbar layout toggle persists the user's last choice; an explicit `cmux diff --layout` option overrides both.", "descriptionKey": "schemaDescriptions.diffViewer.defaultLayout" } } }, "shortcuts": { "title": "shortcuts", "description": "Keyboard shortcut settings from Settings > Keyboard Shortcuts.", "type": "object", "additionalProperties": false, "properties": { "showModifierHoldHints": { "type": "boolean", "default": true, "description": "Show shortcut-hint chips while holding Cmd or Control.", "descriptionKey": "schemaDescriptions.shortcuts.showModifierHoldHints" }, "bindings": { "type": "object", "default": {}, "description": "Shortcut overrides keyed by cmux action id. Use a string for a single shortcut, an array for a chord, null, an empty string, none, clear, unbound, or disabled to unbind.", "propertyNames": { "enum": [ "openSettings", "reloadConfiguration", "showHideAllWindows", "globalSearch", "newWindow", "closeWindow", "toggleFullScreen", "quit", "toggleSidebar", "newTab", "newBrowserWorkspace", "openFolder", "reopenPreviousSession", "goToWorkspace", "commandPalette", "commandPaletteNext", "commandPalettePrevious", "sendFeedback", "showNotifications", "jumpToUnread", "toggleUnread", "markOldestUnreadAndJumpNext", "focusRightSidebar", "switchRightSidebarToFiles", "switchRightSidebarToFind", "switchRightSidebarToSessions", "switchRightSidebarToFeed", "switchRightSidebarToDock", "triggerFlash", "nextSurface", "prevSurface", "moveSurfaceLeft", "moveSurfaceRight", "selectSurfaceByNumber", "nextSidebarTab", "prevSidebarTab", "moveWorkspaceUp", "moveWorkspaceDown", "focusHistoryBack", "focusHistoryForward", "selectWorkspaceByNumber", "renameTab", "renameWorkspace", "editWorkspaceDescription", "markWorkspaceDone", "cycleWorkspaceStatus", "toggleChecklistItemComplete", "closeTab", "closeOtherTabsInPane", "closeWorkspace", "newWorkspaceGroup", "groupSelectedWorkspaces", "toggleFocusedWorkspaceGroupCollapsed", "reopenClosedBrowserPanel", "newSurface", "toggleTerminalCopyMode", "focusTextBoxInput", "cycleTextBoxSubmitAction", "attachTextBoxFile", "sendCtrlFToTerminal", "clearScreenKeepScrollback", "focusLeft", "focusRight", "focusUp", "focusDown", "splitRight", "splitDown", "toggleSplitZoom", "equalizeSplits", "splitBrowserRight", "splitBrowserDown", "toggleCanvasLayout", "canvasRevealFocusedPane", "canvasOverview", "canvasZoomIn", "canvasZoomOut", "canvasZoomReset", "canvasTidy", "canvasAlignLeft", "canvasAlignRight", "canvasAlignTop", "canvasAlignBottom", "canvasEqualizeWidths", "canvasEqualizeHeights", "canvasDistributeHorizontally", "canvasDistributeVertically", "toggleFileExplorer", "fileExplorerOpenSelection", "fileExplorerOpenSelectionFinderAlias", "saveFilePreview", "openBrowser", "focusBrowserAddressBar", "browserBack", "browserForward", "browserReload", "browserHardReload", "browserZoomIn", "browserZoomOut", "browserZoomReset", "markdownZoomIn", "markdownZoomOut", "markdownZoomReset", "find", "findInDirectory", "findNext", "findPrevious", "hideFind", "useSelectionForFind", "toggleBrowserDeveloperTools", "showBrowserJavaScriptConsole", "toggleBrowserFocusMode", "toggleBrowserDesignMode", "toggleReactGrab", "openDiffViewer", "diffViewerScrollDown", "diffViewerScrollUp", "diffViewerScrollHalfPageDown", "diffViewerScrollHalfPageUp", "diffViewerScrollDownEmacs", "diffViewerScrollUpEmacs", "diffViewerScrollToBottom", "diffViewerScrollToTop", "diffViewerOpenFileSearch", "diffViewerNextFile", "diffViewerPreviousFile" ] }, "properties": { "fileExplorerOpenSelection": { "$ref": "#/$defs/singleBareFirstStrokeShortcutBindingNullable" }, "fileExplorerOpenSelectionFinderAlias": { "$ref": "#/$defs/singleBareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollDown": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollUp": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollHalfPageDown": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollHalfPageUp": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollDownEmacs": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollUpEmacs": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollToBottom": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerScrollToTop": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerOpenFileSearch": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerNextFile": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" }, "diffViewerPreviousFile": { "$ref": "#/$defs/bareFirstStrokeShortcutBindingNullable" } }, "additionalProperties": { "$ref": "#/$defs/shortcutBindingNullable" } }, "when": { "type": "object", "default": {}, "description": "Optional per-action context predicates (VS Code-style `when` clauses), keyed by cmux action id. Each value is a boolean expression over context keys combined with !, &&, ||, and parentheses. Boolean keys: sidebarFocus, browserFocus, markdownFocus, filePreviewTextEditorFocus, terminalFocus, commandPaletteVisible, terminalFindVisible, workspaceCanvasLayout. Typed keys support comparisons: the string sidebarMode (files, find, sessions, feed, or dock) and the integers paneCount and workspaceCount. Comparison operators are ==, !=, =~ (regex), <, <=, >, >=, and `in [a, b]`; an unknown or absent key reads as false. The boolean literals true and false are also accepted; `key == false` is the same as `!key`. The action's shortcut only fires (and only conflicts with other shortcuts) when the clause holds. Examples: { \"selectWorkspaceByNumber\": \"!sidebarFocus\" } selects workspaces with Ctrl+1–9 everywhere except when the right sidebar is focused; { \"selectSurfaceByNumber\": \"sidebarMode == 'find' && paneCount > 1\" } scopes a binding to the Find sidebar when the workspace has multiple panes.", "descriptionKey": "schemaDescriptions.shortcuts.when", "additionalProperties": { "type": "string" } } } } }, "$defs": { "colorHex": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$", "description": "Uppercase or lowercase 6-digit hex color." }, "colorHexOrNull": { "oneOf": [ { "$ref": "#/$defs/colorHex" }, { "type": "null" } ] }, "shortcutBinding": { "oneOf": [ { "$ref": "#/$defs/unboundShortcutBinding", "description": "Unbind this shortcut. Accepted values are an empty string, none, clear, unbound, or disabled." }, { "$ref": "#/$defs/shortcutFirstStroke", "description": "Single-stroke shortcut, for example cmd+n or cmd+space." }, { "type": "array", "minItems": 1, "maxItems": 2, "prefixItems": [ { "$ref": "#/$defs/shortcutFirstStroke" }, { "$ref": "#/$defs/shortcutStroke" } ], "description": "Chorded shortcut. Example: [\"ctrl+b\", \"c\"]." } ] }, "shortcutBindingNullable": { "oneOf": [ { "$ref": "#/$defs/shortcutBinding" }, { "type": "null", "description": "Unbind this shortcut." } ] }, "singleBareFirstStrokeShortcutBinding": { "oneOf": [ { "$ref": "#/$defs/unboundShortcutBinding", "description": "Unbind this shortcut. Accepted values are an empty string, none, clear, unbound, or disabled." }, { "$ref": "#/$defs/bareFirstStrokeShortcutFirstStroke", "description": "Single-stroke shortcut. Bare first strokes are accepted for this action." } ] }, "singleBareFirstStrokeShortcutBindingNullable": { "oneOf": [ { "$ref": "#/$defs/singleBareFirstStrokeShortcutBinding" }, { "type": "null", "description": "Unbind this shortcut." } ] }, "bareFirstStrokeShortcutBinding": { "oneOf": [ { "$ref": "#/$defs/unboundShortcutBinding", "description": "Unbind this shortcut. Accepted values are an empty string, none, clear, unbound, or disabled." }, { "$ref": "#/$defs/bareFirstStrokeShortcutFirstStroke", "description": "Single-stroke shortcut. Bare first strokes are accepted for this action." }, { "type": "array", "minItems": 1, "maxItems": 2, "prefixItems": [ { "$ref": "#/$defs/bareFirstStrokeShortcutFirstStroke" }, { "$ref": "#/$defs/shortcutStroke" } ], "description": "Chorded shortcut. Bare first strokes are accepted for this action. Example: [\"g\", \"g\"]." } ] }, "bareFirstStrokeShortcutBindingNullable": { "oneOf": [ { "$ref": "#/$defs/bareFirstStrokeShortcutBinding" }, { "type": "null", "description": "Unbind this shortcut." } ] }, "unboundShortcutBinding": { "type": "string", "enum": ["", "none", "clear", "unbound", "disabled"] }, "shortcutFirstStroke": { "allOf": [ { "$ref": "#/$defs/shortcutStroke" }, { "anyOf": [ { "pattern": "^(?:(?:[cC][mM][dD]|[cC][oO][mM][mM][aA][nN][dD]|[sS][hH][iI][fF][tT]|[oO][pP][tT]|[oO][pP][tT][iI][oO][nN]|[aA][lL][tT]|[cC][tT][rR][lL]|[cC][oO][nN][tT][rR][oO][lL]|[cC][tT][lL]|⌘|⇧|⌥|⌃)\\+)+" }, { "pattern": "^(?: |[sS][pP][aA][cC][eE]|[sS][pP][aA][cC][eE][bB][aA][rR]|<[sS][pP][aA][cC][eE]>)$" } ] } ], "description": "First or only shortcut stroke. Must include a modifier unless the key is Space." }, "bareFirstStrokeShortcutFirstStroke": { "allOf": [ { "$ref": "#/$defs/shortcutStroke" }, { "anyOf": [ { "pattern": "^(?:(?:[cC][mM][dD]|[cC][oO][mM][mM][aA][nN][dD]|[sS][hH][iI][fF][tT]|[oO][pP][tT]|[oO][pP][tT][iI][oO][nN]|[aA][lL][tT]|[cC][tT][rR][lL]|[cC][oO][nN][tT][rR][oO][lL]|[cC][tT][lL]|⌘|⇧|⌥|⌃)\\+)+" }, { "pattern": "^(?: |[sS][pP][aA][cC][eE]|[sS][pP][aA][cC][eE][bB][aA][rR]|<[sS][pP][aA][cC][eE]>)$" }, { "pattern": "^(?:[rR][eE][tT][uU][rR][nN]|[eE][nN][tT][eE][rR]|↩)$" }, { "pattern": "^(?:[lL][eE][fF][tT]|[aA][rR][rR][oO][wW][lL][eE][fF][tT]|[lL][eE][fF][tT][aA][rR][rR][oO][wW]|←|[rR][iI][gG][hH][tT]|[aA][rR][rR][oO][wW][rR][iI][gG][hH][tT]|[rR][iI][gG][hH][tT][aA][rR][rR][oO][wW]|→|[uU][pP]|[aA][rR][rR][oO][wW][uU][pP]|[uU][pP][aA][rR][rR][oO][wW]|↑|[dD][oO][wW][nN]|[aA][rR][rR][oO][wW][dD][oO][wW][nN]|[dD][oO][wW][nN][aA][rR][rR][oO][wW]|↓)$" }, { "pattern": "^(?:[A-Za-z0-9]|[,./\\\\;'`=\\[\\]-]|[cC][oO][mM][mM][aA]|[pP][eE][rR][iI][oO][dD]|[dD][oO][tT]|[sS][lL][aA][sS][hH]|[bB][aA][cC][kK][sS][lL][aA][sS][hH]|[sS][eE][mM][iI][cC][oO][lL][oO][nN]|[qQ][uU][oO][tT][eE]|[aA][pP][oO][sS][tT][rR][oO][pP][hH][eE]|[bB][aA][cC][kK][tT][iI][cC][kK]|[gG][rR][aA][vV][eE]|[mM][iI][nN][uU][sS]|[hH][yY][pP][hH][eE][nN]|[pP][lL][uU][sS]|[eE][qQ][uU][aA][lL][sS]|[lL][eE][fF][tT][bB][rR][aA][cC][kK][eE][tT]|[oO][pP][eE][nN][bB][rR][aA][cC][kK][eE][tT]|[rR][iI][gG][hH][tT][bB][rR][aA][cC][kK][eE][tT]|[cC][lL][oO][sS][eE][bB][rR][aA][cC][kK][eE][tT])$" } ] } ], "description": "First or only shortcut stroke. Bare printable keys are accepted for actions that opt into bare first strokes." }, "shortcutStroke": { "type": "string", "pattern": "^(?:(?:[cC][mM][dD]|[cC][oO][mM][mM][aA][nN][dD]|[sS][hH][iI][fF][tT]|[oO][pP][tT]|[oO][pP][tT][iI][oO][nN]|[aA][lL][tT]|[cC][tT][rR][lL]|[cC][oO][nN][tT][rR][oO][lL]|[cC][tT][lL]|⌘|⇧|⌥|⌃)\\+)*(?: |[A-Za-z0-9]|[lL][eE][fF][tT]|[aA][rR][rR][oO][wW][lL][eE][fF][tT]|[lL][eE][fF][tT][aA][rR][rR][oO][wW]|←|[rR][iI][gG][hH][tT]|[aA][rR][rR][oO][wW][rR][iI][gG][hH][tT]|[rR][iI][gG][hH][tT][aA][rR][rR][oO][wW]|→|[uU][pP]|[aA][rR][rR][oO][wW][uU][pP]|[uU][pP][aA][rR][rR][oO][wW]|↑|[dD][oO][wW][nN]|[aA][rR][rR][oO][wW][dD][oO][wW][nN]|[dD][oO][wW][nN][aA][rR][rR][oO][wW]|↓|[tT][aA][bB]|[rR][eE][tT][uU][rR][nN]|[eE][nN][tT][eE][rR]|↩|[sS][pP][aA][cC][eE]|[sS][pP][aA][cC][eE][bB][aA][rR]|<[sS][pP][aA][cC][eE]>|[,./\\\\;'`=\\[\\]-]|[cC][oO][mM][mM][aA]|[pP][eE][rR][iI][oO][dD]|[dD][oO][tT]|[sS][lL][aA][sS][hH]|[bB][aA][cC][kK][sS][lL][aA][sS][hH]|[sS][eE][mM][iI][cC][oO][lL][oO][nN]|[qQ][uU][oO][tT][eE]|[aA][pP][oO][sS][tT][rR][oO][pP][hH][eE]|[bB][aA][cC][kK][tT][iI][cC][kK]|[gG][rR][aA][vV][eE]|[mM][iI][nN][uU][sS]|[hH][yY][pP][hH][eE][nN]|[pP][lL][uU][sS]|[eE][qQ][uU][aA][lL][sS]|[lL][eE][fF][tT][bB][rR][aA][cC][kK][eE][tT]|[oO][pP][eE][nN][bB][rR][aA][cC][kK][eE][tT]|[rR][iI][gG][hH][tT][bB][rR][aA][cC][kK][eE][tT]|[cC][lL][oO][sS][eE][bB][rR][aA][cC][kK][eE][tT]|[fF](?:[1-9]|1[0-9]|20)|[vV][oO][lL][uU][mM][eE][uU][pP]|[mM][eE][dD][iI][aA][vV][oO][lL][uU][mM][eE][uU][pP]|[mM][eE][dD][iI][aA]\\.[vV][oO][lL][uU][mM][eE][uU][pP]|[vV][oO][lL][uU][mM][eE][dD][oO][wW][nN]|[mM][eE][dD][iI][aA][vV][oO][lL][uU][mM][eE][dD][oO][wW][nN]|[mM][eE][dD][iI][aA]\\.[vV][oO][lL][uU][mM][eE][dD][oO][wW][nN]|[bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][uU][pP]|[mM][eE][dD][iI][aA][bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][uU][pP]|[mM][eE][dD][iI][aA]\\.[bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][uU][pP]|[bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][dD][oO][wW][nN]|[mM][eE][dD][iI][aA][bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][dD][oO][wW][nN]|[mM][eE][dD][iI][aA]\\.[bB][rR][iI][gG][hH][tT][nN][eE][sS][sS][dD][oO][wW][nN]|[mM][uU][tT][eE]|[mM][eE][dD][iI][aA][mM][uU][tT][eE]|[mM][eE][dD][iI][aA]\\.[mM][uU][tT][eE]|[pP][lL][aA][yY][pP][aA][uU][sS][eE]|[mM][eE][dD][iI][aA][pP][lL][aA][yY][pP][aA][uU][sS][eE]|[mM][eE][dD][iI][aA]\\.[pP][lL][aA][yY][pP][aA][uU][sS][eE]|[nN][eE][xX][tT][tT][rR][aA][cC][kK]|[mM][eE][dD][iI][aA][nN][eE][xX][tT]|[mM][eE][dD][iI][aA]\\.[nN][eE][xX][tT]|[mM][eE][dD][iI][aA]\\.[nN][eE][xX][tT][tT][rR][aA][cC][kK]|[pP][rR][eE][vV][iI][oO][uU][sS][tT][rR][aA][cC][kK]|[mM][eE][dD][iI][aA][pP][rR][eE][vV][iI][oO][uU][sS]|[mM][eE][dD][iI][aA]\\.[pP][rR][eE][vV][iI][oO][uU][sS]|[mM][eE][dD][iI][aA]\\.[pP][rR][eE][vV][iI][oO][uU][sS][tT][rR][aA][cC][kK])$", "description": "One keyboard shortcut stroke using modifier+key syntax. Supported key names include space, Space, , and ." } } }