name: sandbox-npm-install description: 'Install npm packages in the Docker Sandbox (Copilot) environment. Use this skill whenever you need to install, reinstall, or update node_modules in the container. Native binaries crash on virtiofs, so packages must be installed on local ext4 and symlinked.'
Sandbox npm Install
When to Use
Use this skill whenever:
- You need to install npm packages for the first time in a new sandbox session
package.jsonorpackage-lock.jsonhas changed and you need to reinstall- You encounter native binary crashes (esbuild, lightningcss, rollup) with errors like
SIGILL,SIGSEGV,mmap, orunaligned sysNoHugePageOS - The
node_modulesdirectory is missing or corrupted
Background
The Docker Sandbox workspace is mounted via virtiofs (file sync between macOS host and Linux VM). Native Go and Rust binaries (esbuild, lightningcss, rollup) crash with mmap alignment failures when executed from virtiofs on aarch64. The fix is to install on the sandbox's local ext4 filesystem and symlink back.
Installation
Run the bundled install script from the workspace root:
bash .github/skills/sandbox-npm-install/install.sh
To also install Playwright browsers for E2E testing:
bash .github/skills/sandbox-npm-install/install.sh --playwright
The script performs these steps automatically:
- Checks for existing
node_modules(user mustnpm installon macOS first) - Installs Linux ARM64 platform packages to a temp dir on ext4
- Copies Linux packages INTO the existing node_modules (preserves macOS packages)
- Copies the esbuild binary to ext4 at
/home/agent/esbuild-bin-dir/esbuild - Sets
ESBUILD_BINARY_PATHenv var (persisted to~/.bashrc) - Verifies all native binaries (esbuild, rollup, lightningcss, vite)
- Optionally installs Playwright browsers
If verification fails, run the script again — crashes can be intermittent.
How It Works
Key insight: Only esbuild's Go binary crashes on virtiofs. Rollup and lightningcss (Rust/napi) work fine.
The dual-platform approach:
- Platform packages have different scoped names (
@esbuild/darwin-arm64vs@esbuild/linux-arm64) — they coexist without conflicts - The script adds Linux packages alongside the existing macOS packages
ESBUILD_BINARY_PATHenv var tells esbuild to use a copy on ext4 instead of the virtiofs binaryvite.config.tshasgetSymlinkAllowPaths()that detects symlinked node_modules and adds the target to Vite'sserver.fs.allow
Neither side needs to reinstall — macOS finds darwin packages, Linux finds linux packages.
Post-Install: Running Commands
All commands run from the original workspace (no mirror needed):
# Unit tests
npm test
# E2E tests
npx playwright test --project=chromium
# TypeScript check
npx svelte-check --tsconfig ./tsconfig.json
# Dev server
npm run dev
Ensure ESBUILD_BINARY_PATH is set in your shell (the install script adds it to ~/.bashrc):
export ESBUILD_BINARY_PATH=/home/agent/esbuild-bin-dir/esbuild
Important Notes
/home/agent/esbuild-bin-dir/is sandbox-local and NOT synced to the macOS host- The user's macOS packages are preserved —
npm installon macOS won't remove the Linux packages - If the user runs
npm cion macOS, it WILL remove Linux packages — re-run the install script - After any
package.jsonorpackage-lock.jsonchange, re-run the install script - Do NOT run
npm ciornpm installdirectly in the sandbox — it will crash during esbuild postinstall