DocsWebAssembly Guests

WebAssembly Guests

Plugins, effects and extensions can be WebAssembly artifacts instead of native executables. The core detects them by their binary header, runs them in a sandboxed wasmtime runtime and keeps the same JSON protocol, so configuration, listing, timeouts and install commands behave the same as with native guests.

Guest Shapes

ShapeTargetContractLanguages
Core modulewasm32-wasip1JSON request on stdin, JSON response on stdout, host calls through xfetch.host_callRust, C, C++, Zig, Go, AssemblyScript, ...
ComponentComponent modelExport run from the xfetch:runtime WIT world with typed host importsPython (componentize-py), JavaScript (componentize-js), Rust/C/Go (wit-bindgen), .NET, ...

Detection is content-based: the first eight bytes distinguish core modules from components. The file extension does not matter.

Installation

# From a local checkout (builds through the manifest when needed)
xfetch plugin install ./plugins/wasm-pacman
xfetch effects install ./effects/wasm-matrix
xfetch extension install ./extensions/wasm-night-mode

# Prebuilt artifact from a URL
xfetch plugin install https://example.com/releases/plugin.wasm

The installer places the artifact as xfetch-<kind>-<name>.wasm plus a sidecar manifest in ~/.config/xfetch/.

Manifest

Capabilities and limits are declared in a JSON manifest: a sidecar (<name>.json next to the artifact), an embedded xfetch:manifest section, or conservative defaults when absent.

{
  "manifest_version": 1,
  "name": "wasm-hello",
  "kind": "info_provider",
  "runtime": "core",
  "capabilities": {
    "http": { "allow": ["https://api.example.com/*"] },
    "exec": { "allow": ["pacman"], "env": ["PATH"] },
    "fs": [{ "host": "/proc", "guest": "/proc", "mode": "ro" }],
    "env": ["LANG"]
  },
  "limits": {
    "timeout_ms": 15000,
    "memory_mb": 64,
    "output_kb": 64,
    "host_call_kb": 256
  }
}

Source repositories use xfetch-plugin.json, xfetch-effect.json or xfetch-extension.json with the same schema; the installer copies it next to the artifact.

Capabilities

Capabilities are deny-by-default; empty or missing fields deny the operation.

CapabilityFieldSemantics
HTTPhttp.allowGlob patterns matched against the full URL. Redirects are re-checked on every hop.
Processesexec.allowProgram file-name patterns. No shell is involved and the environment is cleared except for allowlisted names.
FilesystemfsWASI preopens. Strings mount read-only at the expanded path; objects choose host, guest and mode (ro/rw).
EnvironmentenvVariable names exposed to the guest.
ArgumentsargsWhen true, the guest receives its name as argv[0].

log and version host operations are always available.

Limits

FieldDefaultMeaning
timeout_ms30000Wall-clock deadline; the config timeout_secs value overrides it.
memory_mb256Linear memory cap. Python and Go guests need headroom.
output_kb4096Cap for the JSON response.
host_call_kb4096Cap for a single host-call response.

Host Calls

Core modules call xfetch.host_call with a JSON operation; components use the typed fetch, exec, log and protocol-version imports. Rust core modules can use the xfetch-guest-api crate. See the full reference in the xfetch repository (docs/WASM.md).

Tooling

xfetch wasm inspect ./plugin.wasm                  # header, manifest, capabilities
xfetch wasm inspect ./plugin.wasm --json           # the same report as JSON
xfetch wasm run ./plugin.wasm --request '{"version":1,"kind":"info_provider"}'
xfetch wasm run ./plugin.wasm --request-file req.json --kind plugin --timeout 30
xfetch wasm wit                                    # component contract

wasm run accepts --request or --request-file, an optional --kind (plugin, effect or extension, default plugin) and a --timeout in seconds that overrides the manifest limit.

Logging

Guest log lines go to stderr; by default only warn and error are shown. Set XFETCH_WASM_LOG_LEVEL to off, error, warn, info or debug to change the threshold.

Security

Wasm guests start with no ambient authority: no filesystem, network, environment or process access unless the manifest grants it, and limits bound time, memory and output. Native plugins keep their full process privileges; choosing wasm is choosing the sandbox.

Examples

GuestLanguageShapeRepository
wasm-cryptoRustCore module, HTTPxfetch-cli/plugins
wasm-ip-geoPythonComponent, HTTPxfetch-cli/plugins
wasm-pacmanGoCore module, execxfetch-cli/plugins
wasm-procCCore module, filesystemxfetch-cli/plugins
wasm-matrixRustCore module effectxfetch-cli/effects
wasm-python-pulsePythonComponent effectxfetch-cli/effects
wasm-night-modeRustCore module extensionxfetch-cli/extensions
wasm-updates-footerGoCore module extensionxfetch-cli/extensions
wasm-lang-labelsPythonComponent extensionxfetch-cli/extensions

See docs/WASM.md in the xfetch repository and docs/wasm-guests.md in the api repository for the complete reference.