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 insrc/cli/bunx_command.zig(lines 165‑228). - Integrated package manager: Instead of shelling out to a separate installer, bunx invokes
bun addprogrammatically viabun.spawnSyncwith flags like--no-cacheand--force(lines 222‑260). - Unified runtime: The
--bunflag 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 viaRun.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--verboseprovide 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →