Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
ae23eee
chore(fork-base): fork workflows, stack tools, and docs
github-actions[bot] Jul 31, 2026
568490a
feat(tim): import tim-smart/t3code#4
tim-smart Jul 26, 2026
84af630
feat(tim): import tim-smart/t3code#5
tim-smart Jul 26, 2026
9598a20
feat(tim): import tim-smart/t3code#6
tim-smart Jul 26, 2026
e9302a9
feat(tim): import tim-smart/t3code#7
tim-smart Jul 26, 2026
d9dbda9
feat(tim): import tim-smart/t3code#8
tim-smart Jul 26, 2026
b730307
feat(tim): import tim-smart/t3code#9
tim-smart Jul 26, 2026
848d08e
feat(tim): import tim-smart/t3code#10
tim-smart Jul 26, 2026
8176122
feat(tim): import tim-smart/t3code#11
tim-smart Jul 26, 2026
5c0f2b7
feat(tim): import tim-smart/t3code#12
tim-smart Jul 26, 2026
91cc59d
feat(tim): import tim-smart/t3code#13
tim-smart Jul 26, 2026
f5896e6
feat(tim): import tim-smart/t3code#14
tim-smart Jul 26, 2026
669dbb3
feat(tim): import tim-smart/t3code#15
tim-smart Jul 26, 2026
e48324b
feat(tim): import tim-smart/t3code#16
tim-smart Jul 26, 2026
30bfaae
feat(tim): import tim-smart/t3code#17
tim-smart Jul 26, 2026
355bb29
test(tim-compat): gate macOS bundle fixture to Darwin
patroza Jul 26, 2026
af5dcec
fix(tim-compat): avoid plutil for custom open-with apps
patroza Jul 26, 2026
32a40a3
fix(tim-compat): product-merge VCS #4727 with fork failureKind; green…
github-actions[bot] Jul 29, 2026
0676e3f
fix(tim): restore resource telemetry join + TRACE2 hook exits
github-actions[bot] Jul 29, 2026
e408370
fix(tim): settings search test after worktree-confirm catalog entry
github-actions[bot] Aug 1, 2026
9ac80de
chore: initialize upstream candidate registry
patroza Jul 25, 2026
40f6d10
perf: import bounded web thread history (upstream #4018) (#29)
patroza Jul 25, 2026
9028339
perf: import mobile pagination and bounded replay (upstream #3510) (#35)
patroza Jul 25, 2026
b11b2b4
perf: import bounded long-lived state (upstream #4176) (#34)
patroza Jul 25, 2026
82af154
feat(web): import answered question timeline (upstream #4506) (#44)
patroza Jul 25, 2026
bd79adc
feat(orchestrator): import upstream follow-up queue (#4245) (#63)
patroza Jul 25, 2026
472fc1d
fix(client-runtime): re-read network status when the app resumes (ups…
patroza Jul 26, 2026
6971c03
perf(server): compress and cache packaged web assets (upstream #4516)
patroza Jul 26, 2026
e923c7b
perf(server): back off repeated checkpoint capture failures (upstream…
patroza Jul 26, 2026
9149e6a
fix(server): preserve manually renamed thread titles (upstream #4558)
patroza Jul 26, 2026
78df67e
fix(web): avoid woke status overlap after snooze closes (upstream #4539)
patroza Jul 26, 2026
9aa1934
fix(candidates): rejoin follow-up queue types after tim tip green
github-actions[bot] Jul 29, 2026
a890a9e
fix(candidates): expect thread.unsnoozed on settled turn starts
github-actions[bot] Jul 29, 2026
f6f0f69
fix(candidates): align stale-cursor test with #5147 THREAD_RESUME_MAX…
github-actions[bot] Aug 1, 2026
1a1b817
fix(candidates): accept interleaved sync/live after stale-cursor snap…
github-actions[bot] Aug 1, 2026
90ffd40
fix(candidates): restore SidebarV2 terminal status after restack
github-actions[bot] Aug 1, 2026
ac261bb
chore(fork): stack docs, overlays, tooling, CI, and workspace
github-actions[bot] Jul 31, 2026
d279f9b
feat(contracts): fork protocol and settings schema extensions
github-actions[bot] Jul 31, 2026
8474749
feat(shared): shared helpers and Hermes lint guards
github-actions[bot] Jul 31, 2026
5736f2a
feat(client-runtime): reconnect diagnostics, VCS actions, and list state
github-actions[bot] Jul 31, 2026
c9815a5
feat(packages): ssh, tailscale, and effect-acp fork deltas
github-actions[bot] Jul 31, 2026
32303a3
feat(server): queue, recovery, VCS, Jira, orchestration, and RPC auth
github-actions[bot] Jul 31, 2026
2b75329
feat(web): sidebar, composer, timeline, search, and chrome fork product
github-actions[bot] Jul 31, 2026
5c00c05
feat(mobile): home modes, board, queue composer, and scroll baseline
github-actions[bot] Jul 31, 2026
51b7c56
feat(desktop): packaging, open-with, and backend ownership deltas
github-actions[bot] Jul 31, 2026
5f4e871
fix(desktop): drop obsolete requestSingleInstanceLock from update tests
github-actions[bot] Jul 31, 2026
c4f1be5
fix(mobile,desktop): restore typecheck-green home header and update t…
github-actions[bot] Jul 31, 2026
af18a02
fix(web): isolate ProjectFavicon test so module mocks apply
github-actions[bot] Jul 31, 2026
4b60f6c
ci(compose): run only on merges, not branch pushes
github-actions[bot] Jul 31, 2026
4f49c38
feat(settings): default new threads to new worktree from origin (#252)
omegent-app[bot] Jul 31, 2026
2c81731
ci(fork): disable Blacksmith CI path; green Tim/candidates via Fork CI
github-actions[bot] Jul 31, 2026
7712684
feat(stack): introduce fork/base for fork-only CI plumbing
github-actions[bot] Jul 31, 2026
5edca48
fix(stack): own VS Code build task under vscode overlay
github-actions[bot] Jul 31, 2026
3457b3e
fix(desktop): restore dist:desktop:linux:dir packaging script (#258)
patroza Jul 31, 2026
dc5cdea
fix(grok): always pin Build to agent mode, never leave ask (#260)
patroza Jul 31, 2026
8890934
fix(mobile): unique markdown table cell keys to stop render thrash (#…
patroza Jul 31, 2026
a269da5
fix(web): reload on stale lazy-chunk load after deploy (#263)
omegent-app[bot] Jul 31, 2026
4bfb98e
fix(mobile): hard-unique markdown table cell keys (no table_cell:0:0)…
patroza Jul 31, 2026
4888b65
fix(mobile): stop thread outbox drain spin on reconnect (#265)eeeeeeee
patroza Jul 31, 2026
33acf20
feat(web): move message deep-link wiring onto fork/changes (#267)
patroza Jul 31, 2026
5102d0d
fix(web): open `?thread=` deep links instead of a new draft (#270)
omegent-app[bot] Jul 31, 2026
d3a6368
fix(mobile): ship EAS OTA when Free plan build quota is exhausted (#271)
patroza Jul 31, 2026
104c4ce
fix(web): deep-link open without waiting on shell membership (#272)
omegent-app[bot] Jul 31, 2026
d7b346f
fix(stack): auto-resolve app.config overlay rebase conflicts (#274)
omegent-app[bot] Jul 31, 2026
dc3add3
fix(web): green SidebarV2 after restack onto candidates
github-actions[bot] Aug 1, 2026
77aa540
fix(stack): green changes tip after restack
github-actions[bot] Aug 1, 2026
d8ee8ae
fix(mobile): align list snooze API after candidates restack
github-actions[bot] Aug 1, 2026
87bfe1e
fix(server): durable restartRecovery for post-deploy turn resume (#282)
patroza Aug 1, 2026
c570717
feat(mobile): render settled threads as slim history rows (#283)
omegent-app[bot] Aug 1, 2026
80be0ab
feat(server): blocking lifecycle scripts before worktree removal (#284)
omegent-app[bot] Aug 2, 2026
b8b1881
ci: add one-shot deploy-key helper to force-update overlay tips (#286)
omegent-app[bot] Aug 2, 2026
aa28584
fix(server): bound provider control commands (#288)
patroza Aug 2, 2026
1d4b7d5
feat(server): isolate provider commands by thread (#289)
patroza Aug 2, 2026
331d917
fix(server): retain Grok notification consumer for session (#291)
patroza Aug 2, 2026
291b772
feat(tooling): agent ship gate with draft-free push and pr:ready (#290)
omegent-app[bot] Aug 2, 2026
78c4ad2
feat(web): proactive reload affordance after web hot-swap (draft) (#294)
patroza Aug 2, 2026
8f39e21
feat(tooling): shared-hooks dir so `git worktree add` sets up node_mo…
patroza Aug 2, 2026
8db2390
feat(web): copy thread ID from sidebar v2 menus (#297)
patroza Aug 3, 2026
6ced22e
feat(server): include T3 thread links in Jira replies (#298)
patroza Aug 3, 2026
35dfb20
feat(server): make web-asset serving hot-swap safe + classify web-onl…
patroza Aug 3, 2026
f6b605c
feat(server): reap idle dev stacks from a level-triggered sweep (#296)
patroza Aug 3, 2026
1420bf0
fix(web): align sidebar v1 hide-settled with PR auto-settle (#299)
omegent-app[bot] Aug 3, 2026
607ab64
Use repository-owned native Git hooks (#300)
patroza Aug 3, 2026
2c2f213
fix(mobile): tolerate EAS CLI notices in --json output (#301)
patroza Aug 3, 2026
1975972
Await repository preparation before worktree handoff (#303)
patroza Aug 3, 2026
13e4244
fix(agent): gate undrafting a PR instead of refusing it (#302)
patroza Aug 3, 2026
e91fc3e
test(stack): stop the git fixtures inheriting the caller's repository…
patroza Aug 3, 2026
1f00309
fix(agent): run the pre-push gate without pnpm exec (#305)
patroza Aug 4, 2026
ffd7b92
fix(vcs): name the branch-already-checked-out collision
github-actions[bot] Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 17 additions & 0 deletions .agents/skills/test-t3-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,23 @@ Shared browser dev is single-origin: Vite proxies the backend paths, so never se

The dev runner disables browser auto-open by default. Do not pass `--browser` during automated testing: an automatically opened page can consume the one-time bootstrap token before the controlled browser uses it.

### Previewing the dev server from a remote client

When T3 itself is being driven from another machine — the app connected to this environment over a
tailnet or LAN address rather than `localhost` — a dev server bound to loopback is not reachable at
that address just because the hostname is. Opening it does **not** require `--share`: the
environment resolves the port on demand, reusing an existing `tailscale serve` route, using the
environment's own address when the port already answers there, and otherwise publishing a
tailnet-only HTTPS route for the port and withdrawing it when the dev server exits.

Give the preview a `localhost:<port>` URL and let it resolve. Never hand-write the environment's
hostname with the dev port appended — that is the shape that fails, because nothing promises the
dev port is published under the same number or scheme.

If the port cannot be made reachable, the preview reports why and what to do (dev server not
running, tailscale not logged in, no permission to manage routes, tailnet port already taken).
Treat that message as the result; do not retry the same URL.

### Verify a shared environment before human handoff

When another person will use the printed pairing URL, first open the shared origin without the pairing path or fragment in the controlled browser and confirm the T3 Code app loads. This browser navigation is required even when curl succeeds because browsers block some otherwise reachable ports before making a network request.
Expand Down
56 changes: 56 additions & 0 deletions .easignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Keep EAS project archives small. Mobile only needs the monorepo packages it
# resolves through pnpm — not vendored agent reference trees or desktop shells.

# Vendored reference repos (agents only; never imported by app code)
.repos/

# Desktop / electron / native host tooling
apps/desktop/
apps/vscode/
apps/discord-bot/
native/
release/
release-mock/
dist-electron/
.electron-runtime/

# Infra, docs, agent metadata
docs/
.agents/
.grok/
.github/
.claude/
.cursor/
.vscode/
infra/
artifacts/
.showcase/
apps/mobile/.showcase/

# Tests and snapshots (not needed for EAS bundle)
**/__screenshots__/
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
**/test-results/
**/playwright-report/
**/.vitest-*/

# Local / generated
node_modules/
.t3/
.turbo/
.alchemy/
.dir-deploy-n
.logs/
*.log
.DS_Store
.env
.env.*
!.env.example

# Git / IDE noise
.git/
.idea/
*.tsbuildinfo
21 changes: 21 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@
# Get this from your relay deployment. `infra/relay` deploys update it automatically.
# T3CODE_RELAY_URL=https://relay.example.com

# Optional: GitHub App bridge for continuing an existing worktree-backed T3 thread
# from a pull-request comment. See docs/integrations/github-app-setup.md.
# The webhook route stays disabled unless all four required values are set.
# T3CODE_GITHUB_APP_ID=123456
# T3CODE_GITHUB_APP_PRIVATE_KEY_PATH=/absolute/path/to/private-key.pem
# T3CODE_GITHUB_WEBHOOK_SECRET=replace-with-a-random-secret
# T3CODE_GITHUB_APP_MENTION=t3-code-dev
# T3CODE_GITHUB_ALLOWED_REPOSITORIES=owner/repository,owner/another-repository
# T3CODE_GITHUB_MIN_PERMISSION=write
# T3CODE_GITHUB_TURN_TIMEOUT_MS=1800000

# Optional: hosted app origin used by the CLI's out-of-band OAuth flow.
# Defaults to https://app.t3.codes; override to test against a staging deployment.
# T3CODE_HOSTED_APP_URL=https://nightly.app.t3.codes
Expand All @@ -26,3 +37,13 @@
# T3CODE_MOBILE_OTLP_TRACES_URL=https://api.axiom.co/v1/traces
# T3CODE_MOBILE_OTLP_TRACES_DATASET=t3-code-mobile-traces-dev
# T3CODE_MOBILE_OTLP_TRACES_TOKEN=xaat-...

# Optional: sign and publish the mobile app from your own Expo and Apple teams.
# Development and preview builds append .dev and .preview to the bundle identifier.
# T3CODE_MOBILE_IOS_TEAM_ID=ABC1234567
# T3CODE_MOBILE_IOS_BUNDLE_IDENTIFIER=com.example.t3code
# Set to 1 only for free Xcode Personal Team builds. This disables paid-only
# widgets, push capabilities, App Groups, associated domains, and EAS updates.
# T3CODE_MOBILE_IOS_PERSONAL_TEAM=1
# T3CODE_MOBILE_EAS_PROJECT_ID=00000000-0000-0000-0000-000000000000
# T3CODE_MOBILE_EXPO_OWNER=your-expo-username
9 changes: 9 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Prefer the repo gh policy shim so coding agents cannot undraft with raw
# `gh pr ready` (use `pnpm pr:ready`). Installed by scripts/install-git-hooks.mjs.
PATH_add .tools/bin

# Default bare `gh` commands to the fork, not gh's upstream-parent default
# (`pingdotgg/t3code`). Without this, `gh pr view`/`create`/`checks` resolve
# against upstream and miss the fork's PRs. Explicit `--repo` always overrides,
# so the stack tooling (which always passes `--repo`) is unaffected.
export GH_REPO="${T3CODE_FORK_REPOSITORY:-patroza/t3code}"
14 changes: 14 additions & 0 deletions .githooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Native Git hooks

`pnpm install` configures `core.hooksPath=.githooks`. The tracked hooks exist
immediately in every linked worktree; `post-checkout` reconciles dependencies
after branch checkout and worktree creation before Git returns. T3 configures
the hook path and triggers that checkout once for a fresh clone, before exposing
the repository to the user.

Successful reconciliation records the package/lockfile state under
`node_modules`, so T3's explicit handoff invocation does not repeat an install
which Git already completed. Explicit invocation from the target is required
for bare or stale source repositories.

Lefthook may later orchestrate parallel jobs, but is intentionally unused now.
101 changes: 101 additions & 0 deletions .githooks/post-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/bin/sh
# Reconcile packages after branch checkout and prepare linked git worktrees.
#
# Canonical hook: scripts/install-git-hooks.mjs installs this into the shared
# hooks dir (core.hooksPath) on EVERY host via `pnpm install`, so a raw
# `git worktree add` sets up node_modules identically on smart and the t3vm
# guest -- not only when a worktree is created through the T3 app / t3.json.
#
# Strategy (metadata-safe):
# 1. Copy *small* gitignored seeds from .worktreeinclude (CLAUDE.md, .nuxt, …)
# via reflink/hardlink when available. NEVER clone node_modules -- that
# creates millions of inodes per worktree on btrfs.
# 2. Populate node_modules with `pnpm install --frozen-lockfile --prefer-offline`
# against the shared store (hardlinks -> one inode per package file).
#
# Idempotent: never overwrites existing seed paths; pnpm is safe to re-run.

# Host-agnostic: pick up pnpm/mise from the invoking user's home on either host.
PATH="$HOME/.local/bin:$HOME/.local/share/pnpm:$HOME/.local/share/mise/shims:/run/current-system/sw/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:$PATH"
export PATH

# post-checkout also runs after file-only checkouts; those do not change packages.
[ "${3:-0}" = "1" ] || exit 0

main_wt=$(git worktree list --porcelain | sed -n '1s/^worktree //p')
wt_root=$(git rev-parse --show-toplevel 2>/dev/null)
[ -n "$wt_root" ] || exit 0

if [ -n "$main_wt" ] && [ "$main_wt" != "$wt_root" ]; then
# Effective include: repo .worktreeinclude if present, else nothing to seed-copy.
include=""
if [ -f "$main_wt/.worktreeinclude" ]; then
include="$main_wt/.worktreeinclude"
fi

# Probe once: reflink (CoW fs) > hard link (same fs) > plain copy (cross-device).
probe="$main_wt/.git-hook-clone-probe.$$"
probe_dst="$wt_root/.clone-probe.$$"
: >"$probe"
if cp --reflink=always "$probe" "$probe_dst" 2>/dev/null; then
clone() { cp -a --reflink=always "$1" "$2"; }
elif ln "$probe" "$probe_dst" 2>/dev/null; then
clone() { cp -al "$1" "$2"; }
else
clone() { cp -a "$1" "$2"; }
fi
rm -f "$probe" "$probe_dst"

# True if path is node_modules or under one (never clone these).
is_node_modules_path() {
case "/$1/" in
*/node_modules/*) return 0 ;;
*) return 1 ;;
esac
}

if [ -n "$include" ] && [ -f "$include" ]; then
git -C "$main_wt" ls-files --others --ignored --exclude-from="$include" --directory |
while IFS= read -r rel; do
rel=${rel%/}
[ -n "$rel" ] || continue
is_node_modules_path "$rel" && continue
src="$main_wt/$rel"
dst="$wt_root/$rel"
[ -e "$dst" ] && continue
[ -e "$src" ] || continue
mkdir -p "$(dirname "$dst")"
if [ -d "$src" ]; then
clone "$src" "$dst"
else
cp "$src" "$dst"
fi
done
fi
fi

# Shared-store hardlink install: fast when the store is warm, no inode clone storm.
[ -f "$wt_root/package.json" ] || exit 0
[ -f "$wt_root/pnpm-lock.yaml" ] || {
echo "post-checkout: package.json without pnpm-lock.yaml; skip install" >&2
exit 0
}
state_file="$wt_root/node_modules/.pnpm-checkout-state"
state=$(cksum "$wt_root/package.json" "$wt_root/pnpm-lock.yaml" | cksum | awk '{print $1 ":" $2}')
if [ -f "$wt_root/node_modules/.modules.yaml" ] && [ "$(cat "$state_file" 2>/dev/null)" = "$state" ]; then
exit 0
fi
command -v pnpm >/dev/null 2>&1 || {
echo "post-checkout: pnpm not on PATH; node_modules not installed" >&2
exit 0
}

export CI=1
echo "post-checkout: pnpm install (hardlink from store) in $wt_root" >&2
cd "$wt_root" || exit 1
pnpm install \
--frozen-lockfile \
--prefer-offline \
--config.package-import-method=hardlink \
--config.confirmModulesPurge=false || exit $?
printf '%s\n' "$state" >"$state_file"
8 changes: 8 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
root=$(git rev-parse --show-toplevel 2>/dev/null) || exit 1
if [ ! -x "$root/node_modules/.bin/lint-staged" ]; then
echo "pre-commit: worktree preparation is incomplete (lint-staged is missing)" >&2
echo "pre-commit: T3/manual checkout must finish post-checkout before commit" >&2
exit 1
fi
exec pnpm lint-staged
16 changes: 16 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Agent-only ship gate (humans: no-op). See scripts/agent-pre-push.mjs.
# Draft / no PR: free agent push. Ready PR: vp check + typecheck + tests.
# Publish: pnpm pr:ready, or raw `gh pr ready` — the shim runs the same gate first.
#
# Humans: SKIP_AGENT_PREPUSH=1 git push
# Agents: never SKIP_AGENT_PREPUSH / never --no-verify
# Nested Git commands must discover their own repositories, not inherit this
# hook's GIT_DIR/GIT_WORK_TREE from the outer push.
for name in $(git rev-parse --local-env-vars); do
unset "$name"
done
# Plain `node`, not `pnpm exec node`: pnpm runs a dependency-status check first
# and will try to purge node_modules when the lockfile moved (a rebase does it),
# which aborts without a TTY — the hook then fails with a pnpm error instead of
# anything about the gate. The gate puts node_modules/.bin on PATH itself.
node scripts/agent-pre-push.mjs
35 changes: 0 additions & 35 deletions .github/VOUCHED.td

This file was deleted.

40 changes: 40 additions & 0 deletions .github/client-overlay-ownership.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"overlays": [
{
"id": "desktop-links",
"branch": "t3-discord/f7d37879-desktop-deeplinks",
"pullRequest": 10,
"paths": [
"apps/desktop/src/app/DesktopApp.ts",
"apps/desktop/src/app/DesktopClerk.test.ts",
"apps/desktop/src/app/DesktopClerk.ts",
"apps/desktop/src/app/DesktopDeepLinks.test.ts",
"apps/desktop/src/app/DesktopDeepLinks.ts",
"apps/desktop/src/backend/DesktopBackendPool.test.ts",
"apps/desktop/src/electron/ElectronProtocol.ts",
"apps/desktop/src/main.ts",
"apps/desktop/src/window/DesktopApplicationMenu.test.ts",
"apps/desktop/src/window/DesktopWindow.test.ts",
"apps/desktop/src/window/DesktopWindow.ts",
"scripts/build-desktop-artifact.ts"
]
},
{
"id": "discord",
"branch": "fork/discord",
"pullRequest": 80,
"paths": [
"apps/discord-bot/**",
"docs/integrations/discord-bot.md",
"docs/architecture/discord-browser-automation.md",
"docs/examples/project-aliases.yaml"
]
},
{
"id": "vscode",
"branch": "fork/vscode",
"pullRequest": 79,
"paths": ["apps/vscode/**", ".vscode/launch.json", ".vscode/tasks.json"]
}
]
}
Loading
Loading