Ts Sdk Author
ASecurityDesign, build, verify, and publish production-grade TypeScript SDKs as npm packages inside a pnpm monorepo. Covers workspace layout, public API and module boundaries, plugin extension points, branded types and library-tuned tsconfig, tsdown bundling (vs tsup/tsc-only/unbuild), package.json exports with dual ESM+CJS and isomorphic conditions (browser/workers/RN/deno), Turborepo pipelines, publint and @arethetypeswrong/cli verification, changesets pre-release mode, npm dist-tags (latest/next/be...
- 14,837 stars
- 0 votes
- 0 copies
- 3 views
- Added September 5, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 8 files and shows the line behind each finding
npx -y skills add mindfold-ai/Trellis --skill ts-sdk-author --agent claude-codeAre you the author of Ts Sdk Author?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/mindfold-ai-ts-sdk-author)---
name: ts-sdk-author
description: >
Design, build, verify, and publish production-grade TypeScript SDKs as npm
packages inside a pnpm monorepo. Covers workspace layout, public API and
module boundaries, plugin extension points, branded types and library-tuned
tsconfig, tsdown bundling (vs tsup/tsc-only/unbuild), package.json exports
with dual ESM+CJS and isomorphic conditions (browser/workers/RN/deno),
Turborepo pipelines, publint and @arethetypeswrong/cli verification,
changesets pre-release mode, npm dist-tags (latest/next/beta/rc/canary),
and the alpha→beta→rc→stable release lifecycle. Triggers on: build a TS
SDK, extract core library, package.json exports, dual ESM CJS, tsdown
config, tsup vs tsdown, publint, attw, changesets prerelease, npm
dist-tag, beta to rc, canary release, pnpm workspace SDK, isomorphic SDK,
tsconfig library, npm provenance, shipping a TypeScript library.
license: MIT
metadata:
author: oh-my-openclaw
version: "1.0"
composed_from:
- agent-cli-architecture
- typescript-pro
- turborepo
- monorepo-navigator
sources:
- code-architecture-refactoring
- architecture-patterns
- turborepo
- fastify
- Jeffallan/claude-skills (typescript-pro)
- turborepo (official docs)
- monorepo-navigator
- publint.dev (rule catalog)
- arethetypeswrong.github.io (problem catalog)
- tsdown.dev (official docs)
- changesets/changesets (prerelease + dist-tags docs)
- GitHub package.json originals — tRPC, vercel/ai, Inngest, Sanity client, Hono, Zustand, TanStack query-core
---
# TypeScript SDK Author
End-to-end workflow for shipping a TypeScript SDK as a standalone npm package
from inside a pnpm monorepo: workspace layout, public API design, build
configuration, distribution shape, monorepo pipeline, verification, and the
full release lifecycle including beta / rc / canary channels.
The seven references hold the depth. This file is the unified workflow plus
a quick-reference for the patterns you reach for daily.
---
## When to Use This Skill
- Extracting a core library (e.g. `packages/core`, `packages/sdk`) out of an
existing CLI or app inside a pnpm workspace
- Designing the public API surface of a TypeScript library that strangers will
consume — branded types, generic clients, plugin extension points
- Choosing a build tool — tsdown vs tsup vs tsc-only vs unbuild
- Authoring the `package.json` `exports` field with dual ESM+CJS, isomorphic
runtime conditions, and subpath plugin entries
- Configuring Turborepo so the SDK rebuilds only when its inputs change and
downstream apps consume the SDK's build output (or raw `src` via a custom
condition)
- Wiring `publint --strict` and `attw --pack` into `prepublishOnly` or CI
- Managing pre-release channels — `canary` per commit, `next` for the upcoming
major, `beta` / `rc` for stabilization, `latest` for stable — and the
transitions between them (`beta.N` → `rc.0` → `1.0.0` → `1.1.0-beta.0`)
- Setting up changesets with GitHub Actions `changesets/action@v1` plus
npm provenance
---
## Execution Workflow
A single TS SDK build flows through these seven phases. Skip any phase and
something will break later — the dependencies between phases are real.
### Phase 1 — Workspace & Package Skeleton
Lay down the monorepo and create the empty SDK package.
Core moves:
1. Adopt `apps/` + `packages/` + optional `tools/` at the workspace root
2. Place the SDK in `packages/<sdk-name>/` (or `packages/core/`)
3. Give it a scoped name (`@<org>/<sdk-name>`)
4. Wire workspace-internal deps with the `workspace:*` protocol
5. Decide BEFORE anything else: this package will eventually be published,
so design the boundary and naming with that in mind
```
my-repo/
├── pnpm-workspace.yaml
├── package.json # root: only devDeps + workspace scripts
├── apps/
│ └── example-app/ # consumer of the SDK
└── packages/
├── sdk/ # ← the SDK
└── shared-tsconfig/ # internal-only, never published
```
```yaml
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
```
**Read next:** `references/workspace-and-layout.md` — §2 layout, §3 SDK naming
patterns, §4 internal package creation, §5 `package.json` skeleton, §7 multi
-repo → monorepo migration.
### Phase 2 — Public API Surface
Before writing any code, decide what the SDK's public face looks like.
Two parallel concerns:
**A. Module boundaries.** The `src/` tree splits cleanly into `api/` (what
gets re-exported and is part of the contract) and `internal/` (do not import
from outside the package). The `package.json` `exports` field is your
cheapest enforcement mechanism — anything not listed there cannot be
imported by consumers.
```
packages/sdk/src/
├── index.ts # barrel — re-exports from api/
├── api/
│ ├── client.ts
│ └── types.ts
└── internal/
├── transport.ts # NOT exported
└── state.ts # NOT exported
```
**B. Type design.** SDK types are consumed by strangers, must not leak
internals, must be evolvable. Use:
- **Branded types** for opaque IDs: `type UserId = Brand<string, "UserId">`
- **Generic clients** with sensible defaults so adding type params later is
non-breaking: `createClient<Schema = DefaultSchema>(...)`
- **Discriminated unions** for result types: `Result<T, E>` with
`{ ok: true; value: T } | { ok: false; error: E }`
- **Builder pattern** for type-safe configuration when option combinations
matter
- **Interfaces** (not type aliases) when users may need to extend the type
via declaration merging
**Read next:**
- `references/module-boundaries-and-plugins.md` — §2 `src/` boundary,
§3 runtime layering, §4 provider/adapter, §5 plugin extension, §6 boundary
enforcement, §7 patterns vs anti-patterns
- `references/type-design-for-public-api.md` — §1 branded types, §2 generic
surfaces, §3 conditional/mapped types, §4 type guards, §5 builder, §6
utility types ship/internal, §7 tsconfig for libraries, §8 API evolution
### Phase 3 — Build Configuration
You need (a) a `tsconfig.json` tuned for library output, and (b) a bundler
that produces the actual `dist/`.
**tsconfig for libraries** — the critical flags:
```jsonc
// tsconfig.build.json — library build config
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"declaration": true, // emit .d.ts
"declarationMap": true, // sourcemap from .d.ts → .ts
"sourceMap": true,
"verbatimModuleSyntax": true, // TS 5.0+ — strict import elision
"isolatedDeclarations": true, // TS 5.5+ — explicit return types on public API
"composite": true, // enable project references
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"]
}
```
**Bundler choice in 2026:** `tsdown`. tRPC and Inngest migrated to it from
tsup; tsup's own README now says *"This project is not actively maintained
anymore. Please consider using tsdown instead."*
Minimum viable `tsdown.config.ts`:
```ts
import { defineConfig } from "tsdown";
export default defineConfig({
entry: ["src/index.ts", "src/plugin/index.ts", "src/testing/index.ts"],
format: ["esm", "cjs"],
dts: true,
sourcemap: true,
treeshake: true,
clean: true,
outExtensions: ({ format }) => ({
js: format === "esm" ? ".mjs" : ".cjs",
dts: format === "esm" ? ".d.mts" : ".d.cts",
}),
});
```
**Alternatives:**
- `tsc-only` / `zshy` — small SDK with no runtime deps, source-faithful publish
- `unbuild` — only when already in UnJS ecosystem
- `tsup` — community familiarity but losing mind-share; viable for inertia
**Read next:**
- `references/tsdown-bundling.md` — §3 verdict, §4 working config, §6–§8
alternatives, §11 selection decision tree
- `references/type-design-for-public-api.md` §7 — full library tsconfig
walkthrough
### Phase 4 — Distribution Shape (`package.json` `exports`)
This is where most TS SDK bugs live. Five invariants:
1. `types` **must** be first inside each `import` / `require` branch
2. `default` **must** be last
3. Dual ESM+CJS needs **separate** `.d.mts` and `.d.cts` (TS 5.0+)
4. Always include `"./package.json": "./package.json"` (lets publint/attw introspect)
5. `module` before `require` if you use both
The canonical dual shape (verbatim from `@trpc/server`):
```json
{
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
}
}
```
Add subpaths for plugin entry points so they version separately from the
root barrel:
```json
{
"exports": {
".": { "import": { ... }, "require": { ... } },
"./plugin": { "import": { ... }, "require": { ... } },
"./testing": { "import": { ... }, "require": { ... } }
}
}
```
For isomorphic SDKs (browser / workers / RN / edge), runtime conditions
come **before** `import` / `require`:
```json
{
".": {
"browser": { "import": "./dist/browser.mjs" },
"workerd": { "import": "./dist/workerd.mjs" },
"react-native": { "import": "./dist/rn.mjs" },
"deno": { "import": "./dist/deno.mjs" },
"import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" },
"require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" }
}
}
```
**Read next:** `references/package-json-exports.md` — §3 the five rules,
§4 tRPC dual pattern annotated, §5 ESM-only pattern, §6 subpath plugins,
§7 isomorphic conditions (Sanity client pattern), §9 common mistakes
bad → fixed → why.
### Phase 5 — Monorepo Pipeline (Turborepo)
Once the SDK builds in isolation, wire it into the workspace so:
- Apps rebuild only when SDK output changes (caching)
- Local dev rebuilds SDK in watch mode while the app reloads
- CI builds only affected packages on PRs
Minimum viable `turbo.json`:
```json
{
"$schema": "https://turborepo.com/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["src/**", "tsconfig*.json", "tsdown.config.ts", "package.json"],
"outputs": ["dist/**"]
},
"test": { "dependsOn": ["^build"], "inputs": ["src/**", "test/**"] },
"lint": { "inputs": ["src/**"] },
"typecheck": { "dependsOn": ["^build"], "inputs": ["src/**", "tsconfig*.json"] },
"dev": { "persistent": true, "cache": false }
}
}
```
Daily `--filter` patterns:
```bash
pnpm turbo run build --filter=@acme/sdk # SDK alone
pnpm turbo run dev --filter=@acme/sdk... --filter=@acme/example-app
pnpm turbo run test --filter=...@acme/sdk # affected-by-SDK
pnpm turbo run lint --filter=[HEAD^1] # affected since last commit
```
**Critical rules:** put scripts in **each** package's `package.json`, not in
root. Root only delegates `turbo run X`.
**Read next:** `references/turborepo-for-sdk.md` — §2 minimum viable
`turbo.json`, §3 per-package vs root, §4 `dependsOn`, §5 caching
inputs/outputs, §6 `--filter` patterns, §7 boundaries field, §8 CI patterns,
§9 dev mode with watch.
### Phase 6 — Verification
Before publish, two static checks + one runtime check are non-negotiable:
```bash
# After pnpm build:
pnpm exec publint --strict # static lint of package.json
pnpm exec attw --pack . # simulate Node/Bun/Deno/bundler resolution
# Then pack + install in a sandbox dir
pnpm pack
cd /tmp/sandbox && npm init -y && npm install /path/to/your-pkg-1.0.0.tgz
node -e "console.log(require('@acme/sdk'))" # CJS reaches
node --input-type=module -e "import('@acme/sdk').then(console.log)" # ESM reaches
```
Wire all three into `prepublishOnly`:
```json
{
"scripts": {
"prepublishOnly": "pnpm build && pnpm exec publint --strict && pnpm exec attw --pack ."
}
}
```
**Why both publint and attw?** publint statically checks `package.json`
shape; attw actually simulates how each consumer runtime resolves your
tarball. The most common attw failure is **Masquerading ESM** — a `.js`
file that contains ESM but is exposed under `require` — which publint
cannot catch.
**Read next:** `references/verification-and-publishing.md` — §2 publint
rules + 3 common failures, §3 attw resolution-mode table + 7 failure modes,
§4 smoke tests (tarball → fresh dir).
### Phase 7 — Release Lifecycle
This is where most SDK projects accumulate debt. Get it right from day 1.
**Semver + pre-release identifiers:**
```
0.x.y # pre-1.0 — breaking changes allowed in minors
1.0.0-alpha.0 # internal feature spike
1.0.0-beta.0 # feature-complete, API may still shift
1.0.0-rc.0 # frozen, blocker-only fixes
1.0.0 # stable
1.0.1 # patch on stable
1.1.0-beta.0 # next minor's beta cycle while 1.0.x ships patches
```
**npm dist-tags — never publish a pre-release to `latest`:**
```bash
# Publish a beta under the `beta` tag (NOT `latest`)
npm publish --tag beta
# Recover from a mistaken latest:
npm dist-tag add @acme/sdk@1.0.0 latest # repoint latest to stable
npm dist-tag rm @acme/sdk beta # if no longer needed
```
Convention tags: `latest` (stable), `next` (upcoming major prerelease),
`beta`, `rc`, `canary` (per-commit), `alpha`, `experimental`, `nightly`.
**changesets pre-release mode — the canonical transitions:**
```bash
# Cut beta line
pnpm changeset pre enter beta
pnpm changeset # write a changeset
pnpm changeset version # bumps to 1.0.0-beta.0
pnpm changeset publish
# Feature-complete; move beta → rc
pnpm changeset pre exit
pnpm changeset pre enter rc
pnpm changeset version # bumps to 1.0.0-rc.0
pnpm changeset publish
# RC stable; ship 1.0.0
pnpm changeset pre exit
pnpm changeset version # bumps to 1.0.0
pnpm changeset publish
# Open next minor's beta line
pnpm changeset pre enter beta
pnpm changeset version # bumps to 1.1.0-beta.0
```
**npm provenance** — turn it on:
```json
{
"publishConfig": {
"access": "public",
"provenance": true
}
}
```
Pair with `id-token: write` permission in the GitHub Actions release job;
npm will display a verified attestation on the package page.
**Read next:** `references/verification-and-publishing.md` — §5 semver
refresher, §6 dist-tag rules, §7 full lifecycle state diagram, §8 case
studies (Next.js / vercel-ai / tRPC / Storybook / Stripe with real version
sequences), §9 changesets pre-release flow, §10 GitHub Actions release
workflow, §11 provenance, §12 yank vs deprecate, §13 strategy decision tree.
---
## Quick Reference
### File / Field Cheat Sheet
| File | Owns | Quick check |
|---|---|---|
| `pnpm-workspace.yaml` | Which dirs are packages | `apps/*` + `packages/*` |
| Root `package.json` | Workspace devDeps + `turbo run` delegates | No package-level build script in root |
| Package `package.json` | `name`, `version`, `type`, `exports`, `files`, `sideEffects`, `bin`, `scripts.prepublishOnly` | Run `publint --strict` |
| Package `tsconfig.json` | Editor + `tsc --noEmit` | `strict: true` + `declaration: true` |
| `tsconfig.build.json` | Library build config | `isolatedDeclarations: true` if you want fast `.d.ts` |
| `tsdown.config.ts` | Bundling | `format: ['esm', 'cjs']` + dual `outExtensions` |
| `turbo.json` | Task pipeline | `dependsOn: ['^build']` for compile order |
| `.changeset/config.json` | Release policy | `commit: false`, `access: public` |
### Bundler Selection at a Glance
| Situation | Choice |
|---|---|
| Modern TS SDK, dual ESM+CJS, plugin subpaths | **tsdown** |
| Zero runtime deps, want raw source-faithful publish | `tsc` only / `zshy` |
| Existing project on tsup that works | Stay on tsup; plan tsdown migration |
| UnJS / Nuxt ecosystem | unbuild |
| Need bundle-splitting + advanced rollup config | Direct `rolldown` |
### Module-Format Decision
| Situation | Recommendation |
|---|---|
| Default for new SDK in 2026 | **dual ESM + CJS** |
| Library has stable consumer base ≥ Node 22 | ESM-only is defensible |
| Library is internal-only inside a Node app | ESM-only |
| Library is consumed by Jest, older Next.js, Lambda CJS | **dual** is mandatory |
### Release Tag at a Glance
| Tag | Meaning | `npm install pkg@?` resolves |
|---|---|---|
| `latest` | The current stable | `npm install pkg` |
| `next` | Upcoming major prerelease | `npm install pkg@next` |
| `beta` | Feature-complete stabilization | `npm install pkg@beta` |
| `rc` | Frozen, blocker-only | `npm install pkg@rc` |
| `canary` | Per-commit/per-PR snapshot | `npm install pkg@canary` |
| `experimental` | Unstable spike | `npm install pkg@experimental` |
### One-Liner Snippets You'll Type Often
```bash
# Add the SDK as a workspace-internal dep
pnpm add @acme/sdk@workspace:* --filter @acme/example-app
# Build SDK + everything that depends on it
pnpm turbo run build --filter=...@acme/sdk
# Pre-publish gate
pnpm build && pnpm exec publint --strict && pnpm exec attw --pack .
# Cut a snapshot release for a PR (vercel/ai pattern)
pnpm changeset version --snapshot pr-123
pnpm publish --tag pr-123 --no-git-checks
```
---
## Pre-Publish Checklist
Run through this once per release. Skipping any item is how broken SDKs
ship.
### Build artifact
- [ ] `pnpm build` produces `dist/` with both `.mjs` and `.cjs` (if dual) or just `.mjs` (if ESM-only)
- [ ] `.d.mts` and `.d.cts` exist for dual, OR `.d.ts` only for ESM-only
- [ ] Source maps emitted (`.mjs.map`, `.d.mts.map`)
- [ ] `dist/` size is reasonable (`du -sh dist/` — sanity check, no surprise bloat)
### package.json
- [ ] `name` is scoped (`@org/name`) — required if you'll ever go private later
- [ ] `version` matches what you're about to publish
- [ ] `type` matches your default format (`"module"` for ESM-default, omit for CJS-default)
- [ ] `exports` has `"./package.json": "./package.json"`
- [ ] Every `exports` branch has `types` first, `default` last
- [ ] `files` lists `dist` (and `src` if shipping sources for IDE jump-to-def)
- [ ] `sideEffects: false` (unless you genuinely have top-level side effects)
- [ ] `publishConfig.access: "public"` for first scoped publish
- [ ] `publishConfig.provenance: true`
### Verification
- [ ] `publint --strict` passes
- [ ] `attw --pack .` passes (or only has expected `node10` warnings)
- [ ] Smoke test: pack + install in `/tmp` + CJS + ESM + TS consumer all resolve
### Release
- [ ] Correct dist-tag chosen (`latest` only for stable)
- [ ] If pre-release: `pnpm changeset pre enter <tag>` was run BEFORE `version`
- [ ] If stable: `pnpm changeset pre exit` was run if previously in pre-mode
- [ ] CHANGELOG.md reflects the change
- [ ] Git tag matches version (e.g. `v1.0.0-beta.3`)
- [ ] Provenance attestation visible on npm package page
---
## Common Mistakes
| Mistake | What goes wrong | Fix |
|---|---|---|
| `types` not first inside `exports` branch | TS picks up `.js` as type source → cascade of errors at consumer | Move `types` to top of each `import` / `require` branch (publint will flag) |
| Single `.d.ts` for dual ESM+CJS | TS resolves the `.d.ts` against the wrong module mode | Emit `.d.mts` + `.d.cts` (TS 5.0+); tsdown does this automatically |
| Missing `"./package.json": "./package.json"` in exports | publint/attw cannot introspect your package | Always include it |
| Publishing pre-release to `latest` | Every `npm install pkg` user gets your beta | Use `npm publish --tag beta`; recover via `npm dist-tag add pkg@stable latest` |
| Forgetting `pnpm changeset pre exit` before stable release | Stable version comes out as `1.0.0-beta.N` instead of `1.0.0` | Always `pre exit` before final |
| Root `package.json` containing the actual build script | Defeats Turborepo parallelism + caching | Per-package scripts; root only delegates via `turbo run` |
| Deep imports into `dist/internal/...` from consumers | Consumers couple to internals; your refactors break them | Don't list internals in `exports`; use ESLint `no-restricted-imports` |
| Leaking internal types into public API surface | Users see types they shouldn't depend on | Re-export only from `src/api/*.ts`; don't `export *` from internals |
| Missing `sideEffects: false` with no side effects | Bundlers can't tree-shake your library | Add `"sideEffects": false` or list the actual side-effecting files |
| Forgetting `id-token: write` permission for provenance | Provenance attestation fails silently in CI | Add `permissions: { id-token: write, contents: read }` to release job |
| Mixing watch + build in same Turbo task | Cache invalidates constantly; watch never settles | Separate `build` (cacheable) and `dev` (`persistent: true, cache: false`) |
| `exports` with both `module` and unrelated runtime conditions in wrong order | Edge runtime picks the wrong file | Runtime conditions (`browser`, `workerd`) → `module` → `import` → `require` → `default` |
| Using `enum` in public API types | Forces consumers into TS-only land, breaks erasable syntax | Use union of string literals or `as const` objects |
| Using `default` export from the SDK root | Breaks tree-shaking + interop story | Always named exports |
---
## Reference Files
| File | Use when |
|---|---|
| `references/workspace-and-layout.md` | Setting up `apps/` + `packages/` + `tools/`; naming the SDK package; creating internal packages; choosing dep field (`dependencies` / `peerDependencies` / `devDependencies`); migrating from multi-repo |
| `references/module-boundaries-and-plugins.md` | Splitting `src/` into `api/` vs `internal/`; designing the orchestration layer vs adapters vs tools; building a plugin extension model with lifecycle hooks; enforcing boundaries via eslint-plugin-boundaries / dependency-cruiser / Turbo `boundaries` |
| `references/type-design-for-public-api.md` | Branded types; generic clients; conditional + mapped types; type-safe builders; which utility types to ship vs keep internal; tsconfig flags for libraries (`verbatimModuleSyntax`, `isolatedDeclarations`, `composite`); API evolution patterns |
| `references/package-json-exports.md` | Authoring the `exports` field; dual ESM+CJS with separate `.d.mts`/`.d.cts`; subpath plugin entries; isomorphic runtime conditions (`browser`, `workerd`, `react-native`, `deno`, `edge-light`); fixing common `exports` bugs |
| `references/tsdown-bundling.md` | Choosing tsdown vs tsup vs tsc-only vs unbuild; minimum-viable `tsdown.config.ts`; subpath output mapping; side-effects + tree-shaking; watch & dev mode; bundler selection decision tree |
| `references/turborepo-for-sdk.md` | Writing `turbo.json` for an SDK monorepo; `dependsOn: ['^build']`; caching `inputs`/`outputs`; `--filter` patterns for SDK dev; the `boundaries` field; CI with remote cache + affected-only builds; dev mode with `persistent: true` |
| `references/verification-and-publishing.md` | publint + attw setup; tarball smoke tests; semver + pre-release identifiers; npm dist-tags; the full beta → rc → stable → next-cycle state machine; changesets pre-release mode; the canonical `beta → rc` transition command sequence; GitHub Actions release workflow with snapshot PRs; npm provenance; yank vs deprecate; release-strategy decision tree |
---
## Source Skills
This skill was composed from four source skills inside `oh-my-openclaw`:
- **`agent-cli-architecture`** (architect-claw) — workspace structure, module
boundaries, runtime layering, plugin extension patterns. Generalized from
"agent CLI" framing to general "SDK + supporting CLI".
- **`typescript-pro`** (frontend-claw) — branded types, generics, conditional
types, type guards, utility types, tsconfig deep dive. Reframed toward
library/SDK-author concerns.
- **`turborepo`** (frontend-claw) — task pipelines, caching, `--filter`,
`boundaries`. Heavily trimmed to SDK-monorepo-relevant subset.
- **`monorepo-navigator`** (architect-claw) — pnpm workspaces, changesets,
publishing, migration.
Plus original research on `package.json exports`, dual ESM/CJS in 2026,
the tsdown landscape, publint + attw, and the alpha→beta→rc→stable
lifecycle, with verbatim examples from the GitHub `package.json` of
tRPC, vercel/ai, Inngest, Sanity client, Hono, Zustand, and TanStack
query-core.
Files in this skill
- SKILL.md
- references/module-boundaries-and-plugins.md
- references/package-json-exports.md
- references/tsdown-bundling.md
- references/turborepo-for-sdk.md
- references/type-design-for-public-api.md
- references/verification-and-publishing.md
- references/workspace-and-layout.md
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.