Quick Start

Overview

This guide takes you from a clean checkout to a running wapp. It uses the wsh debug supervisor — an interactive shell wired to the engine's control plane — so every step is a command you type yourself.

Prerequisites

  • A container runtime: Podman (default) or Docker.
  • make.

Nothing else. The toolchain (CMake, Ninja, the WASI SDK, the WAMR runtime) lives in the build container; the host only invokes make, which wraps every command in that container. To use Docker instead of Podman, append RUNNER=docker to any make command.

Build

Compile the sample wapps and the engine with the wsh supervisor:

1make wapps   # compile the sample wapps under wapps/ (produces wapps/hello/hello.wasm)
2make wsh     # build the engine + CLI with the wsh debug supervisor

make wapps compiles each sample to a .wasm binary. make wsh builds build/cmd/wanted-cli with wsh as its boot supervisor.

Package a wapp into the registry

The engine starts wapps by name from a registry — on Linux, the ./registry/ directory scanned for <name>:<version>.wapp images. A .wapp is an OCI-style ustar TAR holding app.wasm (and any optional data files). The compiled samples are not packaged automatically, so package hello once:

1mkdir -p registry
2stage=$(mktemp -d)
3cp wapps/hello/hello.wasm "$stage/app.wasm"
4tar --format=ustar --owner=0 --group=0 --mtime='1970-01-01 00:00:00 UTC' \
5    -C "$stage" -cf registry/hello:0.0.1-1.wapp app.wasm
6rm -rf "$stage"

The registry filename is the image's identity: hello, version 0.0.1, package 1 → hello:0.0.1-1.wapp. The engine reads the name and version from the filename. The wasm binary is renamed to app.wasm inside the TAR — that is the fixed entrypoint name the loader expects.

app.wasm is the only required member. A wapp image can carry any additional files — config, certificates, static assets, data — and they become visible to the wapp as a read-only filesystem at /, served by TarFS. Add such files to the TAR alongside app.wasm and they appear at the matching path inside the wapp. (Small runtime knobs, like the hello sample's ROLE, are better passed as launch-config env vars or args than baked into the image — see Control Plane Reference.)

Image identity

The image's name and version come entirely from its registry filename <name>:<version>-<package>.wapp — for hello, that is name hello, version 0.0.1, package 1. The engine reports them at /proc/wapps and the per-instance version node. Capabilities are not declared in the image; they are exactly what the launch config grants at start (consoles, drivers, mounts, sockets, the control plane). One image can run as several independent instances — see Control Plane Reference.

Run

Boot the engine to an interactive wsh prompt:

1make wsh-shell

You land at the shell:

1Wsh v 0.5.0
2> 

wsh is itself a wapp: a privileged supervisor granted the wanted control-plane driver. Its commands drive /dev/wanted the same way a production supervisor does.

Launch your first wapp

List the running wapps. The supervisor is itself a wapp, so it appears in the list:

1> status
2supervisor      running

Launching a wapp is three deliberate steps — reserve the instance name, give it a JSON launch config, then issue the launch verb:

1> create hello
2> set_config hello {"console":{"in":{"name":"null"},"out":{"name":"log"},"err":{"name":"log"}}}
3> start hello
  • create hello reserves the instance namespace /dev/wanted/wapps/hello/. Its config, ctl, and read nodes exist only after this, and its state reads created.
  • set_config hello <json> buffers the launch config at wapps/hello/config, moving the instance to not_started. The config above gives the wapp a null stdin and routes its stdout/stderr to the per-wapp log console. A wapp's capabilities are exactly what this config grants — consoles, drivers, mounts, sockets, args, and envs (see the Control Plane Reference). Keep the JSON free of spaces: wsh splits a line on whitespace, so a compact object stays one token.
  • start hello writes the bare verb start to wapps/hello/ctl. The engine resolves the image (no image in the config, so the instance name hello → hello:0.0.1-1.wapp), loads it, and runs the wapp as its own thread. A start on a reservation with no config is rejected — the set_config must come first.

Check its state — it is running:

1> status hello
2hello:
3  state    running
4  version  0.0.1-1
5  id       1

The hello sample (launched with no ROLE set) writes an alive marker, lives for two seconds, then exits. A moment later its state is exited. Read its captured output from the log node the config wired up:

1> status hello
2hello:
3  state    exited
4  version  0.0.1-1
5  id       1
6> cat /dev/wanted/wapps/hello/log
7hello-wapp: alive
8hello-wapp: exit

A wapp that runs indefinitely is stopped explicitly — stop writes stop to that wapp's own control node /dev/wanted/wapps/<name>/ctl:

1> stop hello

Once a wapp has reached a terminal state, delete hello releases the name so it leaves wapps/. Richer launch configs — drivers, mounts, sockets, args, and environment variables — go in the same set_config JSON; the full console schema and every control-plane node are documented in the Control Plane Reference.

Next steps