{"slug": "i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed", "title": "I Haunted My Terminal With a Local Ghost (Gemma 3, No Internet Needed)", "summary": "A developer built shell-ghost, an open-source zsh hook that uses preexec and precmd to capture each command and its exit code, then sends them to a local Gemma 3 4B model via Ollama's HTTP API to print a single eerie one-line whisper after roughly one in three commands. The tool runs entirely offline, with a temperature of 0.9 and a 48-token cap keeping replies short, and the author argues that routing terminal commands to a hosted API for a joke would be a bad trade given the secrets a shell can expose.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge: Week 4, \"Ghost in the Machine\"](https://dev.to/challenges/hacktoberfest-week4-2026-10-26).*\n\n**shell-ghost** is a haunted terminal. After some of the commands you run, a ghost whispers one eerie line about what you just did:\n\n``` bash\n$ rm -rf node_modules\n  👻 Don't worry, it just wanted a little... tidier oblivion.\n\n$ git push --force\n  👻 Don't you dare rewrite my carefully crafted digital chaos.\n\n$ sudo make me a sandwich\n  👻 It wants fillings… and a very long, slow, digital chew.\n```\n\nBy default it speaks on about 1 in 3 commands, so it stays a surprise instead of a nuisance.\n\nRepo: [https://github.com/GAlmeidaDev/shell-ghost](https://github.com/GAlmeidaDev/shell-ghost)\n\nTwo tiny files, no dependencies beyond Python 3 and zsh:\n\n`haunt.zsh` hooks into zsh with `preexec` (to remember the command) and `precmd` (to read its exit code). It rolls a die, and if the ghost is feeling chatty it calls the script.`ghost.py` sends the command and exit code to a local model through Ollama's HTTP API and prints one dim purple line.\nThe whole prompt is a few lines: *you are a ghost trapped inside a computer, reply with one short eerie whisper, spooky and a little funny.* Temperature 0.9 and a 48-token cap keep it short and weird.\n\nTry it:\n\n```\nollama pull gemma3:4b\npython3 ghost.py \"rm -rf node_modules\" --code 1\necho 'source /path/to/shell-ghost/haunt.zsh' >> ~/.zshrc\n```\n\nSet `GHOST_ODDS=1` and it speaks after every command.\n\nA terminal sees everything: your commands, paths, hostnames, sometimes secrets typed inline. Sending that to a hosted API for a joke would be a bad trade.\n\nWith an open-weight model running locally:\n\n`localhost`.`--model` swaps in any model Ollama can run.\nA 4B model is plenty for one spooky sentence, and that's the point: small, open models are good enough to make tools feel alive without a cloud dependency.\n\n`splitlines()[0]` is still a cheap safety net.", "url": "https://wpnews.pro/news/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed", "canonical_source": "https://dev.to/ghalmeidadev/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed-k51", "published_at": "2026-10-26 23:30:44+00:00", "updated_at": "2026-10-26 23:42:37.401163+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "developer-tools", "ai-products"], "entities": ["shell-ghost", "Gemma 3", "Ollama", "zsh", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed", "markdown": "https://wpnews.pro/news/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed.md", "text": "https://wpnews.pro/news/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed.txt", "jsonld": "https://wpnews.pro/news/i-haunted-my-terminal-with-a-local-ghost-gemma-3-no-internet-needed.jsonld"}}