Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Targets: interpreter, native, web

You can run a program in the interpreter, build it to a native executable, or build it to a WebAssembly package. After this page you can pick one and fix the usual failures.

One checked meaning feeds every target. A safe program behaves the same on each backend that admits the features it uses.

Run it

semaprax check examples/meaning.spx
semaprax run examples/meaning.spx          # interpreter, prints 42
semaprax run examples/meaning.spx --native # generated C11, needs Clang
semaprax run .                             # a project: runs its entry

The interpreter is bounded: --max-steps N limits work, --max-bytes N limits the output envelope, and call depth stops at 256 frames. --json gives a machine-readable result. A single file needs a fn main() -> i64 (SPX-T105 otherwise). If the interpreter refuses a program (SPX-F102), try --native.

Build it

semaprax build examples/meaning.spx --target native -o meaning-native
semaprax build . --target web -o dist/web
Input--targetYou get
Filenative (default)Executable file. Needs Clang.
Filenative-callableBundle for a function with a direct own resource parameter (SPX-B105 otherwise). Add --function <id>.
Fileweb, wasmPackage directory with app.wasm. --export <id> picks exported functions.
Projectweb (default), wasmPackage directory: app.wasm, index.html, package.json, semaprax.js, bindings and a boundary description. wasm is an alias for web.
ProjectnativeNative executable of the project. Needs Clang.
ProjectnpmOwned-data npm package. Needs a profile that admits it (SPX-W120 for the scalar profile).
ProjectociOffline OCI Image Layout (oci-layout, index.json, blobs/). Scalar and Useful Data profiles only. Not signed, not pushed anywhere.
ProjectrustGenerated Rust SDK. Only in the full toolchain built from source. Read semaprax help build first.

Rules that save time:

  • -o and --output are the same. The path must be new: an existing one fails with SPX-I307, a bad parent with SPX-I301.
  • --json reports status, target, product and output.
  • [targets] matrix in the manifest can forbid a target (SPX-J122). web, wasm and npm need wasm32; the rest need native64.
  • Run semaprax help build for the exact list on your binary.

Strings in a standalone web module

A source file that passes string values between its own functions needs the internal String profile. Name each exported function:

semaprax build app.spx --target web --profile internal-strings-v1 \
  --export app.length -o app-web

It needs a source file, --target web or wasm, and 1 to 32 --export ids. A project, another target or a missing export is a usage error (exit 2). Strings never cross the exported boundary. Spec: Standalone internal String Web package v1.

Check a web package

semaprax test examples/calculator-project
semaprax build examples/calculator-project --target web -o dist/calculator-web
node scripts/verify-wasm-scalar-exports.mjs dist/calculator-web   # source checkout

semaprax.scalar-exports.json lists the exported functions. A build only writes files. Serving them and loading the module is your app’s job; follow the calculator browser consumer.

Edit and re-run (hot reload)

semaprax dev semaprax.toml --human

dev keeps one checked interpreter session open. It starts only after you send a start frame on stdin, then reads one JSON control frame per line (semaprax.hot-reload-control.v1). Operations are start, status, plan, activate, invoke and stop. Saving a file never runs code; invoke does. A broken revision is rejected and the previous one stays usable.

What must stay compatible before a swap

activate replaces the code only if everything reachable from the entry and test roots still agrees with the running revision:

  • entry points and the permit set;
  • type and interface records;
  • the set of reachable functions, with the same parameter and return types and ownership;
  • declared effects;
  • pre- and postconditions, and the cleanup and loan plans.

Otherwise the swap is refused (incompatible_closure, policy_changed, identical_revision or unsupported_target) and the old revision keeps running. Functions no entry or test reaches are not compared.

plan only reports what activate would do. Its output says authority: none, and activate rebuilds the plan itself, so a plan you saved cannot be replayed. If a worker panics or an acknowledgement is lost, the session enters terminal_uncertainty: the status shows the flag (a JSONL boolean, or a line in --human), every later operation is refused, and nothing is retried or rolled back. Start a new session.

Frame limits: 64 frames per session, 4 KiB per input frame, 8 KiB per response.

printf '%s\n' \
  '{"schema":"semaprax.hot-reload-control.v1","id":1,"op":"start"}' \
  '{"schema":"semaprax.hot-reload-control.v1","id":2,"op":"invoke"}' \
  '{"schema":"semaprax.hot-reload-control.v1","id":3,"op":"stop"}' |
  semaprax dev semaprax.toml --human

Use --jsonl for tools. The VS Code extension drives this for you (editor setup). Native and Wasm swapping are not supported; --source-agent is refused by the public binary. Specs: Hot Reload Watcher v1, Hot Reload Session v1.

Check the environment

semaprax doctor                      # versions and OS
semaprax doctor --profile <id>       # probe tools through an admitted offline profile
semaprax doctor --target native|web|all --json

doctor never discovers tools on PATH. Without --profile it reports failed profile: an explicit offline profile is required and lists tools (clang, node, rust) as not probed. That is expected. If a native build fails with SPX-B101 failed to start clang, install Clang and put it on PATH.

Richer data, commands, resources

These use the execution route of their profile. A web scalar package and an owned-data npm package are different interfaces, even though both are WebAssembly.

Next: Integrate with another language, or prepare the package for review. References: Interpreter v1, Wasm Scalar Exports v1, OCI Deployable Artifact v1, Native Callable ABI v3.