bun install reads package.json and .npmrc registry settings the way npm 2,036 does and, for a single-package project, builds the same hoisted node_modules, so Node.js 2,131 and every tool expecting npm's tree keep working.
mkdir ~/v5-ch1/bun-demo && cd ~/v5-ch1/bun-demo
cp -r ../booknest/{package.json,app.js,server.js,db,public,test} .
bun install
find node_modules -path 'node_modules/*/node_modules/content-type' | sort
stat -c '%h links' node_modules/express/index.js
node -e 'require("debug"); console.log("phantom debug resolved")'bun install v1.4.2 (744846f84) ... 80 packages installed [1.95s] node_modules/body-parser/node_modules/content-type node_modules/negotiator/node_modules/content-type node_modules/type-is/node_modules/content-type 5 links phantom debug resolved
The tree matches npm's, down to the three nested content-type copies and the phantom access to debug. Two things differ underneath. Bun 73,307 hard-links files from its global cache (~/.bun/install/cache) on Linux, and clones them on macOS; the count of 5 is the cache plus four Bun projects on this machine sharing one copy. And Bun runs dependencies' lifecycle scripts only for trusted packages: the 367 listed by bun pm default-trusted (including esbuild 126 and bcrypt), or those you add to trustedDependencies with bun pm trust <name>. Once you define trustedDependencies, it replaces the default list rather than extending it.