- C 90.2%
- Makefile 3.2%
- PowerShell 2.3%
- Shell 1.7%
- Python 1.3%
- Other 1.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
make iso recompiled the kernel and every command each time: iso and ramroot wiped build/kernel, build/lib and build/cmd to make sure nothing was compiled for the wrong RAMROOT setting. Only kernel/proc/proc.c and kernel/dev/ramdisk.c read RAMDISK_ROOT, so only their objects go now. Even then a no-op make iso took 69 s, because sysroot.stamp lists every staged file with its mtime and two things re-copied files on every run: the plain cp in etc-install (now cp -p) and fastfetch's install (now install -C). A changed stamp rebuilds the Alpine root, the root image and its zstd -19 compression. A no-op, and a one-file kernel change, now take about 9 s. write.sh read the stick back with a buffered cmp, slowly and possibly from the page cache. It now reads 4 MB at a time with iflag=direct, which checks the stick itself; --no-verify skips the check. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015f73FesGZGYPkmDvUcj6QX |
||
| .claude/memory | ||
| boot | ||
| cmd | ||
| docs | ||
| etc | ||
| include | ||
| kernel | ||
| ldls | ||
| lib | ||
| ports | ||
| projects | ||
| srv | ||
| tools | ||
| .gdbinit | ||
| .gitattributes | ||
| .gitignore | ||
| LICENSE | ||
| LICENSE.MIT | ||
| Makefile | ||
| NOTICE | ||
| README.md | ||
| run.ps1 | ||
| shell.nix | ||
| write.sh | ||
SchOS
A 64-bit operating system, written from the metal up.
SMP kernel · copy-on-write filesystem · Linux syscall ABI · Alpine packages · X11 on real hardware
SchOS began as xv6 and is now mostly something else. The scheduler, the memory manager and the trap path have been rewritten for x86-64 and for more than one processor; the filesystem has been replaced outright; the syscall table speaks Linux numbering, so real Linux software runs on it unmodified — statically or dynamically linked, straight out of Alpine's package repositories.
It is a hobby system built by one person, and it is honest about that: what works below has been run, not inferred, and the gaps are listed as plainly as the features.
In numbers
| First-party code | 61,367 lines, plus 21,128 lines of comments (26%) in 272 files |
Kernel (kernel/, include/) |
45,207 lines of code, 16,111 of comments |
| Syscalls | 208, of which 184 on Linux numbering |
| Drivers | 15 in the kernel |
| First-party programs | 29 in cmd/ |
| Alpine packages in the root | 88, from 11 asked for in ports/alpine/world |
| History | 253 commits since 2026-08-09 (76 days) |
Lines by language
| Language | Code | Comments |
|---|---|---|
| C | 56,580 | 19,427 |
| Assembly | 1,750 | 336 |
| PowerShell | 1,362 | 638 |
| Python | 759 | 147 |
| Shell | 716 | 469 |
| Perl | 129 | 45 |
| Linker script | 71 | 66 |
Measured by tools/python/stats.py; first-party code only, so
ports/ and generated tables are not counted.
The pieces
| Layer | Name | What it is |
|---|---|---|
| System | SchOS | The distribution — kernel, userland, tooling |
| Kernel | SchIFT | Multi-core x86-64 kernel with a modular VFS |
| Filesystem | SchFS | Transactional, copy-on-write, the root filesystem |
| Image format | SCFF | The SchOS Compressed File Format the live root ships in |
| API | SchAPI | System programming interface — the stable surface |
| Compositor | SchCom | Display compositor (planned) |
| Window manager | SchWM | (planned) |
| Desktop | SchDE | (planned) |
uname -s reports SchIFT, the way every Unix reports its kernel rather than
its distribution.
What works
Kernel — Long mode, 4-level paging, preemptive multitasking. SMP up to
64 processors, enumerated from the ACPI MADT. ACPI through
uACPI: interrupt routing from _PRT, the
power button, clean power-off and reset. Memory sized from the E820/UEFI map.
Filesystem — SchFS is the root: a copy-on-write B-tree with a
uberblock ring, so a crash leaves either the old tree or the new one and there
is nothing to repair. The live image ships as SCFF:
the 358 MB root compresses to 102 MB with zstd and is unpacked a chunk at a
time, the first time something reads it. /proc has /proc/<pid>/fd,
/proc/self and the rest that ps, top and Xorg read.
Processes — fork, exec, wait, pipes, signals, sessions and job control,
mmap (anonymous and file-backed), POSIX shared memory, memfd, Unix domain
sockets with descriptor passing (SCM_RIGHTS), poll, epoll, eventfd,
timerfd, signalfd. Dynamic linking: exec loads ld-musl, so
binaries come from Alpine as they are.
Packages — the root is managed by Alpine's apk. ports/alpine/world
says what is installed; the build resolves it once into world.lock and every
image after that is reproducible. SchOS itself is one more package in it.
Graphics — Xorg with Window Maker, preinstalled, on the framebuffer
(/dev/fb0, Linux fbdev). Six virtual terminals, switched with
Ctrl+Alt+F1–F6 or Alt+F1–F6, with X on a terminal of its own; Ctrl+Alt+Backspace
ends the session. Input as Linux evdev on /dev/input/event*.
Devices — PCI with a bus-agnostic device model at /proc/devices.
| Storage | AHCI (SATA), NVMe, IDE, USB mass storage |
| Network | Intel e1000, Realtek r8169 and RTL8139 |
| USB | xHCI, hubs, HID keyboards and mice |
| Input | PS/2, I2C-HID laptop touchpads (DesignWare I2C, found through ACPI) |
| Display | UEFI GOP framebuffer, virtio-gpu, Bochs/stdvga |
| Audio | AC'97 |
Networking — ARP, IPv4, ICMP, UDP, TCP and DHCP on lwIP. DNS, wget
over HTTPS, ping, and an httpd serving a directory back.
Userland — musl, toybox, mksh and zsh, plus whatever Alpine has: ls,
ps, top, awk, diff, xterm, fastfetch behave the way you expect,
because they are the real programs.
Text — a TrueType rasteriser (glyf outlines, composite glyphs, cmap
format 4). JetBrains Mono for the terminal, Roboto for the desktop to come.
When it dies — PSOGM, the Purple Screen of Guru Meditation: stop code, fault address, call chain, and a QR code containing a text copy of the whole report.
On real hardware — booted on an AMD B550 desktop (Ryzen 5 4600G), an ASUS TUF A15 laptop and an Ivy Bridge HP all-in-one, from a USB stick.
Quick start
make # kernel + UEFI loader + root filesystem
make qemu # build it and boot it
make iso # a bootable ISO for VMware or real hardware
The ISO is a hybrid image: write it to a USB stick with
dd if=schos.iso of=/dev/sdX bs=4M (or Rufus/Etcher in DD mode) and boot it
on any UEFI machine.
Builds on Linux, macOS, FreeBSD/OpenBSD/NetBSD and Windows (Git Bash). The toolchain is clang + lld everywhere — it is a cross-compiler by construction, so one LLVM install targets the bare-metal kernel, the 16-bit boot code and musl userland from any host. See docs/guides/building.md for prerequisites per platform, and docs/history/moving-to-linux.md for moving a checkout between machines.
Testing
Booting to a prompt proves nothing: a filesystem can mount and still fail the first real command, and that has happened here. So the test harness drives the serial console and asserts on what comes back.
tools/windows/bootcheck.ps1 # boot, run real commands, check the answers
tools/windows/bootcheck.ps1 -Tty -Ps # terminal behaviour, process enumeration
make schfs-check # SchFS B-tree, object and image suites
bootcheck is PowerShell because pwsh runs on every supported host.
The numbers at the top are measured, not typed: python3 tools/python/stats.py
rewrites them here and on the website.
Layout
kernel/ arch/ core/ dev/ drivers/ fs/ net/ proc/ sys/
fs/schfs/ the filesystem -- same source the host tools compile
include/ kernel and userland headers, by subsystem (arch/ core/ fs/ dev/ ...)
boot/ uefi/ (PE loader) common/ (shared loader UI)
lib/ cmd/ first-party userland runtime and programs
ports/ third-party software built from source
tools/ windows/ (.ps1) posix/ (.sh) python/ (.py) and .c/.pl
docs/ architecture/ (what it is) plan/ (what's next)
guides/ (how to work on it) history/ (why it's like this)
docs/README.md is the index. If you are reading the tree for the first time, docs/architecture/README.md is the system layer by layer.
One rule worth knowing: the kernel and the host tools compile the same SchFS
source. mkschfs cannot disagree with the kernel about the on-disk format,
because there is only one implementation — found and fixed on the host, where a
test takes a second instead of a boot.
Another: syscalls are declared in exactly one place,
kernel/sys/table.inc. Everything else is generated from it.
Not there yet
- No threads.
clonemakes processes, not threads (CLONE_VMis refused), so multi-threaded programs run on one thread or not at all. Xorg runs with-dumbSchedfor this reason. - No udev. Xorg is told its input devices by a config file instead of
finding them;
/sysand the device-event socket are what is missing. - USB 2.0 controllers (EHCI) have no driver. On older machines the ports wired only to EHCI do nothing; xHCI ports work.
- Touchpads run in mouse mode: pointer, click and tap, but no two-finger scroll yet.
- No page cache, so writable
MAP_SHAREDof a file is refused rather than faked. SysV shared memory is missing too. - No installer. SchOS runs live from the USB stick; nothing is written to the machine's disks.
- SchFS has no Linux driver yet; the plan is on-disk format version first, then FUSE, then a kernel module.
- CFF/OpenType outlines and TrueType hinting are deliberately out of scope.
Licensing
GPL-2.0-or-later, copyright Nexoniarz. See LICENSE.
The kernel derives from xv6, which is MIT — see LICENSE.MIT. Third-party code redistributed in a built image (musl, toybox, mksh, zsh, kilo, the fonts) keeps its own licence; NOTICE carries the attributions. See docs/licensing.md.
Drivers may be adapted from BSD sources and, since the move to the GPL, from Linux — GPL-2.0-only code combines with GPL-2.0-or-later, and the result ships under GPLv2. Best of all is still the public specification — xHCI, virtio, AHCI, e1000 — which carries no licence on what you write from it.