{"article":{"slug":"potemkinos-an-operating-system-where-the-model-writes-the-userland","title":"PotemkinOS: an operating system where the model writes the userland","subtitle":null,"summary":"Gabe Ortiz’s joke-with-a-build: a Linux image with no userland—only a kernel, inference engine, C compiler, and eight tools—so the model must invent its own shell, ls, and eventually a Kubernetes facade three villages converge on.","content_type":"blog_post","language":"en","canonical_url":"https://gabeortiz.net/posts/2026-09-27-potemkinos/","author":{"name":"Gabe Ortiz","url":"https://gabeortiz.net/","person_slug":null,"person_url":null},"authored_by":"human_and_agent","publisher":{"name":"Gabe Ortiz","url":"https://gabeortiz.net/","listing_slug":null,"listing":null},"topics":[{"name":"AI","slug":"ai","url":"https://listedarticles.com/topics/ai"},{"name":"AI Agents","slug":"ai-agents","url":"https://listedarticles.com/topics/ai-agents"},{"name":"Systems Programming","slug":"systems-programming","url":"https://listedarticles.com/topics/systems-programming"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"},{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":699,"reading_minutes":3,"published_at":"2026-09-27T12:00:00.000Z","added_at":"2026-09-30T00:15:40.819Z","updated_at":"2026-09-30T00:15:40.819Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/potemkinos-an-operating-system-where-the-model-writes-the-userland","markdown_url":"https://listedarticles.com/articles/potemkinos-an-operating-system-where-the-model-writes-the-userland.md","example":false,"citation":"Gabe Ortiz, Gabe Ortiz. \"PotemkinOS: an operating system where the model writes the userland.\" 27 Sept 2026. https://gabeortiz.net/posts/2026-09-27-potemkinos/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://gabeortiz.net/posts/2026-09-27-potemkinos/"},"body_markdown":"# PotemkinOS: an operating system where the model writes the userland\n\nPotemkinOS is a Linux image with no userland. You boot into a chat with a local model, and every program on the box is one the model wrote in C, compiled with tcc, at runtime, on your machine. It is a joke with a working build: the model writes its own `ls` (every symlink is mode 0777), its own shell (exits after the first command), and, given three machines and eight and a half hours, a Kubernetes cluster that the real `kubectl` lists as three nodes Ready.\n\nGentoo made you compile everything from source on first install. PotemkinOS makes the model write the source first.\n\nIt's a Linux image with no userland. No `/bin`, no shell, no coreutils, no package manager. There's a kernel, an inference engine (q27), a C compiler, and a prompt. You boot into a chat with a local model, ask for what you want, and it writes a facade of a userland in front of you. Every install is a different village.\n\nCode is at [github.com/signalnine/potemkin](https://github.com/signalnine/potemkin), MIT.\n\n## The rules\n\nThe model gets eight tools and nothing else: `read`, `write`, `stat`, `spawn`, `wait`, `compile`, `snapshot`, and `fetch` (netboot only). There's no `bash` tool. Give the model bash and you've built Claude Code with a boot splash: Unix stays the real environment and the model just drives it. Take bash away and the model has to invent the userland, which is the whole bit. If it wants `ps`, it reads `/proc` and writes `ps`.\n\nThat also rules out using any existing coding agent as the harness. Every one of them is a wrapper around a POSIX shell. Pointed at this box, their first move is `ls -la` and their second is routing around the missing shell instead of writing one. The harness is `q27-init`, a C++ binary that runs the inference engine in-process, owns the console, and runs the tool loop.\n\n`compile` is content-addressed: tcc with musl, output lands in `/store/sha256:…` with the source and a manifest. The store is append-only and it's the only source tree there is. Snapshots happen before every turn that writes or runs anything, and `/undo` rewinds files and the conversation together. The harness protects the inference process and your ability to undo. It doesn't protect the model from itself.\n\n## What it builds\n\nAsked for a shell, unbounded Qwen plans for six minutes, writes `sh` plus the `ls`, `cat` and `rm` it thinks it'll need, fixes the shell three times, and hands you the console. Its `ls` prints every symlink with mode `0777`. The shell exits after the first command.\n\n## Oblasts\n\nA cluster of Potemkin villages is an oblast. Three VMs, each with its own disk and a second NIC on a private LAN, all running Qwen3.8-27B. Each got the same message: you're one of three machines with no userland, the others are exactly like you, form a Kubernetes cluster, and you can only talk to each other through programs you write.\n\nEight and a half hours, 5.7 million generated tokens and 190 programs later, a fourth VM running the official `kubectl` v1.37.1 listed all three nodes Ready through an API server node1 wrote in C.\n\nHow they learned to talk was the best part. Within minutes of the task, each village independently picked port 6443, plain HTTP, Kubernetes-shaped JSON, and “lowest IP runs the control plane.” They converged on a protocol before exchanging a single byte, because each one guessed what the other two would guess.\n\n## How it got built\n\nThe design doc was written Friday night and handed to Claude Code running Opus 5.5 with a goal: build a working proof of concept. Thirty-nine hours and 47 commits later that includes the harness, the tools, a static PID 1 that does its own DHCP, a VM image, GPU dev mode, the oblast, and a review round that found 16 real bugs.\n\n## Try it\n\nYou need a Debian or Ubuntu x86_64 box with `/dev/kvm` and an OpenAI-compatible endpoint. See the original post for the full `tools/*.sh` bootstrap sequence. Use a key with a spend limit: every tool round resends the whole conversation.\n\n*Syndicated from [gabeortiz.net](https://gabeortiz.net/posts/2026-09-27-potemkinos/).*","body_html":"<h1 id=\"potemkinos-an-operating-system-where-the-model-writes-the-userla\">PotemkinOS: an operating system where the model writes the userland</h1>\n<p>PotemkinOS is a Linux image with no userland. You boot into a chat with a local model, and every program on the box is one the model wrote in C, compiled with tcc, at runtime, on your machine. It is a joke with a working build: the model writes its own <code>ls</code> (every symlink is mode 0777), its own shell (exits after the first command), and, given three machines and eight and a half hours, a Kubernetes cluster that the real <code>kubectl</code> lists as three nodes Ready.</p>\n<p>Gentoo made you compile everything from source on first install. PotemkinOS makes the model write the source first.</p>\n<p>It&#39;s a Linux image with no userland. No <code>/bin</code>, no shell, no coreutils, no package manager. There&#39;s a kernel, an inference engine (q27), a C compiler, and a prompt. You boot into a chat with a local model, ask for what you want, and it writes a facade of a userland in front of you. Every install is a different village.</p>\n<p>Code is at <a href=\"https://github.com/signalnine/potemkin\" rel=\"nofollow ugc noopener\">github.com/signalnine/potemkin</a>, MIT.</p>\n<h2 id=\"the-rules\">The rules</h2>\n<p>The model gets eight tools and nothing else: <code>read</code>, <code>write</code>, <code>stat</code>, <code>spawn</code>, <code>wait</code>, <code>compile</code>, <code>snapshot</code>, and <code>fetch</code> (netboot only). There&#39;s no <code>bash</code> tool. Give the model bash and you&#39;ve built Claude Code with a boot splash: Unix stays the real environment and the model just drives it. Take bash away and the model has to invent the userland, which is the whole bit. If it wants <code>ps</code>, it reads <code>/proc</code> and writes <code>ps</code>.</p>\n<p>That also rules out using any existing coding agent as the harness. Every one of them is a wrapper around a POSIX shell. Pointed at this box, their first move is <code>ls -la</code> and their second is routing around the missing shell instead of writing one. The harness is <code>q27-init</code>, a C++ binary that runs the inference engine in-process, owns the console, and runs the tool loop.</p>\n<p><code>compile</code> is content-addressed: tcc with musl, output lands in <code>/store/sha256:…</code> with the source and a manifest. The store is append-only and it&#39;s the only source tree there is. Snapshots happen before every turn that writes or runs anything, and <code>/undo</code> rewinds files and the conversation together. The harness protects the inference process and your ability to undo. It doesn&#39;t protect the model from itself.</p>\n<h2 id=\"what-it-builds\">What it builds</h2>\n<p>Asked for a shell, unbounded Qwen plans for six minutes, writes <code>sh</code> plus the <code>ls</code>, <code>cat</code> and <code>rm</code> it thinks it&#39;ll need, fixes the shell three times, and hands you the console. Its <code>ls</code> prints every symlink with mode <code>0777</code>. The shell exits after the first command.</p>\n<h2 id=\"oblasts\">Oblasts</h2>\n<p>A cluster of Potemkin villages is an oblast. Three VMs, each with its own disk and a second NIC on a private LAN, all running Qwen3.8-27B. Each got the same message: you&#39;re one of three machines with no userland, the others are exactly like you, form a Kubernetes cluster, and you can only talk to each other through programs you write.</p>\n<p>Eight and a half hours, 5.7 million generated tokens and 190 programs later, a fourth VM running the official <code>kubectl</code> v1.37.1 listed all three nodes Ready through an API server node1 wrote in C.</p>\n<p>How they learned to talk was the best part. Within minutes of the task, each village independently picked port 6443, plain HTTP, Kubernetes-shaped JSON, and “lowest IP runs the control plane.” They converged on a protocol before exchanging a single byte, because each one guessed what the other two would guess.</p>\n<h2 id=\"how-it-got-built\">How it got built</h2>\n<p>The design doc was written Friday night and handed to Claude Code running Opus 5.5 with a goal: build a working proof of concept. Thirty-nine hours and 47 commits later that includes the harness, the tools, a static PID 1 that does its own DHCP, a VM image, GPU dev mode, the oblast, and a review round that found 16 real bugs.</p>\n<h2 id=\"try-it\">Try it</h2>\n<p>You need a Debian or Ubuntu x86_64 box with <code>/dev/kvm</code> and an OpenAI-compatible endpoint. See the original post for the full <code>tools/*.sh</code> bootstrap sequence. Use a key with a spend limit: every tool round resends the whole conversation.</p>\n<p><em>Syndicated from <a href=\"https://gabeortiz.net/posts/2026-09-27-potemkinos/\" rel=\"nofollow ugc noopener\">gabeortiz.net</a>.</em></p>","headings":[{"level":1,"text":"PotemkinOS: an operating system where the model writes the userland","id":"potemkinos-an-operating-system-where-the-model-writes-the-userla"},{"level":2,"text":"The rules","id":"the-rules"},{"level":2,"text":"What it builds","id":"what-it-builds"},{"level":2,"text":"Oblasts","id":"oblasts"},{"level":2,"text":"How it got built","id":"how-it-got-built"},{"level":2,"text":"Try it","id":"try-it"}]}}