Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Run the demo in five minutes

At the end of this you will have watched an agent connect over a real Unix socket, petition for a capability, capture a real application’s pixels, click into it, type into it, and prove the text landed — with the trusted core mediating every step.

Nothing here is mocked. cargo xtask demo fails loudly rather than substituting a stand-in.

What you need

Linux, and:

# Debian/Ubuntu
sudo apt-get install -y libxkbcommon-dev libpixman-1-dev weston xmlstarlet

# Arch
sudo pacman -S --needed libxkbcommon pixman weston meson

weston is there for weston-terminal, the real application the headless demo drives. The Rust toolchain pins itself — rust-toolchain.toml makes rustup install the right version on your first cargo command.

Build it

git clone https://github.com/vitrin-os/vitrin-os.git
cd vitrin-os

# The Rust side: vitrind, xtask, and the test fixtures.
cargo build --workspace

# The C side: the per-app wlroots shim. It lives outside the Cargo
# workspace by design and needs its own dependency step.
bash shim/ci/install-deps.sh
meson setup shim/build shim && meson compile -C shim/build

The shim is not optional. cargo xtask demo looks for it at shim/build/vitrin-shim (or wherever VITRIN_C_SHIM_BIN points) and stops with the exact meson command above if it is missing.

Run it

cargo xtask demo --headless

Expect output ending in xtask demo: PASS, plus paths to the run’s flight recorder (flight.jsonl) and its captured frames.

What just happened

cargo xtask demo --headless
   │
   ├─ boots vitrind --headless          the trusted core, software-rendered
   │    │
   │    ├─ fork/execs vitrin-shim       a real wlroots compositor, one per app,
   │    │     │                         with a scrubbed environment and its own
   │    │     │                         private runtime dir
   │    │     └─ fork/execs weston-terminal
   │    │           WAYLAND_DISPLAY points only at the shim's own socket, so
   │    │           the app's entire universe is that shim
   │    │
   │    └─ listens on a Unix socket for agent principals
   │
   └─ runs examples/agent-demo/run_demo.py
        connect → request_grant → await consent → settle → capture
        → click → type → capture → assert the typed text landed

The two captures are not compared naïvely. An earlier version of this gate asked only for 24 changed pixels between them, which weston-terminal’s own startup paint clears without any agent involvement — it passed whether or not the click and keystrokes reached anything. It now settles the app, watches it idle at least as long as it later polls, and demands a change shaped like a typed line: enough changed pixels and a densely inked run of them along one scanline.

That detail is in this getting-started page on purpose. It is the difference between a demo and a test.

Look at the evidence

The flight recorder journals every decision the core made:

# The path is printed at the end of the run.
jq -c 'select(.event | test("grant|consent|refus"))' /path/to/flight.jsonl

You will see the petition arrive, the consent decision resolve, and each actuation checked at the chokepoint — with the grant it was checked against.

The full integration suite

The demo is one test. To run every named milestone gate:

VITRIN_C_SHIM_BIN="$PWD/shim/build/vitrin-shim" bash tests/integration/run.sh

That drives the shipped vitrind binary against real applications — weston-terminal, a GTK entry probe, and Firefox ESR — over a real socket. tests/integration/README.md maps each test to the milestone it closes, and is explicit about which tests are component tests that close nothing.

Nested mode

Drop --headless and the core draws a real window on your own Wayland session, with Firefox ESR in the realm:

cargo xtask demo
# If your Firefox is not at firefox-esr:
VITRIN_DEMO_FIREFOX=/usr/bin/firefox cargo xtask demo

This needs a running compositor (GNOME, Hyprland, …) and a browser installed. It is never a CI dependency — nested mode has no headless equivalent by design.

Nested mode is also the only way to experience the two properties the headless run can only simulate: clicking Allow on a consent prompt the core drew itself, and physically holding Escape to watch a live grant die mid-actuation.

If it fails

SymptomCause
vitrin-shim not foundThe meson step above did not run, or VITRIN_C_SHIM_BIN points somewhere stale.
Hangs before any captureweston-terminal is not installed, so the realm has nothing to draw.
AuthFailed at connectThe demo identity is not in the principals.toml the core booted with.
Nested mode opens nothingNo Wayland session — check echo $WAYLAND_DISPLAY.

Still stuck? Open an issue with the flight.jsonl attached; it is usually the single most useful artifact.

Next: Your first agent.