Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
jwynia avatar

Npm Package

  • 310 installs
  • 133 repo stars
  • Updated February 24, 2026
  • jwynia/agent-skills

npm-package is an agent skill that scaffolds, configures, tests, versions, and publishes npm packages using Bun, strict TypeScript, Vitest, Biome, Bunup, and Changesets for developers shipping libraries.

About

npm-package is an agent skill from jwynia/agent-skills that teaches a Bun-first workflow for creating and publishing npm-compatible TypeScript libraries. The toolchain pairs Bun as runtime and package manager, Bunup for ESM and CJS bundle generation with declaration files, strict TypeScript with module nodenext, Biome v2 plus ESLint for linting, Vitest for unit tests, and Changesets for versioning and changelog management. Developers reach for npm-package when scaffolding a new library, fixing CJS and ESM interop or package.exports map issues, configuring conditional exports and .d.ts generation, or preparing CI-ready npm publish pipelines. The skill documents when to create packages from scratch versus migrating existing code, resolving default and named export compatibility across module systems, and reviewing package.json fields before registry release. Keywords include npm, bun, bunup, esm, cjs, vitest, biome, and changesets.

  • package.json setup
  • Entry points
  • Build config
  • Semantic versioning
  • npm publish

Npm Package by the numbers

  • 310 all-time installs (skills.sh)
  • +3 installs in the week ending Aug 2, 2026 (Skillselion tracking)
  • Ranked #63 of 248 Release Management skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jwynia/agent-skills --skill npm-package

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs310
repo stars133
Last updatedFebruary 24, 2026
Repositoryjwynia/agent-skills

How do you publish a TypeScript npm package with Bun?

Scaffold, configure, test, version, and publish npm packages with correct package.json fields, entry points, build steps, and registry publishing workflows.

Who is it for?

TypeScript developers creating npm libraries who want a Bun-first scaffold with strict typing, dual ESM/CJS output, and automated versioning.

Skip if: Teams publishing Python wheels, Rust crates, or monorepo apps without a standalone npm library package boundary.

When should I use this skill?

The user wants to create a new npm library, fix CJS/ESM interop, configure package.exports, set up Vitest and Biome for a package, or publish to the npm registry.

What you get

package.json with exports map, ESM and CJS build artifacts, Vitest test suite, lint configuration, and Changesets release workflow ready for npm publish.

  • package.json exports map
  • bundled ESM/CJS artifacts
  • Changesets release configuration

By the numbers

  • Toolchain spans 5 tools: Bun, Bunup, Vitest, Biome, and Changesets
  • Targets strict TypeScript with module nodenext configuration
  • Covers dual ESM and CJS output with declaration file generation

Files

SKILL.mdMarkdownGitHub ↗

npm Package Development (Bun-First)

Build and publish npm packages using Bun as the primary runtime and toolchain, producing output that works everywhere npm packages are consumed.

When to Use This Skill

Use when:

  • Creating a new npm library package from scratch
  • Setting up build/test/lint tooling for an existing package
  • Fixing CJS/ESM interop, exports map, or TypeScript declaration issues
  • Publishing a package to npm
  • Reviewing or improving package configuration

Do NOT use when:

  • Building an npx-executable CLI tool (use the npx-cli skill)
  • Building an application (not a published package)
  • Working in a monorepo (this skill targets single-package repos)

Toolchain

ConcernToolWhy
Runtime / package managerBunFast install, run, transpile
BundlerBunupBun-native, dual output, .d.ts generation
Type declarationsBunup (via tsc)Integrated with build
TypeScriptmodule: "nodenext", strict: true + extrasMaximum correctness for published code
Formatting + basic lintingBiome v210-25x faster than ESLint, single tool
Type-aware lintingESLint + typescript-eslint40+ type-aware rules Biome can't do
TestingVitestTest isolation, mature mocking, coverage
VersioningChangesetsFile-based, explicit, monorepo-ready
Publishingnpm publish --provenanceTrusted Publishing / OIDC

Scaffolding a New Package

Run the scaffold script to generate a complete project:

bun run <skill-path>/scripts/scaffold.ts ./my-package \
  --name my-package \
  --description "What this package does" \
  --author "Your Name" \
  --license MIT

Options:

  • --dual — Generate dual CJS/ESM output (default: ESM-only)
  • --no-eslint — Skip ESLint, use Biome only

Then install dependencies:

cd 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-eslint

Project Structure

my-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
└── LICENSE

Critical Configuration Details

Read these reference docs before modifying any configuration. They contain the reasoning behind each decision and the sharp edges that cause subtle breakage:

  • [reference/esm-cjs-guide.md](./reference/esm-cjs-guide.md)exports map configuration, dual package hazard, module-sync, common mistakes
  • [reference/strict-typescript.md](./reference/strict-typescript.md) — tsconfig rationale, Biome rules, ESLint type-aware rules, Vitest config
  • [reference/publishing-workflow.md](./reference/publishing-workflow.md) — Changesets, files field, Trusted Publishing, CI pipeline

