Branch from fork/dev, open every PR against fork/dev, and let it merge by squash. That is the
whole branching model. See
docs/stable-dev-release-branch-handover.md.
- Before the documented one-time cutover, implementation PRs continue to target
main. - After cutover,
mainis an upstream mirror. Never merge downstream fork work into it. - Update
mainonly by fast-forwarding it to the upstream tip, never via GitHub's Sync fork button, a PR intomain, or a casual force-push. The stack-rewrite workflow isdisabled_manually— leave it disabled. Do not enable or dispatch it. Local restacks that must move protected tips use the repository-scopedFORK_STACK_DEPLOY_KEY(or an allowed bypass actor) only for that intentional rewrite; agents must never print or reuse that credential. fork/basesits on upstreammainand holds only fork repository plumbing (GitHub-hosted Fork CI, Blacksmith-freeci.ymlrunners,docs/fork-base.md). No Tim, candidates, or product. Permanent draft PR againstmain. Restacks rebuild base first, then Tim → candidates → changes.fork/timcontains only selected Tim Smart integrations abovefork/base.fork/candidatescontains selected open upstream PRs that we run before upstream accepts them, one provenance commit per source PR, above Tim. The permanentfork/changesPR is based onfork/candidates, contains only our downstream layer, remains open, and is the GitHub/T3 default branch.- Integration overlays are retired.
integrationOverlaysis empty, the four registered overlay PRs are closed, and their content lives infork/dev. Do not create one, and do not targetfork/discord,fork/vscode,fork/identityor the desktop deep-links branch. Client-owned work is an ordinary PR againstfork/dev; ownership follows changed paths. - Closed permanent draft PRs (overlays / managed stack PRs): do not open a replacement PR
as the first reaction. (1) Fix the branch tip if needed (rebase onto the intended base, force-
with-lease). (2)
gh pr reopen <n>the same PR number and restore draft +OVERLAY(for overlays). (3) Only if GitHub refuses reopen, create a new draft PR, applyOVERLAY, and update.github/pr-stack.jsonintegrationOverlays[].numberin the same change. Never leave the manifest pointing at a closed PR. - Fixing
fork/changesor an overlay tip: prefer amending / rewriting the commit that introduced the bug (or folding into the existing product/reapply commit), then force-with-lease the layer tip. Do not stack permanent tip-onlyfix(…)/style(…)recovery commits when the tip is still operator-owned stack surface and history rewrite is allowed. New tip commits are OK for ordinary feature work that lands via PR merge into the layer. - Branch from
fork/devand open every PR againstfork/dev. Discord, VS Code, identity and desktop work included: the integration overlays were drained intofork/devand deregistered, so there is no overlay branch to target. Ownership is inferred from changed paths, not from the base branch. - Never open implementation PRs against
main,fork/changesorfork/integration.mainis the upstream mirror; the other two are frozen and superseded byfork/dev. All three produce a huge unrelated diff, andfork/changesis rebased, which silently invalidates a PR based on it. See docs/stable-dev-release-branch-handover.md. - When a PR is CONFLICTING or behind, rebase it onto
fork/devyourself and force-with-lease. There is no stack automation to run: upstream is merged straight intofork/dev, so a PR is only ever behind ordinary commits. - Independent features use parallel PRs based on
fork/dev. Chain PRs only when one change genuinely depends on another, and merge that chain bottom-up. - Treat external forks and open upstream PRs as selective import sources. Tim Smart imports land as
one reviewed commit per source PR on
fork/tim; selected unmerged upstream work lands as one reviewed commit per source PR onfork/candidates; our adaptations land separately onfork/changes. Cherry-pick only wanted commits, explicitly document imported, adapted, and excluded pieces, and never merge a source branch wholesale. - During every Tim/candidates import or restack, inspect all new and changed persistence migrations.
Preserve true upstream migrations unchanged in
Migrations.ts; rewrite every Tim, candidate, overlay, or downstream migration into the fork-local manifest and ledger inForkMigrations.ts. Never share a migration ledger between upstream and fork histories. Full rules: docs/fork-stack.md ("Migration namespaces during provenance imports"). - Run and deploy from
fork/integration, never from a temporary feature or import branch. - All features land in
fork/dev, including upstreamable work. To send something upstream, open a PR from a branch cut against upstreammainin the usual GitHub way. Useadoptonly for work that began upstream-first, anddemoteto close an upstream projection without removing the canonical downstream implementation.
- Opening or updating a PR runs CI but does not deploy.
- Layer status = Fork CI only. Permanent
fork/*/ overlay draft PRs must look green or red solely from Check, Test, Mobile Native Static Analysis, and Release Smoke (.github/workflows/fork-ci.yml). Compose fork integration is an integration rebuild, not a product-layer quality gate — do not add it (or any compose/rebase job) to required status checks for those branches. - Fast path (day-to-day):
.github/workflows/compose-integration.yml(Compose fork integration) runs only when:- a PR is merged into
fork/changes, or - a PR is merged into a registered overlay base (desktop / discord / vscode / identity), or
- it is started with
workflow_dispatch(manual compose after a local tip rewrite). It does not run on branch pushes (force-push rebases, deploy-key updates, compose's own overlay force-with-lease). That avoids check noise on permanent draft PRs and rebase storms. On merge it auto-rebases every registered overlay onto currentfork/changes(no-op when already based; force-with-lease on clean rebases), composes those tips intofork/integration, and dispatches Fork CI on the composed tip. It does not rewrite main/tim/candidates or ordinary feature PRs. Real overlay rebase conflicts fail the job with branch + paths — fix that overlay, then re-run compose (workflow_dispatchor merge again). When adding an overlay to.github/pr-stack.json, also add its branch to theon.pull_requestbase list incompose-integration.yml(and tofork-ci.ymlPR bases).
- a PR is merged into
- Slow path (upstream / Tim / candidates): manual / local only. Run
merge
upstream/mainintofork/devdirectly;mainis then fast-forwarded to the upstream tip. There is no restack workflow any more. Pushes tomain/fork/tim/fork/candidatesmust not auto-restack or auto-compose. Local restacks mirrorpingdotgg/t3code:main, rebuild provenance layers with stop-the-line green gates, rebase overlays, then compose integration viaworkflow_dispatch/ local compose scripts. Deploy key (if used) is only for intentional protected-branch force-with-lease; agents must never print or reuse it. - Fork checks live in
.github/workflows/fork-ci.ymland run for PRs targeting product bases (or by explicitworkflow_dispatchon a branch tip). Permanent stack tips:fork/candidates/fork/changes/ overlays: PR base list infork-ci.ymlfork/tim(PR #1 bases onmain): green viaworkflow_dispatch --ref fork/timso we do not attach Fork CI to every ordinary PR intomain- After a restack that rewrites tips, re-dispatch Fork CI on tim and candidates when you need those permanent draft PRs green again
- The inherited upstream
.github/workflows/ci.yml(Blacksmith runners) anddeploy-relay.ymlworkflows aredisabled_manuallyat repository level. This fork has no Blacksmith runners — if CI is left enabled, Tim/candidates jobs queue forever onblacksmith-*-ubuntu-2404/blacksmith-*-macos-*labels. Do not re-enable upstream CI or relay deploy for fork releases. After any accident re-enable:gh workflow disable CI --repo <fork>. - Successful
fork/integrationCI classifies the complete tree diff from the previous approved integration tree. Runtime-affecting changes hand the exact tested SHA to the private operations repository; tests, documentation, agent metadata, and GitHub-only metadata do not deploy. - Machine topology and deployment implementation belong in a separate private operations repository, not this repository.
- Lockfile after stack rebase / conflict resolution (required): never leave
pnpm-lock.yamlmismatched with anypackage.jsonafter a manual or automated layer rewrite. Taking--ourson the lockfile during conflicts is not finished work whenpackage.json(or workspace package manifests) still declare different deps. Before treating the stack or a recovery PR as done:- On the rewritten tip (usually
fork/changes), runCI= pnpm install --no-frozen-lockfile(orvp installwith frozen lockfile disabled) until the lockfile matches. - Commit the updated
pnpm-lock.yamlon a PR targetingfork/dev(or include it in the recovery commit that lands the rewrite). - Recompose
fork/integrationif the tip already moved, then re-dispatch Fork CI. - Confirm install would succeed under CI: frozen lockfile is on in Fork CI; failures look
like
ERR_PNPM_OUTDATED_LOCKFILE/ "specifiers in the lockfile don't match package.json". Prefer regenerating the lockfile over repeatedly choosing ours/theirs onpnpm-lock.yamlduring multi-commit rebases offork/changes.
- On the rewritten tip (usually
- Per-layer full CI gate after stack rebase (required — stop the line): when rebasing,
replaying, or rewriting the stack, every layer must pass the full local CI gate before you
touch the next layer. Do not rebase, compose, or push a child layer onto a parent that is
still red. Do not “finish the stack rewrite first and green it later.”
- Order:
fork/base→fork/tim→fork/candidates→fork/changes→ each integration overlay → composefork/integrationlast. - On each layer tip after it is rewritten: install/lock consistent, then run the full
local Fork CI gate (not only
vp check) — see Per-layer stack CI (stop the line) under Task Completion Requirements and docs/fork-stack.md (“Per-layer full CI after stack rebase”). - Fix all failures on that layer, commit, force-with-lease push if the layer is shared, then and only then advance.
- Feature PRs: rebase onto
fork/dev, then let the automated agent ship gate validate the tip — a ready-PR push runs it, or publish withpnpm pr:ready. Only stack-layer rewrites (protectedfork/*tips, not PR pushes) run the fuller per-layer manual gate below.
- Order:
- Conflict resolutions (required when stack hits conflicts): do not only hand-resolve and
resume. Update
.github/pr-stack.jsonconflictResolutionsso the next sync auto-applies the same side. Prefer durablecommit: "*"+ path policies; exact SHAs go stale after every rewrite. During rebase,theirs= commit being replayed,ours= new base. Documented in docs/fork-stack.md ("Conflict resolutions"). - Product conflicts (shared UI / app code): never blind whole-file
ours/theirson shared product paths. 3-way merge or re-apply the feature commit; run a pre/post parity check so helpers and tests cannot survive while JSX/wiring is dropped (see #154 remote Open in VS Code button). Full rules: docs/fork-stack.md ("Product conflicts"). - No tip-only product
fix(stack)recovery: whole-file stack resolves that drop VCS/UI must be fixed inside the related provenance/feature commit (or one product-named commit during rewrite), not as permanent tip patches. Same rule for CI format/typecheck recovery onfork/changesand overlay tips: amend/rewrite the offending commit when you have stack push bypass; do not leave a forever-forwardstyle(docs):/fix(stack):tip. See docs/fork-stack.md (“Commit-green during stack rewrite”, “Permanent draft PRs”). - Fork product changes need existence/behavior tests: every user-visible or behavioral fork
change must land with a test that fails if the surface disappears (pure helpers alone are not
enough). Prefer pure gates +
aria-label/data-testidexistence, or markers inapps/web/src/forkSurfaceExistence.test.tsfor chrome. - Integration compose lockfiles: overlay lock commits diverge by design. Compose skips
lockfile-only commits, defers lock-only conflicts, and regenerates one integration
pnpm-lock.yamlat the end. Never push a partialfork/integrationafter a lock conflict. Compose seedsnode_modulesviacp -a --reflink=autofrom a warm tree into a home-side work dir (~/.t3/compose-work, not tmpfs/tmp) before install. See docs/fork-stack.md ("Integration overlay compose and lockfiles").
When implementation work for a user request is done (code, docs, config — not pure Q&A):
- Commit the changes on a feature branch cut from
fork/dev. - Open or update a PR against
fork/devbefore handing off — for every kind of work, including Discord, VS Code, identity and desktop. Nevermain,fork/changesorfork/integration. - Let the agent ship gate own validation before saying “updated the PR” or finishing (see
Task Completion Requirements → Agent ship gate):
- Every agent push is gated. Draft / no-PR pays the static half (
vp check+vpr typecheck). Ready PRs and publish pay the full gate (+vp run test). Do not hand-run those as routine validation — the hook owns them and caches the SHA (focused, scoped proof while iterating is still fine). - Publishing always runs the full ship gate (
vp check→vpr typecheck→vp run test), and only a failing gate stops it.pnpm pr:readyis the explicit path; rawgh pr readyis not refused — the.tools/bin/ghshim runs the same gate first and then lets the command through. Either way the checks run, so there is no way to publish around them and nothing to remember. The huskypre-pushhook enforces the gate on every agent push and fails closed when PR state can’t be resolved. - Same gate for overlay-child PRs. Base = overlay does not relax it; the gate keys off the PR’s ready state, not its base. Compose success or draft-lock green is not the gate.
- Rebase onto
fork/devand force-with-lease; the ensuing push runs the appropriate gate scope. - Confirm with
gh pr view <n> --json baseRefName,mergeable,mergeStateStatus,url baseRefNamemust befork/changesfor ordinary features or the intended overlay/parent branch for a dependent/overlay-child PR.mergeableshould beMERGEABLE(CI may still beUNSTABLEwhile checks run).
- Every agent push is gated. Draft / no-PR pays the static half (
- Before pushing follow-ups, verify PR state with
gh pr view(or equivalent):- If the PR is open → update that branch and push; the gate re-runs for that HEAD (static if draft, full if ready).
- If the PR is merged or closed → do not keep committing on that branch.
Start a new branch, re-apply unmerged work, and open a new PR against the same intended
base (
fork/changesor the overlay).
- Never assume an earlier PR in the session is still open.
- Never merge or request merge (and never tell a bot to merge) a PR that has not passed the ship
gate — publish through
pnpm pr:readyfirst. GitHub required checks onfork/changesand every registered overlay base are the backstop; the ship gate is what runs first.
When the Discord turn includes an Identity map block with ready-to-paste Co-authored-by trailers, attribution is mandatory, not optional:
- Keep the environment default author/committer (usually the GitHub App bot).
- Every
git commityou create for that work MUST end with those exact trailers after a blank line. Do not invent emails for unmapped people. - Before
git push/ opening a PR, verify withgit log -1 --format=%Bthat the trailers are present on each new commit. - A Discord-originated commit without the mapped trailers is incomplete — fix it (amend if not pushed, or a follow-up commit is not enough for GitHub multi-author on already-pushed SHAs; amend/rebase when safe).
GitHub multi-author avatars (bot & human) come from commit trailers, not from PR body prose alone.
When Discord work produces commits (or is clearly intended to land):
- Always open a PR — do not wait for perfect green. Create the PR as a draft as soon as the first meaningful commit gives reviewers something to inspect, and push freely while it stays draft. A missing PR while work sits only on a remote branch is incomplete handoff. Publish only when done, with
pnpm pr:ready— it runs the agent ship gate, then undrafts. Draft is for tracking, not for merging: do not squash-merge, rebase-merge, or instruct a bot to merge a draft or any tip that has not passed the ship gate.
When opening or updating a PR from a Discord thread:
- Discord footer (required in the PR description). Append this exact footer form at the end of the PR body (use the thread starter when known, otherwise the current requester, and that thread’s real jump link):
opened by [<displayName>](discord_user_id) in chat thread **Discord** · [Thread Title](https://discord.com/channels/<guild_id>/<channel_or_thread_id>/<message_id>)Prefer the thread starter’s Discord id/display name from turn context. Do not skip this because the bot might patch the body later — still write it when you create the PR so the first revision is correct. The bot may also hard-append the footer when a PR URL is linked; that is a safety net, not a reason to omit it.
-
If Discord turn context lists Linked work items / Jira issues for the thread, include those Jira issue links in the PR description (and prefer the primary key in the title/branch when one is clear).
-
Prefer opening the PR only after commits already include the Identity map
Co-authored-bytrailers (see above).
Publish validation is automated. Agents do not hand-run the linter/typechecker/tests as a
routine pre-handoff ritual — the ship gate runs them once, at the right moment, and caches the
result. No agent push is free: draft / no-PR still pays the static half; ready and
pnpm pr:ready pay the full gate.
Mechanism (scripts/agent-pre-push.mjs, scripts/agent-pr-ready.mjs, scripts/lib/*.mjs):
- Husky
pre-pushis the agent ship gate. It is a no-op for humans and only fires for coding agents (detected viaGROK_AGENT/T3_AGENT/AI_AGENT/CLAUDECODE/ Cursor / Codex env markers). Humans opt out per push withSKIP_AGENT_PREPUSH=1— agents never set that flag and never usegit push --no-verify. - When it runs, the gate mirrors the CI JS quality path, in order:
vp check— format + lint (the Fork CI Check JS path) — every agent pushvpr typecheck— workspace TypeScript — every agent pushvp run test— unit tests — ready PR / publish only Cargo, mobile native, desktop packaging, and Release Smoke stay CI-only — do not hand-run them for ordinary PR handoff.
- It skips when the HEAD SHA is already cached in
.run/agent-ship-gate.json(static vs complete stages), so a draft push and the publish step never double-run the work already paid for that commit. Force withAGENT_SHIP_GATE_FORCE=1.
When it runs:
| Branch PR state | Agent push |
|---|---|
| No open PR | static (vp check + vpr typecheck) |
| Draft PR | static (unit tests deferred to publish) |
| Ready PR | full ship gate on every push |
| PR state can’t resolve | full ship gate (fail closed) |
This is identical for fork/dev and dependent PRs — the gate keys off the PR’s ready state, not
its base. Managed-PR draft-lock green is not the gate.
Publish path: pnpm pr:ready — runs the full ship gate, then marks the open draft PR ready.
Raw gh pr ready (and the ready-for-review APIs) reach the same place: the .tools/bin/gh policy
shim runs the ship gate first and passes the command through when it is green, so publishing is
gated rather than forbidden and a red gate is the only thing that stops it. AGENT_PR_SHIP=1 marks
a gate already passed — pr:ready sets it for its own undraft call so the gate runs once, not twice.
.envrc puts $REPO/.tools/bin first on PATH so the shim wins over system gh, and sets
GH_REPO to the fork so bare gh pr commands target it instead of gh's upstream-parent default
(explicit --repo still overrides); scripts/install-git-hooks.mjs installs both the hooks and the
shim on prepare.
Agent workflow:
- Open the draft immediately once a PR is in scope (user asked, or Discord/turn rules require it) and the first meaningful commit is useful to review. Keep committing and pushing while it is a draft — each push pays the static gate only (cached per HEAD SHA).
- Publish when the work is done — do not leave a finished PR in draft. The moment implementation
is complete and verified, run
pnpm pr:readyto run the full ship gate and mark the PR ready; this is the immediate next action, before handoff notes, so full CI can start. Draft is only for work-in-progress. Do not run lint / check / typecheck / tests separately first — the gate owns JS validation and caches the passing SHA. - Mid-loop feedback only: while drafting, focused proof is fine —
vp test run <files>for tests you touched, targeted lint/typecheck for the scope you changed. That is edit-loop signal, not a second gate. - Fork product / UI changes still must ship an existence or behavior assertion that fails if the
surface is dropped (not only pure helpers) — see
apps/web/src/forkSurfaceExistence.test.tsand docs/fork-stack.md (“Product conflicts”). The gate’svp run testthen actually exercises it. - Backend / contracts / runtime behavior changes must land with focused tests for the changed
behavior; the gate’s
vp run testruns them.
Pre-commit: husky runs pnpm lint-staged — vp fmt on all staged files plus vp lint --fix on
staged code files (format + lint on commit; typecheck stays in the ship gate; unit tests on ready /
publish). If the hook rewrites files, stage those rewrites, commit, and push again.
Explicitly forbidden:
git push --no-verify/git commit --no-verify, or settingSKIP_AGENT_PREPUSH(human escape hatch only).- Raw
gh pr ready/ the ready-for-review API to undraft — alwayspnpm pr:ready. - Merging or requesting merge (including telling a bot to merge) a draft or any tip that has not passed the ship gate.
- Treating Compose, Managed-PR draft-lock, or “integration CI will catch it” as a substitute for
publishing through the gate. If a PR’s checks panel shows only Compose / draft-lock and no
Check job, it has not been through the gate — publish with
pnpm pr:ready. - Leaving Discord/agent work with commits but no PR (open a draft; draft pushes pay static).
- Leaving a finished PR in draft. Draft is for work-in-progress only; when the work is done,
publish it with
pnpm pr:ready— a completed PR sitting in draft is an incomplete handoff.
The automated agent ship gate covers PR pushes. Stack-layer rewrites push protected fork/*
tips directly — they are not PR pushes, so the husky gate does not fire and this fuller manual
gate is mandatory instead.
When rebasing, replaying, conflict-resolving, or otherwise rewriting any fork stack layer
(fork/tim, fork/candidates, fork/changes, an integration overlay, or composed
fork/integration):
- Finish only the current layer (rebase/replay complete, lockfile consistent, conflicts
resolved and recorded in
conflictResolutionswhen applicable). - On that layer’s tip, run the full local CI gate — every step you can run on the host that
Fork CI runs for a green PR tip:
vp checkELECTRON_SKIP_BINARY_DOWNLOAD=1 vp run -r --cache --log labeled typecheckvp run --cache build:desktopand preload verify (same as Fork CI Check)ELECTRON_SKIP_BINARY_DOWNLOAD=1 vp run test(Fork CI Test — required on every stack layer, not optional)- On macOS hosts when mobile/desktop shell is in play:
vp run lint:mobileand the Open With test from Fork CI Mobile Native Static Analysis when those paths are available node scripts/release-smoke.tswhen release/workflow packaging paths may have changed
- All of those steps must pass on the current layer. Fix failures on this layer (commit + force-with-lease push the layer branch if it is shared). Do not paper over with a fix only on a child layer.
- Only after the current layer is fully green, rebase/replay/compose the next layer onto it. Repeat from step 1.
Layer order (never skip ahead):
main (upstream mirror — do not hand-edit product fixes)
→ fork/base (fork-only CI / repo plumbing)
→ fork/tim
→ fork/candidates
→ fork/changes
→ each integration overlay (in manifest order) onto fork/changes
→ fork/integration (compose last; full CI on the composed tip)
Hard rules:
- One red layer blocks the entire rest of the rewrite. Stop. Fix. Re-run the full gate on that layer. Then continue.
- Never stack “green later” commits, push a known-red parent, or compose
fork/integrationfrom layers that have not each passed the full gate. - Never treat “the next layer will fix typecheck/lint/tests” as acceptable progress.
- Feature PRs and overlay children: after rebasing onto a parent, the child tip goes through the
automated agent ship gate (ready-PR push or
pnpm pr:ready) — plus this stack-layer full test gate if you are rewriting stack automation itself.
Full narrative and examples: docs/fork-stack.md (“Per-layer full CI after stack rebase”).
After frontend feature development or any user-visible frontend behavior change, the primary agent must run one integrated verification pass for each affected client surface after integrating the work:
- Web: use the
test-t3-appskill. Launch one isolated environment, authenticate through the printed pairing URL, and verify the affected flow in the controlled browser. - Mobile: use the
test-t3-mobileskill. Connect one representative iOS Simulator or Android Emulator available on the host to one isolated environment and verify the affected flow. On compatible macOS hosts, prefer iOS for cross-platform changes and stream it through serve-sim in the T3 Code in-app browser or another available agent browser; use Android when it is the affected or viable platform. - Subagents must not independently launch dev servers or repeat integrated client verification unless their delegated task explicitly requires it.
- Stop dev servers, watchers, and other long-running verification processes when the focused verification is complete.
- In a linked git worktree, dev state defaults to that worktree's gitignored
.t3. This deliberately outranks an ambientT3CODE_HOME, which could otherwise select the installed app's live~/.t3/userdatadatabase. An explicit--home-dirstill wins. - Start the web stack with
vp run dev. Sharing over the tailnet is three steps: runvp run dev --sharein the background, wait for thepairingUrl:line in its output, paste that full URL (token included) in your reply. Do not wire uptailscale serveby hand for this, and do not open the URL yourself. - The web app requires pairing. Hand over the pairing URL, not the bare origin. A URL without its token is useless to whoever you gave it to. If the token got consumed, mint a fresh one with
node apps/server/src/bin.ts pair— note it carries standard scopes, while the startup URL carries admin scopes (needed for Settings → Connections management). - Browser dev is single-origin: Vite proxies
/api,/ws,/oauth, and/.well-knownto the backend. Do not setVITE_HTTP_URLorVITE_WS_URLfordev/dev:web. - Worktree paths supply stable preferred port offsets. Read the actual server and web ports from the
[dev-runner]line because occupied ports can still shift them. - Before handing off a
--shareURL, open its origin only (no path, no token) in a controlled browser and confirm the app loads — never the full pairing URL, whose one-time token the check would consume. A successful curl is insufficient because browsers reject some otherwise reachable ports.
apps/server: Node.js WebSocket server. Wraps Codex app-server (JSON-RPC over stdio), serves the React web app, and manages provider sessions.apps/web: React/Vite UI. Owns session UX, conversation/event rendering, and client-side state. Connects to the server via WebSocket.packages/contracts: Shared effect/Schema schemas and TypeScript contracts for provider events, WebSocket protocol, and model/session types. Keep this package schema-only — no runtime logic.packages/shared: Shared runtime utilities consumed by both server and client applications. Uses explicit subpath exports (e.g.@t3tools/shared/git) — no barrel index.packages/client-runtime: Shared runtime package for sharing client code across web and mobile.
- Open-source Codex repo: https://github.com/openai/codex
Use these as implementation references when designing protocol handling, UX flows, and operational safeguards.
This project vendors external repositories under .repos/ as read-only reference material for coding
agents.
- Prefer examples and patterns from the vendored source code over generated guesses or web search results.
- Do not edit files under
.repos/unless explicitly asked. - Do not import from
.repos/; application code must continue importing from normal package dependencies. - Manage vendored subtrees with
vpr sync:repos; usevpr sync:repos --repo <id>to sync one configured repository. - When updating a dependency with a configured vendored subtree, sync that subtree in the same change so
.repos/matches the installed dependency version. - When writing Effect code, read
.repos/effect-smol/LLMS.mdfirst and inspect.repos/effect-smol/for examples of idiomatic usage, tests, module structure, and API design. - When writing relay infrastructure code with Alchemy, inspect
.repos/alchemy-effect/for examples of idiomatic usage, tests, module structure, and API design.