ai newsSa., 31. Okt.
EilmeldungGoogle Opens Connected Apps Platform for AI Mode and Gemini

Haunted Terminal: a local spirit that can change your prompt, but not your shell

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine What I Built Haunted Terminal is a Python REPL with a ghost in it. You type ordinary commands and they run on your machine. Between commands, a spirit comments, and the prompt itself changes mood and pe

dev.toSamstag 08:31 · 31.10.5 Min. Lesezeit
Bild: dev.to

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

Haunted Terminal is a Python REPL with a ghost in it. You type ordinary commands and they run on your machine. Between commands, a spirit comments, and the prompt itself changes mood and personality.

The week asked for something spooky, or something that honors the past. I wanted both. The Poltergeist rattles the pipes when a command fails. The Archivist keeps a candle for finished work, in the spirit of Día de los Muertos: failed commands, deleted files, and commits are names worth remembering. The Keeper watches the prompt the way a lighthouse keeper watches weather.

Each spirit is a TOML file. Switching is /spirit archivist. A new ghost is a new file, not a code change.

The model is Gemma, served by Ollama on 127.0.0.1. The default tag is gemma3:1b. If that tag is not pulled, --model points at whichever Gemma you already have. If Ollama is asleep, or a reply takes longer than the timeout, the panel says the spirit is whispering from memory and prints a canned line. The prompt comes back either way.

Rituals start with / and never reach the operating system:

There is no website. The product is the terminal. haunt --demo records two files.

This first transcript uses the canned voice, so it replays with the network unplugged. The panels say "from memory" on purpose.

poltergeist (rattling):~/haunt-demo λ ls no-such-candle ls: cannot access 'no-such-candle': No such file or directory ┌─ Poltergeist whispers from memory ─┐ │ I knocked twice on the return key. The exit code knocked back harder. │ └─┘ /spirit archivist Archivist takes the prompt. /manifest A file appeared:.haunt/manifestations/ofrenda.txt /epitaph Commit with this epitaph? Remember what this change tried to keep Set among the other finished work. The archivist speaks the subject aloud once, then lets the log hold it. Type y to commit: y Committed: Remember what this change tried to keep /quiet git status On branch master nothing to commit, working tree clean Enter fullscreen mode Exit fullscreen mode /quiet is the tell. git status still ran. The Archivist did not speak over it.

The second file is one live call. This machine already had gemma3:latest on disk, so that is the tag in the recording. The Archivist was given the command ls no-such-candle and exit code 2, and answered:

The flame flickers, acknowledging the lost name. Another echo joins the quiet vigil.

Command output stayed on the terminal. The model saw the command text, the exit code, and the directory name.

https://github.com/Gavinduachintha/Spooky

The piece that makes the project work is the local call, and the wall around it. voice.py is the only module that knows the Ollama URL, and it accepts 127.0.0.1, localhost, or::1. Before a prompt is built, anything that is not the command, the exit code, a short git summary, or a few recent commands is dropped. That includes stdout and stderr.

def shrink_context ( context: dict ) -> dict: """ Keep the prompt small. Unknown keys, including command output, are dropped. """ Enter fullscreen mode Exit fullscreen mode Every request sets num_ctx to 4096, caps the reply (about 70 tokens for a whisper), and keeps the model loaded with keep_alive. Ghost files have to survive a path check before they are written. /epitaph passes the subject and body as git commit -m arguments. It does not push, amend, or force.

Open-weight Gemma on Ollama is the core, not a caption. Four tasks share one client:

The HTTP call is urllib against POST /api/chat. Damiano wrote up why a small local tool often does not need an SDK for this, and also how slow a small Gemma can be on CPU: on the order of tens of seconds for a long answer. A terminal cannot wait that long, so the timeout defaults to 8 seconds and the canned line is the success path, not an error page. Streaming still fills the panel when the model is fast enough.

Structured tasks use Ollama's JSON schema on /api/chat, which is the shape Amareswer's Ollama API guide walks through: chat, options, and a format object when the reply has to be data.

Nazar Boyko is the reason num_ctx is set on every request. Ollama's default window is 2048 tokens, and it clips the rest with no error. These prompts stay short so the spirit is reacting to the command you just typed.

The REPL is prompt_toolkit. Whispers are Rich panels. cd and pwd are remembered by the session, because every other command starts a fresh shell. Twenty-six tests run without a network: a fake HTTP handler stands in for Ollama, path escapes have to stay inside the sandbox, and a declined epitaph must not create a commit.

A spirit that comments on your shell is a bad fit for a hosted model. The text you type includes paths, hostnames, repo names, and the occasional secret you did not mean to type. That stream belongs on the machine that already has the terminal.

A closed API would also be the wrong shape for the rest of it. Commentary is frequent, so a per-token bill is a tax on using your own prompt. The weights stay useful with the network off after the one-time ollama pull. The tag is a flag, so the same spirits can speak through gemma3:1b, gemma3:270m, or gemma3:latest without a rewrite. And a local model will stay in character when the command is kill or a failing ls, which is the whole joke.

The open piece is what makes the haunting honest. The ghost can hear the command. It cannot leave the room.

Best Use of Gemma. Whispers, the prompt's mood, ghost files, and commit messages are Gemma 3 through Ollama on loopback. No hosted model and no API key.

Quelle: dev.to (dev.to). Original öffnen