How to Use bunx to Run Package Binaries in Bun

bunx is Bun's built-in npx equivalent that executes npm package binaries without permanent installation, automatically handling caching, temporary installation, and execution in a single command.

bunx is a core CLI feature of the Bun runtime (oven-sh/bun) designed to streamline running one-off npm package binaries. Unlike traditional global installations, bunx parses your request, checks for existing binaries in the system PATH or temporary cache, installs the package only when necessary, and executes the binary—all while leveraging Bun's fast package manager and runtime.

How bunx Works Under the Hood

The implementation in src/cli/bunx_command.zig follows a four-stage execution pipeline that balances speed with isolation.

Parsing the Command Request

When you type bunx <package>[@version] [args], the CLI parser extracts the package name, optional version tag, and passthrough arguments (lines 6‑33). This creates a typed Options struct that drives the rest of the workflow, handling flags like --bun, --package, and --no-install.

Checking for Existing Binaries

Before hitting the network, bunx searches for an already-installed binary using bun.which. It checks:

  • The system $PATH
  • Bun's temporary cache directory (<temp>/bunx‑<uid>-<pkg>@<ver>)

If a matching, non-stale binary is found (validated via file timestamps), it is executed immediately (lines 51‑71, 84‑112), skipping installation entirely.

Automatic Package Installation

When no suitable binary exists, bunx creates a dedicated temporary cache directory and programmatically invokes bun add <package>@<version> via bun.spawnSync. It passes flags derived from your CLI options (--no-cache, --force, --silent, --verbose) to ensure a clean, isolated install (lines 222‑260).

Binary Execution

After installation, bunx resolves the exact binary name from the package's package.json bin field and calls Run.runBinary (from src/cli/run_command.zig). This sets up the environment—including npm_* variables—and finally execs the binary with your original arguments (lines 270‑340).

Basic bunx Usage Examples

Run the latest version of a package without installing it:


# Run Prisma migrations

bunx prisma migrate

# Format code with Prettier

bunx prettier foo.js

Execute a specific version:

bunx uglify-js@3.14.0 app.js

When the binary name differs from the package name, use the -p (or --package) flag:

bunx -p @angular/cli ng new my-app

Advanced Flags and Options

bunx supports several flags to control execution behavior:

Flag Description
--bun / -b Force the binary to run under Bun's JavaScript engine, even if the shebang is #!/usr/bin/env node.
-p, --package <pkg> Explicitly specify the npm package to install when the binary name differs from the package name.
--no-install Fail if the binary is not already present; do not trigger a network installation.
--verbose Show detailed logs from the installation process.
--silent Suppress all installation output.

Example with Advanced Flags

Run TypeScript compiler with verbose installation logs:

bunx typescript@5.4.0 tsc --verbose

Execute a binary offline using only cached versions:

bunx --no-install -p @angular/cli ng version

Force Bun runtime for a Node-targeted binary:

bunx --bun vite dev foo.js

How bunx Differs from npx

While functionally similar to npx, bunx leverages Bun's architecture for performance optimizations:

  • Temporary cache structure: bunx uses a unique directory format (<temp>/bunx‑<uid>-<pkg>@<ver>) to isolate installations, defined in src/cli/bunx_command.zig (lines 165‑228).
  • Integrated package manager: Instead of shelling out to a separate installer, bunx invokes bun add programmatically via bun.spawnSync with flags like --no-cache and --force (lines 222‑260).
  • Unified runtime: The --bun flag allows forcing Bun's JavaScript engine even when binaries target Node.js, something npx cannot do without external configuration.

Summary

  • bunx is Bun's built-in replacement for npx, executing npm package binaries without permanent installation.
  • The command follows a four-stage pipeline defined in src/cli/bunx_command.zig: parsing, cache checking, conditional installation, and execution via Run.runBinary.
  • It supports version pinning (package@version), scoped packages (@org/pkg), and binary name mapping via -p, --package.
  • Advanced flags like --bun, --no-install, and --verbose provide fine-grained control over execution and runtime behavior.
  • bunx uses isolated temporary cache directories to avoid polluting global or local project dependencies.

Frequently Asked Questions

What is the difference between bunx and bun run?

bun run executes scripts defined in your project's package.json or local JavaScript files, requiring the package to be installed in your project first. bunx is designed for one-off execution of npm package binaries without requiring a local installation—it handles temporary installation and caching automatically, similar to how npx works in the Node.js ecosystem.

How does bunx handle cached binaries?

According to the implementation in src/cli/bunx_command.zig (lines 51‑124), bunx first searches for existing binaries in the system $PATH and in Bun's temporary cache directory using bun.which. If it finds a matching binary that is not stale (validated via file timestamps), it executes it immediately without network activity. The cache directory follows the format <temp>/bunx‑<uid>-<pkg>@<ver> to ensure isolation between different users and package versions.

Can I use bunx with private npm registries?

Yes, bunx respects Bun's global and local configuration for npm registries. Since bunx internally invokes bun add via bun.spawnSync (lines 222‑260 in src/cli/bunx_command.zig), it automatically uses any registry settings defined in your bunfig.toml or environment variables like NPM_CONFIG_REGISTRY. Authentication tokens and registry mappings configured for Bun will apply to packages installed via bunx.

Why does bunx use a temporary cache directory instead of installing globally?

The temporary cache approach in src/cli/bunx_command.zig (lines 165‑228) ensures that bunx remains non-destructive and isolated. By creating a unique directory for each package version under the system temp folder (<temp>/bunx‑<uid>-<pkg>@<ver>), bunx avoids polluting your global npm modules or local project dependencies. This design allows multiple simultaneous executions of different package versions without conflicts, and the temporary nature means disk space is automatically reclaimed when the system clears temp files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →