Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Research dossier: t3code architecture and migratable surface
page:docs-specs-platform-gaps-research-t3code-architecturea5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page overview

page:docs-specs-platform-gaps-research-t3code-architecture

Reference · live

Research dossier: t3code architecture and migratable surface overview

Inspect the raw attributes, linked wiki pages, and inbound or outbound graph edges for page:docs-specs-platform-gaps-research-t3code-architecture.

PageOutgoing · 0Incoming · 1

Attributes

nodeKind
Page
sourcePath
docs/specs/platform-gaps/research/t3code-architecture.md
sourceKind
repo-docs
title
Research dossier: t3code architecture and migratable surface
displayName
Research dossier: t3code architecture and migratable surface
slug
docs/specs/platform-gaps/research/t3code-architecture
articlePath
wiki/docs/specs/platform-gaps/research/t3code-architecture.md
article
# Research dossier: t3code architecture and migratable surface Date: 2026-09-27 · Author: research agent for the platform-gaps spec effort · Status: input to `10-t3code-migration.md` Snapshot investigated: `C:/Users/tmusk/AppData/Local/Temp/claude/C--work-company/368e0399-fd11-4960-8b4d-b4dcf1d79c43/scratchpad/t3code` (MIT, T3 Tools Inc., shallow clone 2026-09-27). All `path:line` citations below are relative to that snapshot root unless prefixed `fabric:`. Method: direct reading of source, manifests, and `docs/internals/`; file/LOC counts via `find`+`wc -l` over `*.ts,*.tsx,*.rs,*.js,*.mjs,*.swift,*.kt,*.c,*.h,*.zig` excluding `node_modules/dist/target`. LOC figures include co-located `*.test.ts` files unless a "non-test" figure is given. Effect-TS depth = share of non-test source files importing from `effect/*`. --- ## 1. What t3code is T3 Code self-describes as an "agent harness control surface" (`README.md:3`): a single Node WebSocket server that wraps provider CLIs/agents — Codex, Claude Code, Cursor, Grok, OpenCode, Antigravity — and serves web, desktop, and mobile clients (`AGENTS.md:3`). It is a bring-your-own-subscription product with ~200,000 users (`AGENTS.md:9`), MIT licensed, `pnpm@11` monorepo, Node `^24.13.1`, Effect-TS `4.0.0-rc.115` throughout (`package.json`, `pnpm-workspace.yaml` catalog). Core execution model (`AGENTS.md:145`): clients send typed WebSocket requests → server turns them into **commands** → a pure **decider** produces persisted **events** → a **projector** derives the read model → provider CLIs run as subprocesses with per-provider **adapters** translating native protocols into orchestration events → side effects run in queue-backed **reactors** emitting **receipts** → every turn ends with a **checkpoint** (hidden git ref) for diff/restore. Events, projections, and command receipts commit in one SQLite transaction (`docs/internals/overview.md:56-60`). The architectural boundary rule that matters most for fabric adoption: *"Complexity belongs at the adapter boundary. Orchestration stays pure, UI stays dumb"* (`AGENTS.md`, Taste section), and *"Anything crossing the wire is typed in `packages/contracts`"* (`AGENTS.md`, Hit-every-surface section). ## 2. Monorepo topology and size | Unit | Files (src) | LOC (incl. tests) | Language | Effect depth (non-test files importing effect) | |---|---|---|---|---| | `apps/server` | 863 | 398,627 | TS | 431/491 = 88% | | `apps/web` | 1,258 | 318,401 | TS/TSX (React 19) | 139/841 = 17% | | `apps/desktop` | 258 | 81,239 | TS (Electron 44) | 89/134 = 66% | | `apps/mobile` | 868 | 154,001 | TS/TSX + Swift/Kotlin (Expo 57/RN) | 125/602 = 21% | | `apps/marketing` | 10 | 514 | TS | n/a | | `packages/contracts` | 74 | 26,979 | TS (Effect Schema) | 47/48 = 98% | | `packages/effect-acp` | 18 | 15,546 (10,375 generated) | TS | 100% | | `packages/effect-codex-app-server` | 18 | 61,816 (58,004 generated) | TS | 100% | | `packages/client-runtime` | 256 | 65,846 | TS | 85/157 = 54% | | `packages/shared` | 154 | 29,241 | TS | 36/86 = 42% | | `packages/ssh` | 10 | 4,143 | TS | 5/5 = 100% | | `packages/tailscale` | 3 | 763 | TS | 1/2 | | `infra/relay` | 78 | 27,381 | TS (Cloudflare Worker) | 40/44 = 91% | | `native/browser-secret` | 2 | 105 | C (libsecret) | — | | `native/hyprland-snap-shot` | 6 | 1,823 | Rust | — | | `native/kde-snap-shot` | 7 | 1,251 | Rust | — | | `native/libghostty-vt` | 30 | 8,915 | C headers (vendored, pinned by `native/libghostty-vt/VERSION`) | — | | `native/resource-monitor` | 1 | 1,334 | Rust (sysinfo) | — | | `packaging/` (aur) | 0 TS | shell/PKGBUILD | — | — | | `scripts/` | 60 | 23,121 | TS | heavy (build scripts written in Effect) | | `oxlint-plugin-t3code` | 17 | 1,771 | JS | — | Workspace globs: `apps/*`, `infra/*`, `packages/*`, `scripts`, `oxlint-plugin-t3code` (`pnpm-workspace.yaml:1-6`). Vendored read-only reference repos live under `.repos/` (`effect-smol`, `alchemy-effect`) and are never imported (`AGENTS.md`, Where-code-lives section). **Tooling stack (CONFIRMED):** pnpm 11 catalogs + overrides + 23 patched dependencies (`pnpm-workspace.yaml`, `patchedDependencies`), `vite-plus` ("vp") as the build/test/lint runner, TypeScript 7.0.2, `@effect/tsgo` compiler patching (`package.json:6` "prepare"), knip for dead-code, oxlint with a custom plugin. Effect is a release candidate (`effect@4.0.0-rc.115`) *and locally patched* (`patches/effect@4.0.0-rc.115.patch`) — a fork-tracking liability the spec must own. ## 3. apps/server — the environment Entry: `apps/server/src/bin.ts` — an `effect/unstable/cli` Command tree (`bin.ts:1-30`) with subcommands: auth, app, connect, pair, project, serve/start/run-server, service (+ launcher, preflight), uninstall, update, claude-history, ssh-helper, theme, trace, triage (`bin.ts:10-29`). The server is simultaneously the product CLI (`t3`). Subsystem sizes (non-test files / non-test LOC, from `apps/server/src/*/`): | Subsystem | Files | LOC | Role | |---|---|---|---| | `provider/` | 109 | 49,072 | drivers, adapters, ACP runtimes, installers, auth flows, model catalogs | | `orchestration/` | 38 | 20,360 | engine, decider, projector, reactors | | `pullRequest/` | 26 | 19,751 | PR providers: GitHub, Bitbucket, Azure DevOps, Forgejo (`pullRequest/` listing) | | `sourceControl/` | 25 | 7,954 | repo/branch discovery, git actions | | `persistence/` | 84 | 7,602 | SQLite event store, projections, receipts, migrations | | `vcs/` | 8 | 6,540 | VCS driver registry (checkpoint capability lives here) | | `cloud/` | 18 | 5,764 | T3 Connect client side: relay auth, managed cloudflared tunnels, self-update | | `cli/` | 20 | 5,681 | the `t3` CLI commands | | `auth/` | 11 | 4,258 | environment auth: DPoP, pairing grants, sessions, scopes | | `device/` | 12 | 4,150 | iOS simulator / Android emulator control | | `usage/` | 11 | 3,894 | provider usage/quota ingestion | | `project/` | 10 | 3,939 | project registry | | `resourceTelemetry/` | 8 | 3,628 | host/process resource history (feeds from native resource-monitor) | | `terminal/` | 4 | 3,453 | thread terminals over node-pty | | `git/` | 4 | 3,417 | git command execution | | `textGeneration/` | 13 | 3,090 | provider-backed helper generations (titles etc.) | | `mcp/` | 11 | 3,057 | T3's own MCP server injected into provider sessions | | others | — | — | workspace search (`@ff-labs/fff-node` native finder, `workspace/WorkspaceSearchIndex.ts:13`), preview, assets, checkpointing (620 LOC), diagnostics, observability, keybindings, desktopUpdate, relay glue | External runtime deps (`apps/server/package.json`): `@anthropic-ai/claude-agent-sdk ^0.3.276`, `@opencode-ai/sdk ^1.3.15`, `@effect/platform-node`, `@ff-labs/fff-node` (native file finder), `@napi-rs/keyring` (OS credential store), `node-pty`, `stream-json`, `yauzl`, `diff`, `yaml`. No web framework — HTTP + WS are Effect platform (`src/http.ts`, `src/ws.ts`). ### 3.1 Orchestration (event-sourced core) - Engine serializes commands; decider is pure; events+projections+command-receipt commit in one DB transaction; reactors do side effects afterwards and feed results back as commands (`docs/internals/overview.md:56-72`, `orchestration/Layers/OrchestrationEngine.ts`, `orchestration/decider.ts`, `orchestration/projector.ts`). - Reactors present: `PullRequestSyncReactor.ts`, `ThreadPullRequestReactor.ts`, `ThreadSettlementReactor.ts`, plus `ThreadLiveEventCoalescer.ts`, `LiveStreamBudget.ts` (bandwidth discipline for WS), `Normalizer.ts` (provider event normalization into canonical activities). - Test-only `RuntimeReceiptBus` (production layer is a no-op) lets tests wait on async milestones instead of sleeping (`docs/internals/overview.md:100-104`); `packages/shared/src/DrainableWorker.ts` is the drain-wait primitive. - Replay constraint: persisted events must remain decodable forever; schema changes affect replay at startup, not just live traffic (`docs/internals/overview.md:70-72`). ### 3.2 Persistence SQLite via a **port of `@effect/sql-sqlite-node` onto the built-in `node:sqlite`** (no better-sqlite3, no native addon) — `packages/shared/src/nodeSqliteClient.ts:1-7`, used by `apps/server/src/persistence/Layers/Sqlite.ts:6,37`. Layers: `OrchestrationEventStore`, `OrchestrationCommandReceipts`, per-view `Projection*` tables (threads, messages, activities, turns, sessions, projects, repositories, pending approvals, proposed plans), `Migrations/` with a migration runner. State lives under T3 home (`~/.t3/userdata/state.sqlite`, `AGENTS.md`, Test-data section). ### 3.3 Auth (environment side) `auth/` implements token+session auth for a personally-owned server: DPoP proofs (`auth/dpop.ts`), pairing grants/one-time tokens (`auth/PairingGrantStore.ts`), auth sessions persisted in SQLite (`persistence/AuthSessions.ts:1-30`, record includes scopes, proof-key thumbprint, expiry/consumed/revoked timestamps; `persistence/AuthPairingLinks.ts:19-31`), per-method scopes (startup URL carries admin scopes, pair tokens standard scopes — `AGENTS.md`, Dev-servers section), RPC-level authorization separate from socket authentication (`auth/RpcAuthorization.ts`; "Authentication of a socket does not authorize every method on it", `docs/internals/overview.md:20-22`). Secrets in `auth/ServerSecretStore.ts` + `@napi-rs/keyring`. ### 3.4 Checkpointing `checkpointing/CheckpointStore.ts:1-15`: repository interface for filesystem-backed workspace checkpoints as **hidden Git refs**; capture/restore/diff delegate to the active VCS driver's optional checkpoint capability (`vcs/VcsDriver.ts` via `VcsDriverRegistry`). Checkpoints never add commits to the user's branch (`docs/internals/overview.md:79-83`). Revert must coordinate workspace state with provider conversation rollback; providers that cannot roll back conversation (Antigravity) reject revert before touching files (`docs/internals/providers.md`, Protocol-traps section). ### 3.5 Claude history workers Claude session history/fork runs in a **separate child process** so the Claude Agent SDK sees the provider's environment without mutating the server's: `claudeHistoryWorker.ts:1-11` (calls `getSessionMessages`/`forkSession` from `@anthropic-ai/claude-agent-sdk`), standalone npm entry `claude-history-worker.ts:1-4`, and a `__claude-history` subcommand inside the single-executable (`cli/claudeHistory.ts`). ### 3.6 Cloud (T3 Connect client side) `cloud/` holds the environment's side of the hosted-relay story: relay-signed bootstrap credential exchange handlers (`cloud/http.ts`; trust analysis in `docs/internals/t3-connect.md:11-33`), managed tunnel runtime spawning **cloudflared** (`cloud/ManagedEndpointRuntime.ts:77` parses cloudflared zerolog output), tunnel startup reconciliation (`cloud/managedTunnelStartup.ts`), CLI token management (`cloud/CliTokenManager.ts`), and server self-update (`cloud/selfUpdate.ts`). Tunnel lifetime rules (release-on-shutdown vs retain across update handoffs) are documented at `docs/internals/t3-connect.md:41-56`. ### 3.7 Terminal `terminal/Manager.ts:1-8` owns terminal lifecycle/fanout per thread; `terminal/NodePtyAdapter.ts` is the PTY boundary (node-pty is one of only three allowed native build scripts, `pnpm-workspace.yaml` allowBuilds). Client rendering is **libghostty-vt compiled to wasm32** driven from the web app (`apps/web/src/terminal/ghostty/core.ts:13-15` "wasm32 C ABI layout … at the libghostty-vt revision pinned alongside this module"; header pin `native/libghostty-vt/VERSION`). ## 4. Harness integration matrix (the part D6 cares about) Registry: `provider/builtInDrivers.ts:49-56` — `BUILT_IN_DRIVERS = [Codex, Claude, Cursor, Grok, OpenCode, Antigravity]`. Driver = integration kind; instance = one configured account; adapters are per-driver `Layers/*Adapter.ts` implementing the shared `Services/ProviderAdapter.ts` contract and emitting canonical `ProviderRuntimeEvent`s from `@t3tools/contracts`. | Harness | Mechanism | Transport | Key files | Notes | |---|---|---|---|---| | **Claude Code** | **Bespoke: `@anthropic-ai/claude-agent-sdk`** in-process `query()` sessions | SDK (spawns the user's own `claude` executable; bundled SDK binaries are stripped via pnpm overrides, `pnpm-workspace.yaml` overrides block) | `provider/Layers/ClaudeAdapter.ts:5,14-27`; `Drivers/ClaudeDriver.ts`, `ClaudeExecutable.ts`, `ClaudeHome.ts`, `ClaudeSkills.ts`; history in child worker (`claudeHistoryWorker.ts:1-11`) | Permission callbacks via SDK `CanUseTool`; usage limits from `SDKRateLimitInfo` (`Layers/claudeUsageLimits.ts`) | | **Codex** | **Bespoke: Codex "app server" JSON-RPC** over child-process stdio, typed by the in-repo `effect-codex-app-server` package | `codex app-server` subprocess (`provider/Layers/codexLaunchArgs.ts:13`) | `provider/Layers/CodexAdapter.ts:45-46`, `CodexSessionRuntime.ts`; schema `packages/effect-codex-app-server/src/_generated/schema.gen.ts` (56,820 LOC generated) | Async questions arrive as notifications answered by a new user message; blocking ones use request/response (`docs/internals/providers.md`, Protocol-traps) | | **Cursor** | **ACP** | `cursor-agent [permission args] acp` subprocess (`provider/acp/CursorAcpSupport.ts:56-60`) | `provider/Layers/CursorAdapter.ts:2` ("Cursor CLI (`agent acp`) via ACP"); ACP extensions `provider/acp/CursorAcpExtension.ts` | Cursor updates only via its own CLI updater (`docs/internals/providers.md`, updates section) | | **Grok Build** | **ACP** | `grok --permission-mode <mode> agent stdio` subprocess (`provider/acp/GrokAcpSupport.ts:33-41,55-56`) | `provider/Layers/GrokAdapter.ts:38-39`; xAI extensions `provider/acp/XAiAcpExtension.ts`, `XAiBackgroundTasks.ts` | Probes avoid auth/session side effects (`docs/internals/providers.md`, setup section) | | **OpenCode** | **Bespoke: OpenCode HTTP server** via `@opencode-ai/sdk/v2` client | one T3-managed `opencode` server **per thread** (or an external server) | `provider/Layers/OpenCodeAdapter.ts:32`; `provider/OpenCodeServerOwner.ts` (shared instance-owned helper for catalog/text-gen); `provider/opencodeRuntime.ts` | Per-directory MCP registration vs thread-scoped connection forces server-per-thread (`docs/internals/providers.md:14-22`) | | **Antigravity** | **ACP** against a T3-downloaded Google Antigravity release (no user-installed CLI) | downloaded executable+harness spawned as ACP agent; identity verified as `agentInfo.name === "antigravity-acp"`, `protocolVersion === 1` (`provider/AntigravityInstallation.ts:484-502`) | spawn builder `provider/antigravityAuthSupport.ts:434`; installer with immutable releases + version leases (`provider/AntigravityInstallation.ts`); OAuth loopback-callback forwarding (`provider/AntigravityAuth.ts`); per-instance profile isolation (`provider/antigravityAuthSupport.ts`) | Can checkpoint workspace but cannot roll back conversation → revert rejected (`docs/internals/providers.md`, capabilities) | Shared ACP machinery on the server side: `provider/acp/AcpSessionRuntime.ts`, `AcpAdapterSupport.ts`, `AcpCoreRuntimeEvents.ts`, `AcpRuntimeModel.ts`, `AcpStderr.ts` — one generic ACP runtime with per-provider support modules (Cursor/Grok/Antigravity) layered on. This is the concrete precedent for D6 ("ACP becomes fabric's canonical harness protocol with per-harness extension modules"). Cross-cutting provider services: `ProviderService` (turn dispatch, attachment paths in turn input — `docs/internals/providers.md`, Attachments), `ProviderInstanceRegistry` (multi-account), `ProviderSessionDirectory`/`ProviderSessionReaper`, `ProviderAuthService` + per-provider auth flows, `providerMaintenance.ts` (updater-ownership proofs for one-click provider updates), `ModelManifest.ts` + `model-manifest.json` (model classification), `RuntimeInstructions.ts` (per-provider runtime prompt injection), `mcp/McpProviderSession.ts` (T3 injects its own MCP endpoint+bearer into each provider session for preview/device toolkits — `mcp/McpProviderSession.ts:1-12`). ## 5. packages/contracts — full module inventory (48 non-test modules, 26,979 LOC incl. tests) Everything crossing the wire. 47/48 modules import Effect Schema; index at `src/index.ts` re-exports the core. Inventory (module — LOC — interface it defines): | Module | LOC | Defines | |---|---|---| | `rpc.ts` | 1,539 | **The client↔server WS RPC contract**: `WS_METHODS` map (`rpc.ts:277`), 144 `Rpc.make` definitions, aggregated `WsRpcGroup` (`rpc.ts:1394`). Groups: projects, shell, filesystem, agent-session import, assets/attachments, provider auth/install/update, server settings/config/probe, diagnostics, resource telemetry, usage, cloud relay client, background policy, pull requests (list/stats/routing/stack/detail/activity/comments/diff-contents/files-viewed) | | `orchestration.ts` | 2,441 | Orchestration domain: `ORCHESTRATION_WS_METHODS` (dispatchCommand, getWorkflowScript, getTurnDiff, getFullThreadDiff, searchThreads, getArchivedShellSnapshot, subscribeShell, subscribeThread — `orchestration.ts:35-44`), `OrchestrationCommand`/events, `ModelSelection` (+ legacy wire transform, `orchestration.ts:60-74`), approval policies, sandbox modes | | `providerRuntime.ts` | 1,234 | Canonical provider runtime event surface: `ProviderRuntimeEvent`, turn token usage, canonical item/request types, task/tool activity models | | `provider.ts` / `providerInstance.ts` / `providerSetup.ts` / `providerUsageLimits.ts` | 162/149/180/167 | Driver kinds, per-instance settings (`ClaudeSettings`, `CodexSettings`, …), auth/install state machines (`ProviderAuthState`, `ProviderInstallState`), rolling quota windows | | `ipc.ts` | 1,388 | Desktop renderer↔main Electron IPC surface | | `settings.ts` | 1,658 | Server/client settings schema (fonts, themes, providers, usage-limit sources) | | `pullRequest.ts` | 1,409 | PR domain: states, snapshots, stacks, multi-link protocol + `linkedPullRequest` legacy field | | `relay.ts` / `relayClient.ts` / `remoteAccess.ts` | 1,194/63/68 | T3 Connect relay protocol (managed endpoint runtime config, signing), relay client status, remote access modes | | `environment.ts` / `environmentHttp.ts` | 232/623 | Environment descriptor + capability flags (`ORCHESTRATION_PROTOCOL_VERSION`, `environment.ts:1-3`); HttpApi groups for the environment's HTTP endpoints (`environmentHttp.ts:1-5`) | | `auth.ts` / `baseSchemas.ts` | 355/195 | Auth posture labels, scopes, DPoP failure categories, shared branded primitives | | `server.ts` | 891 | Server config/probe/update surface, skills dispatch | | `terminal.ts` | 381 | Terminal open/attach/restart events, `term-N` ids | | `composerContext.ts` / `composerContextClipboard.ts` | 281/27 | Typed composer chips: context records keyed by `contextId`, reference links `t3-context://v1/<kind>/<id>`, attachment bindings | | `git.ts` / `vcs.ts` / `sourceControl.ts` / `worktreeSetup.ts` / `projectClone.ts` | 464/287/188/125/122 | Git action progress, VCS errors incl. checkpoint refs, branch/PR discovery, worktree/clone live progress | | `project.ts` / `t3ProjectFile.ts` | 307/143 | Project records; `t3.json` project file (schema URL `t3ProjectFile.ts:1-2`) | | `device.ts` | 583 | First-class iOS Simulator / Android Emulator control schemas | | `preview.ts` / `previewAutomation.ts` / `browserProfile.ts` / `browserImport.ts` | 354/953/99/165 | In-app browser preview surface, automation ops, named browser identities, cookie import from installed browsers | | `assets.ts` / `filesystem.ts` | 320/67 | Signed asset URLs, filesystem browse | | `keybindings.ts` / `editor.ts` / `desktopAppActivation.ts` / `desktopBootstrap.ts` | 211/232/53/31 | Keybinding rules (forward-compatible with unknown commands), editor deep links incl. VS Code remote, desktop activation/update handoff markers | | `model.ts` | 225 | Model/provider option selections (+ legacy on-disk decoding) | | `usage.ts` / `usageLimitSourceId.ts` | 223/9 | Usage reporting contract | | `resourceTelemetry.ts` | 522 | Host/process resource snapshots and history | | `agentSessions.ts` | 116 | Import of external sessions (`claudeAgent`, `codex` sources — `agentSessions.ts:1-2`) | | `review.ts` / `assistantCitations.ts` / `background.ts` | 70/31/110 | Review diff stats, quoted assistant citations (UTF-16 offsets), background/power policy | | `rpc` transport note | — | Runtime is `effect/unstable/rpc` (`Rpc`/`RpcGroup`, `rpc.ts:1-3`); serialization/session handled by client-runtime + server `ws.ts` | Versioning/compat doctrine baked into contracts: clients and environments upgrade independently; capability flags on the environment descriptor (e.g. `threadPullRequests` vs `threadPullRequestLinking`) gate client behavior; legacy wire fields are kept and absorbed by schema transforms, never by runtime compat code (`docs/internals/overview.md:24-44`, `orchestration.ts:66-74`). **Fabric equivalent replaced:** the wire types implicit in `kradle` core/sdk and the adapters event model; this package is the single strongest candidate for tracked-fork adoption per D9. ## 6. packages/effect-acp — ACP protocol implementation Structure (`packages/effect-acp/src/`): `_generated/schema.gen.ts` (10,375 LOC, generated from the ACP schema via `@effect/openapi-generator`; regenerate with `scripts/generate.ts` — `package.json` "generate"), `meta.gen.ts` (method-name constants), `rpc.ts` (22 `Rpc.make` definitions over `AGENT_METHODS`/`CLIENT_METHODS`: initialize, authenticate, logout, session/new, session/load, session/list… — `rpc.ts:8-40`), `protocol.ts` (632 LOC; the JSON-RPC stdio protocol layer producing both an `RpcClient` protocol and an `RpcServer` protocol from one child stdio, with typed incoming notifications, ext-method escape hatches, session-update transforms — `protocol.ts:23-80`), `client.ts` (614 LOC; `AcpClient` Context.Service spawning agent childs — `client.ts:49`), `agent.ts` (538 LOC; `AcpAgent` service for *being* an ACP agent — `agent.ts:31`, used by `apps/server/scripts/acp-mock-agent.ts` for tests), `errors.ts`, `terminal.ts` (ACP terminal handle: output/waitForExit/kill/release with spec links — `terminal.ts:6-25`), exports as five subpaths (client/agent/schema/protocol/errors — `package.json` exports). Sole runtime dependency: `effect` (`packages/effect-acp/package.json`). Highly portable; the Effect-4 `unstable/rpc` runtime is the only coupling. **Fabric equivalent replaced:** the protocol layer that D6 mandates as canonical for `adapters`. Includes both directions (client for driving harnesses, agent for exposing fabric itself as an ACP agent). ## 7. packages/effect-codex-app-server — Codex protocol twin Same generator pattern as effect-acp: `_generated/schema.gen.ts` 56,820 LOC + `meta.gen.ts` 889 + `namespaces.gen.ts` 295; handwritten `client.ts` (262 LOC, spawns `codex app-server` childs), `protocol.ts` (485 LOC), `rpc.ts` is purely re-exported generated meta (`rpc.ts:1`). Probe example at `test/examples/codex-app-server-probe.ts`. Only dep: `effect`. **Fabric equivalent replaced:** fabric's Codex adapter transport (currently hooks/CLI-based in `fabric:packages/adapters/hooks/adapter-codex`). ## 8. packages/client-runtime — shared client brain (web+desktop+mobile) 256 files / 65,846 LOC; 54% Effect. Subpath-exported modules (no barrel): `connection/` (supervisor = single transport-retry owner with backoff/wakeups, `connection/supervisor.ts`; registry scoping connections per environment, `connection/registry.ts`; catalog, credential store, compatibility negotiation, onboarding), `rpc/` (client, session — session waits for initial server config before ready, `rpc/session.ts`; http auth), `authorization/` (HTTP credential refresh decoupled from socket lifetime, `authorization/service.ts`), `state/` (~30 shared state services: threads, orchestration, entities, git, models, filesystem, attachments, checkpointDiff, connections, device …, built on `@effect/atom-react` atoms), `relay/`, `device/`, `environment/`, `operations/`, `platform/` (platform service interfaces the shells implement), `voice-input/`, `work-log/`, plus provider-flavored helpers (codexArtifactTemplates, codexFileCitations, providerSkills). Design rationale: one connection owner prevents divergent reconnect loops across surfaces (`docs/internals/connection-runtime.md:1-27`). **Fabric equivalent replaced:** the client/data layer of `kradle/web` and the retired `genty` UI runtime (per D2c). ## 9. packages/shared — cross-runtime utilities 154 files / 29,241 LOC, subpath exports, no barrel (`AGENTS.md`, Where-code-lives). Notable: `nodeSqliteClient.ts` (the node:sqlite Effect SQL client, §3.2), `DrainableWorker.ts`, `relaySigning`/`relayClient` (T3 Connect crypto), `hostProcess`, `cliRelease` (release download URLs shared by installer/ssh bootstrap), `legacyCliLauncher`, model/usage-limit helpers, composer-context reference machinery shared by clients and server. ## 10. packages/ssh and packages/tailscale — remote access primitives - `ssh` (10 files / 4,143 LOC, 100% Effect): auth, command execution, config, tunnels. Can bootstrap a T3 server on a remote host (downloads via `cliRelease` base URL — `ssh/src/tunnel.ts:9`) and port-forward to it; desktop main owns the lifecycle, renderer consumes the forwarded endpoint (`docs/internals/remote.md:47-50`). Cleanup stops a remote server only if it started it (`ssh/src/tunnel.ts` doc, `remote.md:50`). - `tailscale` (763 LOC): wraps the user's `tailscale` executable (`status`, `serve`) with schema-validated, secret-scrubbing error taxonomy (`tailscale/src/tailscale.ts:10-31`). Tailscale is "an endpoint for ordinary pairing", not a separate environment type (`docs/internals/remote.md:43-45`). **Fabric equivalent replaced:** the remote-access stack demanded by D2d/D12; fabric currently has no equivalent. ## 11. apps/web, apps/desktop — the control surfaces **apps/web** (1,258 files / 318,401 LOC): React 19 + Vite(-plus) + TanStack Router (file routes at `apps/web/src/routes/`, e.g. `routes/projects.$projectKey.tsx`, `routes/connect.tsx`, `routes/pair.tsx`), Tailwind 4, tiptap composer, zustand for local UI state, `@effect/atom-react` bridging client-runtime atoms, `@pierre/diffs` for diff rendering, react-markdown pipeline, Clerk only for the hosted/cloud tier. ~135 top-level components + feature dirs (chat, settings ~140 files, terminal, cloud, device, onboarding). Terminal emulation via libghostty-vt wasm (`src/terminal/ghostty/{core,renderer,runtime,surface}.ts`). Two deployments: hosted app.t3.codes and the server-served local client; dev is single-origin with Vite proxying `/api`, `/ws`, `/oauth` (`AGENTS.md`, Three-ways-to-hurt-yourself #3). Hosted web stores the connection catalog in the browser and connects directly to each environment — it is a pure client, no server-side proxy (`docs/internals/remote.md:28-38`; pairing-URL secret-in-fragment design `apps/web/src/hostedPairing.ts`, `remote.md:33-38`). **apps/desktop** (258 files / 81,239 LOC): Electron 44 wrapping the web renderer, plus: `src/backend/` — a **DesktopBackendManager/Pool** that spawns/bundles the server so the desktop app is also a host environment (`src/backend/DesktopBackendManager.ts`, `DesktopBackendPool.ts`, `DesktopServerExposure.ts`, `tailscaleEndpointProvider.ts`); `src/electron/` service wrappers (window, updater via electron-updater, safe storage, protocol, power monitor, Win32 foreground via lazily-loaded `ffi-rs` — `docs/internals/overview.md:118-124`); `src/snapShot/` screen-capture across OSes (macOS via osascript, Linux via the native hyprland/kde helpers + GNOME extension `apps/desktop/gnome-extension`, a11y via `@crowecawcaw/xa11y` in forked children only); `src/ssh/`, `src/wsl/`, `src/preview/` (playwright-core-driven in-app browser), IPC typed by `contracts/ipc.ts` (1,388 LOC). Linux desktop-identity/portal ordering constraints documented at `docs/internals/overview.md:106-116`. **apps/mobile** (structural notes only, deferred per D13): Expo 57 / React Native (`apps/mobile/package.json:7` `expo start`), EAS build profiles (`eas.json`), native modules under `apps/mobile/modules` incl. Swift/Kotlin (868 files, 154,001 LOC incl. native), `src/{components,connection,features,lib}`, uniwind theming, Clerk Expo for T3 Connect, patched RN ecosystem (19 of the 23 pnpm patches are mobile-related — `pnpm-workspace.yaml` patchedDependencies). It consumes the same `contracts` + `client-runtime` connection stack. ## 12. infra/relay — T3 Connect (hosted remote access) 78 files / 27,381 LOC, 91% Effect. A **Cloudflare Worker** (`src/worker.ts`, `@cloudflare/workers-types`) deployed with **alchemy** (`infra/relay/package.json` "deploy": `alchemy deploy`), Postgres via `@effect/sql-pg` + drizzle, Clerk backend for cloud identity, `@noble/curves`/`@noble/hashes` for the signing protocol. Modules: `environments/` (EnvironmentConnector, EnvironmentLinker/Links, EnvironmentCredentials, EnvironmentPublishSignatures, ManagedEndpointAllocations/Provider/Reaper, ManagedTunnelLimits), `auth/`, `http/Api.ts`, `agentActivity/`, `persistence/`, `queues.ts`, push-notification smoke scripts for mobile. Trust model (CONFIRMED, `docs/internals/t3-connect.md:11-33`): the relay is a broker that asks the environment to mint a one-time bootstrap credential bound to the client's DPoP key; the client redeems it directly with the environment; the relay never sees session tokens; both directions verify signatures; managed tunnels (cloudflared) expose only a validated loopback origin; after bootstrap the relay does not proxy application traffic (`t3-connect.md:3-6`). **Fabric equivalent replaced:** the hosted-remote-access story D12 mandates; fabric has none today. ## 13. native/* | Component | What | Used by | |---|---|---| | `browser-secret` (105 LOC C) | reads Chromium's libsecret cookie key for browser cookie import; exit codes consumed by `ChromiumKeys.ts` (`native/browser-secret/main.c:1-12`) | desktop preview/browser-import | | `hyprland-snap-shot` (1,823 LOC Rust) | Wayland/Hyprland screen capture helper (wlr protocols in `protocols/`) | desktop snapshot | | `kde-snap-shot` (1,251 LOC Rust) | KDE screen capture helper (dbus) | desktop snapshot | | `libghostty-vt` (8,915 LOC C headers, revision-pinned) | vendored ghostty VT API headers; wasm build renders terminals in web | web terminal (`apps/web/src/terminal/ghostty/core.ts:13-15`) | | `resource-monitor` (1,334 LOC Rust, sysinfo, stdin/stdout protocol v3 — `native/resource-monitor/src/main.rs:11`) | host/process CPU/memory sampling with 1h history | server `resourceTelemetry/`, shipped in every CLI archive (`scripts/build-cli-archive.ts:2-15`) | Portability note (CONFIRMED): the Electron main startup path loads **no** native modules; native capability runs in deadline-bounded children (`docs/internals/overview.md:118-124`). The server's own native surface is limited to node-pty, @napi-rs/keyring, fff-node (dlopen'd, kept external to the bundle — `workspace/WorkspaceSearchIndex.ts:30`), and msgpackr-extract. ## 14. Packaging, install, and release machinery - **Single executable**: `apps/server/scripts/cli.ts build-exe` builds the server as a **Node single-executable application** (needs Node 25.7+ `--build-sea`; native packages still resolved from a sibling `node_modules` tree — `apps/server/scripts/cli.ts:160`). Bundle via `vp pack` (`apps/server/package.json` "build:bundle"). - **CLI archive**: `scripts/build-cli-archive.ts:2-15` — per-platform archive = `t3` binary + web client + resource-monitor + production node_modules of the externals (node-pty, msgpackr-extract, fff); "nothing in it may require Node, npm, or a compiler". - **npm distribution**: `scripts/build-npm-platform-packages.ts:3-9` — `@t3code/t3-<platformKey>` per-platform packages holding archive bytes verbatim + a `t3` launcher package with optionalDependencies → `npx t3` / `npm i -g t3`. - **Shell installers**: `scripts/install.sh:2-24` (POSIX sh, sha256-verified GitHub release download into `$T3CODE_HOME/runtime/versions/<version>`, channels stable/nightly/preview, same layout the background service uses) and `scripts/install.ps1`. - **Service + self-update**: `t3 service install`, `t3 update` (`README.md:40-41`); server-side update logic in `cloud/selfUpdate.ts`, `desktopUpdate/`, `serviceLauncher.ts`; update manifests merged by `scripts/merge-update-manifests.ts`, mock update server for dev (`scripts/mock-update-server.ts`). - **Desktop artifacts**: `scripts/build-desktop-artifact.ts` → electron-builder dmg/NSIS/AppImage per arch (root `package.json` dist:desktop:* scripts); macOS signing `scripts/sign-macos.ts`; winget (`winget install T3Tools.T3Code`) and Homebrew cask (`README.md:52-62`); AUR `t3code-bin`/`t3code-nightly-bin` repackage the AppImage, published by `.github/workflows/publish-aur.yml` (`packaging/aur/README.md:1-12`). - **CI/CD**: 18 workflows (`.github/workflows/`); `release.yml` jobs preflight → quality → test → release → finalize (`release.yml:98,230,264,753,1121`) with scheduled nightlies; `release-desktop.yml`, `deploy-relay.yml`, mobile EAS preview/production, `windows-tests.yml`, `web-preview.yml`; release smoke test `scripts/release-smoke.ts`; Discord release notifier. - **Licensing hygiene**: `third-party-licenses.config.json` + `scripts/sync-third-party-license-notices.ts` — directly reusable for D15's attribution work items. ## 15. Effect-TS depth and portability assessment - **Deep-Effect zones** (adopting means adopting Effect 4 rc): server (88%), contracts (98%, Effect Schema is the contract language), effect-acp/effect-codex-app-server (100%, built on `effect/unstable/rpc`), ssh (100%), relay (91%). These use unstable namespaces heavily: `effect/unstable/rpc`, `effect/unstable/sql`, `effect/unstable/process` (ChildProcessSpawner), `effect/unstable/cli`, `effect/unstable/http` — pinned to `4.0.0-rc.115` **with a local patch** (`patches/effect@4.0.0-rc.115.patch`) and a patched `@effect/vitest`. - **Shallow-Effect zones** (Effect quarantined behind services): web UI (17% — Effect lives in the atom/data layer, components are plain React), mobile (21%), shared (42% — many pure-TS utility modules), client-runtime (54%). - **Effect-free zones**: native/* (C/Rust), oxlint plugin, AUR packaging, install.sh/ps1. - Portability risks (CONFIRMED): Node `^24.13.1` engine (server accepts `^22.16 || ^23.11 || >=24.10`, `apps/server/package.json` engines); `node:sqlite` dependency (Node 22.5+); SEA build requires Node 25.7+ host; TypeScript 7 + tsgo patching; vite-plus (`vp`) is a Voidzero-private toolchain (`vite: npm:@voidzero-dev/vite-plus-core`) — fabric would either adopt vite-plus or re-platform builds; pnpm-only workspace mechanics (catalogs, patchedDependencies) vs fabric's npm workspaces (`fabric:package.json` uses npm + package-lock.json). ## 16. Mapping to fabric equivalents (per D2) | t3code unit | Replaces in fabric | Notes | |---|---|---| | `packages/effect-acp` (+ server `provider/acp/*`) | `fabric:packages/adapters` transport core | D6: ACP canonical; per-harness ext modules mirror t3code's Cursor/XAi/Antigravity support files | | `apps/server/src/provider/*` (drivers/adapters/instances/installers/auth) | `fabric:packages/adapters/hooks/adapter-{claude,codex,cursor,opencode,antigravity,…}` | fabric's hook adapters observe harnesses; t3code's adapters *drive* them — a strictly larger capability | | `packages/contracts` | the implicit interfaces of `fabric:packages/kradle/{core,sdk}` and adapters event types | tracked fork per D9; contracts' capability-flag versioning doctrine should come with it | | `apps/server` orchestration/persistence/auth/checkpointing/terminal | `fabric:packages/kradle/core` + parts of babysitter run-state handling | event-sourced core with SQLite receipts is the piece fabric's control surface lacks | | `packages/client-runtime` + `apps/web` | `fabric:packages/kradle/web`, `fabric:packages/observer-dashboard`, retired `genty` UI shells (D2c) | | | `apps/desktop` | no fabric equivalent (new surface) | bundles a host server — relevant to single-node packaging (D3) | | `packages/ssh`, `packages/tailscale`, `apps/server/src/cloud`, `infra/relay` | no fabric equivalent — fills D12 hosted remote access | relay requires Cloudflare+Postgres+Clerk operational stack | | install/release machinery (§14) | fabric packaging gap (D3 all three forms) | curl\|sh + winget + npx + service + self-update all already solved in t3code for the single-node form | | `apps/mobile` | deferred (D13) | consumes same contracts/client-runtime; no fabric work implied now | ## 17. CONFIRMED vs INFERRED **CONFIRMED** (read directly in source/docs, cited above): the six-harness set and each integration mechanism (§4); the event-sourced command/decider/projector/reactor model and its single-transaction commit; SQLite over `node:sqlite`; hidden-git-ref checkpoints; DPoP/pairing environment auth; relay-as-broker trust model with cloudflared managed tunnels; contracts as the sole wire boundary with 144+8 WS RPC methods; generated ACP (10.4k LOC) and Codex app-server (56.8k LOC) schemas; all size/LOC/Effect-depth figures (measured); packaging pipeline end to end; Effect 4.0.0-rc.115 pinned and locally patched; MIT license (`LICENSE`). **INFERRED** (reasonable but not verified end-to-end in this pass): - The libghostty-vt **wasm artifact build/packaging step** was not located in this pass; only the vendored headers, the pinned revision, and the web consumer were read. (The renderer's existence is confirmed; the build provenance of the `.wasm` is not.) - Effect-depth percentages use "imports `effect`" as a proxy; a file can import one Effect utility yet be architecturally plain TS. Treat the zone classification (§15) as directional. - The claim that the desktop renderer reuses the web app wholesale is based on `AGENTS.md:3`/dependency wiring (`@t3tools/web` not a desktop dep; desktop wraps built web assets); the exact asset-embedding path was not traced. - Mobile figures include generated/native scaffolding; the hand-written TS share is smaller than 154k LOC suggests. - `packages/effect-codex-app-server` generation source is presumed to be the Codex app-server JSON schema via `@effect/openapi-generator` (devDep + `scripts/generate.ts` naming); the upstream schema URL was not read. ## 18. Spec inputs Concrete facts the spec author must use verbatim: 1. **Harness matrix**: Cursor (`cursor-agent … acp`, `provider/acp/CursorAcpSupport.ts:56-60`), Grok (`grok --permission-mode <m> agent stdio`, `provider/acp/GrokAcpSupport.ts:33-41`), Antigravity (downloaded release verified as `antigravity-acp` protocolVersion 1, `provider/AntigravityInstallation.ts:484-502`) are **ACP**; Claude is **`@anthropic-ai/claude-agent-sdk` in-process** (`provider/Layers/ClaudeAdapter.ts:5-27`); Codex is **`codex app-server` JSON-RPC stdio** (`provider/Layers/codexLaunchArgs.ts:13`, typed by `effect-codex-app-server`); OpenCode is **HTTP via `@opencode-ai/sdk/v2`, one server per thread** (`provider/Layers/OpenCodeAdapter.ts:32`, `docs/internals/providers.md:14-22`). An ACP-canonical fabric adapters layer therefore still needs three non-ACP lanes (Claude SDK, Codex app-server, OpenCode HTTP) behind the same `ProviderAdapter` contract — exactly t3code's shape (`provider/Services/ProviderAdapter.ts`, registry `provider/builtInDrivers.ts:49-56`). 2. **Adoption units and coupling**: `effect-acp` and `effect-codex-app-server` depend only on `effect` and are extractable as-is; `contracts` depends only on `effect`; `client-runtime` depends on `contracts`+`shared`+`@effect/atom-react`; `apps/server` depends on all of the above plus platform-node. Dependency direction is clean (contracts ← everything; no cycles observed). 3. **Effect stance data (D5)**: adopting server/contracts/effect-acp means adopting `effect@4.0.0-rc.115` + local patch + `effect/unstable/{rpc,sql,process,cli,http}`; web/mobile UI layers prove Effect can be quarantined to a data layer (17-21% file penetration). 4. **RPC surface size**: 144 `Rpc.make` in `contracts/src/rpc.ts` + 8 orchestration methods (`contracts/src/orchestration.ts:35-44`) + HttpApi groups in `environmentHttp.ts` + Electron IPC (`ipc.ts`, 1,388 LOC) — this is the interface fabric's kradle must match or subset. 5. **Compat doctrine to preserve**: environment capability flags negotiate features; persisted events must replay forever; schema transforms (not runtime branches) absorb legacy wire shapes (`docs/internals/overview.md:24-44,70-72`). 6. **Remote-access stack (D12)**: four routes — direct/LAN pairing (DPoP + pairing grants, `apps/server/src/auth/`), Tailscale endpoint (`packages/tailscale`), SSH launch+forward (`packages/ssh`, desktop-owned lifecycle), and T3 Connect (relay = Cloudflare Worker + Postgres + Clerk + cloudflared, broker-not-proxy, `docs/internals/t3-connect.md`). Hosted web is a pure client with browser-held connection catalog (`docs/internals/remote.md:28-38`). 7. **Packaging blueprint (D3 single-node form)**: SEA binary (Node 25.7+ build host, `apps/server/scripts/cli.ts:160`) → per-platform archive with web client + resource-monitor + 3 native externals (`scripts/build-cli-archive.ts:2-15`) → npm platform packages + launcher (`scripts/build-npm-platform-packages.ts:3-9`) → install.sh/ps1 with channels + service layout (`scripts/install.sh:2-24`) → winget/brew/AUR/deb. Release CI: preflight/quality/test/release/finalize (`​.github/workflows/release.yml:98-1121`). 8. **License/attribution (D15)**: MIT (T3 Tools Inc.); reuse `third-party-licenses.config.json` + `scripts/sync-third-party-license-notices.ts` as the attribution mechanism. 9. **Size planning figures**: server 398.6k LOC / web 318.4k / client-runtime 65.8k / contracts 27.0k / effect-acp 15.5k (5.2k handwritten) / effect-codex-app-server 61.8k (3.8k handwritten) / relay 27.4k / ssh 4.1k / tailscale 0.8k. Handwritten-vs-generated distinction matters: both protocol packages are mostly regenerable. 10. **Native/portability constraints**: server native surface = node-pty + @napi-rs/keyring + fff-node (+ optional resource-monitor Rust binary shipped beside it); `node:sqlite` requires Node ≥22.5; desktop keeps native modules out of Electron main (`docs/internals/overview.md:118-124`); terminal rendering needs the libghostty-vt wasm story resolved (see INFERRED). 11. **Testing patterns worth importing into D7**: typed runtime receipts + drainable workers instead of sleeps (`docs/internals/overview.md:96-104`, `packages/shared/src/DrainableWorker.ts`); ACP mock agent for protocol tests (`apps/server/scripts/acp-mock-agent.ts`); release smoke (`scripts/release-smoke.ts`); per-provider adapter test suites co-located with every adapter. 12. **Toolchain divergence to resolve in the spec**: pnpm 11 catalogs/patches + vite-plus + TS7/tsgo (t3code) vs npm workspaces + plain tsc/vitest (fabric). Vendoring any t3code app wholesale imports this toolchain; extracting packages (contracts, effect-acp, ssh, tailscale) does not — they build with plain `tsc --noEmit` and have no bundler coupling.
documents
[]

Outgoing edges

None.

Incoming edges

contains_page1
  • page:docs·PageBabysitter Docs

Related pages

No related wiki pages for this record.

Shortcuts

Open in graph
Browse node kind