Repository navigation
perf(cli): Give __complete its own light entry point - #1762
Merged
Merged
Conversation
Shell completion runs on every TAB press, but `sentry __complete` paid for most of the CLI before printing anything. The npm bin required the whole 7.6 MB `dist/index.cjs` (~340 ms per call), and the completion engine's static imports reached `@sentry/node` anyway: `db/auth.ts` and the cache modules imported telemetry, and `logger.ts` imported `createConsolaReporter`. Its eager graph was 659 modules. `src/bin.ts` and `dist/bin.cjs` now check for `__complete` first and call `runCompletion` in `lib/complete.ts` without loading `cli.ts`; the npm package ships it as a separate `dist/complete.cjs` (322 KB). The database modules get `withDbSpan` and `recordCacheHit` from `db/index.ts`, which requires telemetry lazily like the existing tracing proxy and skips it with telemetry off, and `initSentry` hands the logger its Sentry reporter. The eager graph is now 40 modules. Median on Node 24 (`issue list ""`): npm 356 -> 67 ms, SEA binary 145 -> 97 ms, bare node 26 ms. Completion output is unchanged. `test/script/cli-startup.test.ts` bundles `lib/complete.ts` and fails on any package outside an allowlist or more than 50 source modules, and the npm e2e test checks `__complete` never loads `index.cjs`. Co-Authored-By: BYK <burak.kaya@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f410427. Configure here.
This was referenced Oct 30, 2026
BYK
requested changes
Oct 31, 2026
BYK
added a commit
that referenced
this pull request
Oct 31, 2026
Part of #1761. Zod 4's `core`, `classic`, and `mini` entry points all re-export `locales/index.js`, which statically imports every locale. Nothing we bundle calls `z.config(z.locales.xx())`; Zod sets its English default by importing `locales/en.js` directly. A new esbuild plugin, `script/lib/zod-locales-plugin.ts`, resolves Zod's locales index to a module that exports only `en`. Error messages stay the same, and `z.locales.en` still works. The npm bundle (`script/bundle.ts`) and the standalone binary (`script/build.ts`) now use the plugin. Both inline `@sentry/mcp-core` for `sentry mcp`. The plugin lives in `script/lib/` so the `@sentry/mcp-server` bundle from #1731 can import it next to `require-alias-plugin.ts`. | | before | after | | --- | --- | --- | | CLI `dist/index.cjs` | 7,869,567 B | 7,605,958 B (−263.6 KB) | | Zod in the CLI bundle | 547,614 B | 284,024 B | | `sentry --version` max RSS | 210.4 MB | 207.6 MB | | `sentry mcp --version` max RSS | 178.0 MB | 175.0 MB | | `sentry mcp` idle max RSS (initialize + tools/list) | 180.5 MB | 177.3 MB | | `@sentry/mcp-server` bundle (#1731 branch, plugin applied locally) | 3,663,084 B | 3,399,473 B | | `sentry-mcp --version` / idle max RSS (#1731) | 137 / 143 MB | 134 / 141 MB | Byte counts come from the esbuild metafile. RSS is `process.resourceUsage().maxRSS` from a `-r` preload, on Node 22, 3 runs each. The new test bundles real Zod, ESM and CJS, with and without the plugin. It checks that the messages match and that `z.locales` has only `en`. This touches `script/bundle.ts` in two lines, an import and one entry at the top of the `plugins` array. #1762 adds code just below that array, so the two may need a trivial rebase. <!-- junior-request-attribution:start --> via **BYK**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A97f516d754ebba138e04ff1efc71c075 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/agent%3A97f516d754ebba138e04ff1efc71c075/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: BYK <burak.kaya@sentry.io>
…fine Replace the esbuild resolve plugin that externalized the lazy telemetry require with a SENTRY_CLI_COMPLETION_BUILD define. The complete.cjs build sets it to true, so esbuild drops the require and @sentry/node from that bundle. Source runs keep the SENTRY_CLI_NO_TELEMETRY check.
This was referenced Oct 31, 2026
BYK
approved these changes
Oct 31, 2026
BYK
added a commit
that referenced
this pull request
Oct 31, 2026
This is groundwork for #1731. That PR builds `@sentry/mcp-server` from the real CLI runner with a smaller route map (`{ mcp, auth, help }`, `mcp` as the default command). Today that can't work: `lib/help.ts` and `lib/completions.ts` import `routes` from `app.ts`, and `lib/list-command.ts` loads it lazily with `require()`. Every command imports `help.ts` through `buildCommand`, so bundling any one command pulls in the whole CLI: every other command, `sentry init`, and Mastra. `app.ts` now registers its route map with `setRoutes()` in the new `lib/route-registry.ts`. `help`, `completions`, `list-command`, and the `schema` command read it from there. `getRoutes()` throws a clear error when nothing has been registered. `list-command` uses `findRoutes()` instead, so a command's `func` called on its own, as unit tests do, still runs without subcommand hints, as it did before. Another entry point can register a smaller map. Output doesn't change: `sentry --help`, `sentry help --json`, `sentry cli completion bash`, `sentry schema issues --json`, and `sentry projects list --help` are byte-identical before and after, from source and from the npm bundle. The plural-alias hint (`sentry projects list` → `Tip: "list" is a subcommand`) still works in the bundle. Bundle size with an esbuild metafile (minified ESM, the same plugins as `script/bundle.ts`): | Entry | Before | After | |---|---|---| | `commands/auth/whoami.ts` | 1822 modules, 194 command files, 5.62 MB | 1156 modules, 1 command file, 2.89 MB | | `lib/command.ts` | 1822 modules, 5.62 MB | 1107 modules, 2.55 MB | | `commands/auth/index.ts` | 1822 modules, 5.62 MB | 1171 modules, 2.93 MB | | `commands/mcp.ts` | 1822 modules, 5.62 MB | 1108 modules, 2.55 MB | After the change, none of these include `app.ts` or `@mastra/*`. Guard: `test/lib/route-registry.test.ts` bundles every module in `src/lib/` and fails, naming the importer, if any of them reaches `app.ts`. It follows lazy `_require()` loads too. `sdk-invoke.ts` is the one exception: it's the library-mode runner, reached only from `src/index.ts`, and it executes the whole app. The three `interceptSubcommand` tests that were skipped because that `require()` failed under vitest now run. `list-command` no longer needs the `require-alias` rewrite, so it's removed from the filters in `script/build.ts` and `script/bundle.ts`. Not included, left for #1731 or later PRs: `cli.ts` still imports `./app.js` for `run()` and unknown-command reporting. Making the application injectable is the next step. I left `cli.ts` alone here to stay clear of #1762. This branch merges cleanly with #1762. `whoami` also still reaches `lib/init/ui/ink-ui.ts` through `resolve-target.ts` (the Ink prompt UI, not the init wizard). <!-- junior-request-attribution:start --> via **BYK**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:agent%3A9214c867676f0f724d594cfe3d630133 --> -- [View Session in Sentry](https://sentry.sentry.io/explore/conversations/agent%3A9214c867676f0f724d594cfe3d630133/?project=4510944073809921) <!-- junior-session-footer:end --> Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: BYK <burak.kaya@sentry.io>
sentry-junior Bot
added a commit
that referenced
this pull request
Oct 31, 2026
Brings in #1762 (light `__complete` entry point). Completion now runs from the bin entry points through `lib/complete.ts`'s `runCompletion`, so the branch's `CliEntry.complete` hook and `startCli()`'s completion branch are removed; `bin.ts` keeps main's dispatch and passes `SENTRY_CLI` to `startCli()`. #1762's comment cleanup in `preloadProjectContext` is applied to `lib/project-context.ts`, where this branch moved it.
sentry-junior Bot
added a commit
that referenced
this pull request
Oct 31, 2026
Adds `mcp-server.ts` to #1762's startup guard. The entry's eager graph is 14 source modules with no `@sentry/*` SDK import, so `--version` and a lone `-v` return before `@sentry/node` or OpenTelemetry load; the guard keeps it that way. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
This branch was previously deployed
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.

