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