Skip to main content

Overview

T3 Code is a minimal web GUI for code agents, built with a focus on performance, reliability, and maintainability. The system is designed around a WebSocket-based client-server architecture with provider abstraction.

Core Principles

Performance First

Optimized for low latency and high throughput in event streaming

Reliability First

Predictable behavior under load, failures, and reconnections

Maintainability

Long-term code health through shared logic and clear boundaries

Correctness

Robust over convenient when tradeoffs are required
This is a very early WIP. Sweeping changes that improve long-term maintainability are encouraged.

System Architecture

Package Architecture

/apps/server - WebSocket Server

Purpose: Node.js backend that orchestrates provider sessions and streams events to clients. Key Responsibilities:
  • Wraps Codex app-server (JSON-RPC over stdio)
  • Manages WebSocket connections and protocol
  • Orchestrates provider sessions and lifecycle
  • Persists events and projections in SQLite
  • Serves built web app as static files (production)
Core Modules:
// CLI entrypoint
// Parses args, loads config, starts server
import { t3Cli } from './main';
Effect-TS Integration: The server uses Effect-TS for dependency injection and error handling:
// Service layers provide implementations
const ServerLive = Layer.mergeAll(
  ProviderServiceLive,
  OrchestrationEngineLive,
  GitServiceLive,
  TerminalManagerLive,
);

// Effects compose with type-safe dependencies
const program = Effect.gen(function* () {
  const provider = yield* ProviderService;
  const session = yield* provider.createSession(config);
  return session;
});

/apps/web - React UI

Purpose: React + Vite frontend for session control, conversation, and event rendering. Key Responsibilities:
  • Session UX and conversation rendering
  • WebSocket client and transport layer
  • Client-side state management (Zustand)
  • Terminal emulation (xterm.js)
  • Real-time diff visualization
State Management:
// Global app state
import { useStore } from './store';

// Terminal state per session
import { useTerminalStore } from './terminalStateStore';

// Composer draft state
import { useComposerDraftStore } from './composerDraftStore';
WebSocket Integration:
wsTransport.ts
// WebSocket client with reconnection logic
export class WsTransport {
  connect(url: string): Promise<void>;
  send(message: Protocol.ClientMessage): void;
  on(event: string, handler: Function): void;
}
React Query: API calls use TanStack Query for caching and synchronization:
// Provider queries
import { useProviderQuery } from './lib/providerReactQuery';

// Git queries  
import { useGitQuery } from './lib/gitReactQuery';

/apps/desktop - Electron Shell

Purpose: Native desktop wrapper with auto-updates and system integration. Key Responsibilities:
  • Spawns desktop-scoped t3 backend process
  • Loads shared web app in Electron renderer
  • Auto-update support (electron-updater)
  • Native system integration (menus, dialogs)
Process Model:
// Main process spawns backend
const backend = spawn('t3', ['--auth-token', token]);

// Renderer connects via WebSocket
const wsUrl = `ws://127.0.0.1:${port}?token=${token}`;

/packages/contracts - Shared Schemas

Purpose: Effect/Schema definitions and TypeScript contracts for all protocol messages. Key Responsibilities:
  • Provider event schemas
  • WebSocket protocol messages
  • Model and session types
  • Schema validation and encoding
Keep this package schema-only — no runtime logic!
Schema Examples:
import * as S from 'effect/Schema';

// Provider runtime events
export const ProviderRuntimeEvent = S.Union(
  ProviderStarted,
  ToolInvoked,
  StreamChunk,
  TurnCompleted,
);

// WebSocket protocol
export const ClientMessage = S.Union(
  SendUserMessage,
  CancelTurn,
  ResumeSession,
);

/packages/shared - Runtime Utilities

Purpose: Shared runtime utilities for both server and web. Key Responsibilities:
  • Model parsing and validation
  • Network utilities
  • Git helpers
  • Shared business logic
Subpath Exports:
// Import from specific paths, not barrel index
import { parseModel } from '@t3tools/shared/model';
import { NetService } from '@t3tools/shared/Net';
import { GitUtils } from '@t3tools/shared/git';

Data Flow

User Message Flow

1

User Input

User types message in React composer component
2

WebSocket Send

Web app sends SendUserMessage via WebSocket
3

Provider Dispatch

Server dispatches to Codex app-server via JSON-RPC
4

Event Stream

Codex streams provider events back over stdio
5

Event Projection

Server projects events into orchestration domain events
6

WebSocket Push

Server pushes orchestration events to web via WebSocket
7

UI Update

React components render streaming response

Event Sourcing

The server uses event sourcing for session state:
// Events are stored in SQLite
const event: OrchestrationEvent = {
  type: 'TurnStarted',
  sessionId,
  turnId,
  timestamp,
};

await eventStore.append(sessionId, event);

// Projections build read models
const readModel = await projectionQuery.getSession(sessionId);
Benefits:
  • Full audit trail
  • Session replay capability
  • Temporal debugging
  • Eventual consistency

Codex App Server Integration

T3 Code is Codex-first and wraps the Codex app-server:

JSON-RPC Protocol

Communication happens over stdio using JSON-RPC:
// Start session
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "session.start",
  "params": { "workspaceRoot": "/path/to/project" }
}

// Provider events stream back
{
  "jsonrpc": "2.0",
  "method": "provider.event",
  "params": { "type": "tool_invoked", ... }
}

Key Integration Points

ModuleResponsibilityLocation
Session lifecycleStart, resume, stop sessionscodexAppServerManager.ts:39
Turn managementSend messages, handle turnscodexAppServerManager.ts:156
Event ingestionStream provider eventsproviderManager.ts:84
NativeApi routingRoute NativeApi callswsServer.ts:203
Domain projectionProject to orchestration eventsServer-side
Read the Codex App Server docs for protocol details.

Performance Considerations

WebSocket Optimization

  • Binary Protocol: Consider MessagePack for reduced overhead
  • Backpressure: Handle slow clients with buffering
  • Batching: Batch rapid events for UI efficiency

State Management

  • Selective Subscriptions: Only subscribe to needed data
  • Memoization: Use React.memo and useMemo aggressively
  • Virtual Scrolling: Render large lists efficiently (@tanstack/react-virtual)

Build Optimization

  • Code Splitting: Vite automatically splits routes
  • Tree Shaking: Import only what you need
  • Effect Optimization: Effect-TS enables zero-cost abstractions

Reliability Patterns

Session Recovery

Sessions survive disconnections and restarts:
// Server persists session state
await sessionStore.save(session);

// Client reconnects and resumes
await transport.send({
  type: 'ResumeSession',
  sessionId,
});

// Server replays missed events
const events = await eventStore.getEvents(sessionId, fromSeq);

Error Handling

Robust error boundaries at each layer:
// Effect error channels
const program = Effect.gen(function* () {
  return yield* operation;
}).pipe(
  Effect.catchTag('NetworkError', handleNetwork),
  Effect.catchTag('ProviderError', handleProvider),
  Effect.catchAll(handleUnknown),
);

Graceful Degradation

  • Offline Mode: Queue messages when disconnected
  • Partial Renders: Show what’s available during streams
  • Fallback UI: Graceful error states

Reference Implementations

For implementation guidance, reference:

Codex (Official)

Open-source Codex repository

Codex Monitor

Tauri-based reference implementation
Use these for protocol handling, UX flows, and operational safeguards.

Next Steps

Monorepo Structure

Explore the workspace layout

Testing

Learn testing patterns

Build docs developers (and LLMs) love