Node compile cache
Node can keep compiled module code on disk so a command does not recompile the same modules every
time. LumenFlow turns this on for every command it starts and keeps the cache bounded. On a typical
workstation pnpm mem:inbox goes from about 1.6 s to 1.2 s, and tsc --version from 0.20 s to 0.10 s.
Where it lives
Section titled “Where it lives”| Situation | Location |
|---|---|
NODE_COMPILE_CACHE is unset | ~/.lumenflow/cache/node-compile-cache (per user, all platforms) |
NODE_COMPILE_CACHE is set | the directory you set; LumenFlow never overrides it |
Every lifecycle, gate, hook and sweep command, and the tools they start (tsc, eslint, prettier,
through pnpm and turbo), use this directory. Without it those three tools would write to the shared
temporary directory (/tmp/node-compile-cache), which Node never cleans and which can exhaust a small
temporary filesystem. A tool you start yourself outside a LumenFlow command, such as a raw pnpm lint,
uses whatever NODE_COMPILE_CACHE your shell exports.
The bound
Section titled “The bound”LumenFlow prunes a cache only when it is inside ~/.lumenflow (the default, or a value you set that
resolves there). A directory outside ~/.lumenflow is never pruned.
The check is made on the real filesystem. If the cache directory, or any directory between ~/.lumenflow
and it, is a symbolic link or a Windows junction (Node reports a junction as a link), LumenFlow refuses to prune it. The prune never reads
inside a linked directory, never crosses onto another disk, and removes an entry only if it is still the
same file or directory it inspected, with the same modification time. If the cache directory or an ancestor is replaced while the prune runs, the prune stops. If your filesystem does not report file identity (inode 0, as on some
FAT or network filesystems), the prune refuses rather than guess, and the cache is not bounded there. This
protects against stray and stale links; it is not a sandbox against another process running as you.
| Rule | Value |
|---|---|
| Maximum entry age | 14 days since the entry was last written |
| Maximum entry count | 150000 entries; above that the oldest are removed down to 100000 |
| Always kept | entries written in the last hour |
| How often | at most once per 24 hours, in a separate low-priority background process |
The entry count is a soft bound: entries written in the last hour are always kept, and commands keep
writing while a prune runs, so the count can briefly exceed 150000. The 14-day age rule is the firm limit.
At most one background prune starts per interval, even when several commands start at once. If a command
died while claiming the interval, the next command takes over only when it can prove the first one is gone.
The proof is that the first command’s process no longer exists. That check is exercised on Linux here and relies on the standard process-existence check elsewhere; it holds unless its process
id has since been reused by another process. Telling a reused id apart needs a readable process start identity:
on Linux it is normally readable, and on macOS and Windows it is not available. When it is unavailable or cannot
be read, the claim is treated as belonging to a live or unknown command and that cache is left unpruned until the
claim is removed by hand
(delete the node-compile-cache.prune-stamp.claim-* files beside the cache).
Version and flag directories left by an old Node release empty out and are removed by the same rule. An entry still in use that reaches the age limit is rebuilt on its next use, which costs one slower load. The prune never makes a command wait: it adds about 7 ms to each command and runs its walk in the background. Measured on a test cache of 360000 entries (300000 in one directory), the walk peaked at 67 MiB of memory, 26 MiB above an idle Node process, and finished in 29 s. It is safe while other commands are running, because it only deletes whole entries and Node treats a missing entry as a cache miss.
Reclaim space
Section titled “Reclaim space”Deleting the cache is always safe; commands rebuild what they need.
To turn the cache off for one process, set NODE_DISABLE_COMPILE_CACHE=1. A cache you pointed at your own
directory, or left in the shared temporary directory by a tool started outside LumenFlow, is not touched
by LumenFlow; remove it yourself.