Repository navigation
feat(fork): rebrand T3 Code strings at build time - #60
Merged
Merged
Conversation
Upstream-owned files still say "T3 Code" in about 340 user-visible strings. Swapping them by hand would make every upstream sync conflict, so a fork-owned bundler plugin rewrites them in the built product. scripts/lib/forkBrand.ts parses each module with the oxc parser that vite-plus exports and rewrites only string literals, template quasis and JSX text, longest substitution key first. Identifiers, specifiers, property keys, comments, regex literals and types are untouched, and a source map keeps stack traces exact. Modules without the token are never parsed. Exceptions, each with a reason, keep vendor-facing client identities, the GNOME extension name, the relay API title, the upstream attribution and the triage playbook as upstream has them. The web, desktop and server bundling configs each add the plugin, so dev servers and watch builds show what ships. The server's unbundled dev mode gets the same rewrite from a Node load hook. Vitest skips it.
scripts/brand-leak-check.ts scans built output for "T3 Code" that no brand exception covers and names the file, position and context of each leak. It derives its allowlist from the brand layer's exceptions, and skips source maps, binaries and JavaScript comments. CI runs it after the desktop pipeline build, and the release workflow runs it on the JS bundle before that bundle is uploaded for packaging.
Covers why the product is rebranded at build time, how to add an exception, the leak check, and what the layer does not reach.
jamesainslie
added a commit
that referenced
this pull request
Oct 16, 2026
Upstream now names Codex's app-server client once, in a CODEX_CLIENT_NAME constant used for clientInfo and the originator override. The brand layer's exceptions only matched object properties, so the build would have rebranded the identity OpenAI sees. Property exceptions now also match a variable's initializer, in the rebrand step and in the bundle leak check, and the Codex exception names the constant. The triage playbook goes back to upstream's text: the brand layer keeps it byte-identical to upstream and pointed at upstream's issue tracker, a decision from #60 that the sync had reversed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
About 400 user-visible "T3 Code" strings live in upstream-owned lines across web, desktop, server and packages. The fork's merge rule allows an upstream file only one import and one-line swaps, so rebranding them in source would make every upstream sync conflict. This rebrands the built product instead and fails CI when upstream branding leaks.
How
scripts/lib/forkBrand.ts(fork-owned) rewrites only string literals, template-literal static parts and JSX text with the oxc parser that vite-plus already exports. Identifiers, module specifiers, keys, comments, regex literals and type positions are untouched; replacements never span a line and a source map keeps columns right."T3 Code"becomesFORK_IDENTITY.productBaseName.index.html), all desktop pack entries, and the server pack (which also feeds the CLI executable). Serverdevruns unbundled source, so its dev script loads a Node load hook. Skipped under Vitest, where upstream tests assert upstream strings.Kept as T3 Code (each with a reason in
FORK_BRAND_EXCEPTIONS)Codex
clientInfoand the ChatGPTagent_name_hint(vendor-facing identities), the triage playbook (must match upstream byte for byte), the GNOME extension name, "T3 Code Relay API" (upstream's API title) and the "fork of T3 Code" attribution. Tests also pin strings no substitution may ever reach: T3 Connect and the t3.codes hosts,T3CODE_*,refs/t3/, branch prefixes, storage keys,@t3tools/, MCP names and tools, wire paths,t3.json, repo slugs.Leak check
scripts/brand-leak-check.tsscans built output with an allowlist derived from the same exceptions and names file, line and context. Wired intoci-fork.ymlafter the bundle verification and intorelease-fork.ymlright after the JS bundle build, before packaging.Verification
forkBrand.test.tsandbrand-leak-check.test.ts: 32 tests (rewrites, every skipped syntax, every exception, longest match, untouched files, fixture leaks). Upstream web tests asserting "T3 Code" still pass.Not covered
docs/markdown, the marketing site, the mobile app, the GNOME extension's own files, and strings assembled from parts. Choices worth a look: the new-project README footer links to the fork repo, checkpoint commits are authored "Lathe" (email unchanged), and the MCP server's display name (not itst3-codekey) becomes Lathe.