node_modules directories — not a virtual filesystem and
not symlinked package contents. That’s a deliberate choice: V8, Vite, and bundlers
resolve through fs.realpath, and symlinked package contents break that. meow
gives you the speed of a shared store with the compatibility of real files.
The layout
Packages are materialized into a project-local content-addressed store undernode_modules/.meow, and the top-level names you import are edges pointing
into it:
Contents are cloned, not linked
The actual package files come from the global cache using the fastest primitive each OS offers:
The result: 0 bytes of duplicated disk. A file shared across versions or
projects exists once physically; copy-on-write means a write would fork it rather
than corrupt the shared copy.
Why edges stay links but contents don’t. The pointer inside a package’s
node_modules to another package (a graph edge) is a link — cheap, and traversal
through it is fine. But a package’s own files are cloned/hardlinked, never
symlinked, so tools that call fs.realpath (V8, Vite) see a normal directory and
never trip on symlink traversal.Incremental & skippable
meow writes a small.materialized sidecar that records the state of the tree. If
node_modules is already up to date for the current lockfile, materialization is
skipped entirely:
Cleaning & rebuilding
Vendoring
For fully self-contained, reproducible trees (air-gapped builds, committed dependencies, deterministic CI), use vendor mode, which copies packages instead of linking them and normalizes file metadata for byte-reproducibility:Run package binaries
meow x, global installs, and searching the registry.