Skip to content

fix(standalone): savings-check.js crashes on startup (createRequire(undefined) in CJS bundle)#17

Open
jpr5 wants to merge 1 commit into
WithWoz:mainfrom
jpr5:fix/createrequire-cjs-import-meta
Open

fix(standalone): savings-check.js crashes on startup (createRequire(undefined) in CJS bundle)#17
jpr5 wants to merge 1 commit into
WithWoz:mainfrom
jpr5:fix/createrequire-cjs-import-meta

Conversation

@jpr5

@jpr5 jpr5 commented Jun 18, 2026

Copy link
Copy Markdown

Summary

standalone/savings-check.js crashes on startup with node savings-check.js — the exact invocation the README documents. This fixes it with a one-line change.

Root cause

standalone/package.json declares "type": "commonjs", so the bundle always runs as CommonJS. esbuild emits var import_meta = {} for the bundled @anthropic-ai/claude-agent-sdk (an ESM module that uses import.meta.url), so import_meta.url is always undefined at runtime:

var v6 = (0, import_node_module.createRequire)(import_meta.url); // import_meta.url === undefined

createRequire(undefined) throws ERR_INVALID_ARG_VALUE during top-level module init. This is version-independent — not tied to any particular Node release.

The fix

-var v6 = (0, import_node_module.createRequire)(import_meta.url);
+var v6 = (0, import_node_module.createRequire)(import_meta.url || __filename);

__filename is the absolute path of the bundle under CommonJS, which createRequire accepts. The import_meta.url || prefix preserves correct behavior if the file is ever executed as a real ES module.

Red / green proof

RED — unpatched, on a clean download of the committed blob:

$ node standalone/savings-check.js
TypeError [ERR_INVALID_ARG_VALUE]: The argument 'filename' must be a file URL
object, file URL string, or absolute path string. Received undefined
    at createRequire (node:internal/modules/cjs/loader:2053:11)
    at Object.<anonymous> (.../savings-check.js:15064:47)

Reproduced identically on Node v25.8.0 and Node v20.20.2, confirming it is not version-specific.

GREEN — with the one-line fix, same file, same machine:

$ node standalone/savings-check.js
🧙 WOZCODE — Claude Code Savings Estimator
Scanning ~/.claude/projects/ ...
Analyzed 223 sessions.
... (full savings report) ...
exit 0

Note: don't pipe to node -

The README's curl ... | node - form fails separately with Cannot set property crypto of #<Object> which has only a getter, because in stdin/eval mode the bundle's top-level var crypto = require("crypto") collides with Node's read-only globalThis.crypto getter (Node ≥ 20). Running the file as a file (not stdin-eval) avoids this. Worth updating the install snippet to download-then-run.

Two unrelated observations

  1. node_modules is committed to the repo. The repository is ~1.3 GB largely because of this, which makes clones and forks painfully heavy. node_modules should be in .gitignore and removed from version control — the prebuilt standalone/ bundle is self-contained and doesn't need it shipped in git.

  2. The file header's claims are inaccurate as written. The top comment states "No network calls. No writes. No telemetry. No child processes." That is true of the reachable code path from main() (it only reads ~/.claude/projects/*.jsonl and writes to stdout). But it is not true of the file: the bundle statically includes @anthropic-ai/claude-agent-sdk (and the wozcore file-concurrency utils), which contain fetch(), child_process.execFile, and fs write/unlink/symlink/rmSync calls as dead, unreachable code. The capabilities are present in the shipped bytes even though they're never invoked. Consider either scoping the claim to the executed path, or tree-shaking the agent SDK out of this standalone build so the audit claim matches the contents.

standalone/savings-check.js is an esbuild CommonJS bundle (standalone/package.json
declares "type": "commonjs"), so import.meta is never available at runtime and
import_meta.url is always undefined. createRequire(undefined) throws
ERR_INVALID_ARG_VALUE on every Node version, so running the script as documented
(node savings-check.js) fails immediately on a clean checkout.

Fall back to __filename when import.meta.url is absent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant