braamix/core

Browser Runtime As A Machine

4

stars

212

commits

C++

primary language

Sep 6, 2026

updated

README

BRAAM - Browser Runtime As A Machine

An operating system that runs in a browser tab.

Launch Braam

braamix.github.io — a whole system in under a megabyte, and it is running before you have finished reading this line. Nothing to install, nobody to sign up with, no server anywhere: the page downloads a kernel and gives you a prompt. Your files stay in the browser and are still there tomorrow. It works on a phone.

Braam is a small command-line system: a kernel, a filesystem, a terminal, a shell, forty-five programs and a package manager. It is written from scratch in C++20 and compiled to WebAssembly, which browsers run at close to native speed. There is no server side. The whole system is a few static files, so any web host can serve it.

Nothing is borrowed — no C library, no Emscripten, no xterm.js. Every program is a separate WebAssembly file running in a sandbox of its own, and none of them lives inside the kernel.

Open the page and there is a prompt:

$ ls /bin                            # every program, one wasm file each
$ echo hello > notes                 # your files survive a reload
$ curl https://example.com | less    # a download, into a pager
$ edit notes                         # ^S saves, ^Q quits
$ spin &                             # a program that loops forever
$ kill %1                            # killed anyway

It is not a Unix clone: no POSIX layer, no fork, no VT100 escape codes, and no attempt to run C programs written for other systems. Giving that up makes the system far smaller and lets every part use what the browser already provides.

Three ideas

Programs pause instead of blocking. Anything that would wait pauses, and the browser continues it when the answer arrives. So there are no threads.

The screen is a grid of cells, not a stream of bytes. A colour is a field in a cell and moving the cursor is indexing an array, so there is nothing to parse.

JavaScript never hands data straight back. Answers arrive later through one callback, which keeps the boundary small enough to check by eye.

What is in it

A shell. A Bourne shell after v7: variables, functions, if, loops, case, globbing, command substitution, pipes, redirection, background jobs, and line editing with history. ^C stops whatever is running and gives the prompt back. doc/Shell.md is the manual.

A filesystem. Everything lives in the browser's private storage and survives a reload; /tmp is emptied at boot. /bin and /etc come from an archive downloaded with the kernel, and are replaced whenever a new version is opened. /proc shows what is running, and /dev has null, zero, random and urandom. Where the browser will not store files at all, the system says so and stops.

Access to the browser. curl fetches a URL, chat talks over a WebSocket, fimport and fexport move files in and out, and pbcopy and pbpaste reach the clipboard.

Full-screen programs. less and edit draw into a grid of their own and send only the part that changed. ^C still reaches them.

A usage block in every program. -h asks one what it takes, and asking is not a mistake: the block goes to the screen and the status is 0.

Isolated processes. Each command runs in a worker of its own, with its own memory and its own open files. One stuck in a loop is killed outright, without having to cooperate — spin exists to show that. The shell is one of these programs, not part of the kernel.

A package manager. pkg installs software that did not ship with the system. A repository is just files on a web server: an index and one zip per package. The index is signed, and the keys it is checked against ship inside the archive. An install is committed by renaming a single symbolic link, so a tab that dies partway has installed nothing. The system ships pointed at the public repository https://braamix.github.io, and doc/Package_Formats.md §10 explains running one of your own.

An embedding API. web/braam.js puts a terminal on any web page with mount({ canvas }). web/embed.html is a working example, and web/dual.html splits a window between two screens of one kernel — mount({ screens: [ … ] }), a shell and a ^C of its own on each, over one filesystem. web/quad.html is the same in a 2×2 of four, which is as many terminals as there can be.

Building

You need a clang that can target wasm32, plus CMake, make and Node. On macOS that is brew install llvm lld; on Debian or Ubuntu, apt install clang lld llvm.

make            # build the kernel, the programs and the tests
make run        # run the tests
make serve      # serve the site and open it in a browser
make install    # install the SDK, to /usr/local or ~/.local
make release    # pack the site and the SDK as build/*.zip
make clean

The build leaves a complete website in build/web/. It needs no server program and no special headers, so copying that directory to a web host is a deployment.

Writing a program

Every command is a wasm file, and building one needs nothing private to this repository — make install puts an SDK under /usr/local or ~/.local.

#include "proc/file.h"

Task<i32> proc_main(Args)
{
    co_await write_out("Hello, world!\n");
    co_return 0;
}

write_out is the buffered stream File::stdout(), flushed when the program exits.

find_package(braam REQUIRED)
braam_add_program(NAME hello SOURCES hello.cpp)

A program does not have to be part of the system to run: bring the file in with the browser's file picker and run /import/hello.wasm, or curl it into /home and run it there. doc/Programming_Manual.md is the guide and examples/hello/ is the worked example.

Layout

DirectoryWhat is in it
src/kernel/coroutines, allocator, scheduler, screen, the JavaScript boundary
src/fs/paths, the mount table, the filesystem over browser storage
src/svc/URLs, WebSockets, clipboard, file transfer, clock
src/ui/the layout layer over the grid of cells
src/user/starting programs, system calls, the console, pipes, /proc, boot
src/proc/the runtime every program carries
src/cmd/one file per program; sh/ and pkg/ have directories
web/the page, the workers, the renderer, the browser side of everything
rootfs/what the boot archive carries
tools/the build's scripts, and the ones a package publisher signs with
test/the tests, and a simulated browser to run them against
doc/the specification, the manuals and the release notes

Documentation

Status

Version 0.7. Everything above works and the tests pass. A tablet works too: tap to type, drag to select, with a row of buttons for the keys a touch keyboard does not have.

Some things are missing on purpose. There is no bg and no ^Z yet. Lines are not re-wrapped when the window is resized. One program has the screen at a time. There are no file permissions and no CPU limits — a program can be killed, but not slowed down.

License

MIT. See LICENSE.

Contributors

sergev

212 commits

braamix/core

Browser Runtime As A Machine

4

stars

212

commits

C++

primary language

Sep 6, 2026

updated

README

BRAAM - Browser Runtime As A Machine

An operating system that runs in a browser tab.

Launch Braam

braamix.github.io — a whole system in under a megabyte, and it is running before you have finished reading this line. Nothing to install, nobody to sign up with, no server anywhere: the page downloads a kernel and gives you a prompt. Your files stay in the browser and are still there tomorrow. It works on a phone.

Braam is a small command-line system: a kernel, a filesystem, a terminal, a shell, forty-five programs and a package manager. It is written from scratch in C++20 and compiled to WebAssembly, which browsers run at close to native speed. There is no server side. The whole system is a few static files, so any web host can serve it.

Nothing is borrowed — no C library, no Emscripten, no xterm.js. Every program is a separate WebAssembly file running in a sandbox of its own, and none of them lives inside the kernel.

Open the page and there is a prompt:

$ ls /bin                            # every program, one wasm file each
$ echo hello > notes                 # your files survive a reload
$ curl https://example.com | less    # a download, into a pager
$ edit notes                         # ^S saves, ^Q quits
$ spin &                             # a program that loops forever
$ kill %1                            # killed anyway

It is not a Unix clone: no POSIX layer, no fork, no VT100 escape codes, and no attempt to run C programs written for other systems. Giving that up makes the system far smaller and lets every part use what the browser already provides.

Three ideas

Programs pause instead of blocking. Anything that would wait pauses, and the browser continues it when the answer arrives. So there are no threads.

The screen is a grid of cells, not a stream of bytes. A colour is a field in a cell and moving the cursor is indexing an array, so there is nothing to parse.

JavaScript never hands data straight back. Answers arrive later through one callback, which keeps the boundary small enough to check by eye.

What is in it

A shell. A Bourne shell after v7: variables, functions, if, loops, case, globbing, command substitution, pipes, redirection, background jobs, and line editing with history. ^C stops whatever is running and gives the prompt back. doc/Shell.md is the manual.

A filesystem. Everything lives in the browser's private storage and survives a reload; /tmp is emptied at boot. /bin and /etc come from an archive downloaded with the kernel, and are replaced whenever a new version is opened. /proc shows what is running, and /dev has null, zero, random and urandom. Where the browser will not store files at all, the system says so and stops.

Access to the browser. curl fetches a URL, chat talks over a WebSocket, fimport and fexport move files in and out, and pbcopy and pbpaste reach the clipboard.

Full-screen programs. less and edit draw into a grid of their own and send only the part that changed. ^C still reaches them.

A usage block in every program. -h asks one what it takes, and asking is not a mistake: the block goes to the screen and the status is 0.

Isolated processes. Each command runs in a worker of its own, with its own memory and its own open files. One stuck in a loop is killed outright, without having to cooperate — spin exists to show that. The shell is one of these programs, not part of the kernel.

A package manager. pkg installs software that did not ship with the system. A repository is just files on a web server: an index and one zip per package. The index is signed, and the keys it is checked against ship inside the archive. An install is committed by renaming a single symbolic link, so a tab that dies partway has installed nothing. The system ships pointed at the public repository https://braamix.github.io, and doc/Package_Formats.md §10 explains running one of your own.

An embedding API. web/braam.js puts a terminal on any web page with mount({ canvas }). web/embed.html is a working example, and web/dual.html splits a window between two screens of one kernel — mount({ screens: [ … ] }), a shell and a ^C of its own on each, over one filesystem. web/quad.html is the same in a 2×2 of four, which is as many terminals as there can be.

Building

You need a clang that can target wasm32, plus CMake, make and Node. On macOS that is brew install llvm lld; on Debian or Ubuntu, apt install clang lld llvm.

make            # build the kernel, the programs and the tests
make run        # run the tests
make serve      # serve the site and open it in a browser
make install    # install the SDK, to /usr/local or ~/.local
make release    # pack the site and the SDK as build/*.zip
make clean

The build leaves a complete website in build/web/. It needs no server program and no special headers, so copying that directory to a web host is a deployment.

Writing a program

Every command is a wasm file, and building one needs nothing private to this repository — make install puts an SDK under /usr/local or ~/.local.

#include "proc/file.h"

Task<i32> proc_main(Args)
{
    co_await write_out("Hello, world!\n");
    co_return 0;
}

write_out is the buffered stream File::stdout(), flushed when the program exits.

find_package(braam REQUIRED)
braam_add_program(NAME hello SOURCES hello.cpp)

A program does not have to be part of the system to run: bring the file in with the browser's file picker and run /import/hello.wasm, or curl it into /home and run it there. doc/Programming_Manual.md is the guide and examples/hello/ is the worked example.

Layout

DirectoryWhat is in it
src/kernel/coroutines, allocator, scheduler, screen, the JavaScript boundary
src/fs/paths, the mount table, the filesystem over browser storage
src/svc/URLs, WebSockets, clipboard, file transfer, clock
src/ui/the layout layer over the grid of cells
src/user/starting programs, system calls, the console, pipes, /proc, boot
src/proc/the runtime every program carries
src/cmd/one file per program; sh/ and pkg/ have directories
web/the page, the workers, the renderer, the browser side of everything
rootfs/what the boot archive carries
tools/the build's scripts, and the ones a package publisher signs with
test/the tests, and a simulated browser to run them against
doc/the specification, the manuals and the release notes

Documentation

Status

Version 0.7. Everything above works and the tests pass. A tablet works too: tap to type, drag to select, with a row of buttons for the keys a touch keyboard does not have.

Some things are missing on purpose. There is no bg and no ^Z yet. Lines are not re-wrapped when the window is resized. One program has the screen at a time. There are no file permissions and no CPU limits — a program can be killed, but not slowed down.

License

MIT. See LICENSE.

Contributors

sergev

212 commits

Languages

C++

59.7%

JavaScript

19.5%

C

16.8%

Python

1.7%

CMake

1.4%