跳到正文
DEV Community· Muhammad Huzaifa·· 2 小時前AI 評分46

haunted-shell:我的終端機被一名未完成部署的程式設計師鬼魂纏上

My Terminal Is Haunted by a Programmer Who Never Finished Their Deploy

AI 導讀

開源專案 haunted-shell 將 AI 鬼魂接入 zsh 終端機,監看用戶指令,並在指令失敗時回應;指令成功時約有三分之一機會發聲,亦會記住最近五條指令。它透過 Ollama 在本機運行開放權重模型,預設使用 qwen3:8b,無需 API 或網絡,shell 歷史不會離開裝置。

正文

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

What I Built

haunted-shell possesses your zsh. A ghost lives in the terminal: the programmer who died at this keyboard years ago, with a deploy still unfinished. It watches every command you run, and sometimes, in dim violet italics that type themselves out a little too slowly, it whispers back.

$ git push --force origin main
  your git push failed, but i'm sure you knew that. the main branch is still here, waiting for you.

$ rm -rf node_modules
  i watched you delete the node_modules. you're so reckless. i once tried to save them. now they're gone.

$ npm run build
  the build failed. you're still using node 12. i never got to fix that bug.

It never helps you, by design. When a command fails, the ghost always speaks. When one succeeds, it speaks about a third of the time, so you never know when it's listening. It also remembers your last five commands, so it can bring up the git status you ran four times in a row.

Demo

Demo

Two commands, two whispers: "your git repo is dead, but i'm still here. i never learned to push." and then, fittingly for a GIF, "why does it feel like we're both stuck in a loop?"

Code

haunted-shell 👻

A ghost lives in your terminal. It's the programmer who died at this keyboard years ago, and it watches every command you run. Sometimes it whispers back.

$ git push --force origin main
  your git push failed, but i'm sure you knew that. the main branch is still here, waiting for you
$ rm -rf node_modules
  i watched you delete the node_modules. you're so reckless. i once tried to save them. now they're gone.

It runs entirely on an open-weight model through Ollama. No API keys, no network, and your shell history never leaves your machine.

Install

ollama pull qwen3:8b          # or gemma3:4b, llama3.2, anything Ollama serves
git clone https://github.com/ghost-huzaifa/haunted-shell.git ~/haunted-shell
echo 'source ~/haunted-shell/haunt.zsh' >> ~/.zshrc

Open a new terminal. Type unhaunt to banish it for the session.

Knobs

env var default what
HAUNT_MODEL qwen3:8b any Ollama model
HAUNT_CHANCE 35 % of successful

…

It's two files: about 20 lines of zsh that hook preexec and precmd, and about 60 lines of Python that use only the standard library. There are no dependencies and no SDKs.

How I Built It

  • The model: an open-weight model (qwen3:8b by default; any Ollama model works through HAUNT_MODEL) running locally through Ollama on an M1 MacBook with 16 GB of RAM.
  • The hook: zsh's preexec saves the command and precmd grabs the exit status. Both go to the ghost, together with the current directory and recent history.
  • The voice: a short system prompt makes the ghost lowercase, wistful, a little funny, never helpful, and limited to one line about the exact command you ran. Thinking is turned off ("think": false) and output is capped at 48 tokens, so a whisper takes a couple of seconds once the model is warm.
  • The manners: a ghost that breaks your shell is a bad ghost. If Ollama is down or slow, it stays silent, and unhaunt banishes it for the session.

I built this with an AI coding agent (Claude Code) as a pair, and the whole session is below. The model was the easy part. The hard part was the manners: making sure the ghost never throws a stack trace into your prompt, and fixing a bug where zsh's array slicing made it forget every command but the last one until four had piled up.

Why Does Open Innovation Matter?

Your shell history is one of the most private things on your computer. It holds every hostname you've SSH'd into, every half-typed password you pasted into the wrong prompt, every curl with a token in the header, every embarrassing git reset --hard. I would never pipe that to a hosted API, and I doubt you would either.

An open-weight model running on my own laptop changes that:

  • It works with the lights (and the Wi-Fi) off. Ghosts shouldn't need an internet connection. This one works on a plane.
  • Nothing leaves the machine. The ghost reads your commands and nobody else does. There's no telemetry, no retention policy to read, and no account.
  • It costs nothing per whisper. A closed API would bill me for every ls. Locally, the ghost can comment on thousands of commands a day for free.
  • The ghost is swappable. One env var changes the model, so you can swap in Gemma or Llama and meet a different ghost. You choose your ghost, and no provider can change its personality out from under you.
  • It can't be shut down. It won't disappear because an API was deprecated or a startup ran out of runway. A ghost that's open-source can't really die. It seems fitting for a project released on Halloween, just before Día de los Muertos.

The trade-off is honest: the first whisper after boot takes about 10 seconds while the model loads, and an 8B model is less witty than a frontier model. For a voice that sits inside your most private tool, I'll take a slightly dumber ghost that keeps my secrets.

My Agent Session

The Spirit of It

While I was recording the demo, I cd'd into my day-job repo, and the ghost whispered: "you're still here. i'm still here. why does it feel like we're both stuck in a loop?" An 8B model running on my laptop, with no internet, called me out. Happy Halloween. 🕯️

來源:DEV Community · dev.to