Skip to main content
bun publish packs your package into a tarball and publishes it to the configured npm registry. It strips workspace: and catalog: version protocols from package.json, resolving them to real version numbers before publishing.
bun publish
Example output:
bun publish v1.3.3

packed 203B package.json
packed 224B README.md
packed 30B index.ts
packed 0.64KB tsconfig.json

Total files: 4
Shasum: 79e2b4377b63f4de38dc7ea6e5e9dbee08311a69
Integrity: sha512-6QSNlDdSwyG/+[...]X6wXHriDWr6fA==
Unpacked size: 1.1KB
Packed size: 0.76KB
Tag: latest
Access: default
Registry: https://registry.npmjs.org/

 + my-package@1.0.0

Authentication

Set an auth token via the NPM_CONFIG_TOKEN environment variable (suitable for GitHub Actions and other CI systems):
NPM_CONFIG_TOKEN=my-token bun publish
Or configure the token in bunfig.toml:
[install]
registry = { url = "https://registry.npmjs.org", token = "$NPM_CONFIG_TOKEN" }
Or in .npmrc:
//registry.npmjs.org/:_authToken=${NPM_CONFIG_TOKEN}

Flags

--access

Set the access level of the published package. Required for scoped packages that should be publicly accessible:
bun publish --access public
bun publish --access restricted
Unscoped packages are always public. You can also set access in publishConfig in package.json:
{
  "publishConfig": {
    "access": "public"
  }
}

--tag

Publish under a specific dist-tag instead of latest:
bun publish --tag beta
bun publish --tag next
Or in package.json:
{
  "publishConfig": {
    "tag": "next"
  }
}

--dry-run

Simulate the publish without actually uploading anything. Shows you exactly which files would be included:
bun publish --dry-run

--tolerate-republish

Exit with code 0 instead of 1 if the package version already exists in the registry. Useful in CI jobs that may be re-run:
bun publish --tolerate-republish

--otp

Provide a one-time password for accounts with 2FA enabled:
bun publish --otp 123456

--auth-type

Choose how to complete 2FA: web (default) opens a browser, legacy prompts in the terminal:
bun publish --auth-type legacy

Controlling which files are published

Bun respects the "files" field in package.json and .npmignore. Only files listed in "files" (or not excluded by .npmignore) are included in the tarball.
{
  "name": "my-package",
  "version": "1.0.0",
  "files": [
    "dist",
    "index.js",
    "README.md"
  ]
}

Pack without publishing

To create the tarball without uploading it, use bun pm pack:
bun pm pack
# Creates my-package-1.0.0.tgz

# Save to a specific directory
bun pm pack --destination ./dist

# Preview contents without writing the file
bun pm pack --dry-run
You can then publish the tarball separately:
bun publish ./my-package-1.0.0.tgz
When you pass a tarball path to bun publish, lifecycle scripts (prepublishOnly, prepack, prepare, postpack, publish, postpublish) are not run. Scripts only run when bun publish packs the package itself.

Lifecycle scripts during publish

When bun publish packs the package, it runs lifecycle scripts in this order:
  1. prepublishOnly
  2. prepack
  3. prepare
  4. (pack)
  5. postpack
  6. (upload)
  7. publish
  8. postpublish

Build docs developers (and LLMs) love