# cmux v1 vs v2 Socket API Protocols: Key Differences and Migration Guide

> Discover the key differences between cmux v1 plain text and v2 JSON-RPC protocols. Learn about authentication, response formats, and migration to v2 for your Unix-domain socket.

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

---

**cmux v1 uses simple plain-text line commands while v2 uses JSON-RPC structured messages, with both protocols sharing the same Unix-domain socket but differing in authentication flows, response formats, and UI focus policy enforcement.**

The `manaflow-ai/cmux` repository provides a Unix-domain socket automation API that maintains backward compatibility through dual protocol support. Understanding the architectural differences between **cmux v1 vs v2 socket API protocols** is critical for migrating existing scripts or building new integrations, as the versions handle authentication, command parsing, and focus-stealing protections through entirely different mechanisms.

## Wire Format and Message Parsing

The protocols diverge immediately at the parsing layer within `TerminalController.handleCommandLine`.

**v1 (Legacy)** accepts simple UTF-8 lines terminated by `\n`. The raw line is split on whitespace and matched against a hard-coded command `switch`. In [`Sources/TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/TerminalController.swift), the v1 parser operates at lines 1648–1657, treating inputs like `list_windows` as bare command strings without structured parameters.

**v2 (JSON-RPC)** requires one-line JSON objects terminated with `\n`. The payload must follow a JSON-RPC-like shape: `{ "id": 1, "method": "window.focus", "params": { "window": "uuid" } }`. The JSON decoding block starts at line 2007, extracting the `method` field to route through the same underlying command switch.

## Authentication Mechanisms

Both protocols support password authentication but use incompatible wire formats.

**v1 Authentication** sends a plain-text token: `auth <password>`. The server handles this via `passwordLoginV1ResponseIfNeeded` (lines 1279–1280), validating the password against the raw command string.

**v2 Authentication** uses a structured JSON-RPC method call: `{ "method": "auth.login", "params": { "password": "secret" } }`. This flows through `passwordLoginV2ResponseIfNeeded` (lines 2028–2029), parsing the credentials from the JSON payload rather than whitespace-split strings.

## Response Models and Error Handling

The response structures reflect the protocols' design philosophies.

**v1 Responses** return plain-text strings prefixed with `OK:` or `ERROR:`, requiring clients to parse status from string prefixes.

**v2 Responses** return structured JSON objects: `{ "ok": true, "result": … }` for success or `{ "ok": false, "error": { "code": "…", "message": "…" } }` for failures. The implementation uses helper functions `v2Ok` and `v2Error` throughout the v2 branch to ensure consistent response formatting.

## Focus Policy and Command Classification

v2 introduces granular UI focus protection that v1 lacks.

In [`TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/TerminalController.swift), commands are classified into two static sets: `focusIntentV1Commands` (lines 1818–1827) and `focusIntentV2Methods` (lines 1829–1844). The `withSocketCommandPolicy` function (lines 299–313) records whether a specific method is permitted to mutate UI focus, preventing legacy "focus-steal" bugs where automation commands unintentionally shift user attention.

All v1 commands run with the same focus mutation rules, while v2 methods respect the `socketCommandAllowsInAppFocusMutations` lookup, allowing fine-grained control over which automation actions can disrupt the user's current context.

## Protocol Detection and Version Routing

Both protocols coexist on the same socket connection. The server distinguishes them by inspecting the first character of the payload:

- If the line begins with `{`, it routes to the v2 JSON parser (lines 2020–2030)
- Otherwise, it treats the payload as v1 plain text (lines 1648–1657)

This detection happens inside `handleCommandLine`, allowing legacy clients to operate simultaneously with modern JSON-RPC integrations. Version gating through `SocketControlSettings` applies to both protocols, though the v2 parser runs in all modes except when password authentication blocks unauthenticated access (line 1988–1989).

## Practical Implementation Examples

### Connecting via v1 (Shell)

Use netcat to send bare commands to the Unix socket:

```bash
printf 'list_windows\n' | nc -U /tmp/cmux-debug.sock

# Response: OK: [{ "id":"…", "title":"…" }, …]

```

### Connecting via v2 (Python)

Send structured JSON-RPC requests with explicit method names and parameters:

```python
import socket, json

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/tmp/cmux-debug.sock")

request = {
    "id": 1,
    "method": "window.focus",
    "params": {"window": "e2a2f4b5-…"}
}
sock.sendall((json.dumps(request) + "\n").encode())

response = sock.recv(4096).decode().splitlines()[0]
print(json.loads(response))

# Output: {"ok": true, "result": {"focused": true}}

```

### v2 Authentication Flow

Authenticate using the structured login method before issuing protected commands:

```python
import socket, json

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/tmp/cmux-debug.sock")

login = {
    "id": 2,
    "method": "auth.login",
    "params": {"password": "my-secret"}
}
sock.sendall((json.dumps(login) + "\n").encode())
print(json.loads(sock.recv(4096).decode()))

# Output: {"ok": true, "result": {"authenticated": true}}

```

## Summary

- **Message Format**: v1 uses plain-text lines; v2 uses JSON-RPC objects with `method` and `params` fields.
- **Authentication**: v1 sends `auth <password>` as bare text; v2 uses `auth.login` with JSON credentials.
- **Responses**: v1 returns `OK:`/`ERROR:` strings; v2 returns structured JSON with boolean `ok` fields.
- **Focus Safety**: v2 implements `focusIntentV2Methods` classification through `withSocketCommandPolicy` to prevent focus stealing; v1 commands follow legacy mutation rules.
- **Compatibility**: Both protocols run on the same socket, distinguished by the opening character `{` for v2.

## Frequently Asked Questions

### Can v1 and v2 clients connect to the same cmux instance simultaneously?

Yes. The `TerminalController` accepts both protocols on the same Unix-domain socket. The server inspects the first character of each line—if it is `{`, the message routes to the v2 JSON parser; otherwise, it processes as v1 plain text. This allows gradual migration without breaking existing integrations.

### How does focus policy differ between v1 and v2 commands?

v1 commands execute with legacy focus mutation rules defined in `focusIntentV1Commands`. v2 methods respect granular policies defined in `focusIntentV2Methods` and enforced by `withSocketCommandPolicy`, which prevents automation scripts from stealing UI focus unless explicitly permitted. This fixes "focus-steal" bugs present in the legacy protocol.

### Is v1 deprecated or will it be removed from future cmux releases?

While v2 is the recommended protocol for new development, v1 remains supported for backward compatibility. The source code maintains both `passwordLoginV1ResponseIfNeeded` and `passwordLoginV2ResponseIfNeeded` handlers, and the `SocketControlSettings` gating applies to both versions equally. However, new features and focus protections are implemented primarily in the v2 layer.

### Which protocol should I use for new automation scripts?

Use **v2** for all new implementations. The JSON-RPC format provides structured error handling, extensible parameters through the `params` object, and proper focus policy enforcement. The `v2Ok` and `v2Error` response helpers ensure consistent error codes that are easier to parse programmatically than v1's plain-text prefixes.