Loading...
Loading...
Build and publish npm packages using Bun as the primary toolchain with npm-compatible output. Use when the user wants to create a new npm library, set up a TypeScript package for publishing, configure build/test/lint tooling for a package, fix CJS/ESM interop issues, or publish to npm. Covers scaffolding, strict TypeScript, Biome + ESLint linting, Vitest testing, Bunup bundling, and publishing workflows. Keywords: npm, package, library, publish, bun, bunup, esm, cjs, exports, typescript, biome, vitest, changesets.
npx skill4agent add jwynia/agent-skills npm-packagenpx-cli| Concern | Tool | Why |
|---|---|---|
| Runtime / package manager | Bun | Fast install, run, transpile |
| Bundler | Bunup | Bun-native, dual output, .d.ts generation |
| Type declarations | Bunup (via tsc) | Integrated with build |
| TypeScript | | Maximum correctness for published code |
| Formatting + basic linting | Biome v2 | 10-25x faster than ESLint, single tool |
| Type-aware linting | ESLint + typescript-eslint | 40+ type-aware rules Biome can't do |
| Testing | Vitest | Test isolation, mature mocking, coverage |
| Versioning | Changesets | File-based, explicit, monorepo-ready |
| Publishing | | Trusted Publishing / OIDC |
bun run <skill-path>/scripts/scaffold.ts ./my-package \
--name my-package \
--description "What this package does" \
--author "Your Name" \
--license MIT--dual--no-eslintcd my-package
bun install
bun add -d bunup typescript vitest @vitest/coverage-v8 @biomejs/biome @changesets/cli
bun add -d eslint typescript-eslint # unless --no-eslintmy-package/
├── src/
│ ├── index.ts # Package entry point — all public API exports here
│ └── index.test.ts # Tests co-located with source
├── dist/ # Built output (gitignored, included in published tarball)
├── .changeset/
│ └── config.json
├── package.json
├── tsconfig.json
├── bunup.config.ts
├── biome.json
├── eslint.config.ts # Type-aware rules only
├── vitest.config.ts
├── .gitignore
├── README.md
└── LICENSEexportsmodule-syncfiles"type": "module"require(esm)exportsmainmainexportstypes"./package.json": "./package.json"exportsfiles: ["dist"].npmignorenpm pack --dry-runmodule: "nodenext""bundler"strict: truenoUncheckedIndexedAccessdeclarationMap: truepathsanyunknown// biome-ignore suspicious/noExplicitAny: <reason>import typeverbatimModuleSyntaxuseImportTypeformat: ['esm']['esm', 'cjs']engines.node>=20.19.0require(esm)# Write code and tests
bun run test:watch # Vitest watch mode
# Check everything
bun run lint # Biome + ESLint
bun run typecheck # tsc --noEmit
bun run test # Vitest run
# Build
bun run build # Bunup → dist/
# Prepare release
bunx changeset # Create changeset describing changes
bunx changeset version # Bump version, update CHANGELOG
# Publish
bun run release # Build + npm publish --provenancesrc/utils.tsentry: ['src/index.ts', 'src/utils.ts']{
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./utils": {
"types": "./dist/utils.d.ts",
"default": "./dist/utils.js"
},
"./package.json": "./package.json"
}
}format: ['esm', 'cjs']module-syncimportrequirebun buildtsc --emitDeclarationOnlybun buildtarget: "node"target: "bun"bun buildbun publish--provenancenpm publishbun publishNPM_CONFIG_TOKENNODE_AUTH_TOKEN