A host-side FreeBSD-libc emulator for wasm32 programs.
Userspace, unchained.
Important
yos has been merged into yetty.
Development continues in the
yos/ subtree of the yetty repository;
this repository is an archive. Please file issues and pull requests
against zokrezyl/yetty.
yos runs unmodified wasm32 binaries — built against FreeBSD libc headers — on Linux, macOS / iOS / tvOS, FreeBSD, and Windows. The wasm guest only ever sees a FreeBSD-shaped userspace; yos translates each libc call into the host's native libc on the way through. One wasm binary, every platform, no kernel ABI dragged along for the ride.
yos was built for yetty — the terminal, unchained.
yetty is a GPU-accelerated terminal and
rich-content runtime: it renders plots, images, diagrams, documents, video, and
GUI panels inline with your terminal text. yos is what lets yetty carry a real
BSD userspace — an interactive shell, an editor, a box of tools — onto platforms
where a terminal normally can't spawn one. On iOS and tvOS, apps may not make
kernel calls or JIT native code; in the browser there is no process model at
all. yos sidesteps both: every program is wasm32, every libc call is a host-side
bridge, and the same zsh or nvim build drops into a yetty session on a phone,
a TV, or a browser tab exactly as it does on the desktop.
Try yetty:
curl -fsSL https://yetty.dev/install.sh | bash— see the yetty repo for Windows, docs, and the full rich-content story.
One wasm binary should run across desktop, mobile, and embedded without recompilation, and without the Linux kernel ABI baked in. Targeting FreeBSD libc — not WASI, not musl, not Linux — buys us:
- One ABI to compile against. The wasm binary embeds no host assumptions;
every libc call is a wasm import on
env.<name>. - A natural iOS / tvOS fit via libSystem, which shares FreeBSD libc's BSD heritage.
- Clean licensing. The stack is wasm3 (MIT) + mimalloc (MIT) + FreeBSD libc headers (BSD-2-Clause) + the host's own libc. yos itself is BSL.
The umbrella package (nix build .#all) ships the host yos runtime plus a
working wasm userspace built against FreeBSD libc:
- zsh 5.9 — interactive shell, scripting, pipes, command substitution, fork + exec.
- neovim 0.10.4 — full TUI, runtime tree, plugin loader.
- FreeBSD coreutils —
cat,echo,mkdir,ln,head,id,kill,realpath,test,touch,uniq,basename, and more run cleanly; a second batch (awk,grep,sed,sort,wc, …) builds and is being brought up.
Every tool lives as a bare wasm module in result/libexec/<name> that yos's
exec bridge loads directly. Per-tool runtime status — including the known gaps
and their root causes — is pinned by the test suite under
tests/integration/; a flipped xfail there is a real regression-net win.
nix build .#all # yos + zsh + nvim + tools
nix run .# # sandboxed wasm-zsh under yos, host PATH stripped
./tools/yos.sh # interactive zsh
./tools/yos.sh nvim file.txt # any wasm tool, passthrough args
./tools/yos.sh -c 'echo hi' # one-shot zshEvery libc function the guest imports goes through a 3-tier ladder; yos picks the lowest tier that yields FreeBSD-correct behaviour:
- Host-libc passthrough. A bridge translates wasm pointers, calls the host's
libc of the same name, returns. Covers most pure / stateless functions —
strlen,memcpy,read,sin,qsort, … - FreeBSD source compiled to wasm32. For functions whose host equivalent has
the wrong shape (variadic
printf, locale internals), yos compiles the FreeBSD libc source to wasm and dispatches to a sidecar wasm3 instance. - Hand-written. State-bound operations —
fork,execve,waitpid,pthread_create,mmap/brk, the fd table — live in C undersrc/yos/impl/.
Tier-1 bridges are autogenerated from the FreeBSD libc headers: libclang walks both the guest's FreeBSD-i386 headers and the host's, emits structured YAML deltas (widen / narrow / struct-convert / pointer-descent), and the generator emits one bridge per function. Adding a libc call is usually a header-only change.
wasm guest yos bridge backend
(FreeBSD libc, ──▶ yos_brg_<name>: ┌─▶ host libc
wasm32 imports pop wasm args, │ (glibc / libSystem /
on env.<name>) translate offsets, │ FreeBSD libc)
convert layout, remap ────┤
errno └─▶ yos subsystem
(mem / proc / pthread / vfs)
For the deeper "what's autogenerated, what's hand-written, why, and how the Nix packaging fits" picture, see docs/design.md.
The Nix flake is the canonical build interface:
nix build .#yos # host runtime
nix build .#sysroot # wasm32 sysroot
nix build .#toolchain # wasm-clang + wasm-ld + wasm-opt
nix build .#zsh .#nvim # individual wasm ports
nix build .#all # umbrella: yos + every wasm portWithout Nix (Linux dev):
meson setup build-linux && ninja -C build-linux
meson test -C build-linux # integration suiteOn Windows the host runtime builds with MSVC — no Nix, no MinGW:
build-tools\windows\build.bat
tools\yos.cmd path\to\guest.wasm| Path | Role |
|---|---|
src/yos/ |
host runtime — main.c, hand-written subsystems in impl/, codegen/ |
build-tools/ |
FreeBSD source, wasm toolchain shim, vendored wasm3 + mimalloc, per-package recipes |
nixpkgs/ |
Nix package tree — host runtime, sysroot, toolchain, per-tool derivations |
tests/integration/ |
end-to-end pty + scripted tests against real wasm guests |
tools/ |
convenience launchers (yos.sh, wasm-pkg.sh) |
flake.nix |
single source of truth for Nix outputs |
yos's host runtime builds cleanly on Linux, macOS, FreeBSD, and Windows (MSVC).
zsh, nvim, and the coreutils batch ship in the umbrella; remaining gaps are
tracked next to the xfail entries in the test suite. Next up: bash 5, FreeBSD
bin/sh, and the harder coreutils (ls, mv, cp).
BSL. See LICENSE.