This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
PossessedShell is a Victorian ghost trapped in your terminal. It is an ambient companion for zsh and bash that mourns every command you kill, then tells you how to fix it. It does three things:
- The Failing Command Curse. When a command exits non-zero, the hook captures the command, its stderr and the exit code. A local Gemma 2 model writes a short Victorian lament and a plain-English diagnosis. It also suggests one fix command, which is pre-typed on your next prompt in zsh or placed in history in bash. The ghost never runs the fix for you.
-
The Forbidden Ritual Interceptor. Destructive commands (
rm -rf,git push --force,git reset --hard,chmod 777,DROP DATABASE,mkfs,curl | sh, fork bombs and more) are stopped before they run. The ghost asks whether you truly wish to summon such destruction. - The Ectoplasm Leak Detector. A background monitor watches CPU and RAM and raises a spooky warning when the machine runs hot or one process devours memory.
I took the "haunted terminal that possesses your shell" idea literally. The ghost is Cornelius Vale, a telegraph engineer who perished in 1887 and is now bound inside the machine. The theme is the fun part, but the diagnoses are useful because Gemma sees the real stderr, the exit code, the cwd and a snapshot of system state.
Demo
Here is a typical haunting (a missing Python module):
โ THE PROCESS `python3 -c 'import ectoplasm'` HAS DIED (exit 1) โ
โฐ Diagnosis: The Python package 'ectoplasm' is not installed in this environment.
โญโ the ghost's remedy โโโโโโโโโโโโโโโโฎ
โ python3 -m pip install ectoplasm โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
The remedy waits on your next prompt. Enter to accept, Ctrl-U to refuse.
whispered by gemma2:2b in 1.9s, 212 tokens
Code
๐ป PossessedShell
A Victorian ghost is trapped in your terminal. It mourns every command you kill, and it tells you how to fix them.
.-~~~~~~~~~-
.' _ _ '. ___________
/ (@) (@) \ | |
| ^ | | R.I.P. |
| .-------. | | |
\ \ ~~~~~ / / | here lies |
| '-----' | | your |
| | | process |
| /\ /\ /\ | __|___________|__
|/ \_/ \_/ \_| /////////////////
โ THE PROCESS `python3 -c 'import ectoplasm'` HAS DIED (exit 1) โ
Alas! python3 hath perished, its last breath a ModuleNotFoundError for
'ectoplasm'. I drew the curtains and stopped every clock in the house.
โฐ Diagnosis: The Python package 'ectoplasm' is not installed in this environment.
โญโ the ghost's remedy โโโโโโโโโโโโโโโโฎ
โ python3 -m pip install ectoplasm โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
The remedy waits on your next prompt. Enter to accept, Ctrl-U to refuse.โฆHow I Built It
Open-source AI at the core. Gemma 2 (gemma2:2b by default, gemma2:9b if you want a wiser ghost) runs locally through Ollama. Gemma is asked for strict JSON ({lament, diagnosis, fix}) through Ollama's format JSON schema, so the fix can be extracted reliably. The system prompt forbids inventing files, flags or packages the error doesn't imply, and bans destructive remedies unless there is no other way.
Architecture.
- The hooks are plain shell: zsh
preexec/precmdplus anaccept-linewidget, and bash'sDEBUGtrap plusPROMPT_COMMAND. Python starts only when a command fails, matches the destructive-command prefilter, or an omen is waiting. Successful everyday commands cost nothing. - A small asyncio daemon keeps Gemma warm, runs the resource monitor, and talks newline-delimited JSON over a
0600Unix socket. - If Ollama is down, an offline grimoire of heuristics answers instead (typos, missing modules, missing git upstream, ports in use, OOM kills). The demo never falls flat.
- Rendering uses
rich, with glitch-in ASCII apparitions and a typewriter effect. Resource checks usepsutil.
Sentry agent tracing. With a DSN set, every curse becomes a trace, and the Gemma call follows Sentry's AI agent span conventions. It shows up under Insights โ AI โ Agents:
curse ls shell.curse the transaction
โโ system vital signs ghost.snapshot
โโ backboard recall ghost.memory.recall
โโ invoke_agent Cornelius Vale gen_ai.invoke_agent
โโ chat gemma2:2b gen_ai.chat tokens, timings, prompt and reply
The gen_ai.chat span records token counts, model load time and tokens per second. When Gemma times out or answers with something unusable, the span is marked as an error and the agent span records that it fell back to the grimoire, so a slow model server stands out at a glance. Everything is scrubbed by redact.py before it leaves the machine.
Backboard ghost memory (opt-in). With a BACKBOARD_API_KEY, the ghost remembers your past failures across sessions: "Again, mortal? python3 has died before by your handโฆ". Backboard only ever receives a scrubbed one-line summary per failure.
Tests. Unit tests plus end-to-end tests that start real interactive zsh and bash sessions in a pty. They check that a failing command is cursed with its captured stderr, that a banished rm -rf runs nothing at all, and that omens appear at the next prompt.
Why Does Open Innovation Matter?
-
Your terminal is private. Commands and stderr routinely contain paths, hostnames, tokens and half-typed secrets. Because Gemma runs on
localhost, that text never has to leave the machine. A closed API would force me to ship every failed command to someone else's server. - It works with the lights off. On a plane, on a train, or behind a locked-down network, the ghost still haunts. The default install is 100% offline. Sentry and Backboard are opt-in extras, and the offline grimoire covers the case where even Ollama is down.
-
It isn't locked inside a service that might disappear. The model is a file I hold. I can swap
gemma2:2bforgemma2:9b, or pointPOSSESSED_LLM_URLat any OpenAI-compatible local server such as llama.cpp, without changing a line of code. - Open weights made the tracing honest. Since inference is local, cost is $0 and I could observe the real latency and token counts per failure, and design the fallback around them.
Prize Categories
- Best Use of Gemma: Gemma 2 is the brain, running locally via Ollama and producing structured JSON diagnoses.
-
Best Use of Sentry Agent Tracing: each curse is traced as a
gen_ai.invoke_agent/gen_ai.chatagent run with token usage, timings and error outcomes. - Best Use of Backboard: persistent, scrubbed memory of your past failures, so the ghost can recall earlier sins.
Top comments (0)