跳到正文
DEV Community· Rahul Kumar·· 2 小時前AI 評分49

Bhoot Shell:在終端機中運行的本地 Gemma 鬼魂

Bhoot Shell: My Terminal Is Haunted, and the Ghost Runs on Local Gemma

AI 導讀

Bhoot Shell 以本地 Gemma 模型讀取最近五條終端機指令,生成會提及實際指令的雙語鬼故事式評論,並可透過 ElevenLabs 語音播出。程式以 Ollama 在本機運行模型,指令紀錄不會離開裝置;使用 --no-voice 時完全離線。整個工具只有 bhoot.js 一個檔案,無 npm 依賴。

正文

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

What I Built

I typed exit in PowerShell, ran one script, and my laptop whispered back:

👻  bun dev... यह तो सिर्फ एक शुरुआत थी।
    exit? तुम कहाँ जा रहे हो, मेरे प्यारे?

"bun dev... that was only the beginning. exit? Where are you going, my dear?"

That's Bhoot Shell. Bhoot (भूत) is Hindi for ghost, and this one lives in your terminal. It reads the last five commands you typed, a local Gemma model writes one or two eerie lines about them, and ElevenLabs whispers them through your speakers.

The theme said "a haunted terminal that possesses your shell." I took that literally, and then I made it bilingual. I grew up on ghost stories in Hindi, and फिर से git push --force? पिछली बार भी किसी ने यही किया था... ("git push --force again? Someone did that last time too...") is creepier in Hindi than in English. The ghost picks whichever language feels worse for you, or you can force one with --lang hi|en.

It doesn't make up generic spookiness. It talks about your actual commands. Run cls twice and it says:

"cls… always wiping the slate clean, like forgetting a forgotten ritual."

Demo

A 77-second walkthrough. Sound on: the "What it said" scene plays the real whisper from this run, on the same five commands:

$ node bhoot.js --show
  read from powershell history:
  $ cls
  $ claude
  $ bun dev
  $ cls
  $ exit

👻  cls... फिर से साफ़ किया गया। bun dev... तुम्हारी उंगलियां मुझे याद रखती हैं।

"cls... wiped clean again. bun dev... your fingers remember me."

Same history, a different line every time. The ghost never repeats itself.

Code

It's one file, bhoot.js, with zero npm dependencies. Node 18+ built-ins only: fetch, fs, and child_process.

How I Built It

The pipeline has four steps:

  1. Read the history. Bhoot Shell checks both Git Bash (~/.bash_history) and PowerShell's PSReadLine log (%APPDATA%\...\ConsoleHost_history.txt) and picks whichever was touched most recently. That's the shell you were just in.
  2. Mask secrets. Before the model sees anything, a regex pass masks token=…, Bearer …, sk-…/ghp_… keys, and user:pass@host URLs.
  3. Summon the ghost. The commands go to gemma4:e4b running in Ollama on 127.0.0.1. The prompt casts Gemma as a bhoot who "died at a keyboard long ago and has been watching every command since," and requires it to mention at least one command by name.
  4. Whisper. The ghost's line goes to ElevenLabs text-to-speech with eleven_multilingual_v2, so Devanagari is spoken as real Hindi, not spelled out letter by letter. I picked a spooky voice from the ElevenLabs Voice Library, and low stability with high style makes its delivery uneven, which helps the creepiness. The mp3 plays through ffplay, or your default player if ffmpeg isn't installed.

Three things that haunted me

Gemma 4 gave me silence. My first full run took 40 seconds and returned an empty string. Gemma 4 is a thinking model, and Ollama let it spend the entire num_predict budget on hidden reasoning, so nothing was left for the reply. Adding one field fixed it:

body: JSON.stringify({ model: MODEL, prompt, stream: false, think: false, ... })

The next run took about 20 seconds, voice included, with the ghost actually talking.

localhost refused the connection. Node's fetch tried IPv6 ::1 first, and Ollama listens on IPv4. Hardcoding 127.0.0.1 fixed it.

Bash history lies by omission. Git Bash only writes ~/.bash_history when the shell exits, so the ghost was always one session behind. The fix is one line in ~/.bashrc: PROMPT_COMMAND='history -a'. PowerShell writes after every command, so it just works.

(Bonus: Git Bash's curl -d mangles Devanagari, so every request goes through Node fetch with a UTF-8 JSON body instead.)

Why Open Matters Here

Think about what's in your shell history: paths like C:\Users\you\clients\acme-payroll, internal hostnames, ssh targets, and, if you're honest, at least one API key you pasted inline and forgot about.

That's not something I'd send to a cloud LLM for a Halloween joke. With an open-weight model, I don't have to.

  • Your history never leaves your machine. Gemma runs locally in Ollama. The raw commands go to 127.0.0.1 and nowhere else.
  • It works with the lights and the internet off. node bhoot.js --no-voice is fully offline: no account, no key, no network. A ghost that needs Wi-Fi isn't much of a ghost.
  • The voice is the only part that goes online, and I limited what it gets. Only the ghost's generated sentence goes to ElevenLabs, never your history. Secrets are masked before Gemma sees them, so the model can't quote them back into the TTS request. I'll be upfront that the masking is a regex, not a guarantee. If that matters to you, use --no-voice.
  • Nobody can switch it off. No hosted model can be deprecated out from under it. Swap in any Ollama model with --model, edit the prompt, or change the ghost's personality. It's your ghost.

A closed API would have meant either trusting a vendor with my shell history or not building this at all. Running the model locally is the only reason this project exists.

Prize Categories

  • Best Use of Gemma: gemma4:e4b is the ghost. It runs fully locally through Ollama on a CPU-only laptop and writes context-aware, bilingual (Hindi/English) commentary on real shell history.
  • Best Use of ElevenLabs: eleven_multilingual_v2 gives the ghost its whisper, including properly pronounced Hindi from Devanagari text, in a voice picked from the ElevenLabs Voice Library. Voice settings are tuned for unease: low stability and high style. The same ghost voice narrates the demo video.

Try It

ollama pull gemma4:e4b
git clone <repo> && cd bhoot-shell
cp .env.example .env   # add ELEVENLABS_API_KEY and ELEVENLABS_VOICE_ID
node bhoot.js

Then type something you regret and run it again. It's watching. 👻

來源:DEV Community · dev.to