Skip to content

Run a WASI command ​

Using plugins gets a Preview 1 hello-world running. Here you will build your own command, pass it arguments, and choose which host resources it can see.

You need a standard Wago runtime, Go 1.22 or newer, and a project directory with wago.json.

Choose the preview ​

Add the provider that matches the guest:

  • Preview 1 imports the core module wasi_snapshot_preview1. Use wago add wago-org/wasi/p1 and wago run.
  • Preview 2 uses component interfaces such as wasi:cli/run. Use the typed command service described in Component Model.

The root wago-org/wasi bundles both previews. An interactive root install offers a provider choice; a non-interactive root install selects everything. Preview 1 alone does not activate the Component Model provider.

WASI and Component Model support are experimental. Preview 1 supports Wago's six desktop OS/architecture pairs. Preview 2 currently excludes darwin/amd64; check the provider's platform declaration before choosing a deployment target.

Build a small command ​

Save this as main.go in your project:

go
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    fmt.Println("args:", strings.Join(os.Args[1:], ", "))
    fmt.Println("greeting:", os.Getenv("GREETING"))
}

Build it for WASI Preview 1:

sh
GOOS=wasip1 GOARCH=wasm go build -o command.wasm main.go
powershell
$env:GOOS = 'wasip1'
$env:GOARCH = 'wasm'
go build -o command.wasm main.go
Remove-Item Env:GOOS, Env:GOARCH

The environment overrides apply to the guest build. Clear them before Wago builds native plugins.

If this is a new directory, initialize it and install Preview 1:

sh
wago init --run
wago add wago-org/wasi/p1

Review the source and four requested Authorities: defining imports in exactly wasi_snapshot_preview1, identifying callers, reading guest arguments, and observing instance close. These grants let the plugin integrate with Wago. The plugin still runs as native Go code.

Pass arguments ​

Inspect the imports, then run the command:

sh
wago module imports command.wasm
wago run command.wasm alpha beta

Expected output:

text
args: alpha, beta
greeting:

The file path is argv[0]; the trailing values become the remaining guest arguments. To pass a guest argument that looks like a Wago flag, use --:

sh
wago run command.wasm -- --help

The guest prints args: --help. Core exports with parameters still use Wago's typed invocation rules; this example runs a no-argument _start command.

Choose environment values ​

WASI starts with an empty guest environment. It does not inherit the host process environment.

Save wasi-config.json:

json
{
  "env": ["GREETING=hello from Wago"]
}

Apply it and run again:

sh
wago plugin config github.com/wago-org/wasi/p1 --file wasi-config.json
wago run command.wasm alpha beta

Expected output:

text
args: alpha, beta
greeting: hello from Wago

Configuration is a complete replacement. Include every setting you want to keep when changing the JSON. Commit the reviewed lockfile, but do not put secrets in a committed env value.

Check startup after a configuration change

The command rebuilds the runtime, but provider-specific validation happens when the plugin loads. Run a small guest after changing settings. If it fails, restore the last working JSON with wago plugin config ... --file.

Running wago plugin config <id> without a JSON value or file sets {}. It does not prompt for configuration.

Choose streams ​

By default, stdin, stdout, and stderr are attached to the host process. Pipe input and redirect output in the shell as usual.

For a guest that must not wait for input, add "stdin": "eof" to its configuration. To suppress an output stream, use "stdout": "discard" or "stderr": "discard". Keep output inherited while debugging so you can see the guest's diagnostics.

Grant a directory ​

There are no filesystem mounts by default. For a guest that reads /data, create a host directory and add a rights-bearing mount to the configuration. Replace the host path with your directory's clean absolute path:

json
{
  "env": ["GREETING=hello from Wago"],
  "mounts": [
    {
      "guest": "/data",
      "host": "/absolute/path/to/guest-data",
      "read": true
    }
  ],
  "maxOpenFiles": 256
}

On Windows, use a native absolute host path such as C:\\guest-data in JSON. The guest path remains /data.

  • read permits reads and metadata beneath the mounted directory.
  • write permits file writes and related metadata changes.
  • mutateDirectory permits creating, removing, and renaming directory entries.

No rights are implied by the other fields. Add write or directory-mutation access only when the guest needs it. Host paths must exist and name directories. The guest cannot escape the mounted directory through path traversal or a symlink. Whether a safe internal symlink or .. path is accepted depends on the preview and host filesystem implementation.

A guest may request more WASI descriptor rights than its high-level operation suggests. In the walkthrough, Go 1.27's os.ReadFile requested rights beyond a read-only mount and received Capabilities insufficient. Diagnose the requested rights before widening access; a read-only task should keep a read-only grant. See WASI access failures.

Keep the runtime reproducible ​

sh
wago plugin tree
wago plugin inspect github.com/wago-org/wasi/p1
wago plugin rebuild --locked
wago run command.wasm alpha beta

Commit wago.json and wago-lock.json. The lockfile records the exact provider, configuration, and reviewed Authorities.

Preview 1 commands can also be compiled into a standalone executable. For Preview 2 components or custom WIT exports, continue with Component Model.

Released under the Apache 2.0 License.