Command Line

One command, j2, runs, builds, formats, and tests J2 programs, and holds the keys to the capability sandbox.

Commands

CommandDescription
j2 FILE.j2 [args...]Run a program, interpreter first: instant start, with a silent native fallback for anything the interpreter does not support.
j2 run FILE.j2Run through the interpreter explicitly.
j2 build FILE.j2 -o OUTCompile to a native binary with automatic parallelization. The right mode for compute-heavy programs you run more than once.
j2 emit-native FILE.j2Print the lowered native source, for the curious and for debugging.
j2 fmt [-w] FILE.j2Format a source file; -w rewrites it in place, otherwise the result prints to stdout.
j2 replInteractive session. Bindings persist, expressions print, :quit exits.
j2 test [DIR]Run every J2 file under a directory and report pass and fail counts.
j2 --version, j2 --helpVersion and usage.

Program arguments

Anything after the file name is handed to the program, available through proc.argv(). Element 0 is the program itself, so real arguments start at index 1:

# greet.j2
args = proc.argv()
if count(args) > 1 {
    print(fmt("hello, {}", args[1]))
} else {
    print("usage: greet NAME")
}
$ j2 run greet.j2 Ada
hello, Ada

Capabilities

Programs run inside a deny-by-default sandbox. The parts of the standard library that reach outside the process are switched off until a flag grants them, so running an unfamiliar script cannot quietly read files, spawn programs, or phone home. A denied call raises RuntimeError naming the flag it needs.

FlagGrants
--allow-fsthe fs module: reading and writing files
--allow-procproc.run: spawning processes
--allow-netthe http module: network requests
--allow-unsafethe rust { } escape hatch (see How J2 Runs)
--allow-alleverything above
$ j2 run report.j2                     # no capabilities
$ j2 run --allow-fs report.j2          # may touch files
$ j2 run --allow-fs --allow-net sync.j2

Grant the narrowest set that lets the program do its job, and treat a script that asks for --allow-all the way you would treat one asking for your password.

Environment variables

VariableEffect
J2_FORCE_NATIVE=1Skip the interpreter and run through the native engine, without producing a binary.
J2_NO_NATIVE=1Stay on the dynamic path instead of native lowering. Mostly for testing and triage.
J2_PARALLEL=0Build natively but with automatic parallelism off; single threaded.
J2_NO_NESTED=1Disable only the nested-loop parallel patterns (matrix kernels), keeping the rest.
J2_DEBUG=1On a native build failure, show the underlying compiler diagnostics instead of the one-line summary.
J2_PATHColon-separated directories searched by import; see Imports.
J2_TRUSTED=1Equivalent to --allow-unsafe.
J2_ALLOW_LOCAL_NET=1Let http reach loopback and private addresses, which are otherwise refused even under --allow-net.

When a native build fails

If a program cannot be compiled natively, j2 prints a single line saying so rather than pages of internal diagnostics:

internal error: could not compile the program to native code
(re-run with J2_DEBUG=1 for details, or J2_NO_NATIVE=1 to use the interpreter)

The two suggestions are the two useful moves: J2_DEBUG=1 to see the real error when reporting a bug, and J2_NO_NATIVE=1 or j2 run to keep working through the interpreter meanwhile.

Exit status

A program that completes exits with status 0. An uncaught error prints its one-line report and exits nonzero, so J2 scripts compose with shell tooling and CI the way you would expect.