bun-publishing

v2026.09.24

Publish npm packages built with Bun: package.json config, CLI tool packaging, provenance signing, release automation. Use when setting up `publishConfig`/`files`/`bin`, packaging a CLI, enabling `--provenance`, or wiring release-please.

GitHub
安装命令
npx skhub add laurigates/bun-publishing
Markdown
SKILL.md

Bun npm Publishing

When to Use This Skill

ScenarioUse this skillAlternative
Configuring package.json for npm publishingYesN/A
Publishing a package to npm registryYesN/A
Setting up CLI tool packaging with binYesN/A
Configuring provenance signingYesN/A
Setting up release-please automationYesN/A
Validating tarball contents before publishYesN/A
Installing or updating dependenciesNo - use bun-package-managerbun-add for quick additions
Building/bundling before publishNo - use bun-developmentbun-build for quick builds

Core Expertise

Publishing npm packages built with Bun:

  • Package.json configuration for npm registry
  • CLI tool packaging with executable binaries
  • Provenance signing for supply chain security
  • Release automation with release-please

Package.json Configuration

Essential Publishing Fields

{
  "name": "@org/package-name",
  "version": "1.0.0",
  "description": "Package description",
  "main": "build/index.js",
  "type": "module",
  "publishConfig": {
    "access": "public"
  },
  "files": [
    "build/",
    "README.md",
    "LICENSE"
  ],
  "scripts": {
    "build": "tsc && chmod +x build/index.js",
    "prepublishOnly": "bun run build"
  },
  "engines": {
    "node": ">=20.0.0",
    "bun": ">=1.0.0"
  }
}

Field Reference

FieldPurpose
publishConfig.accesspublic required for scoped packages
filesWhitelist of files/dirs to include in tarball
mainEntry point for CommonJS/ES import
typemodule for ESM, commonjs for CJS
enginesRuntime version requirements
prepublishOnlyRuns before npm publish

Scoped Packages

Scoped packages (@org/name) require explicit public access:

{
  "name": "@myorg/mypackage",
  "publishConfig": {
    "access": "public"
  }
}

Or use the CLI flag:

npm publish --access public

CLI Tool Packaging

Binary Entry Configuration

{
  "bin": {
    "mycli": "build/index.js"
  }
}

For single-command packages:

{
  "bin": "build/index.js"
}

Executable Setup

Entry point requires shebang and executable permission:

#!/usr/bin/env node
// build/index.js

import { main } from "./main.js";
main();

Build script must set permissions:

{
  "scripts": {
    "build": "tsc && chmod +x build/index.js"
  }
}

Makefile Integration

build-prod:
	rm -rf build
	tsc --declaration --sourceMap
	chmod +x build/index.js

publish: build-prod
	npm publish --access public

Publishing Commands

Manual Publishing

# Standard publish (runs prepublishOnly)
npm publish

# Scoped package (requires --access public)
npm publish --access public

# Dry run to verify contents
npm publish --dry-run

# View what would be published
npm pack --dry-run

With Provenance

Supply chain security via npm provenance:

npm publish --provenance --access public

Requires:

  • CI environment (GitHub Actions, GitLab CI)
  • id-token: write permission in workflow
  • npm registry-url configured

Files Whitelist

Recommended Pattern

{
  "files": [
    "build/",
    "README.md",
    "LICENSE"
  ]
}

What to Include

IncludeExamples
Build outputbuild/, dist/
Type definitions*.d.ts (usually in build)
DocumentationREADME.md, LICENSE
Config scriptsUser-facing setup scripts

What to Exclude

Already excluded by npm (no need to list):

  • node_modules/
  • .git/
  • .env*
  • *.log

Explicitly exclude via .npmignore if needed:

src/
tests/
*.test.ts
.github/

Release Automation

Release-Please Integration

.github/workflows/release-please.yml:

name: Release Please

on:
  push:
    branches: [main]

permissions:
  contents: write
  pull-requests: write
  id-token: write

