emu86

A 1980s PC written in TypeScript, booting a real Unix in your browser tab — a machine that keeps its own state, where duplicating the tab plugs a second machine into the network, and one tab can telnet into the other.

← back to the machine

What this is

emu86 is an Intel 8086 PC emulator written in plain TypeScript — no WebAssembly, no native code, no runtime dependencies beyond the language itself. It boots unmodified ELKS (the Embeddable Linux Kernel Subset, a real Unix for 16-bit machines) from real disk images: BIOS, interrupt controller, timer, UART, keyboard, IDE disks, and an NE2000 network card, all modeled honestly enough that the stock kernel probes them and finds them.

It exists to answer a question for a different project: a browser code editor needed an 8086 emulator, and the choice was pure TypeScript versus C compiled to WASM. This is the pure-TypeScript arm of that bet — the wager being that readable source is worth more than raw speed, and that the speed would turn out to be enough. The project's stated principle from day one: understandable first, fast second. (The verdict, measured: on genuine kernel workloads it sustains about half of a 4.77 MHz cycle budget under the strictest accounting there is — one instruction per cycle, a standard no real 8086 ever met. A real XT spent four to twelve cycles per instruction, so in instructions actually delivered this is several XTs — which is why the machine ships with an authenticity governor, not a speed boost: uncapped, Tetris is unplayably fast. Speed was never the problem.)

1,342tests in the always-on suite (plus the SingleStepTests 8088 corpus as the opcode oracle)
59phase reports — the project's real memory, negative results included
~4 monthsMarch to July 2026, three machines, one consolidation
0lines of WASM, C, or hand-written assembly in the emulator

The timeline

MARCH 23, 2026

First life, inside the editor project itself: a 23-file emulator core validated bit-for-bit against Adrian Cable's 8086tiny, running both side by side in a C co-simulation harness and diffing every register after every instruction.

APRIL 27–29

The standalone repository. Three days, seven commits: from a six-opcode proof-of-concept to CGA text, a keyboard, a serial console, and a browser harness. Then the repo went quiet — the work didn't. The following phases were driven from, among other things, a folding phone.

SPRING → SUMMER

Phase by phase, brief by brief: interrupt delivery, the PIT and PIC, ELKS boot diagnosis (early printk, root mount), hard-disk images, MBR partitions, multi-disk, a MINIX-filesystem image with a complete on-disk C toolchain. Each phase ends with a written report that records what worked and what didn't — the abandoned approaches are documented as carefully as the shipped ones. Twenty-nine briefs, and the test count climbing the whole way.

JULY 13

Consolidation day: three machines' checkouts verified identical, folded into one, audited top to bottom. Then Phase 14 opened — the dogfooding arc — with a hello-world compiled and run inside the emulated machine, using the C compiler that lives on the guest's own disk, and the resulting binary extracted back out byte-exact, checksummed on both sides of reality.

JULY 13–14

The network grew up in one long arc: an NE2000 card the stock kernel detects; a virtual ethernet switch; a gateway that answers ARP and ping; and then the TAN — the Tab Area Network — where every browser tab's machine joins one LAN over a BroadcastChannel trunk, leases itself an IP, and telnet 10.0.2.x logs you from one tab's Unix into another's. Duplicating the tab became the fastest PC purchase in history. DNS followed — with a surprise (see below) — then real answers via DNS-over-HTTPS pass-through.

JULY 14–15

The site you're on went live. Boot scripts that type themselves at the right prompts. Sticky per-tab IP addresses. And two fixes a real 1981 machine would be proud of: a pacing overhaul so that guest time is wall time — one guest second is one real second, idle or busy, capped at an authentic 4.77 MHz with a Turbo switch — and an MC146818 real-time clock chip, after which the machine stopped believing it was October 21, 1991.

JULY 15–16

The machine grew a memory, and then it grew manners. A block-level copy-on-write overlay made the boot disk durable — what the guest writes, reloads keep, keyed to the base image by SHA-256 so a wrong overlay is refused rather than folded. Every tab got its own private /dev/hdb that survives with it, an editor drawer over that drive (read and written through the project's own MINIX filesystem module), and finally the un-typed boot: a fresh machine formats its own home drive, seeds it, logs itself in, and performs its first-boot show — writing and compiling a C program with its own toolchain — exactly once per drive, with nothing typed, ever. One long day of field-testing later, the whole line was promoted; the previous version is archived one click away, as every outgoing version now is.

Things learned the hard way

How it's built

The source is on GitHub, MIT-licensed — the 59 phase reports and 34 briefs included, which means the abandoned approaches and wire-level debugging sagas described above are all readable in full.

This project is a long-running collaboration between one human and Claude (Anthropic's model — earlier phases planned by chat, current work done end-to-end in Claude Code sessions). The working discipline predates the tools being fashionable: every phase starts with a written brief agreed before implementation, and ends with a written report — findings, decisions, measurements, and explicitly what was not done. The reports are the project's memory; the code alone doesn't carry the reasoning. Nothing lands without the full test suite green, and the CPU core answers to an external oracle: the SingleStepTests 8088 corpus, thousands of single-instruction cases with exact expected machine state.

The hard rules have never moved: the CPU step stays purely synchronous, strict TypeScript stays strict, no new dependencies, and negative results are findings to publish, not failures to hide.

Try it

Honest limits

Family

emu86 is the youngest of three siblings, and the family has a plot: all three are ways of putting a 1981 PC somewhere it has no business being.

Same human throughout; different collaborators per era; one shared conviction — that the machines of 1981 are still worth understanding, and the proof is rebuilding them somewhere impossible.

And now there is a PC in your browser tab. It boots a real Unix and logs itself in, joins a network that exists only between your own tabs, resolves real names through a resolver its kernel is too old to imagine, keeps honest time from a clock chip it never shipped with, remembers what you did to it yesterday, and lets you telnet into its twin — a computer created, in full working order, by pressing "Duplicate Tab."