You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(server): background service launcher uses 75% less memory - #29284
The background service runs t3 __service-launcher, a tiny supervisor that keeps the real server alive. It loaded the whole CLI just to reach its handler. In the packaged single executable, that is the full 18 MB module, so the launcher alone held ~260 MiB for as long as the service ran.
Now bin.ts is a 31 KB bootstrap. The service's exact t3 __service-launcher call runs straight from it. Every other command, including the launcher with flags or --help, loads the CLI from binMain.ts as before. In packaged builds, that CLI is a separate bundle embedded as a raw executable asset, so the executable is still one file.
Linux x64 packaged executables, medians of alternating runs against main:
main
This PR
Launcher memory (PSS)
259 MiB
66 MiB (-75%)
Launcher time to start the server
467 ms
29 ms
Launcher CPU at startup
590 ms
20 ms
acp-mcp-call startup (wall / CPU)
288 / 294 ms
283 / 293 ms
t3 serve memory
420 MiB
418 MiB
Guards:
build:exe fails if the bootstrap grows past 1 MiB, so the CLI cannot slip back into it.
Both executable configs pass --require-module, so NODE_OPTIONS=--no-require-module cannot break the embedded load.
The release smoke test now also runs __service-launcher on every platform.
Proof:
check:changed, plus focused tests for the launcher, boot service, CLI loading, and the linux-arm64 executable. The CLI test fails if the bare-argv check or the launcher's full-CLI command is removed.
Linux x64 packaged executable: version, launcher errors, launcher --help and flags, symlinked paths, --no-require-module, the speech worker over IPC, and SIGTERM stopping launcher and child.
macOS arm64: built the real release archive on a Mac before the rebase, and the archive smoke test passed. Windows is covered by the release smoke test.
Council review
Rounds: 3
Delegate
Round 1
Round 2
Round 3
Claude Opus 5.5
7/10
8/10
9/10
Muse Wonder Full
7/10
9/10
9/10
Codex GPT-6.1 Sol
9/10
9/10
9/10
Created with Claude Opus 5.5 in Claude Code, running in T3 Code.
Macroscope's review found this PR requires human approval — The change keeps the full CLI out of the service launcher's startup graph and packages it as an embedded asset. New diagnostic suppressions in bin.ts and vite.config.ts require human review.
No code changes detected at 9c7369f. Prior analysis still applies.
You can add or adjust custom eligibility rules. Learn more.
Reviewing files that changed from the base of the PR and between c7810c2 and 9c7369f.
You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.
Use the checkbox below for a quick retry:
Trigger review
No actionable comments were generated in the recent review.
Walkthrough
The executable build now creates a separate bootstrap and CLI asset, validates bundle imports and bootstrap size, and embeds the CLI asset in SEA executables. Runtime startup loads the CLI through the bootstrap or runs the service launcher directly. Tests and an archive smoke check cover these paths.
Changes: CLI Bootstrap and Dispatch
Layer / File(s)
Summary
Build and embed CLI asset apps/server/vite.config.ts, apps/server/scripts/cli.ts, apps/server/scripts/cliErrors.ts, scripts/lib/linux-arm64-sea.ts
Executable packing creates a CLI bundle and a separate bootstrap. The build checks both bundles for external imports, rejects bootstraps larger than 1 MiB, and embeds the CLI asset in SEA executables.
Bootstrap loading and command dispatch apps/server/src/bin.ts, apps/server/src/binMain.ts, apps/server/src/cli/serviceLauncher.ts, apps/server/src/binCli.ts
The entry point loads the CLI from the embedded asset in SEA runs or imports it directly otherwise. It invokes the service launcher for the exact launcher command with no extra arguments. Other invocations use the CLI dispatcher. The service launcher awaits its work and sets the exit code on failure.
CLI startup and archive checks apps/server/src/cliCompileCache.test.ts, scripts/smoke-cli-archive.ts
Tests check CLI loading for normal and service-launcher invocations. The archive smoke check verifies the expected missing-T3CODE_HOME error.
sequenceDiagram
participant BinEntry as bin.ts
participant Launcher as runServiceLauncherCli
participant CliMain as binMain.ts
participant BinCli as binCli.ts
alt Exact __service-launcher invocation
BinEntry->>Launcher: run service launcher
Launcher->>Launcher: await runServiceLauncher
else Other invocation
BinEntry->>CliMain: load CLI and call runCliCommand
CliMain->>BinCli: import and run CLI
end
This change moves the background service launcher into a small bootstrap to cut its memory use, and no merge-blocking defect was found. Windows and macOS SEA loading was not run directly and depends on the PR's reported release smoke tests.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title describes the launcher memory reduction, which is the main change.
Description check
The description covers the problem, change, and verification. It does not include the required scope and approval information.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Finishing Touches
Generate docstrings
Commit to this branch
Create a new PR
Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Small start-up cost on fast paths. About 36 ms (6%): acp-mcp-call went from 557 to 593 ms median, and acp-mcp-bridge from 557 to 589 ms (10 runs each, one batch per build). This looks like a fair trade, though acp-mcp-call pays it on every tool call.
Not tested: update handoff and rollback through the real update flow, Windows, macOS, and the web UI (client not built, so / returned 503).
t3dotgg
changed the title
perf(server): background service launcher uses 85% less memory
perf(server): background service launcher uses 75% less memory
Nov 6, 2026
Native Windows runners generate the server compile cache in afterPack,
which upstream's Linux-hosted Windows packaging skips. Since pingdotgg#29284 split
the server bundle, the cache pushes the Windows x64 payload to 82 files,
over upstream's 80-file limit, so every patched nightly failed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actionsBot
added a commit
to omarcresp/t3code-flake
that referenced
this pull request
Nov 6, 2026
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
size:L100-499 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.
2 participants
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.
The background service runs
t3 __service-launcher, a tiny supervisor that keeps the real server alive. It loaded the whole CLI just to reach its handler. In the packaged single executable, that is the full 18 MB module, so the launcher alone held ~260 MiB for as long as the service ran.Now
bin.tsis a 31 KB bootstrap. The service's exactt3 __service-launchercall runs straight from it. Every other command, including the launcher with flags or--help, loads the CLI frombinMain.tsas before. In packaged builds, that CLI is a separate bundle embedded as a raw executable asset, so the executable is still one file.Linux x64 packaged executables, medians of alternating runs against
main:mainacp-mcp-callstartup (wall / CPU)t3 servememoryGuards:
build:exefails if the bootstrap grows past 1 MiB, so the CLI cannot slip back into it.--require-module, soNODE_OPTIONS=--no-require-modulecannot break the embedded load.__service-launcheron every platform.Proof:
check:changed, plus focused tests for the launcher, boot service, CLI loading, and the linux-arm64 executable. The CLI test fails if the bare-argv check or the launcher's full-CLI command is removed.--helpand flags, symlinked paths,--no-require-module, the speech worker over IPC, and SIGTERM stopping launcher and child.Council review
Rounds: 3
Created with Claude Opus 5.5 in Claude Code, running in T3 Code.
🤖 Generated with Claude Code