jobs:
  release-please:
    runs-on: ubuntu-latest
    outputs:
      release_created: ${{ steps.release.outputs.release_created }}
    steps:
      - uses: google-github-actions/release-please-action@v4
        id: release
        with:
          release-type: node
          package-name: mypackage

  publish:
    needs: release-please
    if: ${{ needs.release-please.outputs.release_created == 'true' }}
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 24
          registry-url: https://registry.npmjs.org

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - run: bun install --frozen-lockfile
      - run: bun run build
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Conventional Commits for Versioning

Commit TypeVersion Bump
feat:Minor (1.x.0)
fix:Patch (1.0.x)
feat!: or BREAKING CHANGE:Major (x.0.0)
chore:, docs:, refactor:No bump

Pre-publish Validation

Build Hook

{
  "scripts": {
    "prepublishOnly": "bun run build"
  }
}

Full Validation

# Type check
bun run tsc --noEmit

# Lint
bun run check

# Test
bun test

# Build
bun run build

# Verify tarball contents
npm pack --dry-run

Repository Metadata

Complete metadata for npm and GitHub:

{
  "repository": {
    "type": "git",
    "url": "https://github.com/org/repo.git"
  },
  "homepage": "https://github.com/org/repo#readme",
  "bugs": {
    "url": "https://github.com/org/repo/issues"
  },
  "keywords": ["keyword1", "keyword2"],
  "author": "Name <email>",
  "license": "MIT"
}

Agentic Optimizations

ContextCommand
Preview tarballnpm pack --dry-run
Preview publishnpm publish --dry-run
Scoped publishnpm publish --access public
Provenancenpm publish --provenance --access public
Check outdatednpm outdated
View packagenpm view @org/pkg

Quick Reference

Publishing Flags

FlagDescription
--access publicRequired for scoped packages
--provenanceEnable supply chain provenance
--dry-runPreview without publishing
--tag <tag>Publish with dist-tag (e.g., beta)

Package.json Scripts

ScriptWhen It Runs
prepublishBefore pack and publish (deprecated)
prepublishOnlyBefore publish only
prepackBefore pack and publish
postpackAfter pack
postpublishAfter publish

CI Environment Variables

VariablePurpose
NODE_AUTH_TOKENnpm authentication
NPM_TOKENAlternative npm token name

Common Issues

Scoped package 402 error:

# Add --access public for scoped packages
npm publish --access public

Missing files in tarball:

# Check what's included
npm pack --dry-run

# Verify files array in package.json

Binary not executable after install:

# Ensure shebang in entry point
#!/usr/bin/env node

# Ensure chmod in build script
chmod +x build/index.js

2FA publish (EOTP) is not automatable:

A non-interactive shell — a CI step, or an agent's Bash tool — cannot supply a one-time password. npm publish fails with:

npm error code EOTP
npm error This operation requires a one-time password.

Two ways through:

  • Human, interactive: npm publish --otp=<6-digit-code> (the code comes from the publisher's authenticator app, not from npm on demand).
  • Automation token (CI / unattended): a Granular/Automation token (npmjs.com → Access Tokens) bypasses 2FA at publish time. Put it in NODE_AUTH_TOKEN / NPM_TOKEN. This is exactly why the release-please workflow above publishes cleanly while a local npm publish prompts — CI uses the token, the human uses the OTP.

An agent that hits EOTP should hand the publish to the user or switch the repo to an automation token — it cannot mint or supply one itself (npm token create also requires a valid, OTP-satisfied session).

Fresh publish 404s for a few minutes (propagation lag):

Right after a first publish, public / unauthenticated reads can 404 while the package is genuinely live — the access record updates instantly but the public metadata CDN lags. Don't conclude the publish failed. Confirm with authenticated, version-pinned checks:

npm access list packages              # shows it under your account immediately
npm view @org/pkg@<version> _id       # version-pinned, authed — resolves once live
npm pack @org/pkg@<version>           # actually fetches the tarball (definitive)

Signature of propagation lag (not a private/failed publish): a public 404 plus npm access list packages shows the package plus an authed npm pack @org/pkg@<version> succeeds. (npm config get //registry.npmjs.org/:_authToken often returns empty even when logged in, so a hand-rolled curl with that "token" is an unauthenticated probe — use the npm CLI itself, which reads auth correctly, to test.)

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

typescript-plugin/skills/bun-publishing

默认分支

main

最新提交

1668324

Tree SHA

b2d4cc3