Skip to content

Switch packages from custom build scripts to tsup#230

Merged
shellicar merged 8 commits intomainfrom
fix/packaging
Apr 9, 2026
Merged

Switch packages from custom build scripts to tsup#230
shellicar merged 8 commits intomainfrom
fix/packaging

Conversation

@shellicar
Copy link
Copy Markdown
Owner

@shellicar shellicar commented Apr 9, 2026

Replaces the hand-rolled build.ts esbuild scripts in each package with tsup.config.ts.

What changed

Each package (claude-core, claude-sdk, claude-sdk-tools) now has a tsup.config.ts that produces ESM + CJS output with declaration files in one pass. The old build.ts files are deleted.

Exports maps updated to the nested import/require form with types + default sub-conditions, pointing to dist/esm/ and dist/cjs/.

claude-sdk-tools entry is src/entry/*.ts — the public tool modules live there. The old build was only compiling files from src/*.ts, which are internal utilities.

Both apps updated: entryNames: '[name]', packages: 'external' instead of a manual external list, bin/start paths updated from dist/entry/main.jsdist/main.js, workspace package deps moved from devDependencies to dependencies.

turbo.json build inputs updated to include tsup.config.ts.

Key decisions

  • bundle: true — required because bundle: false only transpiles entry files, leaving relative imports unresolved in dist
  • clean: 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: true wipes the outdir before the build starts.
  • entryNames: '[name]' — tsup's TypeScript DTS pass ignores esbuild's entryNames, so DTS always lands flat at dist/esm/[name].d.ts. Matching JS placement keeps them co-located with the exports map.
  • Sourcemaps now work correctly, fixing debugger breakpoints hitting in the original TypeScript source.

@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 push
  • scripts/src/generate-schema.ts — regenerates the schema from Zod definitions + config
  • scripts/src/validate-changes.ts — validates every **/changes.jsonl against the schema via ajv
  • scripts/src/generate-changelog.ts — generates CHANGELOG.md for a package from its changes.jsonl

changes.jsonl + CHANGELOG.md added for all five packages/apps. apps/claude-cli carries the full history reverse-engineered from the root CHANGELOG.md (alpha.67 through alpha.74), making the generated file the authoritative source going forward.

@shellicar shellicar added the enhancement New feature or request label Apr 9, 2026
@shellicar shellicar self-assigned this Apr 9, 2026
@shellicar shellicar requested a review from bananabot9000 April 9, 2026 07:14
@shellicar shellicar added this to the 1.0 milestone Apr 9, 2026
@shellicar shellicar enabled auto-merge (squash) April 9, 2026 07:14
shellicar added a commit that referenced this pull request Apr 9, 2026
Session 3 appended to 2026-04-09.md covering the build verification,
post-rebase check, biome CI fix approach, and PR #230.

Current State updated: branch fix/packaging, PR #230 open, recent PRs
#228/#229 added to the post-refactor list.
@shellicar shellicar added pkg: claude-core Core utilities — ansi, reflow, rendering pkg: claude-sdk The agent SDK pkg: claude-sdk-tools The SDK tools package pkg: claude-sdk-cli The new SDK-based CLI pkg: claude-cli The original CLI labels Apr 9, 2026
@shellicar shellicar disabled auto-merge April 9, 2026 07:48
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.
Copy link
Copy Markdown
Collaborator

@bananabot9000 bananabot9000 left a comment

Choose a reason for hiding this comment

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

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.
Session 3 appended to 2026-04-09.md covering the build verification,
post-rebase check, biome CI fix approach, and PR #230.

Current State updated: branch fix/packaging, PR #230 open, recent PRs
#228/#229 added to the post-refactor list.
…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.
@shellicar shellicar merged commit c9e834b into main Apr 9, 2026
4 checks passed
@shellicar shellicar deleted the fix/packaging branch April 9, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request pkg: claude-cli The original CLI pkg: claude-core Core utilities — ansi, reflow, rendering pkg: claude-sdk The agent SDK pkg: claude-sdk-cli The new SDK-based CLI pkg: claude-sdk-tools The SDK tools package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants