Launching vibeOS 2.0
Give your Codex an OS.
Codex — the agent you get when you log in with ChatGPT — normally lives in a chat box. vibeOS gives it a real operating system underneath: a screen, a kernel, windows, a folder on your disk. Then it writes the rest.
All of that runs in a browser tab. No Docker, no install, nothing to pull: vibeos.sh/app.
That sentence is doing a lot of work, so here is the whole stack, from the bottom.
An OS needs hardware. The browser is the hardware.
Every operating system starts the same way: something has to own the screen, the disk, the network, and the CPU. Normally that something is a machine. Here there isn't one, so the job is split in two.
The first half is a real x86 computer running inside the page. That's
v86, which JIT-compiles x86 instructions to WebAssembly. It
boots an actual Linux kernel — 4.16.13, i686 — with a virtual disk, a virtual NIC, and a
serial console. It is not a simulation of a shell. When you type uname -a you are talking
to a kernel that booted forty seconds ago in your browser.
The second half is the browser's own APIs. The File System Access API is the disk. WebSockets are the network card. Canvas is the framebuffer. IndexedDB is where the machine remembers which folder is yours. Between them, those two halves cover most of what a kernel is for.
A very small userland, on purpose
The image is Buildroot 2018.08 with BusyBox 1.28.4 — about 7 MB.
It boots fast and it is genuinely Linux, but it is deliberately spartan: there is no apt,
no apk, no package manager at all. w3m and git are not in there.
That is the image you get on load, because it boots in seconds. When you want more, the
menu bar has Install apt — which really means "boot Debian instead". A 1 GB Debian 12
disk is cut into 128 KB chunks and streamed from a CDN as the kernel touches them, so it is
a reboot rather than a download: about eighty seconds to a prompt, and then apt-get install works like it does anywhere else.
Measured on a real tab, over the relay described below:
apt-get update 9256 kB in 33s
apt-get install hello -> "Hello, world!"
The catch is that installs live in RAM. Reload and you are back to a clean Debian, because the streamed disk is read-only upstream — your files survive in the workspace folder, but packages do not.
Networking, which a tab is not supposed to have
Browsers expose no TCP. A page can make HTTP requests and open WebSockets and that is the entire list — so a VM in a tab normally has no internet at all.
vibeOS gets around this with a WISP relay: the guest's TCP streams are tunnelled over a single WebSocket to a server that opens the real sockets. That server is a function on vibeos.sh, so it is ours rather than a third party's, and it refuses loopback, private ranges, and anything off a small port whitelist — otherwise it would be a proxy pointed at our own infrastructure that anyone could drive.
The guest takes a DHCP lease and reaches the open internet. It also drops when the function hits its duration limit, and v86 can't redial, so the desktop notices, says so in the menu bar, and offers to restart the machine.
The part that is actually new
On top of that sits a deliberately minimal shell: a menu bar, windows, a dock, and one app called vibeOS. That app is an agent, and everything else is written on demand.
Ask for a window and it writes a JavaScript module, which becomes a blob URL and is
imported live. There is no bundler, no build server, no container rebuild — the constraint
that buys this is that generated apps are plain JS rather than JSX. Ask for something that
wants a shell instead and it writes a POSIX script, installs it into the VM at /mnt, and
runs it there.
So the agent writes code at both ends: the syscalls underneath and the interface on top. That is the actual claim of the project, and it is the part I care about.
Anything your browser can do, vibeOS can do — because the browser is the hardware layer. Cameras, USB, MIDI, serial, clipboard, gamepads: if the page can reach it, a generated app can reach it. That framing cuts both ways and I'd rather own the other edge too: the browser is also the ceiling. A tab cannot see your processes, run your binaries, or read files outside a folder you explicitly hand it. The desktop marks apps that need capabilities it doesn't have instead of letting them fail when you open them.
Your workspace is a folder on your disk
Pick a folder once and everything the agent builds is written into it as ordinary .js
files. Not IndexedDB, not a cloud account — a directory you can open in Finder, zip, or put
in git.
That choice is what makes leaving easy. Close the tab, come back next week, and it asks for that folder again and your apps are still there. The native build opens the same directory and finds the same files, so "download the binary" is a folder path rather than a migration. Files move both ways between the folder and the VM, on a diff you can see, and conflicts are never resolved for you.
The caveat: the real-folder part is Chromium-only. Firefox and Safari don't ship the File System Access API, and there is no sign they will.
Bring your own model
Log in with OpenAI, or paste an API key. It is stored in your browser and goes straight to the provider — it never touches vibeos.sh. Decline both and the desktop still works; the agent just falls back to stock modules, and says so rather than pretending.
What this is not
It is still an experiment. The browser build boots a real machine, installs real packages and writes real software — and it is also a proxied browser that runs no JavaScript, a network that drops on a timer, and a Debian whose installs vanish on reload.
The docker build is still the one with your actual shell and your actual files. This one is the front door: no install, a URL you can send someone, and a way to find out in thirty seconds whether any of this is real.
Which, given the last thing I wrote, feels like the right thing to have built.
The whole thing is MIT and the browser build lives in
web/.