ΦΜΛ
A library that is also an operating system. Documents have margins that run when you read them.
Working. Open source under MIT. The manual and documentation are at oma.ooo.
| Role | Year | Kind | Try it |
|---|---|---|---|
| Concept, world and language design, engineering | 2026 | Operating system, interactive fiction | oma.ooo |
| 3,497 | lines of Rust, in 10 modules |
| 2 | dependencies |
| 28 | commands, every one a word a reader would use |
The problem
A command line asks you to learn its words: ls, cd, cat. The files it shows you are inert.
I wanted to find out what a system feels like when it uses the reader's words instead, and when the documents in it are allowed to do things.
What I built
- A shell in a reader's vocabulary.
browseinstead ofls,walkinstead ofcd,inscribeinstead ofcat >. Rooms are directories, shelves are their contents, the journal is the system log written as prose. - Three registers on every document. Φ is where it is, Μ is what it says, Λ is what it does.
readshows the text.inspectshows all three. - A small language for the margins. Λ has twelve instructions. A document can speak, ask the reader something, create other documents, delete them, and rewrite or erode its own text.
- A founding collection. The documents on the shelves at first boot are the manual, and each one is also a program: one loses a line every time it is read, one deletes itself after a single reading, one writes the next lesson when you finish it.
- Two daemons. A librarian tidies and writes to the journal every five minutes. A dreamer reads random fragments once an hour and inscribes new documents, which expire after a day.
- A second language underneath. A two-dimensional grid language in which the three registers must agree before an instruction runs.
How it is structured
Rust, with two dependencies (chrono for time, libc for the terminal). One binary, 37 commits.
How a document is stored
A document is an ordinary text file. If it has a margin, the file holds the text, then a line reading --- Λ ---, then the margin. Nothing else: no database, no hidden attributes. You can open any document in another editor and see exactly what it will do.
The Λ language
| Instruction | What it does |
|---|---|
say | Prints text, with variables filled in |
set | Sets a variable: to a value, a count of files, the number of times this document has been read, a random line, a random file, or the reader's answer to a question |
if, loop while | Run the indented lines below, once or repeatedly |
write | Adds a line to a file |
inscribe | Creates a document from the indented lines below |
withdraw | Deletes a document |
erode self | Removes lines from this document's own text |
mutate self | Replaces words in this document's own text |
wait | Pauses |
In the code
From Beach-Bum/OMA-Library-OS, which is public.
/// Document metadata separator
const META_SEPARATOR: &str = "\n--- Λ ---\n";
pub struct Document {
pub name: String,
pub mu: String, // visible text (Μ)
pub lambda: String, // executable logic (Λ)
pub is_process: bool,
}
impl Document {
pub fn load(path: &Path) -> Option<Self> {
let content = fs::read_to_string(path).ok()?;
let name = path.file_name()?.to_string_lossy().to_string();
let is_process = path.starts_with("east-wing/processes")
|| content.contains(META_SEPARATOR);
let (mu, lambda) = if let Some(idx) = content.find(META_SEPARATOR) {
let (m, l) = content.split_at(idx);
(m.to_string(), l[META_SEPARATOR.len()..].to_string())
} else {
(content, String::new())
};
Some(Document { name, mu, lambda, is_process })
}
}The grid language
Under the readable margin language is a stranger one. A program is a grid of cells that wraps at its edges, and execution moves across it in four directions. Each instruction passes through three stages, one per register: declared, populated, activated. If the registers do not agree, the instruction does not run and the disagreement is written down as a schism, not raised as an error. A cell changes after it has been executed, so no program runs the same way twice.
I wrote it first as a reference interpreter in Python (970 lines) and then ported it to Rust (526 lines). The written specification is in the repository.
How it is built
cargo build --release, then the binary is stripped. The Makefile also cross-compiles for a Raspberry Pi and has a target for a bootable SD card image, so the library can be the only thing a small computer does.
How it is tested
There are no automated tests. The Python reference interpreter is the one cross-check for the grid language: the same program should produce the same log in both.
What it does not do
- Margins are not confined. A margin's file paths are joined to the library's folder without checking them, so a document could write or delete outside the library. It is safe for documents you wrote yourself; it is not safe to read a stranger's.
as-archivistis a word, not a password. It marks intent. It does not check who you are.- One reader at a time.