Shell completion runs
sentry __completeon every TAB press, and since #1760 also for every flag name in bash and fish. Each call was paying for most of the CLI before it printed anything. This addresses the review thread on #1751 (complete.ts).Where the time went
dist/index.cjsjust to reach the completion branch incli.ts.@sentry/node, even with telemetry off.db/auth.tsanddb/user.tsimportedwithDbSpanfromtelemetry.ts, the cache modules importedrecordCacheHit, andlogger.tsimportedcreateConsolaReporter. That graph was 659 modules: Sentry SDK, OpenTelemetry, and the API client. The completers themselves cost under 10 ms.What changed
src/bin.tsanddist/bin.cjscheck for__completefirst. They callrunCompletioninsrc/lib/complete.tswithout loadingcli.ts. The npm package ships that path as a separatedist/complete.cjs(322 KB). The SEA binary takes it as a lazily evaluated chunk of its single bundle.withDbSpanandrecordCacheHitfromdb/index.ts. Like the existing tracing proxy there, these require telemetry lazily and skip it when telemetry is off, whichrunCompletionsets.initSentrynow passes the Sentry reporter toattachSentryReporter, sologger.tsno longer imports the SDK.Numbers. Median of 20 runs on Node 24 (Linux x64), against a seeded config DB:
issue list ""issue list --init ./(directory)In dev (tsx), the same calls went from about 650 ms to about 315 ms; most of what's left is tsx's own startup.
Guard.
test/script/cli-startup.test.tsbundleslib/complete.tswithout its deferred imports. It fails on any package outsideCOMPLETION_PACKAGES, naming the importer, or when there are more than 50 source modules. It also now coversbin.ts. The npm e2e suite checks that__completeloadscomplete.cjsand neverindex.cjs. The "Shell completion" section ofAGENTS.mddescribes the rule.What's left.
consolais about 15 ms of the remaining npm time, and Stricli (througherrors.ts) about 3 ms. In the SEA binary, the rest is mostly the cost of loading the single 7.6 MB embedded script. Each of these would need a larger change (a lazy logger, a second SEA script), so they are left for follow-ups.via BYK.
--
View Session in Sentry