SwiftOS Examples
These examples are complete, current workflows for the checked-in system. They are written as operator and developer recipes, not as future design notes.
Prerequisite for all guest examples:
make build base-image build/virt.dtb
make run
At boot, complete the interactive TTY smoke prompt, log in as root with
password swordfish, and run the guest commands shown below.
1. Confirm A Healthy Boot
Guest:
id
cat /etc/motd
ls -l /
ps
top -b -n 2 -d 1
Expected signals:
idshowsprincipal=1(root)andcaps=0x3f./etc/motdprints the welcome text./bin,/etc,/tmp, and/wwware visible.toprenders two frames and returns to the shell.
Verification:
./tests/boot_test.sh
./tests/top_test.sh
2. Use /tmp As Scratch Space
Guest:
mkdir /tmp/work
echo first >/tmp/work/log.txt
echo second >>/tmp/work/log.txt
cat /tmp/work/log.txt
wc /tmp/work/log.txt
chmod 600 /tmp/work/log.txt
chown 2 /tmp/work/log.txt
ls -l /tmp/work/log.txt
rm /tmp/work/log.txt
rmdir /tmp/work
This exercises tmpfs creation, append redirection, readback, metadata changes, and cleanup. The data is gone after reboot.
Verification:
./tests/swift_fileops_test.sh
3. Compare Account Capabilities
Guest:
id
exit
Log in as user / swordfish:
id
cat /etc/motd
echo ok >/tmp/user-write.txt
/bin/nslookup example.com
The filesystem commands should work; the network command should fail because
user does not have capNet.
Log in as guest / guest:
id
cat /etc/motd
The read should fail because guest has only spawn authority in the seeded
image.
Verification:
./tests/console_login_test.sh
./tests/cap_enforce_test.sh
4. Serve Static Files Over HTTP
Host:
make build base-image build/virt.dtb
qemu-system-aarch64 -M virt -cpu cortex-a72 -m 256M -nographic \
-global virtio-mmio.force-legacy=false \
-device loader,file=build/virt.dtb,addr=0x4FF00000,force-raw=on \
-drive file=build/base.img,format=raw,if=none,id=swosbase,readonly=on \
-device virtio-blk-device,drive=swosbase \
-netdev user,id=n0,hostfwd=tcp:127.0.0.1:8080-:8080 \
-device virtio-net-device,netdev=n0 \
-kernel build/kernel.elf
Guest:
/bin/httpd
Host:
curl http://127.0.0.1:8080/
curl http://127.0.0.1:8080/hello.txt
curl http://127.0.0.1:8080/sub/
curl -i http://127.0.0.1:8080/nope
Expected:
/returns/www/index.html./hello.txtreturns plain text./sub/returns a generated directory listing./nopereturns404.
Equivalent automated check:
./tests/httpd_test.sh
5. Run TCP Echo
Host boot command: use the network profile with TCP host forwarding:
hostfwd=tcp:127.0.0.1:5555-:5555
Guest:
/bin/tcpecho
Host:
printf 'hello tcp\n' | nc -w8 127.0.0.1 5555
Expected host output:
hello tcp
tcpecho exits after one accepted connection. Run it again for another
round-trip.
Equivalent automated check:
./tests/tcp_echo_test.sh
6. Run UDP Echo
Host boot command: use the network profile with UDP host forwarding:
hostfwd=udp:127.0.0.1:5555-:5555
Guest:
/bin/udpecho
Host:
printf 'hello udp' | nc -u -w2 127.0.0.1 5555
Expected host output:
hello udp
Equivalent automated check:
./tests/udp_echo_test.sh
7. Make A Guest-Initiated TCP Request
Boot QEMU with virtio-net attached. On the host, start a simple listener:
printf 'srv-reply\n' | nc -l 5555
Guest:
/bin/tcpget 10.0.2.2 5555
Expected guest output includes:
tcpget: connected
tcpget: got
srv-reply
10.0.2.2 is the QEMU slirp host alias.
Equivalent automated check:
./tests/tcp_connect_test.sh
8. Resolve DNS
Boot with virtio-net attached.
Guest:
/bin/nslookup example.com
With the default path, the resolver uses QEMU slirp DNS at 10.0.2.3. Test
fixtures may pass an explicit server and port.
Equivalent automated check:
./tests/dns_test.sh
9. Boot A Package Payload Overlay
Host:
make build base-image build/virt.dtb package-fixture
qemu-system-aarch64 -M virt -cpu cortex-a72 -m 256M -nographic -no-reboot \
-global virtio-mmio.force-legacy=false \
-device loader,file=build/virt.dtb,addr=0x4FF00000,force-raw=on \
-drive file=build/base.img,format=raw,if=none,id=swosbase,readonly=on \
-device virtio-blk-device,drive=swosbase \
-drive file=build/pkghello-payload.img,format=raw,if=none,id=swospkg0,readonly=on \
-device virtio-blk-device,drive=swospkg0 \
-kernel build/kernel.elf
Guest:
ls -l /usr/bin
/usr/bin/pkghello
Expected:
pkghello: hello from package overlay
Equivalent automated check:
make package-overlay-test
This is the direct read-only package overlay path. Local install and repository install use a writable package-store image instead.
10. Install A Package From A Signed Repository Fixture
Host:
make build base-image build/virt.dtb
make package-repo-fixture
make package-local-install-fixture
make package-repo-install-test
The automated test starts a host HTTP server, boots QEMU with virtio-net and a writable package-store image, then drives this guest flow:
pkg update http://10.0.2.2:<port>/good/aarch64/current
pkg search pkghello
pkg info pkghello
pkg install pkghello
/usr/bin/pkghello
Expected signals:
pkg updateaccepts the signedcatalog.signed.pkg search pkghelloandpkg info pkghelloshowpkghello-1.0.0_1.pkg install pkghellodownloads the content-addressed.swpkg, verifies its SHA-256, and activates the package-store generation./usr/bin/pkghelloprintspkghello: hello from package overlay.
Equivalent automated check:
make package-repo-install-test
11. Install Source-Built Packages From A Static-Host Fixture
The current ports fixture cross-builds Lua, zlib, bzip2, zstd, xz, libarchive, OpenSSL, pcre2, nginx, and sqlite, packages ca-certificates and tzdata, publishes them into one signed seed repository, copies that repository into a static-hostable web root, and proves that the guest can install from the hosted layout.
Host:
make ports-static-host-publish
make package-static-host-repo-install-test
make ports-hosted-url-verify-test
make package-static-host-dns-repo-install-test
The automated test serves build/ports-static-host-root, injects the default
repository URL into the base image, attaches a writable package-store image, and
drives this guest flow:
pkg update
pkg search lua
pkg search zlib
pkg search bzip2
pkg search zstd
pkg search xz
pkg search libarchive
pkg search ca-certificates
pkg search pcre2
pkg search tzdata
pkg search nginx
pkg search sqlite
pkg install lua
pkg install zlib
pkg install bzip2
pkg install zstd
pkg install xz
pkg install libarchive
pkg install ca-certificates
pkg install pcre2
pkg install tzdata
pkg install nginx
pkg install sqlite
/usr/bin/lua -e 'print(21 * 2)'
echo static-host-ok > /tmp/zlib.txt
/usr/bin/minigzip /tmp/zlib.txt
/usr/bin/minigzip -d /tmp/zlib.txt.gz
cat /tmp/zlib.txt
/usr/bin/bzip2 -V
cat /usr/share/bzip2/swiftos-bzip2.version
echo zstd-static-host-ok | /usr/bin/zstd -q -c | /usr/bin/zstd -q -d -c
cat /usr/share/zstd/swiftos-zstd.version
echo xz-static-host-ok | /usr/bin/xz -q -c | /usr/bin/xz -q -d -c
cat /usr/share/xz/swiftos-xz.version
/usr/bin/bsdtar --version
cd /tmp && echo libarchive-static-host-ok > libarchive.txt && /usr/bin/bsdtar -cf libarchive.tar libarchive.txt && /usr/bin/bsdtar -tf libarchive.tar
cat /usr/share/libarchive/swiftos-libarchive.version
cat /usr/share/certs/swiftos-ca-bundle.version
echo nginx-lighttpd > /tmp/pcre2.txt
/usr/bin/pcre2grep 'nginx|lighttpd' /tmp/pcre2.txt
cat /usr/share/zoneinfo/swiftos-tzdata.version
/usr/sbin/nginx -v
cat /usr/share/nginx/swiftos-nginx.version
/usr/bin/sqlite3 -batch -noheader -cmd '.mode list' :memory: 'select 6*7;'
cat /usr/share/sqlite/swiftos-sqlite.version
Expected signals:
pkg updateaccepts the static-hosted signed catalog.pkg search lua,pkg search zlib,pkg search bzip2,pkg search zstd,pkg search xz,pkg search libarchive,pkg search ca-certificates,pkg search pcre2, andpkg search sqlitefind the current seed packages.pkg install lua,pkg install zlib,pkg install bzip2,pkg install zstd,pkg install xz,pkg install libarchive,pkg install ca-certificates,pkg install pcre2,pkg install tzdata,pkg install nginx, andpkg install sqliteactivate all twelve packages.- Lua evaluates the expression and prints
42;minigzipround-trips/tmp/zlib.txtand printsstatic-host-okafter decompression; bzip2 round-tripsbzip2-static-host-ok; zstd and xz round-trip their marker strings;bsdtarcreates and lists a tiny archive; the CA marker printscurl-ca-bundle 2026-05-14 121 certificates;pcre2grepprintsnginx-lighttpd; tzdata, nginx, and SQLite print their package markers; SQLite prints42in list mode.
Equivalent automated check:
make package-static-host-repo-install-test
make package-static-host-dns-repo-install-test
12. Run Local Swift LLM Inference
Host:
make model
make base-image
make run
Guest:
/bin/llm
Shorter run:
/bin/llm "Once upon a time" 16
Expected output includes:
llm: stories260K
llm: generating
--- output ---
...
llm: done
Equivalent automated check:
./tests/llm_run_test.sh
13. Serve LLM Completions Over TCP
Host:
make model
make base-image
qemu-system-aarch64 -M virt -cpu cortex-a72 -m 256M -nographic \
-global virtio-mmio.force-legacy=false \
-device loader,file=build/virt.dtb,addr=0x4FF00000,force-raw=on \
-drive file=build/base.img,format=raw,if=none,id=swosbase,readonly=on \
-device virtio-blk-device,drive=swosbase \
-netdev user,id=n0,hostfwd=tcp:127.0.0.1:8080-:8080 \
-device virtio-net-device,netdev=n0 \
-kernel build/kernel.elf
Guest:
/bin/llmd
Host:
curl http://127.0.0.1:8080/health
curl -X POST --data "Once upon a time" http://127.0.0.1:8080/completion
curl http://127.0.0.1:8080/metrics
Expected signals:
/healthincludesok model dim=288for the default Q8_0stories15Mserving bundle./completionreturns generated story text from the quantized model./metricsincludesrequests,tokens_total,last_ttft_ms, andlast_tok_s.- The serial log includes
llmd: generation 2 rejected (model size/sha256 mismatch),llmd: bundle stories15M generation 1 verified (ed25519+sha256),llmd: model int8 Q8_0 GS=32, andllmd: served.
Equivalent automated check:
./tests/llm_serve_test.sh
14. Exercise The Swift REPL Tools
Guest:
calc
Inside calc:
2+3*4
x = 10
x*x
:sum
:mem
:q
Guest:
kv
Inside kv, use its prompt to set, list, and reduce in-memory values. Both
programs exercise Swift String, Array, Dictionary, ARC, and the userland
allocator.
Automated checks:
./tests/calc_test.sh
./tests/kv_test.sh
15. Validate UEFI Boot
Host:
make disk base-image
make disk-run
Automated checks:
UEFI_BOOT=disk ./tests/uefi_boot_test.sh
SMP_CPUS=4 UEFI_BOOT=disk ./tests/uefi_boot_test.sh
Use this path before claiming firmware, disk-image, or VirtualBox-related changes are healthy.
16. Run The Driver-Service Device-Metadata Smoke
Guest:
/bin/drvsvcdemo
Expected serial markers:
drvsvc: C5a supervisor starting
drvsvc: generation 1 ready
drvsvc: generation 1 event
drvsvc: generation 1 stopped
drvsvc: generation 2 ready
drvsvc: generation 2 event
drvsvc: C5c device manifest matched
drvsvc: C5d virtio-input metadata discovered
drvsvc: C5c discovery exhausted
drvsvc: C5b device grant claimed
drvsvc: C5c virtio-input grant matched
drvsvc: C5b device grant moved
drvinputd: C5b device grant accepted
drvinputd: C5c virtio-input grant accepted
drvsvc: C5b device busy while service owns grant
drvsvc: generation 2 stopped
drvsvc: C5b device grant reclaimed
drvsvc: C5c virtio-input grant reclaimed
C5a OK: restartable driver service recovered over IPC
C5b OK: opaque device handle transferred and released
C5c OK: virtio-input device grant discovered and matched
C5d OK: virtio input discovery metadata surfaced
C5e OK: device authority withheld until explicit handoff
This proves the current restartable service shape, virtio-input discovery
metadata, opaque device-grant transfer, and withheld hardware authority. It is
still metadata-only authority: C5e does not hand MMIO, IRQ, DMA, or real
virtio-input queue ownership to userland. A broad headless boot without a QEMU
keyboard device exercises the same lifecycle through the pseudo-input.0
fallback and emits
C5c OK: device discovery manifest matched pseudo input.
Equivalent automated check:
make c5-device-authority-test
The automated gate boots with -smp 4, attaches a QEMU virtio keyboard, and
checks the same serial markers.
make c5-device-discovery-test and make c5-device-handle-test remain
compatible aliases.
17. Run The Full Gate
Host:
make test
The full gate builds the kernel, base image, package fixture, model artifacts,
host-side unit tests, and many QEMU acceptance tests. For day-to-day work, run a
targeted test first, then make test before merging a milestone.
Verification:
make test