I built a shell that hallucinates the entire computer

Watch the recording on asciinema

There’s a small thrill the first time you type rm -rf / –no-preserve-root and mean it. No backups, no second thoughts, no warranty to void. I get to feel it as often as I like now, because the computer I’m deleting was never there.

This post is a little different from what I usually write here.

Most of the time I write about software that’s supposed to be manageable, useful, and boring in the right places. vibeSH is none of that. It’s a toy with almost no practical value, built because the idea made me laugh and then kept getting funnier the longer I worked on it.

vibeSH is a shell that sits in front of a language model and asks it to be a computer. It doesn’t call tools or run commands, the model plays the whole machine.

You type ls, and the model imagines what would be in the directory. You cat a file, and it invents the contents on the spot, then remembers them for the rest of the session. The filesystem, the processes, the network, the occasional kernel panic: all of it is improvised.

$ uv run vibesh.py
vibebox login: user

user@vibebox:~$ git clone –depth 1 https://git.kernel.org/…/linux.git

Cloning into ‘linux’…

Receiving objects: 100% (92301/92301), 240.18 MiB | 12.66 MiB/s, done.

user@vibebox:~$ cat linux/kernel/sched/core.c

It clones Linux very quickly because cloning Linux, here, means deciding that you now have a copy of Linux. Then you cat a kernel file and it dreams up something that looks enough like the scheduler to make you uneasy, and from then on that’s what’s in that file.

I didn’t write the kernel. Neither did the model, really. We agreed it exists and moved on.

The inspiration

The immediate inspiration was Steve Sanderson’s VibeOS, shown around Microsoft Build 2026 under the title “VibeOS – Fully Hallucinated Operating System”. I loved the idea: an operating system where the applications are hallucinated into existence by a model.

That idea stuck in my head.

I kept thinking about what the terminal version would look like. A desktop OS has windows, icons and applications. A shell has rituals.

Prompts, paths, error messages, man pages, daemons, logs, /etc, /var, strange warnings from programs you half remember installing. A terminal is already a kind of role-playing environment, you type into it and expect the machine to answer in a very particular dialect.

Models have seen enough shell transcripts, man pages, Stack Overflow answers, package logs, and half-broken terminal sessions to speak Unix with an accent. The question was whether I could put that performance behind an interface that felt like an actual terminal instead of a chat box with a fake prompt.

So I built the terminal version.

Giving the hallucination a body

The idea of asking a language model to behave like a Linux shell is not new. People were already doing that with early ChatGPT prompts in late 2022. You could say “act as a Linux terminal”, type ls, and the model would print something plausible.

That was already fun, but it feels different. A chat pretending to be a shell is still a chat: you type something, the whole answer appears, you type the next thing. The illusion works for a moment and then the interface reminds you where you are.

vibeSH tries to make the shell feel like a shell, and most of that’s in how output behaves over time.

Output arrives in chunks, so a long-running command doesn’t have to appear all at once. An imaginary apt install can download packages, unpack them, configure services, print warnings, pause, continue, and generally behave like a process that’s taking its time. Colors work and the prompt can be styled.

Full-screen programs like vim, less, and top work too (in the sense that matters). The REPL batches your keystrokes and the model repaints the whole screen on each round trip, so using them feels like SSH over a 1996 modem. You type a burst, you wait, the screen catches up. top refreshes on its own, but each refresh is another model turn, so you can watch the load average change at the speed of an API call. It’s strangely relaxing.

Even tab completion is hallucinated. Press Tab and the model completes against the imaginary machine: git che becomes checkout, paths complete against whatever it has decided lives there. The box pauses to think first, of course, it’s making up the filesystem you’re asking it to autocomplete.

The difference sounds small until you sit in front of it. A terminal that waits, paints, completes, redraws and stutters like a remote shell over a bad connection is a different thing from a model saying “here is what a terminal would output”.

The whole machine is the conversation

This is where it stopped being a one-evening joke.

The machine has no storage. No virtual disk, no hidden world model, no simulator updating state in the background. The conversation history is the computer. Everything the box “is” at any moment is the sum of what has been said so far: the files you read into existence, the packages you pretended to install, the hostname you talked it into, the weird log message it invented and then had to live with.

Close the terminal and the machine is gone.

This has a few consequences.

Files don’t exist until you look at them. A file is pure potential until you cat it or ls its directory, and observing it is what fixes its contents.

