Notes6 min · 8 Jun 2026

What is actually in Bun?

Bun is called a runtime and a bundler at once, so where is the file for each? Looking for them showed that npm isn't Node, that the engine is one part of a browser, and that Docker's answer is to ship the files with the code.

  1. 01Where it started
  2. 02One file or several
  3. 03The engine underneath
  4. 04Brave, Chromium and the engine
  5. 05Vercel and Cloudflare
  6. 06The whole tree
  7. 07Taking the tree with you
  8. 08Back to the box

01Where it started

This picked up from How does my terminal find a tool?, which ended with Node in /usr/local/bin and Bun in ~/.bun/bin. Bun is described as a runtime, a package manager, a bundler and a test runner. So is there a binary for the runtime and another for the bundler somewhere in its folder? And what does Node, the classic one, ship instead?

02One file or several

Installing Node gives you three files: node, npm and npx. They arrive together, and they aren't the same thing. node is the : the V8 and its , about 190 MB of compiled code here. npm is a , and on this Mac it is a JavaScript file whose first line is #!/usr/bin/env node, which means run me with whichever node PATH finds first. npm is a program Node runs. npx is a second script from the same package that runs a package without installing it for good.

Like macOS shipping Safari: it comes with the system, and it isn't the system. pnpm and Yarn do npm's job differently and arrive separately. Each still needs Node to run. pnpm's trick is that every version of every package is stored once on the disk, and projects get links to it instead of copies. A bundler such as Vite or esbuild is another install again. Each piece can be swapped, and you assemble the set yourself.

Bun is the other way round: one file, 58 MB here, that does every job. bun run, bun install, bun build and bun test are the same file told different things, and bunx is just a link back to it. There is no bundler binary to find. There is no Node inside it either: Bun is a runtime of its own that runs most Node code and npm packages unchanged.

Fig 01
  • Run code
    node app.jsThe runtime: V8 and its harness
  • Install packages
    npm installA JavaScript file. Node runs it
  • Run one, no install
    npx viteAnother script from npm's package
  • Bundle
    vite buildNot in the box. Install Vite or esbuild
  • Test
    node --testBuilt into node since version 20

Three names on PATH. node is 190 MB here; npm and npx are scripts it runs.

Five jobs. With Node they are spread over several programs, two of them scripts Node runs; with Bun they are one file.

npm isn't Node. It is a program written in JavaScript that Node runs, and Bun replaced it and the rest with one file.

Claude Code shows where that leads. Bun can compile a JavaScript program into one file with Bun's runtime inside it, and Claude Code ships that way, so it needs no Node of yours at all. Anthropic bought Bun in December 2025, citing that dependence.

03The engine underneath

The processor only runs . The engine is the part that turns JavaScript into it, and it is the one piece Node, Bun and a browser can't do without. The runtimes note has the three layers in full: an engine that can only calculate, a harness that lets it reach files, the network or a page, and the environment round both. Node is V8 plus a harness for servers. Chrome is V8 plus a harness for pages. Bun is JavaScriptCore plus a harness of its own.

"Node is written in C++" means both parts: V8 is C++, and so is the layer that reaches files and the network, though much of Node's own API is written in JavaScript on top of it. Bun's engine is C++ too, Apple's; only Bun's layer is written in Zig. They are two programs glued together, each written in whatever its makers chose.

04Brave, Chromium and the engine

If Bun uses JavaScriptCore, does Brave? No. The engine only runs JavaScript. It doesn't draw pages, fetch them or know there is a mouse. The browser is the rest.

Chromium is the open source browser Google maintains: V8 for JavaScript, Blink to turn HTML and CSS into pixels, a network stack, a sandbox that keeps sites apart, the tabs and the address bar. Chrome is Chromium with Google's accounts and sync added. Brave and Edge take the same Chromium and add their own, which is why Chrome extensions work in Brave and its developer tools look the same. Safari is built on WebKit, with JavaScriptCore. Firefox has its own of both, Gecko and SpiderMonkey.

Fig 02
Added on top
Shields, ad blocking
Built from
Chromium
Draws the page
Blink
Runs JavaScript
V8Node's engine too
Five browsers, three families. Most of what you use is one project with different paint.

So Brave runs V8, and Bun's engine has more in common with Safari than with the browser on this Mac. Bun chose it because it starts faster than V8, which counts when a command line tool is started and stopped all day.

05Vercel and Cloudflare

Hosts are the same idea one level up, and the runtimes note has them in full. Vercel runs your server code as , on Node by default. Cloudflare Workers run in Cloudflare's data centres all over the world, close to whoever asked, on workerd: Cloudflare's own runtime round V8. Not "V8 with nothing round it", but a different, smaller harness, with no Node in it.

06The whole tree

