Cloud Sandboxes
A cloud agent sandbox opens a repository with the sandbox image’s default Node runtime, not necessarily the Node line the repository pins. Running any LumenFlow lifecycle command under the wrong Node ABI corrupts the shared CLI dist for every later session that reuses it, because the CLI dist hashes the Node ABI it was built with. Installing this project’s own private packages as a consumer also needs a registry npmrc carrying a licence-scoped credential, and a cloud sandbox has no interactive step to supply one.
The fix is a committed, cross-platform
Node script run from a SessionStart hook
registered once in .claude/settings.json (matcher startup|resume —
deliberately not clear/compact, which already carry the repo’s own
recovery hook and are not a genuinely new session environment), alongside
its other session-start hooks.
What it does, inside a cloud session only
Section titled “What it does, inside a cloud session only”-
Detects the cloud/remote session. Only
LUMENFLOW_CLOUD=1(an explicit, repo-owned override) or the harness’s own remote-session environment signal activate the rest of the script. Neither present means a strict no-op: no PATH change, no build, no npmrc write. -
Selects the pinned Node version through nvm, when nvm is present. Resolves the nvm-managed bin directory for the version in
.nvmrcand, when the harness exposes a session-environment file to appendexportlines to, persists the selection for the rest of the session. ASessionStarthook cannot change its caller’s shell PATH just by exiting. -
Runs
pnpm bootstrap(turbo build --filter=@hellmai/lumenflow-cli) under the selected Node, so the first lifecycle command in the session finds a dist already built for the right ABI. This script runs before any workspace dist exists, so it cannot take a workspace package dependency to resolve pnpm’s Windows shim safely; instead it resolves the spawn form itself: onwin32it launches the command processor (ComSpec, orcmd.exe) with/d /s /cand the constant command linepnpm bootstrap(never user input) — pnpm ships as a.cmdshim there, and Node refuses to launch one directly since CVE-2024-27980. Elsewhere it resolvespnpmnormally through PATH. -
Writes the consumer registry credential, when supplied, without clobbering the rest of the file. When
LUMENFLOW_CONSUMER_NPMRCis set, writes it into a managed block (bounded by begin/end marker comments) inside the user-level npmrc (~/.npmrc), with restricted permissions (POSIX mode0600on Linux/macOS; Windows has no equivalent POSIX bit, so the script reports that instead of failing). Any pre-existing content in that file — including a line a developer added by hand outside the managed block — survives untouched; a later run (for example after the secret rotates) replaces only its own block. The value is never printed or logged.
Every step reports its own failure and the script always exits 0: a
SessionStart hook cannot block session start for this event, so a broken
bootstrap must never prevent the session itself from starting.
See Cloud sandbox session-start bootstrap for the full deployment contract.
Adding an equivalent bootstrap to your own repository
Section titled “Adding an equivalent bootstrap to your own repository”A repository that consumes LumenFlow and also runs in cloud sandboxes can follow the same shape:
-
Write a small, cross-platform Node script (for example a script under a
scripts/directory) that:- returns immediately unless a cloud/remote signal is present in the environment;
- otherwise, selects your project’s pinned Node version (through nvm, Volta, or whatever version manager your sandbox image provides) and runs your project’s own build/bootstrap command;
- when a registry credential is supplied through an environment variable, writes it to the user-level npmrc with restricted file permissions and never logs it.
-
Register that script once as a
SessionStarthook in your project’s own.claude/settings.json(or the equivalent hook configuration for your agent harness), alongside any hooks already registered for that event — never replacing them. -
Prove the no-op branch and each active branch with an injected environment, a fake version-manager directory layout, and a temporary home directory, never against a real version-manager install or a real build.