Flags
Every CLI option, what it does, and the dispatch rules between them.
<file> (positional)
Path to the .wasm binary to run. Required. The file is read as raw bytes; nothing about the path matters beyond that — there’s no virtual-fs lookup, no env-var substitution.
<wasi-args>... (trailing positional)
Anything positional after <file> is captured and passed to the WASI program’s _start as argv[1..]. argv[0] is synthesised from the file basename (stripped of any .wasm suffix), matching the wasmtime / wasmer convention.
sbt 'cliJVM/run --preopen ./data:/data examples/rust/word_count.wasm /data/input.txt'
# argv inside word_count.wasm: ["word_count", "/data/input.txt"]
If any value starts with - it would otherwise be parsed as a CLI flag — use the standard POSIX -- separator to stop option parsing:
sbt 'cliJVM/run examples/rust/word_count.wasm -- -v --quiet /data/input.txt'
# argv: ["word_count", "-v", "--quiet", "/data/input.txt"]
Non-WASI modules (main or --invoke-named exports) don’t see these args — argv is a WASI concept; non-WASI exports take i32 operands through --args instead.
-i, --invoke <export>
Name of the export to invoke. Overrides the default dispatch. Use this when the module exports neither _start nor main, or when you want to run a specific function instead of the default entry point:
sbt 'cliJVM/run --invoke fact -a 5 examples/fact.wasm'
# 120
-a, --args n1,n2,...
Comma-separated decimal i32 values to pass as arguments to the invoked export. Each n is parsed as Int.parseInt(_), so values must fit in a signed 32-bit int. Negative numbers, hex, and floats are not accepted.
--args only applies when the dispatch is not _start (the WASI command-mode entry point takes no wasm-level arguments — its argv comes from the WASI context, populated by trailing positional args after <file>; see <wasi-args>... above). When dispatch is main or an --invoke-named export, the --args values are pushed onto the operand stack in order before the call.
--list-exports
Prints every exported function name on its own line and exits with status 0. No instantiation traps run, no _start fires, no preopens are needed.
sbt 'cliJVM/run --list-exports interp/shared/src/test/resources/fixtures/fact.wasm'
# fact
# memory
-e, --env <key>=<value>
Sets an environment variable for the WASI program. Repeatable; each --env adds one entry to WasiContext.envs in order. Empty keys (=value) are rejected; values may themselves contain = signs (PATH=/usr/bin:/bin is fine).
sbt 'cliJVM/run -e HOME=/root -e LANG=C.UTF-8 my-program.wasm'
From the guest’s perspective, these reach userspace through environ_sizes_get + environ_get. std::env::vars() in Rust, getenv in C through wasi-libc.
--env is for WASI programs specifically — non-WASI modules don’t have an environ surface.
-p, --preopen <host-path>:<virtual-name>
Mounts a real host directory as a wasi preopen, backed by HostPreopen.fromDir. Repeatable; each --preopen adds one entry to the WASI context’s preopen list in order.
The split is on the last colon in the spec, so Windows-style paths like C:\data:/data parse correctly (C:\data host → /data virtual). The virtual name should start with / — that’s the convention wasi-libc expects, and it’s what guest code matches path_open calls against.
sbt 'cliJVM/run -p /tmp/sandbox:/sandbox -p /var/log:/logs my-program.wasm'
If a --preopen‘s host path doesn’t exist or isn’t a directory, the CLI exits with an error before instantiating the module.
--stdin <path>
Redirects the guest’s fd 0 (stdin) to read from a host file. The file is read once at startup and streamed byte-for-byte through fd_read until exhausted (subsequent reads return 0 = EOF).
echo "hello" > /tmp/in.txt
sbt 'cliJVM/run --stdin /tmp/in.txt examples/wc.wasm'
When omitted, fd 0 reads return 0 (EOF) immediately — wasi programs that probe stdin without writing prerequisites still terminate cleanly. A non-existent --stdin path is rejected with a clear diagnostic before instantiation.
Non-WASI modules never call fd_read, so this flag is inert for them.
--trace
Installs a counting Tracer on the run and prints the totals to stderr after _start / main / --invoke returns:
$ sbt 'cliJVM/run --trace examples/hello.wasm'
Hello, world!
[trace] ops=53 calls=2 hostCalls=14 throws=0 traps=0 maxDepth=2
Counts are: opcode dispatches (ops), wasm-defined function calls (calls), host-function calls (hostCalls), throw opcodes (throws), traps surfaced as WasmError (traps), and the maximum wasm-frame depth observed at any point.
Use this for quick performance / instrumentation triage. For finer-grained tracing (per-block, per-branch), write your own Tracer implementation and wire it through the library API — the CLI’s --trace deliberately picks the minimal default.
--validate-only
Parse and validate the module, then exit. No instantiation, no start function, no host imports needed. Useful as a CI lint step on generated wasm:
$ wasm-cli --validate-only build/output.wasm
build/output.wasm: ok
$ wasm-cli --validate-only build/broken.wasm
build/broken.wasm: InvalidModule(function 0: byte offset 0x12: expected i32, got i64)
Exit code is 0 if the binary parses and the validator accepts every function body; 1 with the diagnostic otherwise. Any other CLI flags (--preopen, --invoke, etc.) are ignored when --validate-only is set.
--help / --version
Standard. --help prints the synopsis above; --version prints wasm 0.4.0 and exits.
Dispatch rules
The CLI picks what to invoke based on what’s exported:
- If
--invokeis given, that export is invoked._startand WASI dispatch are bypassed. - Otherwise, if the module exports
_start, it’s treated as a WASI command-mode binary. The CLI runs it throughWasi.run, soproc_exit(N)becomes the process exit code, args/envs/preopens go throughWasiContext, trailing positional args becomeargv[1..], and--argsis ignored. - Otherwise, if the module exports
main, that’s invoked.--argsis passed to it asi32operands; trailing positional args are ignored. - Otherwise, the CLI exits with
ExportNotFound("_start")(the default it tried first).
Exit codes
0— clean exit (WASI_startreturned, or non-WASI export returned a single non-trapping result).N(1–255) —proc_exit(N)from a WASI binary.1— any non-proc_exitfailure (parse error, validator error, instantiate error, trap during execution, missing export).
Non-WASI exports that return a single i32 print the result to stdout as result: <decimal>; multi-result exports print result: <decimal>, <decimal>, …. Zero-result exports print nothing.