Monorepo for Aesthetic.Computer
aesthetic.computer
FedAC Native OS — Progress Report#
Last updated: 2026-03-12
What It Is#
Bare-metal Linux OS that boots from USB via UEFI as PID 1. Runs a QuickJS engine
executing .mjs pieces (interactive programs) with direct hardware access — DRM
display, ALSA audio, evdev input, WiFi, TTS, camera. No userspace, no systemd, no shell.
Current State: Fully Functional#
Boot & Runtime#
- Custom kernel (6.14.2) with embedded LZ4 initramfs
- Boot time: ~7.3s from power to piece running
- Per-user config:
config.jsonon EFI partition injects@handleinto boot splash (rainbow animated text), TTS greeting ("hi jeffrey"), and shutdown ("bye jeffrey") - Build naming: Each build gets a unique adjective-animal name (e.g., "keen-egret")
displayed in golden text on boot screen (top-right panel) and spoken via TTS
- Animal rotates daily (365 pool), adjective bumps every build (200 pool)
- Counter persisted in
.build-counter, auto-bumped by Makefile
- Auth-gated image generation:
GET /api/os-native?piece=notepatrequires handle - Piece navigation:
system.jump("prompt")hot-swaps pieces without reboot
Pieces#
- notepat.mjs (~7800 lines) — Full chromatic keyboard instrument
- 12-note grid, 6 octaves, 5 wave types (sine/tri/saw/square/noise)
- Echo (room reverb) slider, pitch shift slider, metronome
- Touch + keyboard + NuPhy analog pressure support
- Status bar: clock (LA time w/ DST), wave, octave, kHz, vol, brt, battery, WiFi
- HDMI secondary display output (blended note colors)
- prompt.mjs — Command-line piece with pink block cursor, history, escape→notepat
- os.mjs — System management & hardware info
- OTA update: check version, download, flash, verify, reboot (with animations)
- Flash target selector (tab to cycle USB/NVMe/etc.)
- Responsive layout: two-column on wide screens (>260px)
- System stats: model/vendor, CPU, RAM usage (text + graphical bar), battery
- Cores, process count, load average (1/5/15 min), CPU governor
- Connected devices list: USB, input/HID, cameras, audio, disks (with size/removable), display connectors (with connected status)
- claude.mjs — Claude AI chat client
- OAuth refresh token auth (via Claude Code subscription)
- Token provisioning: QR code scan (camera) or manual paste
- Camera preview: live V4L2 feed during QR scan with crosshair overlay
- Chat mode: word-wrapped conversation, scrollable history
- Commands:
/clear,/token,/scan
Camera (V4L2 + quirc)#
- UVC driver built into kernel (CONFIG_USB_VIDEO_CLASS)
- V4L2 capture: tries /dev/video0-3, YUYV format, 640x480
- Background scan thread: grabs frames at ~30fps, scans for QR codes
- Display buffer: mutex-protected grayscale copy for main thread rendering
system.cameraBlit(x, y, w, h): renders camera feed to framebuffer with nearest-neighbor scaling- quirc library (vendored v1.2) for QR code decoding
Audio#
- ALSA direct
hw:access, 192kHz (negotiated), 128-sample periods - 32 max voices with oldest-voice stealing
- Room reverb: 3-tap delay, 0.55 feedback, controllable wet mix
- Glitch mode: sample-hold + 6-bit bitcrush
- TTS via flite (male + female voices)
WiFi#
- Auto-connect: scan → pick strongest known SSID → connect (fully silent, no TTS)
- 5s timeout on failed connects, retry with next scan cycle
- Only connects to networks actually detected in scan (no blind attempts)
- WiFi panel: select-then-confirm interface (first tap selects, second connects)
- Panel doesn't disrupt active connections (no scan while connected)
- Deduplicated SSID list (strongest signal per network)
- Saved/preset networks shown below scan results with visual distinction
- Password entry mode for new encrypted networks
Chat (WebSocket)#
- Connects to
wss://chat-system.aesthetic.computer/after WiFi - Displays latest message in status bar with TTS
- Dedup: same message not re-TTS'd on WS reconnect cycles
- Silent reconnection (server sends history then closes, client auto-reconnects)
- Mute toggle (M key or tap)
OS Update System#
- Background auto-update: checks version on WiFi connect, silent download + flash + reboot
- Manual OS panel: responsive layout, connection-aware, version check with 10s timeout
- Release uploads to Digital Ocean Spaces (
upload-release.sh) - Progress bar for downloads, "do not power off" during flash
- Shutdown animation with scrolling telemetry
Hardware Info (system.hw)#
Exposed to JS pieces every frame:
model,vendor— DMI product/vendor stringscpu— model name from /proc/cpuinfocores— logical core countramTotalMB,ramAvailMB— from /proc/meminfoprocesses— count of running PIDsload1,load5,load15— from /proc/loadavggovernor— CPU frequency scaling governorbuildName— compile-time adjective-animal namedevices[]— array of detected peripherals:- USB devices (product name, vendor, bus ID)
- Input/HID devices (evdev name)
- Cameras (V4L2 device name)
- Audio cards (ALSA card name)
- Block devices (model, size in GB, removable flag)
- Display connectors (DRM name, connected status)
Controls#
- Volume & brightness: hardware keys (F1-F6) + mouse drag on status bar indicators
- JS bindings:
system.volumeAdjust(delta),system.brightnessAdjust(delta) - Echo/pitch sliders: touch drag or trackpad
- Trackpad FX mode (\ toggle): trackpad X→echo, Y→pitch
- Pixel scaling: Ctrl+= / Ctrl+- (wraps through 1-8x)
Fonts#
font_0: built-in 8x8 bitmapfont_1: 6x10 BDF (from system assets)font_matrix: MatrixChunky8 BDF
Key Files#
| File | Description |
|---|---|
src/ac-native.c |
Main loop, DRM init, boot splash, shutdown |
src/js-bindings.c |
QuickJS API surface, lifecycle calls, system bindings |
src/js-bindings.h |
ACRuntime struct (state for everything) |
src/audio.c |
ALSA engine, synthesis, reverb, glitch |
src/graph.c |
Software framebuffer (wipe/ink/box/line/circle/write) |
src/font.c |
BDF font renderers |
src/input.c |
evdev keyboard/mouse/touchpad, NuPhy hidraw analog |
src/wifi.c |
WiFi management (wpa_supplicant, dhclient) |
src/ws-client.c |
WebSocket client (TLS, background thread) |
src/udp-client.c |
UDP fairy point co-presence |
src/camera.c |
V4L2 capture, grayscale conversion, QR scanning |
src/camera.h |
ACCamera struct (V4L2 state, display buffer, scan results) |
src/tts.c |
Text-to-speech via flite |
src/drm-display.c |
KMS/DRM modesetting |
pieces/notepat.mjs |
Main instrument piece |
pieces/prompt.mjs |
Command-line navigation piece |
pieces/os.mjs |
OS update + system info piece |
pieces/claude.mjs |
Claude AI chat client piece |
lib/quirc/ |
Vendored quirc v1.2 QR decoder |
scripts/build-name.sh |
Unique build name generator (adjective-animal) |
scripts/build-and-flash.sh |
Full build pipeline (binary + initramfs + kernel) |
scripts/upload-release.sh |
Publish release to DO Spaces |
Makefile |
Binary build (auto-bumps build name) |
ac-os |
Single-command build/flash/upload tool |
Build & Flash#
# Full build + flash (ALWAYS use this — never just `make` alone):
cd fedac/native
./ac-os flash
# Build only (no flash):
./ac-os build
# Build + flash + upload OTA release:
./ac-os flash+upload
# Upload current build as OTA:
./ac-os upload
Important: Always use ./ac-os flash for the full pipeline. Running make alone
only compiles the binary but doesn't rebuild the initramfs or kernel. The kernel embeds
the initramfs, so a standalone make + separate flash results in stale code on the USB.
Known Issues / Next Steps#
- Audio tearing at high echo + many simultaneous voices (buffer underrun)
- No regulatory.db for WiFi (region defaults)
- i915 DMC firmware missing (cosmetic kernel warning, no functional impact)
console.logfrom JS writes to USB log ([js]prefix) — useful for debugging- NuPhy analog keyboard support compiled in but untested on current hardware
- Camera preview is grayscale only (YUYV Y-channel extraction)