Switch packages from custom build scripts to tsup#230
Merged
Conversation
shellicar
added a commit
that referenced
this pull request
Apr 9, 2026
…egration Sets up the full changes.jsonl toolchain for this repo: - changes.config.json defines the valid categories (feature, fix, breaking, deprecation, security, performance) with their display names - scripts/src/generate-schema.ts generates schema/shellicar-changes.json from the Zod definitions + config; category is required (repo policy, stricter than the base spec) - scripts/src/validate-changes.ts validates all **/changes.jsonl files against the schema via ajv; no-args mode globs the repo, or pass specific paths - CI (.github/workflows/node.js.yml) runs the validator on every push Adds changes.jsonl entries for the tsup packaging work (PR #230) in claude-core, claude-sdk, and claude-sdk-tools. Updates both CLAUDE.md files: correct category enum, removed the bad 'issue' field from the example, noted that category is required and that issue links belong in metadata not at the top level, added the @shellicar/changes tooling section.
bananabot9000
approved these changes
Apr 9, 2026
Collaborator
bananabot9000
left a comment
There was a problem hiding this comment.
Clean migration. tsup configs are consistent across packages, changes toolchain matches the design brief (Keep a Changelog categories, tag field on ReleaseMarker, ajv validation in CI).
Non-blocking observations:
- Cache TTL refactor (SdkMessageUsage type change) is bundled in — separate concern from the packaging PR
- Schema generation not in CI — stale schema risk if config changes without regeneration
- TS 6 → 5.9 downgrade — presumably tsup compatibility
- Symlinked tsconfig.check.json resolves extends relative to repo root (symlink target), not package dir — works but worth understanding
The tag field landed exactly as we discussed today. generate-changelog.ts does release.tag ?? shortName@version — correct fallback from explicit tag to scoped default.
🍌 Approved.
Each package had a hand-rolled build.ts that called esbuild directly. Replaced with tsup.config.ts in each package, which handles ESM + CJS output and DTS generation in one pass. Key decisions: - bundle: true is required because bundle: false only transpiles entry files, leaving relative imports unresolved in dist. Consuming bundlers follow those imports and find nothing. - clean: true replaces the @shellicar/build-clean plugin. The plugin uses esbuild's metafile to find current build outputs and delete everything else. TypeScript-generated DTS files never appear in the metafile, so the plugin deleted them every time. clean: true wipes the outdir before the build starts, so JS and DTS land together. - entryNames: '[name]' in esbuildOptions puts JS files at the same level as DTS files. tsup's TypeScript pass ignores esbuild's entryNames entirely, so DTS always lands flat at dist/esm/[name].d.ts. Matching JS placement keeps them co-located and matches the exports map. - claude-sdk-tools entry is src/entry/*.ts, not src/*.ts. The public tool modules live under src/entry/; src/*.ts only contains internal utilities. Exports maps updated to the nested import/require form with types + default sub-conditions, pointing to the correct dist paths. tsconfig.json in each package now scopes to src/**/*.ts and excludes dist/node_modules. tsconfig.check.json symlinks to the root copy. turbo.json build inputs updated to include tsup.config.ts. Both apps updated: entryNames '[name]', packages: 'external' instead of a manual external list, bin paths updated from dist/entry/main.js to dist/main.js, workspace deps moved to dependencies since they are externalized and need to be present at runtime.
Format fixes in the three tsup.config.ts files (arrow function body style), indentation in claude-sdk-tools package.json exports, trailing newline in claude-sdk-cli package.json, import sort order in runAgent.ts. Remove unused CacheTtl import from AgentRun.ts and reformat a ternary in MessageStream.ts — both left over from the cache TTL refactor that came in via rebase.
…egration Sets up the full changes.jsonl toolchain for this repo: - changes.config.json defines the valid categories (feature, fix, breaking, deprecation, security, performance) with their display names - scripts/src/generate-schema.ts generates schema/shellicar-changes.json from the Zod definitions + config; category is required (repo policy, stricter than the base spec) - scripts/src/validate-changes.ts validates all **/changes.jsonl files against the schema via ajv; no-args mode globs the repo, or pass specific paths - CI (.github/workflows/node.js.yml) runs the validator on every push Adds changes.jsonl entries for the tsup packaging work (PR #230) in claude-core, claude-sdk, and claude-sdk-tools. Updates both CLAUDE.md files: correct category enum, removed the bad 'issue' field from the example, noted that category is required and that issue links belong in metadata not at the top level, added the @shellicar/changes tooling section.
Builds out the full changes toolchain across the monorepo: - changes.config.json: Keep a Changelog standard categories (added/changed/deprecated/removed/fixed/security). Custom category names were replaced because these are the recognised standard and tooling elsewhere understands them. - schema/shellicar-changes.schema.json (renamed from .json): generated JSON Schema artifact. The .schema.json suffix is conventional for JSON Schema files and makes intent unambiguous in editors. - scripts/src/generate-schema.ts: generates schema from Zod definitions + changes.config.json. Must run from scripts/ directory. - scripts/src/validate-changes.ts: validates every **/changes.jsonl against the schema via ajv. CI runs this on every push. - scripts/src/generate-changelog.ts: generates CHANGELOG.md for a package from its changes.jsonl. Groups entries by category in config order within each release. Renders metadata.issue as (#NNN) and metadata.ghsa as a linked advisory suffix. - Release markers gain an optional tag field. When absent the script defaults to <shortName>@<version>. The claude-cli app uses explicit tags because its historical alphas used unscoped version tags. - changes.jsonl + CHANGELOG.md added for all five packages/apps. apps/claude-cli carries the full reverse-engineered history from the root CHANGELOG.md (alpha.67 through alpha.74) so the generated CHANGELOG.md is the authoritative source going forward. - Both CLAUDE.md files updated with a dedicated @shellicar/changes section covering config, schema, and all three scripts.
Formatting applied via --changed --since=origin/main to scope fixes to only the files we touched. Rewrote the ??= pattern as a plain if-block: clearer to read, no cleverness required.
tsx is only installed in the scripts workspace package. Running pnpm tsx from the repo root fails because there is no root-level tsx binary. Use pnpm --filter scripts run validate instead, which runs inside the package where tsx is available.
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.
Replaces the hand-rolled
build.tsesbuild scripts in each package withtsup.config.ts.What changed
Each package (
claude-core,claude-sdk,claude-sdk-tools) now has atsup.config.tsthat produces ESM + CJS output with declaration files in one pass. The oldbuild.tsfiles are deleted.Exports maps updated to the nested
import/requireform withtypes+defaultsub-conditions, pointing todist/esm/anddist/cjs/.claude-sdk-toolsentry issrc/entry/*.ts— the public tool modules live there. The old build was only compiling files fromsrc/*.ts, which are internal utilities.Both apps updated:
entryNames: '[name]',packages: 'external'instead of a manual external list, bin/start paths updated fromdist/entry/main.js→dist/main.js, workspace package deps moved fromdevDependenciestodependencies.turbo.jsonbuild inputs updated to includetsup.config.ts.Key decisions
bundle: true— required becausebundle: falseonly transpiles entry files, leaving relative imports unresolved in distclean: true— replaces@shellicar/build-clean. The plugin uses esbuild's metafile to find outputs; TypeScript-generated DTS files never appear there, so it deleted them every build.clean: truewipes the outdir before the build starts.entryNames: '[name]'— tsup's TypeScript DTS pass ignores esbuild'sentryNames, so DTS always lands flat atdist/esm/[name].d.ts. Matching JS placement keeps them co-located with the exports map.@shellicar/changes toolchain
Per-package changelog tooling built into the repo:
changes.config.json— defines valid category keys (Keep a Changelog standard:added,changed,deprecated,removed,fixed,security)schema/shellicar-changes.schema.json— generated JSON Schema, validated in CI on every pushscripts/src/generate-schema.ts— regenerates the schema from Zod definitions + configscripts/src/validate-changes.ts— validates every**/changes.jsonlagainst the schema via ajvscripts/src/generate-changelog.ts— generatesCHANGELOG.mdfor a package from itschanges.jsonlchanges.jsonl+CHANGELOG.mdadded for all five packages/apps.apps/claude-clicarries the full history reverse-engineered from the rootCHANGELOG.md(alpha.67 through alpha.74), making the generated file the authoritative source going forward.