Architecture
taiku has three main components: a CLI client, a relay server, and a browser frontend. The server never sees plaintext terminal data.
Overview
Section titled “Overview”flowchart LR
subgraph CLI["CLI (Rust)"]
PTY[PTY Shell]
ENC1[AES-128 Encrypt]
end
subgraph Server["Server (Rust)"]
Relay[Relay + Store]
Meta[Presence & Metadata]
end
subgraph Browser["Browser (Svelte)"]
Term[xterm.js]
ENC2[AES-128 Decrypt]
end
PTY --> ENC1
ENC1 -- "gRPC / HTTP2<br/>encrypted terminal data" --> Relay
Relay -- "WebSocket / CBOR<br/>encrypted stream" --> ENC2
ENC2 --> Term
Term -- "encrypted input" --> Relay
Relay -- "encrypted input" --> ENC1
Meta -. "cursor positions,<br/>user presence" .-> Browser
CLI → Server
Section titled “CLI → Server”The CLI opens a bidirectional gRPC stream (Channel RPC) over HTTP/2. It sends:
- Encrypted terminal output — AES-128-CTR ciphertext, chunked
- Shell lifecycle events — creation acknowledgments, closure
It receives:
- Encrypted keyboard input — from browser users
- Resize events — when browser users resize a terminal
- Session events — user join/leave, adoption requests
Server
Section titled “Server”The server is a Rust binary using Tonic (gRPC) and Axum (HTTP/WebSocket). It stores:
- Encrypted terminal chunks in memory (up to 2 MiB per shell)
- User presence (names, cursor positions, focus state)
- Session metadata (not terminal content)
With Redis configured, sessions can be snapshotted and routed across multiple server instances. Browser WebSocket connections are transparently proxied between nodes.
Sessions expire 5 minutes after the CLI disconnects.
Server → Browser
Section titled “Server → Browser”Browsers connect via WebSocket to /api/s/{session_id}. The wire format is CBOR (binary, compact) — not JSON. The client wrapper handles automatic reconnection with offline message queuing.
sequenceDiagram
participant B as Browser
participant S as Server
B->>S: WebSocket connect
S->>B: Hello (user ID assigned)
B->>S: Key verification (encrypted zeros)
S->>S: Constant-time comparison
S->>B: Connection established
S->>B: Stream encrypted terminal chunks
B->>S: Encrypted keyboard input
Browser rendering
Section titled “Browser rendering”The frontend is SvelteKit with xterm.js (WebGL-accelerated). Terminal layout uses a tiling binary split tree computed as a flat rect map — terminals are absolutely positioned and never remounted when the layout changes.
A type-ahead addon provides optimistic local echo for typed characters before round-trip confirmation, making the experience feel local even over high-latency connections.