How to Contribute to pingdotgg/t3code: A Complete Developer Guide

Contribute to pingdotgg/t3code by setting up a local development environment with Bun, making small focused bug fixes or performance improvements, and submitting PRs that pass the quality gates defined in AGENTS.md.

The t3code repository is a minimal web GUI that wraps a Codex/Claude app-server (JSON-RPC over stdio) in a Node.js WebSocket server and serves a React + Vite front-end. If you want to contribute to pingdotgg/t3code, you must understand its monorepo structure, runtime architecture, and strict contribution policy that only accepts small, focused improvements.


Understanding the Repository Structure

The codebase is organized as a monorepo with distinct applications and shared packages. Knowing these paths is essential when navigating the source code to contribute to pingdotgg/t3code.

Directory / File Purpose
apps/server Node.js WebSocket server, provider orchestration, and background workers
apps/web React + Vite UI and WebSocket client (WsTransport)
packages/contracts Shared TypeScript contracts and schema definitions with no runtime logic
packages/shared Runtime utilities including DrainableWorker and logging
.docs/architecture.md Narrative documentation of end-to-end data flow
CONTRIBUTING.md Official contribution policy limiting scope to small fixes
AGENTS.md Quality gate requirements (bun fmt, bun lint, bun typecheck)

Core Architecture and Runtime Flow

To contribute to pingdotgg/t3code effectively, you must understand the runtime flow from browser to provider and back.

Data Flow Sequence

  1. Browser → WebSocket – The UI opens a WebSocket to ws://localhost:3773 using WsTransport in apps/web/src/wsTransport.ts. Typed push events are decoded using contracts from packages/contracts/src/ws.ts.

  2. Server Acceptance – The server accepts the socket, runs startup barriers (ServerReadiness), then publishes a server.welcome push via ServerPushBus.

  3. Provider Orchestration – ProviderServiceLive in apps/server/src/provider/Layers/ProviderService.ts coordinates provider adapters (Codex, Claude) and persists session bindings. It publishes runtime events through a PubSub consumed by workers such as ProviderRuntimeIngestion and CheckpointReactor.

  4. Provider Runtime – The system communicates with the codex app-server over JSON-RPC on stdio. The server converts provider events into orchestration domain events via OrchestrationEngine and pushes them back to the client.

Key Module: ProviderServiceLive

Located in apps/server/src/provider/Layers/ProviderService.ts, this is the core orchestrator for all provider actions.

Feature Implementation Details
Session Startup startSession (lines 36-78) validates input, checks settings, starts a provider session, and persists the binding.
Turn Handling sendTurn (lines 19-91) resolves the routable session, forwards the turn to the provider adapter, and records analytics.
Event Streaming streamEvents getter (lines 93-95) creates a fresh PubSub subscription for each consumer.
Graceful Shutdown runStopAll and finalizer (lines 40-78) stop all sessions on application teardown.

Development Workflow to Contribute to pingdotgg/t3code

Follow these steps to set up your environment and submit a contribution.

1. Fork and Clone

Fork the repository on GitHub, then clone your fork locally.

2. Install Development Tools

The project uses mise to manage Node ≥ 20, Bun, and other tools. If you have mise installed, run:

mise install

Otherwise, ensure you have Bun installed directly.

3. Install Dependencies

bun install .

4. Run the Application Locally

Hot-reload (web + server):

bun run dev

Desktop-only development:

bun run dev:desktop

5. Make Focused Changes

Contribute only small, focused bug fixes, reliability improvements, or performance tweaks. Examples include tightening a validation schema, improving a log message, or fixing a TypeScript type.

6. Run Quality Gates

All CI jobs require these commands to pass:

bun fmt
bun lint
bun typecheck

Run the test suite with Vitest:

bun run test

Tests live under apps/**/__tests__.

7. Submit a Pull Request

The repository automatically labels PRs with vouch:* and size:*. External contributors start with vouch:unvouched until a maintainer adds them to .github/VOUCHED.td.

Include a clear description of the fix, and add before/after screenshots for any UI changes as required by CONTRIBUTING.md.


