lpm <file> and lpm exec
Run JS/TS source files directly, or run project-local binaries from node_modules/.bin.
lpm <file> [--env <mode>] [--watch] [--plain-node] [args...]
lpm exec [--env <mode>] [--no-env-check] <bin> [args...]LPM CLI has two execution lanes:
lpm <file>runs a JavaScript or TypeScript source file directly.lpm exec <bin>runs a project-local binary fromnode_modules/.bin, matching npm/pnpm muscle memory.
lpm exec does not run source files. Use lpm scripts/seed.ts, not lpm exec scripts/seed.ts.
There is also a shorthand: lpm <bin> tries a project-local binary only after the name does not match a built-in command, a source-file/path invocation, a package.json script, or an lpm.json task. Use lpm exec <bin> when you want the local-bin lane explicitly.
Source Files
lpm scripts/seed.ts
lpm scripts/view.tsx
lpm scripts/migrate.js
lpm scripts/seed.ts --env staging
lpm scripts/seed.ts --watch
lpm scripts/seed.ts --plain-node
lpm scripts/seed.ts -- --env=stagingRuns a single JavaScript or TypeScript file without adding a scripts entry to package.json. .js / .mjs / .cjs go through plain node; .ts / .tsx / .mts / .cts use LPM CLI's OXC-backed TypeScript runtime on supported Node versions. If no safe runtime is available, LPM CLI fails with a fix-it message instead of downloading tsx through npx.
Human progress goes to stderr and names the selected runtime before the file starts:
› Executing scripts/seed.ts with Node.js v22.18.0 + LPM CLI TS runtime
✓ Done · exited 0 in 412msLocal Binaries
lpm exec eslint --fix src
lpm exec vitest run
lpm exec --env staging prisma migrate deploy
lpm jest --watch # shorthand when no script/task named "jest" existslpm exec <bin> resolves <bin> only from project node_modules/.bin directories, walking upward through the workspace. It loads project env, injects the same local-bin PATH used by lpm run, strips inherited runtime-hook env like NODE_OPTIONS and LD_PRELOAD, then spawns the binary directly without a shell.
It does not fetch packages and does not fall back to system PATH. The bare shorthand uses the same local-bin lookup, but only after scripts/tasks miss. Use lpm dlx when you want to run a package binary without adding it to the project.
Runtime Selection
| Extension | Runtime |
|---|---|
.js, .mjs, .cjs | node - direct spawn, no shell, no LPM CLI TS preload |
.ts, .mts, .cts | Node 22.18+ / 23.6+ / 24+ with the LPM CLI TS runtime -> Node 22.6-22.17 / 23.0-23.5 with --experimental-strip-types -> project-local tsx |
.tsx | Node 22.18+ / 23.6+ / 24+ with the LPM CLI TS runtime's OXC JSX transform -> project-local tsx when the Node version cannot load the LPM CLI runtime |
The effective PATH includes project node_modules/.bin, any matching managed Node that LPM CLI resolved for the project, and then your existing system PATH.
LPM CLI source-file execution does not fall back to npx tsx. That fallback can download and execute npm code outside LPM CLI's install-policy/security model. If TypeScript execution cannot use the LPM CLI runtime, Node's built-in strip-types path, or a project-local tsx, use lpm use node@22.18+ or add and pin tsx in the project explicitly.
The LPM CLI TS runtime is LPM CLI-owned: it writes LPM CLI's bundled loader into the LPM CLI cache, calls LPM CLI's Rust/OXC transformer without fetching npm packages, executes .ts, .tsx, .mts, and .cts, reads tsconfig.json baseUrl / paths mappings for project-local imports, emits source maps, and caches transforms by source content, runtime version, Node version, platform, architecture, file path, tsconfig fingerprint, and transform options. Cache entries are validated before reuse.
TSX uses OXC's JSX transform. By default it emits the React automatic JSX runtime (react/jsx-runtime). jsx: "react" or explicit jsxFactory / jsxFragmentFactory selects the classic runtime, jsx: "react-jsxdev" enables development JSX output, and jsxImportSource changes the automatic-runtime import source. JSX runtime packages still need to be present in the project or otherwise resolvable by Node; LPM CLI does not download them during execution.
Plain Node Mode
--plain-node disables the LPM CLI TS runtime preload and child Node propagation for lpm <file>. --no-augment is an alias.
Use it when you need to check what Node itself can run without LPM CLI augmentation:
lpm scripts/seed.ts --plain-nodeIn plain mode, .ts / .mts / .cts use Node's built-in TypeScript support when available. .tsx is refused because plain Node does not support TSX.
Child Node Processes
When a TypeScript entrypoint runs with the LPM CLI TS runtime, child processes spawned as node child.ts inherit a controlled LPM CLI NODE_OPTIONS preload. That lets TypeScript child scripts use the same loader and tsconfig.json path mappings without invoking npx or a project-local wrapper.
Inherited parent NODE_OPTIONS is stripped before execution, so a developer shell or CI environment cannot silently replace the LPM CLI loader. --plain-node / --no-augment disables this child propagation.
Environment Loading
Both execution lanes load the project's env files and env secrets before spawn. Pass --env <mode> to load the same mode-specific files as lpm run, such as .env.staging and .env.staging.local.
--no-env-check skips env-schema validation only; it does not disable env loading.
Before spawning, LPM CLI strips inherited runtime-hook env like NODE_OPTIONS, LD_PRELOAD, LD_AUDIT, BASH_ENV, and DYLD_INSERT_LIBRARIES. Project env files, env secrets, and env-schema defaults are filtered for the same runtime-hook names before they are applied, so those keys are ignored when they come from project env. LPM CLI-controlled runtime env is added after that filtering.
Watch Mode
--watch re-runs the same source-file execution plan when the target file changes:
lpm scripts/seed.ts --watchIt watches the requested file only; dependency-graph watching is not part of direct source-file execution yet.
Argument Forwarding
For source files, put LPM CLI flags after the file and use -- when the script arg starts with -:
lpm scripts/seed.ts --env staging -- --verbose --env=prodFor local binaries, flags for LPM CLI belong before the binary name. Everything after the binary name is passed to the binary:
lpm exec --env staging eslint --fix src/index.tsFlags
| Lane | Flag | Effect |
|---|---|---|
| Both | --env <mode> | Load env files and secrets for the selected mode |
| Both | --no-env-check | Skip env-var schema validation before execution |
| Source files | --watch | Re-run the same plan when the target file changes |
| Source files | --plain-node | Disable the LPM CLI TS runtime preload and child Node propagation |
| Source files | --no-augment | Alias for --plain-node |
Plus the global flags.