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
III.Related pagespp. 1 - 1
II.
Page reference

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

Reading · 25 min

Research dossier: t3code architecture and migratable surface reference

Date: 2026-09-27 · Author: research agent for the platform-gaps spec effort · Status: input to 10-t3code-migration.md

Pagewiki/docs/specs/platform-gaps/research/t3code-architecture.mdOutgoing · 0Incoming · 1

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

UnitFiles (src)LOC (incl. tests)LanguageEffect depth (non-test files importing effect)
apps/server863398,627TS431/491 = 88%
apps/web1,258318,401TS/TSX (React 19)139/841 = 17%
apps/desktop25881,239TS (Electron 44)89/134 = 66%
apps/mobile868154,001TS/TSX + Swift/Kotlin (Expo 57/RN)125/602 = 21%
apps/marketing10514TSn/a
packages/contracts7426,979TS (Effect Schema)47/48 = 98%
packages/effect-acp1815,546 (10,375 generated)TS100%
packages/effect-codex-app-server1861,816 (58,004 generated)TS100%
packages/client-runtime25665,846TS85/157 = 54%
packages/shared15429,241TS36/86 = 42%
packages/ssh104,143TS5/5 = 100%
packages/tailscale3763TS1/2
infra/relay7827,381TS (Cloudflare Worker)40/44 = 91%
native/browser-secret2105C (libsecret)—
native/hyprland-snap-shot61,823Rust—
native/kde-snap-shot71,251Rust—
native/libghostty-vt308,915C headers (vendored, pinned by native/libghostty-vt/VERSION)—
native/resource-monitor11,334Rust (sysinfo)—
packaging/ (aur)0 TSshell/PKGBUILD——
scripts/6023,121TSheavy (build scripts written in Effect)
oxlint-plugin-t3code171,771JS—

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/*/):

SubsystemFilesLOCRole
provider/10949,072drivers, adapters, ACP runtimes, installers, auth flows, model catalogs
orchestration/3820,360engine, decider, projector, reactors
pullRequest/2619,751PR providers: GitHub, Bitbucket, Azure DevOps, Forgejo (pullRequest/ listing)
sourceControl/257,954repo/branch discovery, git actions
persistence/847,602SQLite event store, projections, receipts, migrations
vcs/86,540VCS driver registry (checkpoint capability lives here)
cloud/185,764T3 Connect client side: relay auth, managed cloudflared tunnels, self-update
cli/205,681the t3 CLI commands
auth/114,258environment auth: DPoP, pairing grants, sessions, scopes
device/124,150iOS simulator / Android emulator control
usage/113,894provider usage/quota ingestion
project/103,939project registry
resourceTelemetry/83,628host/process resource history (feeds from native resource-monitor)
terminal/43,453thread terminals over node-pty
git/43,417git command execution
textGeneration/133,090provider-backed helper generations (titles etc.)
mcp/113,057T3'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 ProviderRuntimeEvents from @t3tools/contracts.

HarnessMechanismTransportKey filesNotes
**Claude Code****Bespoke: @anthropic-ai/claude-agent-sdk** in-process query() sessionsSDK (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 packagecodex 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.tsCursor 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.tsProbes avoid auth/session side effects (docs/internals/providers.md, setup section)
**OpenCode****Bespoke: OpenCode HTTP server** via @opencode-ai/sdk/v2 clientone 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.tsPer-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):

ModuleLOCDefines
rpc.ts1,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.ts2,441Orchestration 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.ts1,234Canonical provider runtime event surface: ProviderRuntimeEvent, turn token usage, canonical item/request types, task/tool activity models
provider.ts / providerInstance.ts / providerSetup.ts / providerUsageLimits.ts162/149/180/167Driver kinds, per-instance settings (ClaudeSettings, CodexSettings, …), auth/install state machines (ProviderAuthState, ProviderInstallState), rolling quota windows
ipc.ts1,388Desktop renderer↔main Electron IPC surface
settings.ts1,658Server/client settings schema (fonts, themes, providers, usage-limit sources)
pullRequest.ts1,409PR domain: states, snapshots, stacks, multi-link protocol + linkedPullRequest legacy field
relay.ts / relayClient.ts / remoteAccess.ts1,194/63/68T3 Connect relay protocol (managed endpoint runtime config, signing), relay client status, remote access modes
environment.ts / environmentHttp.ts232/623Environment 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.ts355/195Auth posture labels, scopes, DPoP failure categories, shared branded primitives
server.ts891Server config/probe/update surface, skills dispatch
terminal.ts381Terminal open/attach/restart events, term-N ids
composerContext.ts / composerContextClipboard.ts281/27Typed 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.ts464/287/188/125/122Git action progress, VCS errors incl. checkpoint refs, branch/PR discovery, worktree/clone live progress
project.ts / t3ProjectFile.ts307/143Project records; t3.json project file (schema URL t3ProjectFile.ts:1-2)
device.ts583First-class iOS Simulator / Android Emulator control schemas
preview.ts / previewAutomation.ts / browserProfile.ts / browserImport.ts354/953/99/165In-app browser preview surface, automation ops, named browser identities, cookie import from installed browsers
assets.ts / filesystem.ts320/67Signed asset URLs, filesystem browse
keybindings.ts / editor.ts / desktopAppActivation.ts / desktopBootstrap.ts211/232/53/31Keybinding rules (forward-compatible with unknown commands), editor deep links incl. VS Code remote, desktop activation/update handoff markers
model.ts225Model/provider option selections (+ legacy on-disk decoding)
usage.ts / usageLimitSourceId.ts223/9Usage reporting contract
resourceTelemetry.ts522Host/process resource snapshots and history
agentSessions.ts116Import of external sessions (claudeAgent, codex sources — agentSessions.ts:1-2)
review.ts / assistantCitations.ts / background.ts70/31/110Review 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/*

ComponentWhatUsed 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 webweb 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 historyserver 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 unitReplaces in fabricNotes
packages/effect-acp (+ server provider/acp/*)fabric:packages/adapters transport coreD6: 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/contractsthe implicit interfaces of fabric:packages/kradle/{core,sdk} and adapters event typestracked fork per D9; contracts' capability-flag versioning doctrine should come with it
apps/server orchestration/persistence/auth/checkpointing/terminalfabric:packages/kradle/core + parts of babysitter run-state handlingevent-sourced core with SQLite receipts is the piece fabric's control surface lacks
packages/client-runtime + apps/webfabric:packages/kradle/web, fabric:packages/observer-dashboard, retired genty UI shells (D2c)
apps/desktopno fabric equivalent (new surface)bundles a host server — relevant to single-node packaging (D3)
packages/ssh, packages/tailscale, apps/server/src/cloud, infra/relayno fabric equivalent — fills D12 hosted remote accessrelay requires Cloudflare+Postgres+Clerk operational stack
install/release machinery (§14)fabric packaging gap (D3 all three forms)curl\
apps/mobiledeferred (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.

Article source

The article body is owned directly by this record.

Related pages

No related wiki pages for this record.

Shortcuts

Open overview
Open JSON
Open graph