Important
Browser-native Linux terminals powered by x86 emulation. Full Alpine Linux virtual machines running entirely in your browser via WebAssembly. No servers, no installs, no accounts. Inter-VM networking, file transfer, state snapshots, and offline support. Just open and type.
Shallow water is where the bottom is still in reach. Felt fitting for a tab that loads a real Linux kernel without leaving your browser.
Each terminal is a complete Alpine Linux x86 virtual machine running in WebAssembly via v86. Not a shell emulator — a real kernel, real filesystem, real processes. BusyBox utilities and the APK package manager are included.
All terminals share a virtual ethernet switch on 10.0.0.0/24 with auto-assigned MACs and IPs, so VMs can ping, nc, and run server/client pairs against each other. Drag-and-drop drops files into /tmp/<filename>; sendfile pulls files back to your browser. After the first ISO boot (~30s), full VM state (memory + CPU) is snapshot-cached in IndexedDB for near-instant restore.
| KEY | VALUE |
|---|---|
| GUEST OS | Alpine Linux 3.20 virt (x86 32-bit) · BusyBox · APK |
| EMULATOR | v86 0.5.319 · x86-to-WASM |
| VMs | Up to 6 concurrent · 128 MB RAM each · ID pool recycling |
| NETWORK | Virtual ethernet switch · 10.0.0.0/24 · auto-assigned MACs and IPs |
| TRANSFER | Drag-drop upload (max 2 MB) · sendfile for download · serial port (ttyS0) |
| SNAPSHOTS | Full memory + CPU · IndexedDB · near-instant restore |
| OFFLINE | Service worker · cache-first · COOP/COEP injection |
| THEME | Catppuccin Mocha |
| STACK | Vanilla HTML/CSS/JS · no Node, no bundler, no package manager · MIT |
Architecture in §5 below.
git clone https://github.com/Real-Fruit-Snacks/Shallows.git
cd Shallows
python3 -m http.server 8000 # any static server worksOpen http://localhost:8000 in Chrome, Firefox, or Edge. Click New Terminal to boot an Alpine Linux VM.
If
SharedArrayBufferis unavailable, VMs still work but run slower. The included service worker injects the requiredCOOP/COEPheaders automatically.
Inside the VM:
apk add curl
uname -a
cat /etc/os-releaseBetween two VMs:
# Terminal 1 (10.0.0.1)
nc -l -p 8080
# Terminal 2 (10.0.0.2)
echo "hello" | nc 10.0.0.1 8080
ping 10.0.0.2CLIPBOARD
Ctrl+Shift+C Copy screen text
Ctrl+Shift+V Paste into VM
Copy / Paste buttons Topbar equivalents
FILE TRANSFER
Drag-drop onto terminal Upload — written to /tmp/<filename> (max 2 MB)
sendfile <path> Download file from VM to browser
NETWORKING
10.0.0.0/24 Auto-assigned VM addresses
ip a Inspect interface inside VM
nc -l -p <port> Listen
nc <ip> <port> Connect
ping <ip> ICMP between VMs
LIFECYCLE
New Terminal Spawn a fresh VM (boots from ISO first time, then snapshot)
Tab / Grid view Focused vs side-by-side layouts
Snapshot Persisted in IndexedDB after first successful boot
PRIVACY
No servers All computation happens locally in your browser
No accounts No authentication, no tracking, no analytics
No network calls After initial load, fully offline
Local-only state VM state in IndexedDB on your machine
PLATFORM
Chrome / Firefox / Edge Full support — VM boot, snapshots, networking, clipboard
Safari Limited — partial SharedArrayBuffer + clipboard
Shallows/
index.html Entry — topbar, tabs, viewport
sw.js Service worker — offline + COOP/COEP
css/style.css Catppuccin Mocha theme
js/
app.js Event wiring, clipboard, shortcuts
ui.js Tab/grid management, drag-and-drop
terminal-manager.js VM lifecycle, IndexedDB snapshots
virtual-network.js VirtualSwitch + FakeWebSocket
file-transfer.js Serial-based upload/download
libv86.js v86 x86 emulator (WASM loader)
v86.wasm v86 emulator core
assets/
bios/seabios.bin SeaBIOS firmware
bios/vgabios.bin VGA BIOS firmware
images/alpine-virt-3.20.3-x86.iso Alpine 3.20 (~47 MB)
| Layer | Implementation |
|---|---|
| Emulator | v86 0.5.319 · emulates x86 CPU in WebAssembly |
| Display | VGA canvas per VM · PS/2 keyboard for input |
| Network | In-memory VirtualSwitch broadcasts ethernet frames between FakeWebSocket adapters |
| Transfer | Serial port (ttyS0) with base64 marker protocol |
| Cache | IndexedDB snapshot of full VM memory + CPU |
| Offline | Service worker · cache-first strategy · injects COOP/COEP |
| Build | None — vanilla HTML/CSS/JS · static-host friendly |
Key patterns: All assets are self-contained — BIOS, WASM engine, Alpine ISO ship with the repo. No external scripts, no CDN dependencies at runtime. The included GitHub Actions workflow deploys on every push to main; enable Pages with Source: GitHub Actions.
| Problem | Solution |
|---|---|
| VM won't boot | Check console for WASM errors. Ensure js/v86.wasm and assets/ are accessible |
| Slow VM performance | SharedArrayBuffer may be unavailable — confirm sw.js is registered for COOP/COEP |
| Terminals can't ping | VMs auto-assigned unique MACs — check console for ip link set |
| File upload not working | Wait for VM to fully boot (loading overlay disappears) |
sendfile not found |
Command installed during auto-login; reinstall manually if boot was interrupted |
| Clipboard buttons fail | Browser requires HTTPS or localhost for clipboard API |
License: MIT · Part of Real-Fruit-Snacks — building offensive security tools, one wave at a time.