Skip to content
This repository was archived by the owner on Oct 16, 2026. It is now read-only.

perf(build): bundle dist with esbuild so installs fetch only native dependencies - #71

Merged
kody-bot merged 1 commit into
mainfrom
cursor/esbuild-bundle-009e
Oct 16, 2026
Merged

kody-bot merged 1 commit into
mainfrom
cursor/esbuild-bundle-009e

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

Retargeted to main after #70 merged. This is decision C from the Devin performance audit.

Why: cold npx @kodycodes/cli is ~2.5 s, and ~1.9 s of that is npm fetching 47 packages / 38 MB, mostly zod (8.4 MB) and the MCP SDK (8 MB) that the CLI imports in two or three commands.

What: npm run build runs scripts/build.mjs (esbuild, entries bin.ts and cli.ts, ESM, code splitting, target node22) and then tsc --emitDeclarationOnly for the declarations behind the package exports. Every pure-JS dependency is bundled and moves to devDependencies; esbuild, @napi-rs/keyring and ps-list stay as dependencies because they ship native code or platform binaries; kody:* (resolved by workerd) and msw (installed into the Kody cache on demand) stay external. Code splitting preserves every lazy await import() boundary from #31, so --version still loads one chunk plus keyring and does not evaluate the SDK. CJS dependencies (mute-stream, @iarna/toml, cli-width) call require() for Node builtins, so each output file gets a require from createRequire; mainFields: ['module', 'main'] picks ESM builds for packages without exports (jsonc-parser's UMD build otherwise breaks under bundling). No source changes, no CLI flag/output/auth changes, package bin, main, exports and files unchanged.

Results (Devin, Node 24.21): cold npx --version 2.50 s → 1.05 s; cold install 1.85 s → 1.0 s, 38.2 MB / 47 packages → 17.9 MB / 6 packages; warm whoami / search / git-credential ~120 → ~93 ms, dev 154 → 121 ms; --version, status and execute --local unchanged (interleaved A/B within 1 ms). Unpacked tarball grows from 1.39 MB (256 files) to about 3.8 MB (171 files; 1.7 MB of that is source maps for the bundled dependencies).

Independently reproduced here (Node 22.14, fresh isolated npm cache, 3 runs):

metric before (1.26.2) after (this PR, packed tarball)
cold npx … --version 2.45 / 2.70 / 2.68 s 1.44 / 1.37 / 1.47 s
cold npm install 2.44 / 2.33 / 2.41 s 1.16 / 1.26 / 2.37 s
install size / package.json count 38 MB / 60 18 MB / 6
warm p50 --version 50 ms 52 ms
warm p50 status 49 ms 52 ms
warm p50 whoami 173 ms 112 ms
warm p50 execute --local empty 126 ms 123 ms

npm run validate green (388 pass / 1 skip). Smoke-ran every top-level command from built dist and from the packed tarball install. Confirmed msw still installs on demand for --target mock (into XDG_CACHE_HOME/kody/deps/msw), kody:* stays unresolved by the bundle, bin/main/exports/files and .d.ts emissions intact.

One review point: esbuild's own binary (~10 MB) is now ~55% of the install and cannot be bundled; the only way below ~1 s cold is dropping esbuild from the dependency set, which is a product change (see Devin proposal 2).

Authored by Devin (performance audit v2); applied via git am with authorship preserved.

Open in Web Open in Cursor 

Note

Low Risk
Build and packaging only—no src changes—though bundling and a slimmer dependency tree could surface subtle runtime or publish-time issues if not fully covered by tests.

Reviewed by Cursor Bugbot for commit 2a76fb8. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor
cursor Bot force-pushed the cursor/esbuild-bundle-009e branch from a56f5b2 to 8efddb3 Compare October 16, 2026 17:08
@kentcdodds

Copy link
Copy Markdown
Owner Author

bugbot run

…ependencies

dist/ was one file per module plus nine runtime dependencies (47 packages, 38 MB on disk), and a cold `npx @kodycodes/cli` spent most of its 2.5 s downloading them. esbuild now bundles bin.ts and cli.ts with code splitting, so each `await import()` stays its own chunk and a command loads only what it uses, while every pure-JS dependency (MCP SDK, zod, add-mcp, inquirer, chokidar, es-module-lexer, trace-mapping) is compiled in. Only esbuild, @napi-rs/keyring and ps-list, which ship native code or platform binaries, remain dependencies. tsc still emits the declarations behind the package's `exports`.

Co-Authored-By: bot_apk <apk@cognition.ai>
@cursor
cursor Bot force-pushed the cursor/esbuild-bundle-009e branch from 8efddb3 to 2a76fb8 Compare October 16, 2026 17:12
@cursor
cursor Bot changed the base branch from cursor/bench-matrix-009e to main October 16, 2026 17:12
An error occurred while trying to automatically change base from cursor/bench-matrix-009e to main October 16, 2026 17:12
@kody-bot
kody-bot marked this pull request as ready for review October 16, 2026 17:12
@kentcdodds

Copy link
Copy Markdown
Owner Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2a76fb8. Configure here.

@kody-bot
kody-bot merged commit bac4f44 into main Oct 16, 2026
8 of 13 checks passed
@kody-bot
kody-bot deleted the cursor/esbuild-bundle-009e branch October 16, 2026 17:21
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.26.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants