> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PTY-for-AI

> Terminal-level AI session control — run, read, and orchestrate any AI CLI through PTY, not structured I/O.

# PTY-for-AI

A pattern for controlling AI CLI tools at the terminal level,
enabling cross-LLM orchestration without provider-specific APIs.

## The Problem

Every AI coding CLI (Claude Code, Codex, Gemini CLI, Aider) communicates with its agents through **structured I/O** — JSON pipes, API calls, or protocol messages. This creates walls:

* Subagents can only call tools, not run interactive terminal sessions
* One AI cannot control another AI at the terminal level
* Multi-agent teams are locked to a single provider
* Cross-LLM collaboration requires per-pair plugins (N² problem)

## The Pattern

Instead of structured I/O between agents, use **PTY sessions** — real terminal instances that any CLI can run in.

```
Structured I/O (how everyone else does it):
  Parent AI → spawn child → stdin(JSON) → stdout(JSON) → parse
  = Pipe. Not a terminal. Not interactive.
  = Child can call tools but cannot run another CLI.

PTY-for-AI (what NIIA does):
  Daemon → PTY session → real terminal
  = Anything that runs in a terminal is controllable.
  = Interactive read/write. Any CLI. Any LLM.
```

## How It Works

### 1. Daemon manages PTY sessions

A persistent daemon (launchd/systemd) owns PTY sessions.
Sessions survive terminal closures, reboots, and SSH disconnects.

### 2. Headless server bridges to network

A headless server connects PTY sessions to a gateway,
enabling remote access without a visible terminal window.

### 3. CLI commands control sessions

```bash theme={null}
# Write to a PTY session (type into terminal)
niia write --session <ID> $'claude\r'

# Wait for output to settle
niia wait-idle --session <ID>

# Read the answer
niia get-answer --session <ID> "your question"
```

### 4. Any CLI is a "worker"

```bash theme={null}
# Claude as worker
niia write --session S1 $'claude\r'

# Gemini as worker
niia write --session S2 $'gemini\r'

# Codex as worker
niia write --session S3 $'codex\r'

# SSH into a server
niia write --session S4 $'ssh production\r'
```

The daemon doesn't know or care what's running inside.
PTY-level control is LLM-agnostic by design.

## Why PTY, Not Pipe

|                     | Structured I/O (pipe) | PTY-for-AI         |
| ------------------- | --------------------- | ------------------ |
| Protocol            | JSON/NDJSON           | Terminal I/O       |
| Interactive         | No                    | Yes                |
| Target              | Same LLM only         | Any CLI            |
| Cross-LLM           | Plugin per pair (N²)  | One interface (N)  |
| Provider lock-in    | Yes                   | No                 |
| Heterogeneous teams | No                    | Yes                |
| Cost routing        | Model selection only  | LLM-level routing  |
| Failover            | Not possible          | Switch PTY session |
| Offline             | Not possible          | Local LLM in PTY   |

## Session Plugins

PTY sessions are configured through daemon-external plugins.
The daemon binary is never modified — plugins transform session parameters before spawn.

| Plugin         | What it does               | How                             |
| -------------- | -------------------------- | ------------------------------- |
| **worktree**   | Git-isolated workspace     | Changes `cwd` to worktree path  |
| **sandbox**    | OS-level process isolation | Wraps `shell` with sandbox-exec |
| **scratchpad** | Shared knowledge directory | Creates shared dir in workspace |
| **env**        | Environment injection      | Sets env vars on session        |
| **timeout**    | Session lifetime limit     | Wraps shell with timeout        |

Plugins compose. Order matters: worktree runs before sandbox,
so sandbox restricts writes to the worktree path.

```bash theme={null}
# Worktree + sandbox in one command
niia serve --worktree feat-x --sandbox
```

## Architecture

```
┌──────────────────────────────────────────────────┐
│  niia CLI (plugin layer)                         │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐          │
│  │worktree  │ │ sandbox  │ │scratchpad│  ...     │
│  └────┬─────┘ └────┬─────┘ └──────────┘          │
│       │            │                             │
│       ▼            ▼                             │
│  CreateSession { cwd: wt_path, shell: sb_cmd }   │
├───────────────────┬──────────────────────────────┤
│  PTY daemon       │  Just spawn. Unchanged.      │
├───────────────────┼──────────────────────────────┤
│  Headless server  │  Bridge to network.          │
├───────────────────┼──────────────────────────────┤
│  Gateway / P2P    │  Remote access.              │
└───────────────────┘──────────────────────────────┘
```

The daemon protocol already supports `cwd` and `shell` fields.
Plugins work by transforming these fields before the daemon sees them.
No daemon modification needed — ever.

## Cross-Machine

PTY-for-AI extends across machines through gateway relay or P2P:

```bash theme={null}
# Control AI on a remote machine
niia remote write MACHINE-B "claude\r"
niia remote read MACHINE-B

# Remote machine's PTY sessions are accessible
# as if they were local
```

No VPN required. Works through NAT. Encrypted end-to-end.

## Comparison with Existing Approaches

### Claude Code Teams

Spawns Claude CLI instances in tmux/iTerm2 panes.
Limited to Claude only. Requires visible terminal. Single machine.

### Codex Plugin for Claude Code

Subprocess JSON-RPC to Codex server.
One direction (Codex → Claude). Requires both installed. Single machine.

### claude-squad

Tmux session manager for multiple AI CLIs.
Requires tmux. No headless. No remote. No daemon persistence.

### Warp

Terminal replacement with multi-agent UI.
Requires Warp app. No headless. No cross-machine. No daemon.

### PTY-for-AI (NIIA)

Daemon-managed headless PTY sessions.
Any CLI. Any LLM. Cross-machine. Persistent. Plugin-extensible.

## The Declarative Layer: connector.json

PTY-for-AI is the execution layer. [connector.json](/openclis/specs/connector-json) is the declarative spec that sits on top.

connector.json describes *which* agents run, in *what* topology (pipeline, dialogue, meeting, mesh, recursive), on *which* machines, with *what* isolation. The runtime reads connector.json and translates it into PTY daemon calls.

```bash theme={null}
niia run workflow.connector.json
# → reads spec → creates PTY sessions → applies plugins → runs pipeline
```

See [Introducing connector.json](/openclis/specs/connector-json/introducing) for the full spec.

## Design Principles

1. **PTY, not pipe** — terminal-level control, not structured I/O
2. **Daemon, not process** — persistent, survives everything
3. **Headless, not visual** — no terminal window needed
4. **Plugins, not patches** — extend without modifying daemon
5. **LLM-agnostic** — if it runs in a terminal, it's controllable
6. **Infrastructure, not prompts** — orchestration in daemon, not in system prompts

***

PTY-for-AI is an open spec by [OpenCLIs](https://openclis.com).
Runtime implementation by [NIIA](https://monolex.ai) (Monolex).

Spec: [pty4ai.com](https://pty4ai.com)
