Run, check and repair JavaScript from a terminal or a CI job with the oneecma command: the same reports as the library on stderr, JSON on stdout, exit status 1 on an error, and a REPL.
Install
dotnet tool install -g RecursiveAI.OneEcma.Cli --version 1.0.0The 1.0.0 tool needs the .NET runtime 10.0.14 or later; on an older runtime it stops with “You must install or update .NET to run this application.” Without .NET, use a self-contained NativeAOT binary from the v1.0.0 release: win-x64, linux-x64, linux-arm64 and osx-arm64, each with a .sha256 file.
curl -sSLO https://github.com/recursive-ai-oss/oneecma-csharp/releases/download/v1.0.0/oneecma-1.0.0-linux-x64.tar.gz curl -sSL https://github.com/recursive-ai-oss/oneecma-csharp/releases/download/v1.0.0/oneecma-1.0.0-linux-x64.tar.gz.sha256 sha256sum oneecma-1.0.0-linux-x64.tar.gz tar -xzf oneecma-1.0.0-linux-x64.tar.gz
62ceaf3a44b1e0cdfe3ac255b0d020a79db9023aa9d498220dd0036ab4c04046 oneecma-1.0.0-linux-x64.tar.gz 62ceaf3a44b1e0cdfe3ac255b0d020a79db9023aa9d498220dd0036ab4c04046 oneecma-1.0.0-linux-x64.tar.gz
The binary prints the same reports as the tool. Every example below was run with NO_COLOR=1; on a terminal the reports are in color.
Run a script
area.js misspells a variable:
function area(shape) { const { width, height } = shape; return width * heigth; } area({ width: 3, height: 4 });
oneecma run --locals area.jserror[ReferenceError]: heigth is not defined --> area.js:3:18 | 3 | return width * heigth; | ^^^^^^ `heigth` is not declared in this scope | = help: did you mean `height`? (number) = stack: area (area.js:3) ← <top-level> (area.js:5) = locals in area: shape = { width, height }, width = 3, height = 4
The report goes to stderr and the exit status is 1. --locals adds each frame’s bindings; leave it off for the shorter report. --module runs the file as a module. Scripts get a print function for output:
$ oneecma run fixed.js 2,4,6
The compact report
--compact prints the short form, for a model’s context or a CI log. On the checkout.js from Error reports:
oneecma run --compact checkout.jserror[TypeError]: Cannot read properties of undefined (reading 'reduce') --> checkout.js:7:23 6 | const order = await loadOrder(7); | ------------------ `order` comes from here: { id, lineItems, total } 7 | const total = order.items.reduce((sum, i) => sum + i.price, 0); | ^^^^^ `order.items` is undefined = help: did you mean `order.lineItems`? (Array, 2 items)
Check without running
check parses and runs the early errors only, and reports every error of the file at once. two.js:
let a = 1; let a = 2; let b = ;
oneecma check two.jserror[SyntaxError]: Identifier 'a' has already been declared --> two.js:2:5 | 1 | let a = 1; | ----- first declared here 2 | let a = 2; | ^^^^^ declared again here | = help: rename one of them, or assign with `a = 2` if `a` should change = note: not repaired automatically: every fix changes what the program means = note: a second error follows: both are reported from one parse error[SyntaxError]: Unexpected token ';' --> two.js:3:9 | 3 | let b = ; | ^ expected an expression before `;` | = help: give `b` a value, or remove the declaration error: aborting due to 2 syntax errors
The exit status is 1; a file that parses exits 0 with no output. --format json writes the JSON report to stdout instead:
oneecma check --format json two.js{"version":1,"format":"oneecma.report","summary":{"errors":2,"warnings":0,"repairs":0},"diagnostics":[{"kind":"SyntaxError","code":"redeclaration","severity":"error","headline":"Identifier 'a' has already been declared",…Repair
--repair applies only the syntax fixes that are the single plausible one and still parse. extra.js has one ) too many:
const items = [1, 2, 3]; const doubled = items.map(x => x * 2)); print(doubled);
oneecma check --repair --out fixed.js extra.jsrepair[R001]: removed an extra closing delimiter --> extra.js:2:38 | 2 | const doubled = items.map(x => x * 2)); | ^ removed | = note: the repaired source parses and is returned with this report
The exit status is 0 and fixed.js holds the repaired source. Without --out, the repaired source is printed after the report. The duplicate let a above is not repaired: every fix would change what the program means.
The REPL
oneecma repl takes multi-line input and top-level await; .exit leaves. Here the input is piped in:
printf 'let rate;\nrate = await Promise.resolve(0.92);\nconst prices = [10, 25];\nprices.map(p => (p * rate).toFixed(2))\nfunction total(xs) {\n return xs.reduce((a, b) => a + b, 0);\n}\ntotal(prices)\n.exit\n' | oneecma repl0.92 [ "9.20", "23.00" ] 35
In 1.0.0 a declaration in an input that uses await doesn’t carry over to the next input, so declare first and assign with await on its own line, as above.
Options
oneecma run [--module] [--locals] [--compact] <file> oneecma check [--module] [--compact] [--format text|json] [--source-map <map>] [--repair [--out <path>]] <file> oneecma repl
--source-map <map>remaps syntax errors in generated code to the original;checkalso follows a map comment in the file. See source maps.- Color is used only on a terminal and never when
NO_COLORis set. - Each repair rule is in the auto-repair table.