Skip to content

chore(cli): migrate the CLI bundle from tsup to tsdown - #2803

Merged
cliffhall merged 2 commits into
v2/mainfrom
v2/chore/1492-tsdown-cli
Oct 25, 2026
Merged

cliffhall merged 2 commits into
v2/mainfrom
v2/chore/1492-tsdown-cli

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #1492

Summary

#1492 asked for an inventory, a prototype on one client, and a recommendation. The recommendation is to migrate. This PR moves clients/cli to tsdown for real as the prototype. The full write-up, including the option mapping, every gotcha and the order for the rest, is in docs/tsdown-migration.md. The other three builds (web runner, mcpdo, TUI) are tracked in #2797.

What changed

  • clients/cli/tsdown.config.ts replaces tsup.config.ts. It keeps the same entry, ESM output, node22 target, @inspector/core alias and inlining, and the same documented externals list.
    • Externals sit in a hoisted const EXTERNALS = [...], and each name is expanded to also match its subpaths. A bare string in deps.neverBundle matches only that exact specifier, and with bare names alone six packages' subpaths (zod/v4, @modelcontextprotocol/client/stdio, …) were inlined and the build still succeeded.
    • fixedExtension: false keeps build/index.js (tsdown defaults to .mjs).
    • comments: { jsdoc: false } takes the bundle from 1.22 MB to 684 KB, against tsup's 844 KB.
  • CLI manifest: tsup is swapped for tsdown@^0.23.1, with 0.23.1 locked rather than the day-old 0.23.2. The esbuild override and both allowScripts entries are gone, since neither esbuild nor fsevents is in this install any more.
    • A new rolldown: 1.2.13 override pins the CLI's copy to the root's. Vite also uses Rolldown, and verify:dep-lockstep rejected the 1.2.13 (root) vs 1.2.15 (CLI) skew.
  • verify:bundle-externals:
    • It reads the EXTERNALS array as well as external: [.
    • It accepts Rolldown's //#region <path> banners as well as esbuild's // <path>. Rolldown 1.2.13 emits the #region form, so without this the guard would read the CLI bundle as banner-less.
    • Its enrolment test also discovers tsdown*.config.ts.
    • New test cases cover both changes.
  • Docs and references: AGENTS.md, README, the local-dev and project-structure skills, docs/{architecture,publishing,quality-gate}.md, the CLI README, the spec table and the sdk-watch checklist now name the new config. There's also a new docs entry in the README table.

Verification

  • The CLI build emits the identical set of 31 bare imports as the tsup build.
  • clients/cli test:coverage: 37 files, 710 tests pass, including the e2e tests that spawn the built binary. Coverage is 99.4% statements and 96.8% branches.
  • Negative check: with the subpath expansion removed, verify:bundle-externals named all six inlined packages.
  • npm run local:gate is green end to end. It covers verify:bundle-externals on all 4 bundles, verify:dep-lockstep, verify:install-scripts, the smokes (Firefox included) and Storybook.

No UI change, so no screenshots.

🤖 Generated with Claude Code

cliffhall and others added 2 commits October 24, 2026 23:23
tsup is unmaintained and points users at tsdown. Move clients/cli as the
prototype the issue asks for, and record the findings and the path for the
remaining three builds in docs/tsdown-migration.md.

- clients/cli/tsdown.config.ts replaces tsup.config.ts. Externals live in
  a hoisted EXTERNALS array expanded with subpath patterns, because a bare
  string in deps.neverBundle matches the exact specifier only and subpaths
  would otherwise be inlined silently.
- fixedExtension: false keeps build/index.js; comments.jsdoc: false keeps
  the bundle at 681 KB against tsup's 844 KB.
- Drop the CLI's esbuild override and allowScripts entries: neither esbuild
  nor fsevents is in its install without tsup.
- verify:bundle-externals reads the EXTERNALS array, accepts Rolldown's
  //#region banners as well as the plain form, and discovers tsdown configs.
- Docs and references updated; remaining clients tracked in #2797.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
tsdown resolved rolldown 1.2.15 while the root's vite holds 1.2.13, and
verify:dep-lockstep rejects the skew. An overrides entry aligns the cli's
transitive copy, as it already does for @types/node. 1.2.13 writes
//#region banners, which the guard now reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Oct 25, 2026
@cliffhall cliffhall linked an issue Oct 25, 2026 that may be closed by this pull request
@cliffhall
cliffhall requested a balanced review from Copilot October 25, 2026 03:56

Copilot AI 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.

🟢 Approval recommended

No blocking issues remain, and the preserved build contracts, focused regression coverage, and reported full-gate verification support approval.

No open issues 🎉

1 file not reviewed
  • clients/cli/package-lock.json: Generated file
What changed in this PR

Migrates the one-shot CLI bundle to tsdown as the prototype for #1492, preserving its output path and shared-core dependency boundaries. The remaining client migrations are tracked in #2797.

Changes:

  • Replaces the CLI’s tsup configuration and dependencies with tsdown, including explicit external-subpath matching.
  • Extends the bundle-external guard and regression tests to recognize tsdown configs and Rolldown banners.
  • Documents migration results, remaining work, and updated build references.
File Description
specification/​v2_cli_tui_launcher.md Names tsdown as the CLI builder.
scripts/​verify-bundle-externals.test.mjs Tests hoisted externals, Rolldown banners, and config discovery.
scripts/​verify-bundle-externals.mjs Supports tsdown configuration and bundle inspection.
scripts/​sdk-watch.mjs Updates the generated upgrade checklist’s config path.
README.md Updates the CLI builder and links the migration guide.
docs/​tsdown-migration.md Records findings, measurements, and follow-up migration steps.
docs/​quality-gate.md Includes tsdown in bundle-guard documentation.
docs/​publishing.md Updates the CLI source-map configuration reference.
docs/​architecture.md Explains the CLI’s tsdown alias and inlining settings.
core/​auth/​node/​file-lock.ts Updates bundler names in a comment only.
clients/​cli/​tsup.config.ts Removes the previous bundler configuration.
clients/​cli/​tsdown.config.ts Preserves CLI output and external dependencies under tsdown.
clients/​cli/​tsconfig.json Includes the replacement configuration in typechecking.
clients/​cli/​README.md Updates dependency-externalization documentation.
clients/​cli/​package.json Switches builders and replaces obsolete dependency controls.
clients/​cli/​package-lock.json Locks the tsdown toolchain and removes tsup dependencies.
AGENTS.md Aligns build and dependency rules with the migration.
.claude/​skills/​project-structure/​SKILL.md Updates the CLI builder in the project map.
.claude/​skills/​local-dev/​SKILL.md Documents tsdown alias and externalization settings.

Review effort: Balanced

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review loop closed: round 1 was clean (no inline comments, no findings in the summary, no suppressed comments), which is the stop condition. No further rounds requested.

@cliffhall
cliffhall merged commit c621b99 into v2/main Oct 25, 2026
11 checks passed
@cliffhall
cliffhall deleted the v2/chore/1492-tsdown-cli branch October 25, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate migrating from unmaintained tsup to tsdown

2 participants