npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

onlybun

v1.0.1

Published

Terminates your program the moment it notices it is not running on Bun. Zero dependencies, CJS + ESM.

Readme

onlybun

⚠️ This project is for people who like Bun. If you don't like Bun, please go look at neverbun instead.

Traditional Chinese Readme

Import it once, and your program refuses to run anywhere that isn't Bun. Zero dependencies, CJS and ESM, no opinions about anything else.

The evil twin of neverbun, same machinery, opposite conclusion.

Install

bun add onlybun

Yes, with Bun. Obviously.

Usage

Put this at the very top of your entry file and forget about it:

import 'onlybun';      // ESM
require('onlybun');    // CJS

On Bun: absolutely nothing happens. That's the good ending.

On Node.js:

  ✗ This project requires Bun.

    Detected runtime: Node.js v26.5.0
    Please use Bun instead (e.g. `bun run`, `bun install`).

    To skip this check anyway: ONLYBUN_DISABLE=1

...followed immediately by process.exit(1). Deno gets the same treatment, for consistency.

Two layers of defence

Because one layer would be complacent.

  1. Module resolution. The exports map declares a "node" condition pointing at src/unsupported.js. Node walks confidently into a dead end before the real entry point is ever loaded.
  2. Runtime detection. The entry points check process.versions.bun and the global Bun object on load. This catches every bundler that ignores export conditions (which, as it turns out, is most of them).

Browsers are left alone

No browser is ever going to be Bun, so refusing to run in one would just break your client bundle for no reason. There's a "browser" export condition that resolves to a passive entry point, and even the normal entry only terminates on node or deno specifically — never on "anything that isn't Bun".

So getRuntime() returning 'browser' is fine. 'node' is not.

API

If you'd rather not have an import that terminates your process, use onlybun/check. That subpath has no side effects whatsoever.

import { isBun, getRuntime, getBunVersion, assertBun, terminateIfNotBun } from 'onlybun/check';

isBun();              // boolean
getRuntime();         // 'bun' | 'node' | 'deno' | 'browser' | 'unknown'
getBunVersion();      // '1.4.0' | null
assertBun();          // throws on Node/Deno (code: 'ERR_BUN_REQUIRED')
terminateIfNotBun({ message: 'Please run `bun server.js`', exitCode: 2 });

The main entry point re-exports the same functions, it just also pulls the trigger on the way in.

Environment variables

| Variable | What it does | | --- | --- | | ONLYBUN_DISABLE=1 | The escape hatch. Disables the check entirely, even on Node. | | ONLYBUN_EXIT_CODE | Exit code used when terminating. Defaults to 1. |

Where to put this in a framework project

The one rule: this package only helps when the runtime actually executes that import. Bundlers bundle your app code, they don't run it — so putting the import in the wrong file buys you exactly nothing.

The reliable spot is your config file, which is always evaluated directly by whichever runtime is running the CLI:

// vite.config.js / astro.config.mjs / next.config.mjs
import 'onlybun';
export default { /* ... */ };

Blocking everything

An import can't stop npm install, because by then it's too late. For total coverage, add one more layer in package.json:

{
  "scripts": {
    "preinstall": "bun -e \"if(!process.versions.bun)throw new Error('Use bun, not npm')\""
  }
}

Which, admittedly, requires Bun to be installed to tell you that you need Bun installed. We're comfortable with that.

Tests

bun test/run.cjs

This builds a real consumer fixture (with a node_modules symlink) and runs it under both Bun and Node. If Bun isn't installed locally, those tests are skipped — and so, frankly, is the point of this package.

License

MIT