Skip to main content

Workspace Overview

T3 Code uses a Bun workspace managed by Turbo for build orchestration. The monorepo is organized into apps and shared packages.
t3code/
├── apps/
│   ├── server/          # Node.js WebSocket server
│   ├── web/             # React + Vite UI
│   ├── desktop/         # Electron shell
│   └── marketing/       # Marketing website
├── packages/
│   ├── contracts/       # Shared schemas (Effect/Schema)
│   └── shared/          # Runtime utilities
├── scripts/             # Build and dev scripts
├── package.json         # Root workspace config
└── turbo.json          # Turbo build config

Apps

/apps/server - Backend Server

Published as: t3 (npm package) Purpose: Node.js WebSocket server that wraps Codex and manages provider sessions.
{
  "name": "t3",
  "version": "0.0.3",
  "bin": {
    "t3": "./dist/index.mjs"
  },
  "scripts": {
    "dev": "bun run src/index.ts",
    "build": "node scripts/cli.ts build",
    "start": "node dist/index.mjs",
    "test": "vitest run"
  }
}
Key Technologies:
  • Runtime: Node.js 24+
  • Effects: Effect-TS for DI and error handling
  • Database: @effect/sql-sqlite-bun
  • WebSocket: ws library
  • Processes: node-pty for terminals
Build Output:
  • Bundled ESM: dist/index.mjs
  • Includes web app assets (production)

/apps/web - Frontend UI

Published as: @t3tools/web (workspace-only) Purpose: React web application for session control and conversation rendering.
{
  "name": "@t3tools/web",
  "version": "0.0.3",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "test": "vitest run --passWithNoTests",
    "test:browser": "vitest run --config vitest.browser.config.ts"
  }
}
Key Technologies:
  • Framework: React 19
  • Build Tool: Vite 8
  • Routing: TanStack Router
  • State: Zustand + TanStack Query
  • Styling: Tailwind CSS 4
  • Terminal: xterm.js
  • Compiler: Babel React Compiler
Build Output:
  • Static HTML/JS/CSS in dist/
  • Served by server in production
  • Bundled in desktop app

/apps/desktop - Electron App

Published as: @t3tools/desktop (workspace-only) Purpose: Native desktop wrapper with auto-updates.
{
  "name": "@t3tools/desktop",
  "version": "0.0.3",
  "private": true,
  "main": "dist-electron/main.js",
  "scripts": {
    "dev": "bun run --parallel dev:bundle dev:electron",
    "build": "tsdown",
    "start": "bun run scripts/start-electron.mjs",
    "smoke-test": "node scripts/smoke-test.mjs"
  },
  "productName": "T3 Code (Alpha)"
}
Key Technologies:
  • Platform: Electron 40
  • Updates: electron-updater
  • Build: tsdown
  • Backend: Spawns t3 CLI
Distribution:
  • macOS: .dmg (arm64/x64)
  • Linux: .AppImage
  • Windows: NSIS installer

/apps/marketing - Marketing Site

Published as: @t3tools/marketing (workspace-only) Purpose: Marketing and documentation website.
package.json
{
  "name": "@t3tools/marketing",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

Packages

/packages/contracts - Shared Schemas

Purpose: Effect/Schema definitions for all protocol types.
{
  "name": "@t3tools/contracts",
  "version": "0.0.3",
  "private": true,
  "exports": {
    ".": {
      "types": "./src/index.ts",
      "import": "./src/index.ts",
      "require": "./dist/index.cjs"
    }
  },
  "scripts": {
    "dev": "tsdown src/index.ts --format esm,cjs --dts --watch --clean",
    "build": "tsdown src/index.ts --format esm,cjs --dts --clean"
  }
}
Schema Example:
src/provider.ts
import * as S from 'effect/Schema';

export class ProviderConfig extends S.Class<ProviderConfig>('ProviderConfig')({
  providerId: S.String,
  model: S.String,
  workspaceRoot: S.String,
}) {}

export const ProviderConfigEncoded = S.encode(ProviderConfig);
export const ProviderConfigDecoded = S.decode(ProviderConfig);
Keep this package schema-only. No runtime logic!

/packages/shared - Runtime Utilities

Purpose: Shared runtime code for server and web.
{
  "name": "@t3tools/shared",
  "version": "0.0.3",
  "private": true,
  "exports": {
    "./model": "./src/model.ts",
    "./Net": "./src/Net.ts",
    "./git": "./src/git.ts"
  }
}
Subpath Exports:
// Import from specific subpaths
import { parseModel } from '@t3tools/shared/model';
import { NetService } from '@t3tools/shared/Net';

// ❌ No barrel index
import { parseModel, NetService } from '@t3tools/shared';

Build Scripts

/scripts - Build and Dev Tooling

scripts/
├── dev-runner.ts                 # Dev mode orchestrator
├── build-desktop-artifact.ts     # Desktop distribution builder
├── sync-vscode-icons.mjs         # Icon asset sync
└── cli.ts                        # Server build script
Key Scripts:
ScriptPurpose
dev-runner.tsManages Turbo watch mode and env vars
build-desktop-artifact.tsBuilds platform-specific installers
sync-vscode-icons.mjsSyncs VSCode icon themes

Workspace Configuration

package.json (Root)

{
  "workspaces": {
    "packages": [
      "apps/*",
      "packages/*",
      "scripts"
    ],
    "catalog": {
      "effect": "https://pkg.pr.new/Effect-TS/effect-smol/effect@8881a9b",
      "typescript": "^5.7.3",
      "vitest": "^4.0.0"
    }
  },
  "engines": {
    "bun": "^1.3.9",
    "node": "^24.13.1"
  }
}
Catalog Dependencies: Shared versions across all packages:
  • effect - Effect-TS (smol fork)
  • typescript - TypeScript compiler
  • vitest - Test runner
  • @types/node - Node.js types

turbo.json - Build Pipeline

{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "dist-electron/**"]
    },
    "dev": {
      "dependsOn": ["@t3tools/contracts#build"],
      "cache": false,
      "persistent": true
    },
    "test": {
      "dependsOn": ["^build"],
      "cache": false
    }
  }
}
Task Dependencies:
  • ^build - Depends on dependencies’ build tasks
  • @t3tools/contracts#build - Contracts must build first in dev

Dependency Graph

Build Order:
  1. packages/contracts (no dependencies)
  2. packages/shared (no dependencies)
  3. apps/web (depends on contracts, shared)
  4. apps/server (depends on contracts, shared, web)
  5. apps/desktop (depends on all)

Adding New Packages

Create a New App

1

Create directory

mkdir apps/my-app
cd apps/my-app
2

Initialize package.json

{
  "name": "@t3tools/my-app",
  "version": "0.0.3",
  "private": true,
  "scripts": {
    "dev": "...",
    "build": "...",
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  },
  "dependencies": {
    "@t3tools/contracts": "workspace:*"
  },
  "devDependencies": {
    "typescript": "catalog:",
    "vitest": "catalog:"
  }
}
3

Add to Turbo config

turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}
4

Install dependencies

bun install

Create a New Shared Package

1

Create directory

mkdir packages/my-utils
cd packages/my-utils
2

Initialize with subpath exports

{
  "name": "@t3tools/my-utils",
  "version": "0.0.3",
  "private": true,
  "exports": {
    "./foo": "./src/foo.ts",
    "./bar": "./src/bar.ts"
  }
}
3

Add TypeScript config

tsconfig.json
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist"
  },
  "include": ["src"]
}

Best Practices

Shared Logic

Extract duplicate logic into packages/shared to avoid code smell

Type Safety

Use schemas from contracts for all cross-boundary data

Workspace Deps

Always use workspace:* for internal dependencies

Catalog Versions

Use catalog: for shared dependencies across packages
Long-term maintainability is a core priority. Don’t be afraid to refactor!

Next Steps

Testing

Learn how to write and run tests

Building

Build for production and distribution