T3 Code runs as a Node.js WebSocket server that wraps codex app-server (JSON-RPC over stdio) and serves a React web app.
┌─────────────────────────────────┐
│ Browser (React + Vite) │
│ wsTransport (state machine) │
│ Typed push decode at boundary │
└──────────┬──────────────────────┘
│ ws://localhost:3773
┌──────────▼──────────────────────┐
│ apps/server (Node.js) │
│ WebSocket + HTTP static server │
│ ServerPushBus (ordered pushes) │
│ ServerReadiness (startup gate) │
│ OrchestrationEngine │
│ ProviderService │
│ CheckpointReactor │
│ RuntimeReceiptBus │
└──────────┬──────────────────────┘
│ JSON-RPC over stdio
┌──────────▼──────────────────────┐
│ codex app-server │
└─────────────────────────────────┘
-
Browser app: The React app renders session state, owns the client-side WebSocket transport, and treats typed push events as the boundary between server runtime details and UI state.
-
Server:
apps/serveris the main coordinator. It serves the web app, accepts WebSocket requests, waits for startup readiness before welcoming clients, and sends all outbound pushes through a single ordered push path. -
Provider runtime:
codex app-serverdoes the actual provider/session work. The server talks to it over JSON-RPC on stdio and translates those runtime events into the app's orchestration model. -
Background workers: Long-running async flows such as runtime ingestion, command reaction, and checkpoint processing run as queue-backed workers. This keeps work ordered, reduces timing races, and gives tests a deterministic way to wait for the system to go idle.
-
Runtime signals: The server emits lightweight typed receipts when important async milestones finish, such as checkpoint capture, diff finalization, or a turn becoming fully quiescent. Tests and orchestration code wait on these signals instead of polling internal state.
sequenceDiagram
participant Browser
participant Transport as WsTransport
participant Server as wsServer
participant Layers as serverLayers
participant Ready as ServerReadiness
participant Push as ServerPushBus
Browser->>Transport: Load app and open WebSocket
Transport->>Server: Connect
Server->>Layers: Start runtime services
Server->>Ready: Wait for startup barriers
Ready-->>Server: Ready
Server->>Push: Publish server.welcome
Push-->>Transport: Ordered welcome push
Transport-->>Browser: Hydrate initial state
- The browser boots
WsTransportand registers typed listeners inwsNativeApi. - The server accepts the connection in
wsServerand brings up the runtime graph defined inserverLayers. ServerReadinesswaits until the key startup barriers are complete.- Once the server is ready,
wsServersendsserver.welcomefrom the contracts inws.tsthroughServerPushBus. - The browser receives that ordered push through
WsTransport, andwsNativeApiuses it to seed local client state.
sequenceDiagram
participant Browser
participant Transport as WsTransport
participant Server as wsServer
participant Provider as ProviderService
participant Codex as codex app-server
participant Ingest as ProviderRuntimeIngestion
participant Engine as OrchestrationEngine
participant Push as ServerPushBus
Browser->>Transport: Send user action
Transport->>Server: Typed WebSocket request
Server->>Provider: Route request
Provider->>Codex: JSON-RPC over stdio
Codex-->>Ingest: Provider runtime events
Ingest->>Engine: Normalize into orchestration events
Engine-->>Server: Domain events
Server->>Push: Publish orchestration.domainEvent
Push-->>Browser: Typed push
- A user action in the browser becomes a typed request through
WsTransportand the browser API layer innativeApi. wsServerdecodes that request using the shared WebSocket contracts inws.tsand routes it to the right service.ProviderServicestarts or resumes a session and talks tocodex app-serverover JSON-RPC on stdio.- Provider-native events are pulled back into the server by
ProviderRuntimeIngestion, which converts them into orchestration events. OrchestrationEnginepersists those events, updates the read model, and exposes them as domain events.wsServerpushes those updates to the browser throughServerPushBuson channels defined inorchestration.ts.
sequenceDiagram
participant Server as wsServer
participant Worker as Queue-backed workers
participant Cmd as ProviderCommandReactor
participant Checkpoint as CheckpointReactor
participant Receipt as RuntimeReceiptBus
participant Push as ServerPushBus
participant Browser
Server->>Worker: Enqueue follow-up work
Worker->>Cmd: Process provider commands
Worker->>Checkpoint: Process checkpoint tasks
Checkpoint->>Receipt: Publish completion receipt
Cmd-->>Server: Produce orchestration changes
Checkpoint-->>Server: Produce orchestration changes
Server->>Push: Publish resulting state updates
Push-->>Browser: User-visible push
- Some work continues after the initial request returns, especially in
ProviderRuntimeIngestion,ProviderCommandReactor, andCheckpointReactor. - These flows run as queue-backed workers using
DrainableWorker, which helps keep side effects ordered and test synchronization deterministic. - When a milestone completes, the server emits a typed receipt on
RuntimeReceiptBus, such as checkpoint completion or turn quiescence. - Tests and orchestration code wait on those receipts instead of polling git state, projections, or timers.
- Any user-visible state changes produced by that async work still go back through
wsServerandServerPushBus.