feat: rebrand fork to Phoenix with side-by-side install support - #2
Conversation
Renames the fork's user-visible identity from T3 Code to Phoenix, and gives it a distinct OS-level identity so it can be installed and run alongside upstream T3 Code on the same machine. The guiding rule is "runtime identity diverges, source identity does not": anything written to disk, bound to a port, or registered with the OS becomes a Phoenix name; anything that only exists inside the repository (the @t3tools package scope, t3-prefixed paths, internal symbols) is left exactly as upstream has it, so merges from upstream stay cheap. Runtime identity now diverging: - state dir ~/.t3 -> ~/.phoenix, env var T3CODE_HOME -> PHOENIX_HOME - desktop userData t3code -> phoenix, product name Phoenix (Alpha) - URL scheme t3code:// -> phoenix:// - bundle/AppUserModelID com.t3tools.t3code -> com.goodbird.phoenix - Linux desktop entry, WM class and URL-handler entry - systemd unit t3code.service -> phoenix.service - ports 3773 -> 3873, 13773/5733 -> 13873/5833 - CLI binary t3 -> phoenix, MCP server id t3-code -> phoenix Two deliberate subtleties: - The legacy-userData adoption step is removed entirely. Upstream migrates its pre-rename directory into the current one; keeping that would point two live applications at a single directory. A test asserts it never comes back. - PHOENIX_HOME has no T3CODE_HOME fallback, unlike every other variable. The base dir holds the SQLite database and auth state, so inheriting a T3CODE_HOME set for T3 Code would recreate the exact collision this change exists to prevent. Other environment variables read PHOENIX_* first and fall back to T3CODE_*. Attribution to T3 Code is added to the README and to Settings -> About, and the original MIT copyright in LICENSE is untouched. Marketing legal pages and podspec author metadata still name T3 Tools Inc., which remains accurate. docs/internals/branding.md records the policy and the post-merge leak check.
Completes the Phoenix rebrand across the session-orchestration feature, which landed on main after the initial rebrand branch was cut. Agent-facing prose, which is injected into spawned sessions' context and would otherwise have agents calling the product "T3 Code" while running inside Phoenix: - the spawned-session report instructions - the list_session_providers / spawn_session tool descriptions - the "[Phoenix]" prefix on spawned-session report and error messages Also renames three MCP clientInfo identities missed in the first pass (GrokProvider's provider probe, and the Cursor/Grok git text-generation clients), which left CursorProvider announcing "phoenix" while its Grok counterpart still announced "t3-code". Adds .omc/ to .gitignore: the agent tooling writes session history and project memory into the working tree, and an automated commit had swept 169 of those files onto this branch.
95830f4 to
cb8b6ab
Compare
The GitHub repository was renamed from goodbirdhq/t3code to goodbirdhq/phoenix, so the README's desktop-builds link redirected instead of resolving directly.
Updated: folded in the session-orchestration strings
Note on the force-pushAn automated commit ("chore: persist OMX project memory and session history") pushed 330 Those files contained no credentials or conversation content — only session IDs, timestamps, PIDs, VerificationServer 229 files pass, desktop 444, mobile 623, client-runtime 591, scripts 201, shared 337, ssh 25, Pre-existing failures inherited from
Lint clean apart from two warnings that also pre-date this work. |
…ifacts Upstream's pipelines assume T3 Tools' infrastructure, so almost none of them can run here. Three changes make CI useful for Phoenix. Runners. Upstream targets Blacksmith; a fork without a Blacksmith installation queues those jobs forever rather than failing them, which is why every check on the rebrand PR sat pending indefinitely. ci.yml now targets GitHub-hosted runners, which are free on this public repository. Disabled workflows. The nine that deploy to, or authenticate against, T3's infrastructure are switched off GitHub-side with `gh workflow disable` rather than edited, so the files stay byte-identical to upstream and never conflict on merge. docs/internals/ci.md records which and why, since that state is invisible in a fresh clone. The mobile native static analysis job is the exception: it lives inside an otherwise-enabled workflow, so it is parked with `if: false`. Phoenix Build. A new, Phoenix-only workflow that builds an unsigned arm64 macOS DMG on every merge to main, publishes it as a GitHub pre-release, and posts to Slack. Unsigned builds are quarantined by Gatekeeper, which reports a missing signature as "Phoenix is damaged and can't be opened" — indistinguishable from a corrupted download — so both the release notes and the Slack message carry the `xattr -dr com.apple.quarantine` fix. The Slack step reads SLACK_RELEASE_WEBHOOK_URL and no-ops when it is unset, so builds do not fail before the secret exists. It reports failures as well as successes.
CI had never actually executed on this fork - every job targeted Blacksmith runners that were never connected, so checks queued indefinitely instead of failing. Pointing them at GitHub-hosted runners surfaced two problems that had been invisible. threadActivity: the session-spawning feature (577c251) added a required `reports` field to OrchestrationThread, but this fixture's defaults were never updated, so it could not satisfy the type. This is our own regression, merged without CI ever running. Adds `reports: []` alongside `proposedPlans`. imageCompression: this test stubbed every encode at 8MB, and it is the only case where nothing fits the budget, so it runs the full 3 dimension scales x (probe + 4 quality steps) = 15 encodes, each base64-encoded to ~10.7MB. It passes in isolation and only times out when the suite runs in parallel and that churn competes for CPU - upstream's 8-vCPU runners absorb it, ours do not. Drops the stub to 2MB, which still encodes to roughly double the 1_300_000-char budget so the assertion is unchanged, and comments why the size is bounded.
ProjectionSnapshotQuery: the session-spawning feature added `spawnedByThreadId` to the projected thread, but neither expected snapshot in this test was updated. Both assertions needed it - deepEqual aborts on the first mismatch, so fixing the snapshot.threads case simply unmasked the shellSnapshot one. Same class of regression as the `reports` field, and same cause: PR #1 merged without CI ever executing. imageCompression: give the give-up-path case a 90s timeout. It is the only case where nothing fits the budget, so it runs 3 dimension scales x (probe + 4 quality steps) = 15 encodes, each a base64 round-trip through jsdom's FileReader. That takes ~8s on its own and overruns the 15s default once the rest of the suite is competing for CPU. An earlier attempt to fix this by shrinking the stubbed encode from 8MB to 2MB did not work - the test passes in isolation even at 8MB, so volume was never the driver, contention is. The smaller stub is kept because there is no reason to do more work than the assertion needs, but the timeout is what actually fixes it. The product path is bounded at 15 encodes and returns correctly; this is a slow test, not a hanging implementation.
CI now runs — and this is the first green build this repository has hadWhy nothing ever ran. Upstream targets Blacksmith runners (26 of 27 jobs). Without a Blacksmith Nine workflows disabled GitHub-side ( New Three defects this surfaced, all from PR #1None are rebrand-related. All three had been sitting on
The image test needed a 90s timeout rather than a smaller payload — it passes in 7.8s in isolation Still outstanding
|
Renames this fork's user-visible identity from T3 Code to Phoenix, and gives it a distinct
OS-level identity so it can be installed and run alongside upstream T3 Code on the same machine.
Approach
Anything written to disk, bound to a port, registered with the OS, or shown to a user becomes a
Phoenix name. Anything that only exists inside the repository — the
@t3tools/*package scope,t3-prefixed file paths, internal symbols liket3Home— is left exactly as upstream has it, somerges from upstream stay cheap.
docs/internals/branding.mdrecords the policy and a post-mergeleak check.
Runtime identity now diverging
~/.t3/T3CODE_HOME~/.phoenix/PHOENIX_HOMEt3codephoenixT3 Code (Alpha)Phoenix (Alpha)t3code://phoenix://com.t3tools.t3codecom.goodbird.phoenixt3code*phoenix*t3code.servicephoenix.service3773,13773/57333873,13873/5833t3phoenixt3-codephoenixPoints worth reviewer attention
The legacy-userData adoption step is removed. Upstream migrates its pre-rename directory
(
T3 Code (Alpha)) into the current one. Keeping that would have pointed two live applications at asingle directory the moment both were installed. A test asserts it never comes back.
PHOENIX_HOMEhas noT3CODE_HOMEfallback, unlike every other variable. The base dir holds theSQLite database and auth state, so inheriting a
T3CODE_HOMEset for T3 Code would recreate exactlythe collision this change exists to prevent. Every other variable reads
PHOENIX_*first and fallsback to
T3CODE_*, so existing configuration keeps working.Two env-isolation follow-ons that the rename would otherwise have silently broken:
T3CODE_HOME, so it now stripsPHOENIX_HOMEtoo. Without this the Linux backend would share theWindows database via
/mnt/c.PHOENIX_PORTis added to the desktop backend's cleared-env list. The server prefers it overT3CODE_PORT, so an ambient value from the dev runner would otherwise outrank the port thebackend was configured with.
.gitignorekeeps ignoring.t3as well as.phoenix, so a checkout that has run either app(or taken an upstream merge) never commits local dev state.
Attribution
Credit to T3 Code is added to the README ("Built on T3 Code") and to Settings → About. The
original MIT copyright in
LICENSEis untouched. Marketing legal pages and podspec author metadatastill name T3 Tools Inc., which remains accurate. README install instructions were corrected — they
previously described upstream's App Store / winget / Homebrew /
npx t3@latestdistributions, noneof which install Phoenix.
Verification
main(unrelatedrequestId/reportsAPI drift).ssh 25, web 2153. The only web failures are the 8 pre-existing
promptStashStore.test.tscases,verified failing identically on a clean tree.
main.Not included
Four files touched by the in-flight
feat/session-spawningbranch don't exist onmain, so theirstrings are not rebranded here: the sessions MCP toolkit (
handlers.ts,tools.ts),SessionSpawnReactor.ts, anddocs/user/session-orchestration.md. They need a small follow-up oncethat branch lands.
Deliberately left alone: the
t3codeOAuth referrer sent to x.ai (changing it risks theirallowlist), upstream's Play Store link on the marketing site, and mobile showcase demo fixtures.
🤖 Generated with Claude Code