Summary
The node command shim in almostnode appears to take its first positional argument as the script filename, regardless of whether it's a flag. Common flags fail with Cannot find module '/work/<flag>':
node -e "console.log('hello')"
# → Error: Cannot find module '/work/-e'
node --test fib.test.ts
# → Error: Cannot find module '/work/--test'
Both are everyday Node usage:
node -e "<code>" is the canonical "run a one-liner" pattern, used constantly by humans and by LLM agents for quick debugging ("let me check what's in this var")
node --test <file> runs node:test, the built-in test runner shipped since Node 18
Treating these as script paths means the moment an agent or developer reaches for them, they hit a confusing error and have to invent a workaround (write a tempfile, then node tempfile.js).
Repro
import { createContainer } from "almostnode";
const c = createContainer();
console.log(await c.run('node -e "console.log(1+1)"'));
// { stdout: '', stderr: "Error: Cannot find module '/work/-e'\n", exitCode: 1 }
Why this matters
node -e is what training data teaches LLMs to use for inline checks. Agents reach for it before reaching for "write a file first."
node --test is what the official Node docs prescribe for the built-in test runner. Anyone following modern Node tutorials hits this immediately.
- Other useful flags in the same boat:
node -p "<expr>" (eval + print), node -r <module> (require before main), node --input-type=module -e "<code>".
Suggested fix
In the node custom command (src/shims/child_process.ts), parse argv before treating arg[0] as the script path:
// pseudocode for the node command handler
const args = parseArgs(rawArgs); // handle -e, -p, --test, -r, etc.
if (args.eval) {
// -e / --eval "<code>" → execute the string directly
return runtime.execute(args.eval, '__eval__.js');
}
if (args.print) {
// -p / --print "<expr>" → execute as expression, print result
const result = runtime.execute(`module.exports = (${args.print});`, '__print__.js');
return { stdout: String(result.exports) + '\\n', stderr: '', exitCode: 0 };
}
if (args.test) {
// --test [file...] → wrap node:test runner around the listed files
// (implementation could either: a) execute each file in sequence and let
// node:test's auto-run kick in, or b) explicitly call test.run from the
// node:test shim)
...
}
// fallback: arg[0] is the script path
return runtime.runFile(args._[0]);
-e and -p are the high-leverage ones (zero new behaviour needed — they just delegate to runtime.execute). --test is bigger work because it needs the test runner.
Environment
Related
Summary
The
nodecommand shim in almostnode appears to take its first positional argument as the script filename, regardless of whether it's a flag. Common flags fail withCannot find module '/work/<flag>':Both are everyday Node usage:
node -e "<code>"is the canonical "run a one-liner" pattern, used constantly by humans and by LLM agents for quick debugging ("let me check what's in this var")node --test <file>runsnode:test, the built-in test runner shipped since Node 18Treating these as script paths means the moment an agent or developer reaches for them, they hit a confusing error and have to invent a workaround (write a tempfile, then
node tempfile.js).Repro
Why this matters
node -eis what training data teaches LLMs to use for inline checks. Agents reach for it before reaching for "write a file first."node --testis what the official Node docs prescribe for the built-in test runner. Anyone following modern Node tutorials hits this immediately.node -p "<expr>"(eval + print),node -r <module>(require before main),node --input-type=module -e "<code>".Suggested fix
In the
nodecustom command (src/shims/child_process.ts), parse argv before treating arg[0] as the script path:-eand-pare the high-leverage ones (zero new behaviour needed — they just delegate toruntime.execute).--testis bigger work because it needs the test runner.Environment
0.2.14Related
styleText— breakscreate-vite@9and other Node 21+ scaffolders #16 (util.styleTextmissing) andnpm install(no args) silently skips devDependencies #17 (npm installskips devDeps) — when those hit and an agent tries to debug withnode -e, this bug compounds the dead end.