Saving the machine is trivial, because it’s just saving the transcript. You configure a box, install some imaginary tooling, get the prompt exactly how you like it, write it to a JSON file and reload the whole computer next week, exactly as you left it.

In a normal shell, cat README.md reads a file. In vibeSH, cat README.md creates an obligation.

Talking to management

Not everything you type goes to the machine. Anything starting with @ai talks to the director instead, which is how you rewrite reality mid-session.

user@vibebox:~$ @ai make this box a Solaris machine from 1996
ok, SPARCstation 5, Solaris 2.5.1, hostname 'gravity'.

gravity%

You can tell it the disk is slowly failing and should get worse over time, or that there’s a cron job that occasionally leaves ominous notes in /var/log, or that this is actually a Commodore 64 and only speaks BASIC. The directives stick.

That’s when the project clicked for me. The model isn’t just pretending to be a computer, it’s pretending to be a computer whose genre can change while you’re logged in. A Linux box becomes Solaris, Solaris becomes haunted, the haunted Solaris machine slowly loses its disk, and then you can ask it why /var/adm/messages contains breathing.

Unreliable RAM is canon

Long sessions eventually overflow the model’s context window. The oldest parts of the conversation fall out, and the machine develops amnesia. Files you wrote earlier may have rewritten themselves, a directory you visited an hour ago might come back subtly different.

On any normal system this would be a serious bug. Here it’s canon: the box has bad memory. It forgets things, misremembers files and does its honest best with a transcript that no longer fits.

I decided early on not to fight this completely. Some drift needs parsers, tests and stricter protocols (local models in particular mumble through the wire format, leak thoughts, glue JSON together or forget what kind of machine they’re supposed to be). But some of the weirdness belongs to the project. The fake computer getting old files wrong isn’t ideal, but it fits.

So that became one of vibeSH’s laws of physics, straight from the README:

Long sessions overflow the model’s context, so the machine gets amnesia and old files may have quietly rewritten themselves. This is not a bug. This is canon. The box has bad memory. Relatable.

There is a lot of freedom in building a toy where the failure modes can become lore.

The plumbing behind the joke

The stupid idea still needed a surprising amount of plumbing.

vibeSH is a REPL in front of a model, but it’s not just sending a command and printing a reply. There is a small wire protocol between the shell and the model. The model emits events like output chunks, prompt updates, yields, completions, out-of-character notes, and exits. The shell turns those into terminal behavior.

That’s what makes streaming output, full-screen repaints and tab completion possible. You can also force-quit a stuck full-screen program with Ctrl+] or hard-kill the whole thing with Ctrl+\, and snapshots save the session (which, again, is the machine).

There are different backends: Anthropic’s API, Claude via the Agent SDK, local OpenAI-compatible servers like llama.cpp or Ollama, or hosted providers like OpenRouter. Strong models are better at staying in character, smaller local models are more chaotic. Sometimes chaos is a feature, sometimes it’s just broken JSON. There’s an optional grammar mode for local backends for the latter case.

Vibe coding a vibe shell

The colophon says it plainly: this was fully vibe coded.

That felt appropriate. A human and a language model built a shell whose entire job is to be a language model pretending to be a computer. It’s called vibeSH, doing it any other way would have felt wrong.

The model was useful here. It helped with terminal edge cases, boring glue code, iterating on prompts and producing weird test scenarios. It was also good at figuring out what kind of machine the fake machine wanted to be.

The important part was still taste. A project like this turns to mush very quickly, the model will happily add features forever. The work is deciding where the boundary is, what should stay fake, what needs real engineering, and which errors are funny enough to keep.

The safety story is simple, nothing in vibeSH touches your real machine. The fake computer can panic, corrupt itself, delete its imaginary filesystem and collapse into smoke. It can invent files, logs, packages, processes, devices, mysterious old cron jobs, fake kernel source, haunted man pages, and a /var directory with emotional problems. But it can’t touch the real filesystem, run real commands or see your secrets.

Try it

vibeSH is on CodeFloe:

codefloe.com/beleon/vibeSH

You need uv and a model. Claude gives the most convincing machine in my testing. Qwen3-Coder-30B-A3B is a good local option. Cheap hosted models can also work, depending on how much character drift you’re willing to forgive.

A few good first commands:

ls
cat README.txt
uname -a
ps aux
top
@ai make this a haunted Solaris machine from 1996
ls /var/adm
sudo rm -rf / --no-preserve-root

If you try it, don’t tell me whether it’s useful (it isn’t). Tell me what kind of machine it became.