# Understanding the Structure of cmux v2 JSON Socket Protocol Requests and Responses

> Explore the cmux v2 JSON socket protocol structure. Learn how this JSON-RPC 2.0 style API uses Unix-domain sockets for efficient communication with specific envelope fields.

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

---

**The cmux v2 JSON socket protocol uses a lightweight JSON-RPC 2.0 style API over Unix-domain sockets, requiring each request and response to be a single UTF-8 JSON line terminated by `\n` with specific envelope fields for routing and error handling.**

The cmux v2 JSON socket protocol defines the wire format that external clients use to communicate with the terminal multiplexer daemon in the manaflow-ai/cmux repository. This protocol enables programmatic control of windows, workspaces, and terminal surfaces through a line-delimited JSON interface that follows JSON-RPC 2.0 conventions while using a simplified response envelope.

## Request Envelope Structure

Every v2 protocol request must be a single line of UTF-8 JSON ending with a newline character. According to the source code in [`Sources/TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/TerminalController.swift), the `processV2Command` method (lines 1885–2009) validates and dispatches incoming requests.

A valid request contains four required fields:

- **`jsonrpc`**: Must be the string `"2.0"` to identify the protocol version
- **`id`**: Any JSON value (typically a number or string) used to correlate responses
- **`method`**: A dot-separated string identifying the operation (e.g., `window.list`, `surface.send_text`)
- **`params`**: An optional JSON object containing method arguments; may be an empty object

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "window.list",
  "params": {}
}

```

The server validates that `jsonrpc` equals `"2.0"` and checks the `method` against an internal allow-list called `focusIntentV2Methods` before dispatching to the appropriate handler.

## Response Format Specifications

Responses mirror the request's `id` field and use a boolean `ok` field to indicate success or failure. The `v2Ok` (lines 2923–2929) and `v2Error` (lines 2931–2939) helper functions in [`TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/TerminalController.swift) construct these envelopes.

### Success Responses

A successful response returns `ok: true` with the result payload:

```json
{
  "id": 1,
  "ok": true,
  "result": {
    "windows": [...]
  }
}

```

### Error Responses

Failed operations return `ok: false` with a structured error object:

```json
{
  "id": 1,
  "ok": false,
  "error": {
    "code": "method_not_found",
    "message": "Method does not exist",
    "data": null
  }
}

```

The error object always contains `code` (a short string identifier) and `message` (human-readable description), with an optional `data` field for additional context.

### Encoding Rules

The `v2Encode` function (lines 2957–2966) handles serialization, ensuring that any internal newline characters within JSON values are escaped as `\\n` to maintain the single-line-per-message protocol invariant.

## Method Taxonomy

The v2 protocol organizes commands into functional domains. The complete method dispatch table lives inside the `switch method` block within `processV2Command`.

**System methods**: `system.ping`, `system.capabilities`, `system.identify`, `system.tree`

**Authentication**: `auth.login` returns an object with `authenticated` and `required` boolean fields

**Window management**: `window.list`, `window.current`, `window.focus`, `window.create`, `window.close`

**Workspace operations**: `workspace.list`, `workspace.create`, `workspace.select`, `workspace.current`

**Surface (pane) control**: `surface.list`, `surface.current`, `surface.focus`, `surface.send_text`, `surface.send_key`, `surface.refresh`, `surface.health`

**Debug utilities**: `debug.terminals`

## Protocol Implementation in Swift

The built-in `ControlSocketClient` class demonstrates the proper wire format. This example mirrors the implementation in `TerminalControllerTests.sendV2Request`:

```swift
import Foundation

let socketPath = "/tmp/cmux-debug.sock"
let client = ControlSocketClient(path: socketPath, responseTimeout: 2.0)

let request: [String: Any] = [
    "jsonrpc": "2.0",
    "id": 1,
    "method": "window.list",
    "params": [:]
]
let json = try JSONSerialization.data(withJSONObject: request)
let line = String(data: json, encoding: .utf8)! + "\n"

if let rawResponse = client.sendLine(line) {
    let data = rawResponse.data(using: .utf8)!
    let obj = try JSONSerialization.jsonObject(with: data) as! [String: Any]
    
    if let ok = obj["ok"] as? Bool, ok {
        print("Success →", obj["result"]!)
    } else {
        print("Error →", (obj["error"] as? [String: Any])?["message"] ?? "unknown")
    }
}

```

## Python Client Example

For raw socket interaction without Swift dependencies:

```python
import socket, json

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

payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "system.ping",
    "params": {}
}
line = json.dumps(payload) + "\n"
sock.sendall(line.encode("utf-8"))

response = b""
while not response.endswith(b"\n"):
    chunk = sock.recv(4096)
    if not chunk:
        break
    response += chunk

resp_obj = json.loads(response.decode())
print(resp_obj)  # → {'id': 1, 'ok': True, 'result': {'pong': True}}

sock.close()

```

## Bash One-Liner with Socat

For quick debugging or shell scripts:

```bash
payload='{"jsonrpc":"2.0","id":1,"method":"window.list","params":{}}'
printf '%s\n' "$payload" | socat - UNIX-CONNECT:/tmp/cmux-debug.sock

```

## Key Source Files

Understanding these files is essential for implementing compatible clients:

- **[`Sources/TerminalController.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/TerminalController.swift)**: Contains the core socket server implementation, including `processV2Command` for request parsing, `v2Ok`/`v2Error` response builders, and the complete method dispatch table.
- **[`cmuxTests/TerminalControllerSocketSecurityTests.swift`](https://github.com/manaflow-ai/cmux/blob/main/cmuxTests/TerminalControllerSocketSecurityTests.swift)**: Provides reference implementations showing valid JSON-RPC request construction and response verification.
- **[`CLI/cmux.swift`](https://github.com/manaflow-ai/cmux/blob/main/CLI/cmux.swift)**: Demonstrates how command-line arguments map to socket protocol invocations.
- **[`Sources/SocketControlSettings.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/SocketControlSettings.swift)**: Defines default socket paths and permission handling required for client connection setup.

## Summary

- The cmux v2 JSON socket protocol requires **single-line, newline-terminated JSON messages** over Unix-domain sockets.
- Requests must include **`jsonrpc: "2.0"`**, an **`id`**, a **`method`**, and optional **`params`**.
- Responses use an **`ok`** boolean field to indicate success, with **`result`** for data or **`error`** (containing `code`, `message`, and optional `data`) for failures.
- Internal newlines are escaped by the **`v2Encode`** function to maintain the line-delimited format.
- Method handlers are validated against an allow-list in **`processV2Command`** before execution.

## Frequently Asked Questions

### What transport layer does the cmux v2 protocol use?

The protocol communicates over **Unix-domain sockets** (AF_UNIX) using stream sockets (SOCK_STREAM). The default socket path is typically `/tmp/cmux-debug.sock` or a path specified during daemon startup, as defined in [`Sources/SocketControlSettings.swift`](https://github.com/manaflow-ai/cmux/blob/main/Sources/SocketControlSettings.swift).

### How does the server handle malformed JSON or protocol violations?

The `processV2Command` function validates that the `jsonrpc` field equals exactly `"2.0"` and that the `method` exists in the `focusIntentV2Methods` allow-list. Invalid requests receive an error response with `ok: false` and an appropriate error code, while parse failures at the JSON level typically result in connection termination or silent dropping depending on the server's error handling context.

### Can the `id` field be any JSON type, or must it be a number?

The `id` field can be **any valid JSON value**, including numbers, strings, or null, though the implementation typically uses integers. The server echoes this value verbatim in the response to allow clients to correlate asynchronous responses with their original requests.

### Are batch requests (multiple JSON objects in one message) supported?

No, the v2 protocol does not support JSON-RPC batch requests. Each request must be a **single JSON object** terminated by a newline character (`\n`). The `v2Encode` function explicitly ensures responses are single-line by escaping internal newlines, and the parser reads line-by-line from the socket buffer.