# Compiler Toolchain

> **NOTE:** These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed.

The commands a guest runs through [process execution](/agentos/docs/processes), the shell
(`sh`) and the coreutils behind it, are not native host binaries. They are
WebAssembly modules compiled ahead of time and mounted into the VM. This page
covers how that command suite is produced: which toolchains compile it, what it
links against, and how the resulting `.wasm` files become the guest's commands.

For *why* WASM is a first-class guest and *how* it presents a POSIX surface at
runtime, see the [WASM VM](/agentos/docs/architecture/posix-syscalls) page. This page is the build-side
counterpart: it documents the toolchain that emits binaries carrying both
[the host-import layer and the WASI shim](/agentos/docs/architecture/posix-syscalls).

## Target: `wasm32-wasip1`

Everything in the command suite is compiled to a single target,
`wasm32-wasip1`: the WASI preview 1 ABI on the 32-bit WebAssembly architecture.
Picking one target for the whole suite means a single libc, a single set of
host import declarations, and a single runtime shim can serve every command.

A guest module built for this target expects standard WASI (preopened file
descriptors, clocks, randomness, file I/O) plus the extra agentOS import modules
described below. Both halves are satisfied at runtime by the kernel-backed
runtime; nothing in a compiled command reaches a real host syscall.

## Two source languages, two compilers

The suite is heterogeneous: most tools are Rust, some are C. Each language uses
its own compiler driver, but both emit the same `wasm32-wasip1` ABI and link
against the same sysroot, so the outputs are interchangeable at runtime.

- **Rust coreutils** are built with **`cargo`** targeting `wasm32-wasip1`. Rust's
  standard library already has first-class support for this target, so the
  coreutils crates compile with an ordinary cross-compile invocation.
- **C programs** are built with the **`wasi-sdk`** toolchain, a packaged
  `clang` plus sysroot tuned for WASI. C tools that have no Rust equivalent (or
  that are easier to carry as upstream C) go through this path.

```bash
# Rust coreutils
cargo build --target wasm32-wasip1 --release

# C programs via wasi-sdk, linked against the patched libc + wasi-ext
$WASI_SDK/bin/clang --target=wasm32-wasip1 \
  --sysroot=$WASI_SYSROOT \
  -lwasi-ext \
  tool.c -o tool.wasm
```

## What every binary links against

Regardless of source language, each command links against the same two pieces.
Together they give a single binary both the standard WASI calls and the agentOS
process / user / network extensions.

- **A patched `wasi-libc`.** The libc is the WASI standard library, modified so
  that the calls a normal command-line program performs resolve against the
  agentOS surface instead of failing or hitting unimplemented stubs. This is the
  same patched libc the [Layer 2 shim](/agentos/docs/architecture/posix-syscalls) adapts at runtime; the
  build side and the runtime side are two ends of the same contract.
- **The `wasi-ext` bindings.** These declare the extra WebAssembly import
  modules (`host_process`, `host_user`, `host_net`, and the small
  `host_sleep_ms` binding) that base WASI cannot express. Linking `wasi-ext`
  into a binary is what lets its libc emit `fork` / `exec`, `getuid` / `getgid`,
  and `connect` / `listen` as ordinary-looking syscalls that the host runtime
  then services through the kernel. See
  [Layer 1: custom host import modules](/agentos/docs/architecture/posix-syscalls) for the runtime half.

> **NOTE:** The import declarations are compile-time only: linking `wasi-ext` tells the module *which* host imports to reference, but the calls are still routed through the kernel and gated by the VM's [permission policy](/agentos/docs/permissions) at runtime. Building against `host_net` does not grant network access.

## From `.wasm` to a guest command

The compiler toolchain's product is a set of `.wasm` files, one per command.
Those files are what the runtime mounts as the guest's executables: when a guest
invokes `ls`, `sh`, or any other bundled tool, the kernel resolves the name to
the corresponding module, instantiates it with the host imports and the WASI
shim wired in, and runs it as a [child process](/agentos/docs/processes) with real
process, user, and network semantics, all virtualized.

The same path is open to your own programs. A program you compile for
`wasm32-wasip1` runs as a guest command exactly like the bundled ones; link the
`wasi-ext` bindings if it needs processes, users, or sockets, and leave them out
for a pure-compute tool. Heavy native binaries that are not yet available as
WASM belong in an [external sandbox](/agentos/docs/sandboxes) instead.

## Recommendations

- Use the bundled WASM coreutils and `sh` for normal shell workloads; they
  already carry the patched libc and the `wasi-ext` extensions.
- To ship your own command, compile it for `wasm32-wasip1` with `cargo` (Rust)
  or the `wasi-sdk` `clang` (C), and link `wasi-ext` only if it needs the
  process / user / network host imports.
- Keep the build and runtime contracts aligned: the patched `wasi-libc` and the
  `wasi-ext` import declarations a binary is compiled against are the same ones
  the [WASM VM](/agentos/docs/architecture/posix-syscalls) runtime expects to satisfy.