Key Rules (Non-Negotiable)

These are the rules that, when violated, cause the most common and painful bugs in published packages. Follow these without exception.

Package Configuration

1. Always use `"type": "module"` in package.json. ESM-only is the correct default. require(esm) works in all supported Node.js versions.

2. Always use `exports` field, not `main`. main is legacy. exports gives precise control over what consumers can access.

3. `types` must be the first condition in every exports block. TypeScript silently fails to resolve types if it isn't.

4. Always export `"./package.json": "./package.json"`. Many tools need access to the package.json and exports encapsulates completely.

5. Use `files: ["dist"]` in package.json. Whitelist approach prevents shipping secrets. Never use .npmignore.

6. Run `npm pack --dry-run` before every publish. Verify the tarball contains exactly what you intend.

TypeScript

7. Use `module: "nodenext"` for published packages. Not "bundler". Code satisfying nodenext works everywhere; the reverse is not true.

8. `strict: true` is non-negotiable. Without it, your .d.ts files can contain types that error for consumers using strict mode.

9. Enable `noUncheckedIndexedAccess`. Catches real runtime bugs from unguarded array/object access.

10. Ship `declarationMap: true`. Enables "Go to Definition" to reach original source for consumers.

11. Do not use path aliases (`paths`) in published packages. tsc does not rewrite them in emitted code. Consumers can't resolve them.

Code Quality

12. `any` is banned. Use unknown and narrow. Suppress with // biome-ignore suspicious/noExplicitAny: <reason> only when genuinely unavoidable, and always include the reason.

13. Prefer named exports over default exports. Default exports behave differently across CJS/ESM boundaries.

14. Always use `import type` for type-only imports. Enforced by both verbatimModuleSyntax and Biome's useImportType rule.

Build

15. Build with Bunup using format: ['esm'] (or ['esm', 'cjs'] for dual). Bunup handles .d.ts generation, external detection, and correct file extensions.

16. Set `engines.node` to `>=20.19.0` in package.json. This documents the minimum supported Node.js version (first LTS with stable require(esm)).

Testing

17. Use Vitest, not bun:test. bun:test lacks test isolation — module mocks leak between files. Vitest runs each test file in its own worker.

18. Set coverage thresholds (branches, functions, lines, statements all ≥ 80%). Enforced in vitest.config.ts.

Development Workflow

# 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 --provenance

Adding Subpath Exports

When the package needs to expose multiple entry points:

1. Add the source file: src/utils.ts 2. Add to bunup.config.ts entry: entry: ['src/index.ts', 'src/utils.ts'] 3. Add to package.json exports:

{
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    },
    "./utils": {
      "types": "./dist/utils.d.ts",
      "default": "./dist/utils.js"
    },
    "./package.json": "./package.json"
  }
}

Reminder: Adding or removing export paths is a semver-major change.

Switching to Dual CJS/ESM Output

If consumers require CJS support for Node.js < 20.19.0:

1. Update bunup.config.ts: format: ['esm', 'cjs'] 2. Update package.json exports to include module-sync, import, and require conditions 3. See reference/esm-cjs-guide.md for the exact exports map structure

Bun-Specific Gotchas

  • `bun build` does not generate .d.ts files. Use Bunup (which delegates to tsc) or run tsc --emitDeclarationOnly separately.
  • `bun build` CJS output is experimental. Always use target: "node" for npm-publishable CJS. target: "bun" produces Bun-specific wrappers.
  • `bun build` does not downlevel syntax. Modern ES2022+ syntax ships as-is. If targeting older runtimes, additional transpilation is needed.
  • `bun publish` does not support `--provenance`. Use npm publish for provenance signing.
  • `bun publish` uses `NPM_CONFIG_TOKEN`, not NODE_AUTH_TOKEN. CI pipelines may need adjustment.

Related skills

How it compares

Pick npm-package for Bun-first library scaffolding with dual-module output; use generic Node templates when you do not need Changesets or CJS interop guidance.

FAQ

What toolchain does npm-package recommend?

npm-package recommends Bun as runtime and package manager, Bunup for bundling ESM and CJS artifacts with TypeScript declarations, Biome v2 plus ESLint for linting, Vitest for tests, and Changesets for version bumps and changelogs.

Does npm-package handle ESM and CommonJS together?

npm-package documents package.exports conditional maps, Bunup dual builds, and common interop fixes for default versus named exports so libraries work in both import and require consumption paths.

When should you invoke npm-package?

npm-package triggers when a developer wants to create a new npm library, configure build and test tooling for an existing package, resolve module interop errors, or publish a TypeScript package to the npm registry.

Release Managementbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.