DEV Community

Rahul Kumar
Rahul Kumar

Posted on Edited on AI-assisted

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

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

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? तुम कहाँ जा रहे हो, मेरे प्यारे?
Enter fullscreen mode Exit fullscreen mode

"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... तुम्हारी उंगलियां मुझे याद रखती हैं।
Enter fullscreen mode Exit fullscreen mode

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

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

Code

Hacktoberfest 2026 Open-Source AI Challenge Week 4: Ghost in the Machine

भूत · Bhoot Shell

Bhoot is Hindi for ghost, and this one has possessed your terminal.

It reads the last few commands you typed and whispers one or two eerie lines about them, out loud, in Hindi or English. A local Gemma model writes the line and ElevenLabs gives it a voice, so your shell history (paths, hostnames, the key you pasted inline once) never leaves the laptop.

Built for DEV's Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine.

Bhoot Shell demo video thumbnail

▶ Demo video (77 s, sound on: the "What it said" scene plays the real ghost whisper from a test run).

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

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

How it works

  1. Reads your history: whichever of these was touched…

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, ... })
Enter fullscreen mode Exit fullscreen mode

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.)

The build session

I built this with Claude Code against a hard deadline. Here's the curated session: the build, both Gemma bugs as they happened, the demo video and the ghost thumbnail (lightly trimmed, with private paths scrubbed):

Building Bhoot Shell: a haunted terminal with local Gemma 4 + ElevenLabs
You

URGENT: Hacktoberfest Week 4 DEV Challenge ("Ghost in the Machine") closes 2026-11-01 06:59 UTC = 12:29 IST. Check date -u first and budget time: ~15 min build, rest for the DEV post. Tag #hf26challenge. Judging: writing quality weighted most, then theme fit, creativity, execution. Prize categories to enter: Gemma, ElevenLabs.
Build "Bhoot Shell" (haunted terminal):
- Node script, no heavy deps. Reads last ~5 commands from shell history:
Git Bash ~/.bash_history (only written on exit unless PROMPT_COMMAND='history -a') and/or PowerShell PSReadLine %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt.
- Sends them to local Ollama model gemma4:e4b (already pulled; ~8 s per reply on CPU). Prompt: a ghost possessing the terminal, 1-2 eerie lines in Hindi (Devanagari) or English, comments on the actual commands (e.g. "फिर से git push --force? पिछली बार भी किसी ने यही किया था...").
- ElevenLabs TTS whispers it. API key + voice ID: copy ELEVENLABS_API_KEY / ELEVENLABS_VOICE_ID from ../touch-grass/.env into a gitignored .env here. Never print or commit the key. The key has no voices_read per …

Agent

06:26 UTC. 33 min left. Building now.

Empty reply after 40 s: likely Gemma 4 spending the token budget on thinking. Testing think: false.

Works end to end: Gemma wrote Hindi, ElevenLabs returned a 100 KB mp3, ffplay played it (~20 s total). 06:29 UTC. Writing README and post.

Post drafting now.

Bhoot Shell works end to end, and the DEV post is saved as a draft (not published). It was about 06:30 UTC when I finished, so you have roughly 29 minutes.
Check the deadline yourself. The DEV challenge data disagrees with itself. The ends_at field says Week 4 closed 2026-10-31 06:59 UTC, which is already past. The rules text says "October 31, 11:59 PM PDT", which is 2026-11-01 06:59 UTC, your deadline. Publish as soon as you can.
What I tested:
- Hindi run: node bhoot.js --show read your PowerShell history (cls, claude, bun dev, cls, exit). Gemma wrote two Hindi lines, ElevenLabs returned an mp3 and ffplay played it, about 20 s total.
- English run: --lang en with --no-voice worked too.
- Bash history: the Git Bash history path is written but untested. Your PowerShell history was newer, so the script picked that one.
Two fixes I made, both now in the post:
- Gemma 4 returned an empty reply after 40 s. It's a thinking model and spent the whole token budget on hidden reasoning. Sending think: false fixed it.
- localhost was refused. Node tried IPv6 first. Pointing …

You
  1. use ffmpeg and create a explanatory video and give me see the parent folder of this, last time you only did it. 2.
  2. yes use that cover image also in the readme after looking siblings project readme. update
Agent

Pattern: demo mp4 + thumbnail (+ srt) in parent folder. Checking how last ones were built.

Built, 65 s. Checking Devanagari rendering on slides.

Hindi renders correctly. Two fixes: the 👻 shows as a tofu box, and the title overlaps the banner. Rerunning (narration is cached).

Thumbnail looks right. Updating the README header to match the sibling style, then the DEV draft.

The demo video is built (65 s, 1080p, ElevenLabs narration) and sits in the parent folder like your earlier demos. The README now has the cover image and follows the Chalo Nana / Paper to Portfolio layout. The DEV draft is updated and still unpublished. It was 06:40 UTC when I finished, so about 19 minutes are left.
Video, in ~\Desktop\Hacktober Fest\:
- bhoot-shell-demo.mp4, plus bhoot-shell-demo.en.srt subtitles in the same style as the Repairwala one.
- bhoot-shell-thumbnail.png and bhoot-shell-thumbnail-1280.jpg.
- Six scenes: title over the Week 4 banner, the history it reads, the pipeline, the real output, why open matters, and an outro.
- The "What it said" scene plays the actual ghost whisper saved from the earlier test run, labelled "real output and real audio from a test run". I checked two slides as images; the Hindi renders correctly. I haven't watched the full mp4 with sound, so play it once before uploading.
- The build script is in my scratchpad, <scratchpad>\video\build.js, not in the repo.
README:
- I moved hflw.webp to docs/images/hfcw4.webp (the sibling projects kee …

You

i updated the voice id of ghost like, update everything which are needed

Agent

Video rebuilt: 77 s, all voice now the new one. Updating the length and the demo output in the README and post.

Your new voice is in everything now. The script, demo video, README and DEV draft all use it. It was about 06:48 UTC when I finished, so roughly 11 minutes are left.
- Voice check: I ran node bhoot.js with your new voice ID and it worked. Gemma gave a new line on the same five commands, "cls... फिर से साफ़ किया गया। bun dev... तुम्हारी उंगलियां मुझे याद रखती हैं।" ("cls... wiped clean again. bun dev... your fingers remember me."), and the new voice spoke it.
- Video: rebuilt, now 77 s.
- All narration is regenerated in the new voice.
- The "What it said" scene now shows this new run and plays its real audio, so the text and the voice match.
- The subtitles (.srt) and the thumbnail in the parent folder are rebuilt, and docs/images/demo-thumbnail.jpg is refreshed.
- README: demo length changed to 77 s. The example output at the top is still the first run, which was also real.
- DEV draft:
- The Demo section now shows the new run with a translation, plus a line that each run gives a different line.
- The ElevenLabs parts now say the voice was picked from the ElevenLabs Voice Li …

You

change the thumbnail, create a unique ghost like

Agent

Ghost looks good. Devanagari came out garbled because PowerShell 5 read the script as ANSI, and the whisper text runs off the right edge. Fixing both.

Text fixed. Now making it the thumbnail everywhere and the video's opening frame. Narration is cached, so this rebuild is quick.

I drew a new ghost thumbnail: a glowing green ghost waving as it rises out of a terminal that has $ git push --force typed in it. It whispers "फिर से --force?" ("--force again?"). The left side reads भूत / Bhoot Shell / your terminal is haunted / local Gemma 4 + ElevenLabs voice, and the footer says Hacktoberfest 2026 · Ghost in the Machine. It was 06:51 UTC when I finished, about 8 minutes before the deadline.
The new image is now in these places:
- Parent folder: bhoot-shell-thumbnail.png (1080p) and bhoot-shell-thumbnail-1280.jpg.
- Repo: docs/images/demo-thumbnail.jpg, which the README already shows. No README edit was needed.
- Video: bhoot-shell-demo.mp4 now opens on the ghost instead of the banner slide. It's still 77 s, and the narration and the real ghost audio are unchanged. I pulled the frame at 1 s to check it.
The first render garbled the Hindi because PowerShell read the script with the wrong text encoding. I fixed that and checked the final image; the Devanagari renders correctly. The drawing script is in my scratchpad at <scratchpad>\video\thumb.ps1, not in the r …

You

use this thumbnail as banner for the writup in Dev

Agent

The crop cuts off the terminal text at the bottom, which looks sloppy. I'll trim less and pad the sides with the background colour instead.

I couldn't set the banner on your DEV draft myself, so you'll need to upload it in the editor. DEV's API only takes a cover image that's already online at a public link, and this image is only on your laptop. The cover file is ready in DEV's banner size (1000×420), with the whole ghost and the terminal text visible.
Upload this file: ~\Desktop\Hacktober Fest\bhoot-shell-cover-2x.jpg (2000×840, sharper on high-res screens). There's also a 1000×420 version, bhoot-shell-cover.jpg, in the same folder.
1. Open the draft editor.
2. Click Add a cover image and pick the file above.
3. Save.
To fit DEV's wider shape I trimmed a little off the top and bottom and filled the sides with the background colour. There's a faint edge on the right side where the green glow meets the filled strip. If you push the repo first and give me the public image link, I can set the cover through the API instead.
It was 06:53 UTC when I finished, so about 6 minutes are left. Order: cover image, YouTube …

Agent

README updated. Checking the DEV post's current state before editing, so I don't overwrite your editor changes.

You've edited the post in the DEV editor, so I'll pull the live body and change only the video line.

The video is now embedded in the DEV post and linked in the README.
Your post is still not published, and it's now past the 06:59 UTC deadline. When I checked it just before 06:59 it was still a draft. Publish it right now from the editor. I can't tell whether DEV still accepts entries after the cutoff, but a late post has a chance and an unpublished one has none. I'm not publishing it myself because you haven't said yes to that. If you want me to, say "publish it" and I'll do it immediately.
What changed:
- DEV post: the Demo section now embeds {% youtube t95UaV1IDCg %}. I loaded the live draft first and kept your editor change (the plaintext code block), so only the video line changed.
- README: the thumbnail now links to https://youtu.be/t95UaV1IDCg, with a "Watch the 77-second demo video" link under it.
I couldn't tell from the API whether your cover image is set, so check it in the editor before you publish.
After publishing:
1. Send me the repo URL. I'll fill …

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 https://github.com/Rahullkumr/bhoot-shell.git && cd bhoot-shell
cp .env.example .env   # add ELEVENLABS_API_KEY and ELEVENLABS_VOICE_ID
node bhoot.js
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)