ctos (ctsOS)
ctos is a small operating-system kernel you can study. It is written in Rust for 64-bit ARM (AArch64). You run it in the QEMU emulator, not as a desktop or phone OS. The nickname ctsOS is only for display; the repo and crate stay ctos. Why Rust (and what it does not buy): Advantages — Why Rust.
This book is the website. The same markdown lives under docs/ in the GitHub repo. There is no second marketing copy.
It is not a product site. Do not say “secure OS” or “production ready.” Say “EL0 isolated” only as the accepted ADR-091 sentence, with its limits (one core, TCG default smoke machine; not speculative-execution / side-channel, not real hardware, not a certification). Status words need a probe.
What it is
ctos boots under QEMU’s virt machine and prints on a serial port (the PL011 UART). After that it grows one honest mile at a time: exceptions, paging, a heap, a tiny scheduler, then measured security and performance cuts.
Core principles drive. Roadmap tracks (A = freestanding hosting, B = Linux-compat research, N = network foundation — N1 first-frame ADR-066, N2 ICMP ping ADR-067, N3 UDP ADR-070, N3.x EL0 UDP SVC ADR-071, N4 EL0 net sample ADR-068, N5 thin TCP ADR-074, scope ADR-063) are subordinate. A track does not outrank a principle.
Primary path: QEMU virt + UART (ADR-003). Frozen requirement IDs: FR-01–FR-15 and NFR-01–NFR-14.
Driving principles
Everyday meaning first; frozen IDs second. Same list as the pillars hub. This landing is the visitor-facing source. docs/framework/ stays for deep links — do not keep a second marketing copy.
| Principle | In everyday words | Frozen ID |
|---|---|---|
| Honesty | If we did not run a check, we do not say it works. Unprobed stays Unknown. | NFR-06 · ledger |
| Antifragility | The same miss twice becomes an automated sensor, not another README paragraph. | NFR-05 · Antifragility |
| Security | Write down what we fear, then prove a slice. Not a “secure OS” slogan. | NFR-10 · Security |
| Performance | Measure a known path first. No invented benches. | NFR-07 · Performance |
| Document-first | Write the decision, then the code. One milestone → one branch → one PR. | FR-14 / NFR-13 |
flowchart TD P["Core principles<br/>honesty · antifragility · security<br/>performance · document-first"] L["Three pillars<br/>antifragility · security · performance"] T["Tracks A / B / N<br/>hosting · Linux research · net first-frame<br/>subordinate — not the driver"] P --> L --> T
Principles sit above pillars. Tracks sit below both. A1–A4 are ABI + CRT + loader + standing-task miles only. Not a claim that Track A hosting is built.
What runs today
Rebuild recipes for samples that already have probes. Details: What can run today. In-tree index: user/README.md.
- Two kernel tasks that take turns — they print on the serial port and yield. Not preemptive. Not two CPUs.
- A serial echo gadget — one byte in, a line out. No terminal, no line editor.
- A short lower-privilege stub — a few instructions in the CPU’s user mode, including the A1 SVC ABI trip, an A2
libctoshello, an A3 guestPT_LOADof that same hello, and an A4 standing task untilexit(exit/uart_write/yield), then a call back into the kernel. Not a process. No libc. Freestanding catalog on FAT:/hello,/fsdemo(memfs VFS),/fatdemo(FAT/probe),/yldemo(yield rounds). Optional recipes: memfs named buffers and FAT16 on virtio-blk (read + write depth).
Cannot run: Linux programs, a shell, Python, network servers (Track N has virtio-net ARP + ICMP + minimal UDP + thin TCP plus tiny EL0 net/UDP SVC samples — ADR-066 / ADR-067 / ADR-070 / ADR-071 / ADR-068 / ADR-074; not BSD sockets / TCP product), POSIX filesystem apps, extra CPUs, or containers (guest OCI/Docker is a non-goal). An OS slot vs a separate app slot has an A9 first cut (FAT /hello) plus leftover cross-update on ba6541c (Verified miles); catalog also has /fsdemo / /fatdemo / /yldemo / /netdemo / /udpdemo. Product freestanding app hosting is Verified under ADR-048 / ADR-052 (not Linux/POSIX). Umbrella “EL0 isolated” is Verified only as the accepted ADR-091 sentence (M6, 2026-09-28; closure table ADR-060).
flowchart LR
subgraph today ["Verified today"]
W["Two UART workers"]
E["Serial echo gadget"]
S["Short user-mode stub"]
end
subgraph no ["Cannot run"]
L["Linux binaries / shell / Python"]
N["Network / files / extra CPUs"]
C["Containers"]
end
today -.-> no
Left side matches existing smoke markers. Right side is out of scope. Do not say “apps run.”
How to build
You need nightly Rust and QEMU. Pages is not required for kernel work. Full list: Prerequisites.
rustup toolchain install nightly
rustup component add rust-src llvm-tools-preview
cargo build # ELF at target/aarch64-ctos/debug/ctos
./scripts/qemu-smoke.sh # fail-closed serial + tests
flowchart LR R["rustup nightly"] --> B["cargo build"] --> Q["qemu-smoke"]
That rebuilds the kernel, including any in-tree code you add. It is not “port an app.”
Read next
| If you want… | Go here |
|---|---|
| What is in vs out (rebuild recipes) | What can run today · Drawbacks / limits |
| Why POSIX does not port | Building or porting |
| Files (memfs + FAT16) | Filesystem |
| App host / containers | Hosting apps — freestanding product claim Verified (ADR-048 / ADR-052); containers: non-goal (ADR-029). Linux-compat frame: ADR-031 (not userspace). |
| How we measure | KPIs |
| Why the repo is run this way · Why Rust | Advantages · Why Rust |
| Deep dives | Vision · FR / NFR · Architecture · Roadmap · Ledger |
Kernel build notes also live in the GitHub README.
URLs
| URL | Honesty |
|---|---|
https://ctos.artof.link | Verified. HTTPS 200, cert for this name, landing shows Driving principles. Main deploy 34653046584 after #30. |
https://artofdream.github.io/ctos | Redirect. This path (no trailing slash) 301s to the custom domain. A trailing slash 404’d on the 2026-09-11 probe — do not treat github.io as a second live tree. |
Publish mechanics: Docs website + DNS.