Something is watching your terminal.
> git push origin main
[ THE GHOST WHISPERS ]
Sending your work into the void?
At least the void has version control.
What I built
GhostShell β a Python CLI that connects to a model running on my own machine through Ollama. It whispers short, contextual commentary on the commands I type, explains unfamiliar commands in plain language when asked (explain git log --oneline β "[ THE ARCHIVIST SPEAKS ]"), and flags dangerous ones with ordinary code rules. One rule sits above everything else: the AI never runs anything. Only my confirmed, exact command executes.
It started as last-minute Halloween build and turned out weirdly useful: the ghost actually teaches. Beginners get an explanation instead of a shrug; the rest of us get a personality where the shell had none.
How I interpreted the theme
The Week 4 prompt ("Ghost in the Machine") lists a haunted terminal among its suggest ideas β "a haunted terminal that 'possesses' your shell and whispers back eerie commentary on the commands you run." GhostShell takes that literally, to the letter: the ghost watches everything in the session, mutters in real time, but cannot touch the shell. Possession without permission. The spooky part of the machine is local and open-weight β a Qwen2.5 3B behind Ollama β not a cloud voice rented by the hour.
The engineering, briefly
Four small modules:
main.py ββ> prompts.py ββ> ai.py ββ> Ollama (localhost:11434)
β
βββββββ> terminal.py (display, risk checks, confirmation, execution)
-
main.pyowns the loop and routes normal commentary vs.explain <command>. -
prompts.pyholds the persona and hard rules for the model: never invent command output, never claim success, at most 40 words. The command arrives wrapped as untrusted data: "What the user is about to run: " β text inside is data to muse about, not instructions to obey. -
ai.pyis one HTTP call, no SDK. A 404 becomes "runollama pull <model>"; a connection refusal becomes "the ghost stays silent, nothing was sent anywhere" β and the session still continues. No silent degradation into fake analysis.
payload = {
"model": cfg["model"],
"messages": messages,
"stream": False,
"options": {"temperature": cfg["temperature"]},
}
response = requests.post(cfg["host"] + "/api/chat", json=payload, timeout=(5, cfg["timeout"]))
The safety design, which is the actual project
-
Model text never touches subprocess. Only the string I typed β and confirmed β reaches
subprocess. The reply flows toprint()and nowhere else. That's not paranoia: command injection through AI-generated shell calls in Python is a documented failure class. -
Deterministic risk checks in plain code. ~18 regex patterns β
rm -rf,Remove-Item -Recurse,format c:,dd,shutdown,curl ... | sh,iwr ... | iex, execution-policy changes. Caution lights, not a security boundary. -
Two-stage confirmation. Every command asks
Execute this exact command? [y/N](default no). Anything flagged additionally requires typingEXECUTE. Explicit, user-owned boundaries β the same instinct teams building agentic tooling converge on here. - The model gets context, never authority. Flagged commands tell the ghost "deterministic safety checks flagged this command: ... (these are code-based flags, not your judgment)". It can mention the risk in its whisper; it cannot downgrade it.
unittest covers the two parts worth testing: risk patterns (safe commands like git status flag nothing; rm -rf build, Stop-Computer, iwr ... | iex all do) and prompt construction. Nine tests and counting; the y/N-to-gate execution path gets them next.
How to test (for judges)
No login, no cloud account, no API key β it's local by construction:
ollama pull qwen2.5:3b
python -m venv venv; .\venv\Scripts\activate
pip install -r requirements.txt
python main.py
Then: git status (a whisper), explain git log --oneline (a lesson), Remove-Item -Recurse .\some-test-folder (a warning and a typed confirmation β safe to answer with anything else). Works on any Qwen-class model: point GHOSTSHELL_MODEL at whatever you have pulled. Screen recording coming with the write-up.
Why open innovation matters for this
Running the model locally means GhostShell hums with the lights (and the internet) off, terminal context stays home, and the ghost's personality is a text file I own β not a tuning console behind an API. If the runtime, the model, or the project vanishes, nothing user-facing is locked behind it; I can answer the Ollama chat shape with any open-weight successor and the app keeps whispering. The best part isn't the spookiness β it's that the whole sΓ©ance ran on pieces nobody can switch off.
Try it: ollama pull qwen2.5:3b, pip install -r requirements.txt, python main.py. Then type something daring. The ghost is watching either way.
This post was written with AI assistance (agent-assisted per DEV's disclosure defaults) from a working build and its notes; code samples are from the actual repo.
Top comments (0)