Then a detour: trace the Mac's folders from the root. The folders already sorted the ones that hold programs. The rest, briefly:

  • /etc holds settings for the whole machine, such as paths and hosts. On a Mac it is a link to /private/etc, as are /tmp and /var.
  • /dev holds devices shown as files: the disk, and /dev/null, where output goes to vanish.
  • /tmp holds scratch files, cleared on restart. /var holds things that keep changing, such as logs.
  • /sbin and /usr/sbin hold tools for running the system itself, such as mount.
  • /Library holds settings and support files for every user, and ~/Library the same for you alone. /System is Apple's, sealed.
  • /Applications holds the apps you click. /Volumes holds the disks plugged in. /Users holds a home for each person, yours written ~.

Going from /bin towards ~, each step is less the system's and more yours. Everything a project needs is somewhere in this tree, and that is the problem Docker was made for.

07Taking the tree with you

A project works on your Mac because node there is 22 and a library is in /usr/lib. On a server where node is 18, or missing, it breaks. "Works on my machine" is really "works with my folders".

Docker's answer is to ship the folders. A is a program given its own view of the file system, and that view is an : a whole tree from / down, with its own /bin, its own /usr/local/bin/node, your code and its packages. Whatever the host has in its folders, the program inside only sees the image's.

A container doesn't fix PATH. It ships the folders PATH points into.

An image is built from a Dockerfile, a recipe read top to bottom. FROM node:20 starts from someone else's image that already holds Node. Each RUN, COPY or ADD after it adds a , just the files that step changed, stacked on the ones before. CMD, the command to start with, is a setting and adds no files.

Layers are kept between builds. The next build reuses each one until it reaches a step whose inputs have changed, and from there every step runs again. So the order is the speed: what rarely changes goes first.

Fig 03
  1. FROM node:20Someone else's layers
  2. COPY . .Layer · ran · 0.2 s
  3. RUN npm installLayer · ran · 40 s
  4. CMD ["node", "app.js"]A setting, no files

First build: every step runs. About 40 s.

Change one line of your code and build again. Ink runs; outlines come from the cache.

The chat's own example got this backwards. It copied all the code in, then ran npm install, so any change to any file ran the whole install again. Copy package.json and the lock file alone, install, then copy the rest, and a change to your code only redoes the last step.

Recipe, built tree, running copy: a Dockerfile builds an image, and an image can start any number of containers. They share the kernel of the machine they run on, which is why they start in seconds where a brings a whole system with it. On a Mac that kernel is Linux, inside a small virtual machine Docker Desktop runs, because the Mac's own kernel can't host Linux containers.

08Back to the box

So there is no bundler binary in ~/.bun. There is one file, and every job is a word you give it. Node's set is three names on PATH, two of them scripts Node runs, with the rest left for you to choose.

Each step of the chat was the same question asked bigger: what comes in the box? Bun puts every tool in one file. A browser puts the engine in a whole project of other parts. An image puts the runtime, the packages and the code in one tree, so the machine it lands on has nothing left to get wrong.

Connected

  • Note · same thingSuggested
    How does my terminal find a tool?

    This chat picked that one up at /usr/local/bin: that note is how the shell finds the files, this one is what the files are.

  • Note · same thingSuggested
    What actually runs my code?

    Node and Bun are two runtimes in that note's sense: V8 and JavaScriptCore, each with a harness. And that note's containers are the image here, a whole folder tree packed up. It had listed the chat about containers as unwritten; this is it.

  • Hole · same patternSuggested
    What happens when I press play in Stremio?

    Bring your own runtime. Stremio ships its own Node for stremio-server, Claude Code carries Bun inside it, and Docker is the far end: bring the whole tree.

Terms

Checked

What the chat had wrong or only half right, against sources. The note above already says the corrected thing.

  1. Bun runs TypeScript natively; Node needs it transpiled.Node also runs TypeScript files by default since 22.18 and 23.6, by stripping the types. Syntax that needs translating, such as enums, still doesn't work.Node.js docs, TypeScript
  2. Vercel runs your code on its servers, the traditional model.Server code runs as functions that Vercel starts and stops per request, on Node by default, with no server of yours to look after.Vercel docs, Functions
  3. Cloudflare Workers run your code on V8 directly, with no runtime layer.There is a runtime round V8, workerd. It isn't Node, though it can offer many Node APIs when asked.Cloudflare, workerd
  4. With code copied before npm install, a code change reuses the npm install layer.Once one step's input changes, every step after it runs again. Copy the package files first, install, then copy the code.Docker docs, Build cache
  5. Each Dockerfile line, CMD included, becomes a layer.Only RUN, COPY and ADD add a layer of files. CMD and the others are settings stored with the image.Docker docs, Understanding image layers
  6. Containers on a Mac share the macOS kernel.They share a Linux kernel, in a virtual machine Docker Desktop runs.Docker docs, Docker Desktop on Mac
  7. npm is made by the npm company.npm, Inc. was bought by GitHub in 2020; GitHub runs npm now.GitHub blog, 2020