# How cmux Integrates with AppleScript and System Automation

> Discover how cmux integrates with AppleScript for powerful macOS system automation. Programmatically control windows, tabs, panes, and text injection in your terminal workflow.

- Repository: [manaflow-ai/cmux](https://github.com/manaflow-ai/cmux)
- Tags: how-to-guide
- Published: 2026-03-29

---

**TLDR:** cmux exposes a comprehensive AppleScript API through Swift scripting objects, allowing macOS automation tools to programmatically create windows, manage tabs, split panes, and inject text into terminals.

The manaflow-ai/cmux terminal multiplexer provides deep system automation capabilities through native AppleScript integration. By implementing scriptable objects in Swift, cmux allows macOS automation tools like Shortcuts and Keyboard Maestro to control terminal sessions without launching external binaries. This integration relies on three core architectural components that bridge the gap between AppleScript commands and the application's UI state.

## Architecture Overview

The cmux AppleScript integration rests on three Swift components that expose the terminal multiplexer’s internal state to macOS automation frameworks.

### NSApplication Extension

In [`Sources/AppleScriptSupport.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/AppleScriptSupport.swift) (lines 81‑115), the `NSApplication` extension provides global scripting entry points such as `scriptWindows`, `terminals`, and `validateScript`. This extension registers custom script commands and acts as the primary bridge that macOS uses when AppleScript targets the cmux application.

### AppDelegate Helpers

The [`AppDelegate.swift`](https://github.com/manaflow-ai/cmux/blob/main/AppDelegate.swift) file (lines 4432‑4476) maintains the list of scriptable windows, tabs, and terminals through helper methods including `scriptableMainWindows()`, `scriptableMainWindow(windowId:)`, and `scriptableMainWindowForTab(_:)`. These functions supply the concrete model objects that back the scripting layer’s object graph.

### Scripting Objects

The `ScriptWindow`, `ScriptTab`, and `ScriptTerminal` classes — defined in [`Sources/AppleScriptSupport.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/AppleScriptSupport.swift) (lines 120‑290) — are `NSObject` subclasses that map directly to cmux UI elements. These classes implement `NSScriptCommand` selectors such as `handleActivateWindowCommand:`, `handleCloseCommand:`, and `handlePerformActionScriptCommand:`, exposing properties like `id`, `title`, and `terminals` as AppleScript-compatible selectors.

## How the Scripting Bridge Works

The integration follows a six-step architecture that translates AppleScript instructions into UI actions.

**1. Enabling the Bridge**

The `NSApplication.isAppleScriptEnabled` property always returns `true` (lines 84‑90), ensuring the scripting bridge is active. This flag gates every scriptable property and command in the application.

**2. Discoverable Object Hierarchies**

The `scriptWindows` property returns an array of `ScriptWindow` objects gathered from `AppDelegate.shared?.scriptableMainWindows()` (line 106). The `terminals` property flattens all terminals across every window and tab (lines 129‑138).

**3. Object Specifiers**

Each scripting class overrides `objectSpecifier` to provide a unique `NSUniqueIDSpecifier` keyed by the underlying model object’s UUID. This allows AppleScript to resolve objects via selectors like `valueInScriptWindowsWithUniqueID:` (lines 194‑202, 236‑244).

**4. Command Handling**

Custom `NSScriptCommand` subclasses implement the actual work:

- `handleNewWindowScriptCommand:` creates a new cmux window via `AppDelegate.shared?.createMainWindow()` (line 182)
- `handleNewTabScriptCommand:` adds a new workspace (tab) to a specified or frontmost window
- `handlePerformActionScriptCommand:` forwards string actions (such as Ghostty bindings) to a terminal
- `handleSplitCommand:` performs pane splits within a terminal
- `handleFocusCommand:` brings a terminal to the foreground
- `ScriptInputTextCommand` reads the direct parameter as text and sends it to the target terminal (lines 662‑686)

**5. Error Handling**

When scripts request invalid objects or missing parameters, the code populates `command.scriptErrorNumber` and `command.scriptErrorString` using localized strings from `AppleScriptStrings` (lines 94‑99, 165‑172).

**6. Security and Focus Policy**

All script commands first call `NSApp.validateScript(command:)` to verify AppleScript is enabled. Commands that could steal focus, such as `handleActivateWindowCommand:`, explicitly check `focusScriptableMainWindow(..., bringToFront: true)` before executing.

## Practical AppleScript Examples

### Creating Windows and Typing Commands

```applescript
tell application "cmux"
    set newWin to make new script window
    set termList to terminals of newWin
    set firstTerm to item 1 of termList
    input text "ls -la" to firstTerm
end tell

```

This script invokes `NSApplication.handleNewWindowScriptCommand:` (line 182), retrieves terminals via `NSApplication.terminals` (lines 129‑138), and executes `ScriptInputTextCommand` (lines 662‑686) to inject text.

### Splitting Terminal Panes

```applescript
tell application "cmux"
    set frontTerm to first terminal of front window
    split frontTerm direction "GSdn"
end tell

```

The `split` command resolves the terminal via `valueInTerminalsWithUniqueID:` (line 206), then maps `"GSdn"` to `SplitDirection.down` using `ScriptSplitDirection` (lines 90‑104) before executing `ScriptTerminal.handleSplitCommand:` (lines 620‑665).

### Focusing Tabs by UUID

```applescript
set targetID to "A1B2C3D4-E5F6-7890-1234-56789ABCDEF0"
tell application "cmux"
    set targetTab to value in tabs with unique ID targetID
    select targetTab
end tell

```

This resolves the tab via `ScriptWindow.valueInTabs(uniqueID:)` (lines 296‑304), then invokes `ScriptTab.handleSelectTabCommand:` (lines 446‑459) to activate it.

### Closing Windows

```applescript
tell application "cmux"
    close front window
end tell

```

The `close` command triggers `ScriptWindow.handleCloseWindowCommand:` (lines 334‑352) to dismiss the frontmost window.

## Key Implementation Files

| File | Purpose | Key Lines |
|------|---------|-----------|
| [`Sources/AppleScriptSupport.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/AppleScriptSupport.swift) | Scripting objects, command handlers, error strings, and `NSApplication` extension | 81‑115, 120‑290, 662‑686 |
| [`Sources/AppDelegate.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/AppDelegate.swift) | Helper methods mapping UI state to scriptable objects | 4432‑4476 |
| [`Sources/TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/TerminalController.swift) | Internal usage of `scriptableMainWindows()` for command broadcasting | ~5154 |
| `Resources/Info.plist` | Declares AppleScript terminology and class names (`CmuxScriptWindow`, `CmuxScriptTab`, `CmuxScriptTerminal`) for runtime resolution | N/A |

## Summary

- cmux implements **three core Swift components** — an `NSApplication` extension, `AppDelegate` helpers, and scripting objects — to expose its UI to AppleScript.
- **Object specifiers** use UUID-based `NSUniqueIDSpecifier` instances to ensure reliable script-to-object resolution.
- **Command handlers** translate high-level AppleScript commands like `make new script window` or `split` into concrete cmux actions.
- **Security checks** via `validateScript:` and focus policies prevent unauthorized automation actions.
- The integration supports **Shortcuts, Keyboard Maestro**, and any macOS tool that drives scriptable applications.

## Frequently Asked Questions

### How do I enable AppleScript support for cmux?

AppleScript support is always enabled in cmux. The `NSApplication.isAppleScriptEnabled` property returns `true` by default (lines 84‑90 in [`AppleScriptSupport.swift`](https://github.com/manaflow-ai/cmux/blob/main/AppleScriptSupport.swift)), meaning the application immediately responds to AppleScript commands without requiring additional configuration or preferences changes.

### Which cmux objects can I control via AppleScript?

You can control three primary object types: **ScriptWindow** (top-level windows), **ScriptTab** (workspace tabs), and **ScriptTerminal** (individual terminal panes). Each exposes properties like `id`, `title`, and collections of child objects (e.g., `terminals of newWin`), allowing you to navigate the entire window hierarchy programmatically.

### How does cmux handle AppleScript errors?

When a script provides invalid parameters or requests non-existent objects, cmux populates `command.scriptErrorNumber` and `command.scriptErrorString` with localized error descriptions from the `AppleScriptStrings` table (lines 94‑99 and 165‑172). These error messages surface directly in the macOS Script Editor or calling automation tool, providing clear feedback about what went wrong.

### Can I use the macOS Shortcuts app with cmux?

Yes. Because cmux exposes a standard AppleScript dictionary, you can use the **Run AppleScript** action in Shortcuts, or any automation tool like Keyboard Maestro, Hammerspoon, or Alfred, to drive cmux. The `validateScript:` security check ensures that only authorized scripts can execute focus-stealing commands, making the integration safe for automated workflows.