System Overview
Key Components
PTY Sessions (node-pty)
Each terminal session spawns a real pseudo-terminal usingnode-pty. The agent process runs inside this PTY and behaves exactly as if it were in a normal terminal. CliDeck doesn’t inject any middleware between you and the agent.
Terminal output is buffered (up to 200KB per session) and sent to the browser over WebSocket. The browser renders it using xterm.js.
WebSocket Communication
A single WebSocket connection carries all messages between the browser and server. Messages are JSON-encoded with atype field for routing. The server broadcasts to all connected clients — you can have multiple browser tabs open.
OTLP Telemetry Receiver
The server runs an HTTP endpoint atPOST /v1/logs that accepts OpenTelemetry log data in JSON format. When an agent is launched, CliDeck sets environment variables that point the agent’s OTLP exporter to this local endpoint.
The receiver:
- Parses the OTLP resource logs
- Matches the log to the correct session (via
termix.session_idresource attribute) - Extracts the agent’s session ID from log record attributes
- Detects if telemetry is properly configured (triggers setup toast if not)
OpenCode Plugin Bridge
OpenCode uses a different integration path. A JavaScript plugin inside OpenCode sends HTTP events toPOST /opencode-events. The bridge maps these events to the correct CliDeck session by matching the working directory.
Activity Monitor
A 1-second polling loop measures I/O rates for each session:- Bytes in/out since last poll
- Burst duration — how long the current output burst has been going
- Resets after 2 seconds of silence
Plugin System
Plugins live in~/.clideck/plugins/. Each plugin is a folder with an index.js (backend) and optional client.js (frontend), clideck-plugin.json (manifest), and public/ (static assets).
On startup, CliDeck seeds bundled plugins (Trim Clip, Voice Input) into the plugins directory if they don’t already exist. Then it loads all plugin folders, calls their init() with a sandboxed API, and wires up their hooks (input/output/status). Plugins communicate with the browser through namespaced WebSocket messages.
The plugin API provides:
- Session hooks — observe output, transform input, react to status changes
- Frontend messaging — bidirectional communication between backend and browser
- Toolbar actions — add buttons to the terminal toolbar
- Settings — user-configurable settings with type validation, persisted in
config.json - Lifecycle — shutdown handlers for cleanup
Transcript Store
Every session’s I/O is recorded as plain-text JSONL in~/.clideck/transcripts/. ANSI codes are stripped, short lines filtered out. The transcript is used for sidebar search — a cache is built on startup and updated incrementally.
Data Flow: Agent Status
Data Flow: Session Resume
Startup Detection
When CliDeck starts, it scans for existing agent configurations on disk:- Codex: checks
~/.codex/config.tomlfor an[otel]section pointing to localhost:4000 - Gemini CLI: checks
~/.gemini/settings.jsonfor atelemetryobject with the local endpoint - OpenCode: checks if
~/.config/opencode/plugins/clideck-bridge.jsexists - Claude Code: always detected (built-in telemetry)
Local Only
CliDeck runs entirely on your machine. There’s no cloud service, no account, no external API calls. The Node.js server binds to127.0.0.1:4000 — it’s not accessible from other machines on your network.
If the Node.js server stops, all PTY processes stop too. This is intentional — CliDeck manages terminal sessions locally.