Practical Code Examples for Contributors

These snippets demonstrate how to interact with the core modules when contributing to pingdotgg/t3code.

Starting a Provider Session (Server-Side)

import { ProviderService } from "@t3tools/server";

// `threadId` is a UUID generated by the client.
// `rawInput` follows the `ProviderSessionStartInput` schema.
const session = await ProviderService.startSession(threadId, rawInput);
console.log("Provider session started:", session.provider, session.threadId);

Reference: startSession implementation (lines 35-78) in apps/server/src/provider/Layers/ProviderService.ts.

Sending a Turn from the UI (Client-Side)

import { wsTransport } from "./wsTransport";

await wsTransport.send({
  type: "provider.sendTurn",
  threadId: "c1a9…",
  input: "Explain the observer pattern",
  interactionMode: "text",
  // optional modelSelection, attachments, etc.
});

The transport serializes the request, and the server resolves the routable session and forwards it to the appropriate adapter via ProviderService.sendTurn. See the flow diagram in .docs/architecture.md.

Subscribing to Runtime Events (Any Component)

import { ProviderService } from "@t3tools/server";

const subscription = ProviderService.streamEvents.subscribe({
  next: (event) => console.log("Runtime event:", event.type, event.threadId),
  error: (err) => console.error(err),
});

Each call to streamEvents creates a fresh PubSub subscription, allowing independent consumers such as ProviderRuntimeIngestion and CheckpointReactor. See the getter at lines 93-95 in ProviderService.ts.


Key Files Every Contributor Should Know

File Purpose Path
ProviderService.ts Core orchestrator for provider actions (start, turn, stop, list) apps/server/src/provider/Layers/ProviderService.ts
wsTransport.ts Client-side WebSocket abstraction; entry point for UI → server messages apps/web/src/wsTransport.ts
ws.ts Typed contract definitions shared between server and client packages/contracts/src/ws.ts
architecture.md End-to-end data flow documentation .docs/architecture.md
CONTRIBUTING.md Official contribution policy and guidelines CONTRIBUTING.md
AGENTS.md Quality gate requirements and automation rules AGENTS.md

Summary

  • pingdotgg/t3code is a minimal web GUI wrapping a Codex/Claude app-server in a Node.js WebSocket server with a React + Vite frontend.
  • Contributions are limited to small, focused bug fixes, reliability improvements, and performance tweaks only.
  • The core orchestration logic lives in apps/server/src/provider/Layers/ProviderService.ts, specifically the startSession, sendTurn, and streamEvents methods.
  • All contributions must pass quality gates defined in AGENTS.md: bun fmt, bun lint, and bun typecheck.
  • External contributors start with vouch:unvouched status until added to .github/VOUCHED.td by a maintainer.

Frequently Asked Questions

What types of contributions does pingdotgg/t3code accept?

The project only accepts small, focused bug fixes, reliability improvements, and performance optimizations. Large feature work or major architectural changes are unlikely to be merged. According to CONTRIBUTING.md, you should keep changes under 200 lines and focused on a single logical fix.

How do I set up the development environment for t3code?

First, fork and clone the repository. Install dependencies using bun install . (the project uses Bun as its package manager). You can optionally use mise to manage Node.js ≥ 20 and Bun versions via mise install. Run bun run dev to start both the WebSocket server and Vite UI with hot-reload.

What are the quality gates I need to pass before submitting a PR?

All pull requests must pass the quality gates defined in AGENTS.md. You must run bun fmt (formatting), bun lint (linting), and bun typecheck (TypeScript validation) locally before submitting. Additionally, run bun run test to execute the Vitest test suite. CI will block merges if any of these steps fail.

Where is the main orchestration logic located in the codebase?

The core orchestration logic resides in apps/server/src/provider/Layers/ProviderService.ts. This file contains the ProviderServiceLive class with critical methods including startSession (lines 36-78), sendTurn (lines 19-91), and the streamEvents getter (lines 93-95). This service coordinates provider adapters, manages session lifecycle, and publishes runtime events to workers like ProviderRuntimeIngestion and CheckpointReactor.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →