<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ankit Kumar Jha</title>
    <description>The latest articles on DEV Community by Ankit Kumar Jha (@ankitjha1405).</description>
    <link>https://dev.to/ankitjha1405</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4202161%2Fa7d60b9b-6573-4da1-9ba7-125c3c4a223b.png</url>
      <title>DEV Community: Ankit Kumar Jha</title>
      <link>https://dev.to/ankitjha1405</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ankitjha1405"/>
    <language>en</language>
    <item>
      <title>A ghost moved into my terminal. It runs on Gemma, and it never leaves my laptop</title>
      <dc:creator>Ankit Kumar Jha</dc:creator>
      <pubDate>Sat, 31 Oct 2026 05:51:58 +0000</pubDate>
      <link>https://dev.to/ankitjha1405/a-ghost-moved-into-my-terminal-it-runs-on-gemma-and-it-never-leaves-my-laptop-3jb0</link>
      <guid>https://dev.to/ankitjha1405/a-ghost-moved-into-my-terminal-it-runs-on-gemma-and-it-never-leaves-my-laptop-3jb0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first time I ran it for real, Gemma said nothing at all. Eight commands, eight empty lines. The ghost was there, it just wouldn't speak. That turned out to be the most honest bug I've ever hit in a Halloween project, and I'll get to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;haunted-terminal&lt;/strong&gt; is a ghost that moves into your zsh, and it doesn't just leave comments. It haunts the place.&lt;/p&gt;

&lt;p&gt;When you open a terminal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The ghost rises.&lt;/strong&gt; A full-screen ASCII ghost fades in out of the dark, bobs, blinks, and fades away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The music starts.&lt;/strong&gt; A horror soundtrack loops for as long as any haunted tab is open, and stops when you close the last one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The welcome card appears.&lt;/strong&gt; The same ghost floats beside your status (is Gemma awake, is the music on, where you are) until you press a key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then it stays.&lt;/strong&gt; About one command in three, it whispers a line about what you just did. Every few commands, something in the room makes a sound: a whispered &lt;em&gt;boo&lt;/em&gt; right behind your ear, a wolf, a witch cackling, chains on stone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ghost is a programmer who died in 1987 at a VT100 terminal, halfway through a COBOL migration. He is cold, a little jealous of the living, and he never gives advice.&lt;/p&gt;

&lt;p&gt;He also has one job that is not a joke. Before you press Enter on &lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;git push --force&lt;/code&gt;, &lt;code&gt;git reset --hard&lt;/code&gt;, &lt;code&gt;DROP TABLE&lt;/code&gt; or &lt;code&gt;curl ... | sh&lt;/code&gt;, he stops you and asks if you're sure.&lt;/p&gt;

&lt;p&gt;And on &lt;strong&gt;November 1 and 2&lt;/strong&gt;, for Día de los Muertos, the welcome card turns marigold, and the ghost builds a small ofrenda for everything you deleted that day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wij1fx2cczviytmsfl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wij1fx2cczviytmsfl5.png" alt="The Día de los Muertos welcome card: a marigold title, the ghost, and &amp;quot;in memory of: old-project, legacy_auth.py&amp;quot;" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ghost is &lt;strong&gt;Gemma 4 E2B&lt;/strong&gt;, running on my laptop through llama.cpp. Nothing I type goes to a server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Vtko3aHe9m8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A two-minute tour: the ghost rising, the welcome card, real Gemma whispers on &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;npm test&lt;/code&gt; and a typo, a wolf howl from the ElevenLabs sounds, the &lt;code&gt;rm -rf&lt;/code&gt; guard, the Día de los Muertos card, and how to install it. Turn the sound on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxxqa60qiqscihejhdawi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxxqa60qiqscihejhdawi.png" alt="The welcome card, then a normal day: the ghost comments on npm test and a typo, then stops rm -rf" width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every ghost line in that picture is real Gemma output. A few more from the test runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;-5&lt;/span&gt;
&lt;span class="go"&gt;  👻 Five commits remain, the ghosts of my forgotten logic.
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git checkout feature/login        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;128&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;  👻 The branch is gone, just like my last memory of warmth.
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;git status
&lt;span class="go"&gt;  👻 The changes remain, just like the dust on this old screen.
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt;                           &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;  👻 That error is familiar;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;the same ghost &lt;span class="k"&gt;in &lt;/span&gt;the machine.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://haunted-terminal-lovat.vercel.app" rel="noopener noreferrer"&gt;haunted-terminal-lovat.vercel.app&lt;/a&gt;, with the same ghost animated in your browser and a button to play the soundtrack.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ankitjha1405" rel="noopener noreferrer"&gt;
        ankitjha1405
      &lt;/a&gt; / &lt;a href="https://github.com/ankitjha1405/haunted-terminal" rel="noopener noreferrer"&gt;
        haunted-terminal
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A local Gemma ghost that haunts zsh
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;👻 haunted-terminal&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A ghost moves into your terminal.&lt;/strong&gt; Open a tab and it rises out of the dark while a horror soundtrack starts. Then it stays. It whispers about the commands you run, and stops you before you &lt;code&gt;rm -rf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The ghost is &lt;a href="https://huggingface.co/ggml-org/gemma-4-E2B-it-GGUF" rel="nofollow noopener noreferrer"&gt;Gemma 4&lt;/a&gt;, running on your own machine through &lt;a href="https://github.com/ggml-org/llama.cpp" rel="noopener noreferrer"&gt;llama.cpp&lt;/a&gt;. Your shell history never leaves your laptop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ankitjha1405/haunted-terminal/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/ankitjha1405/haunted-terminal/actions/workflows/ci.yml/badge.svg" alt="ci"&gt;&lt;/a&gt;
&amp;nbsp;&lt;strong&gt;&lt;a href="https://haunted-terminal-lovat.vercel.app" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/strong&gt; · Built for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26" rel="nofollow"&gt;DEV Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/ankitjha1405/haunted-terminal/site/welcome-card.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fankitjha1405%2Fhaunted-terminal%2FHEAD%2Fsite%2Fwelcome-card.svg" alt="The haunted-terminal welcome card: an ASCII ghost beside status for Gemma and the music, followed by commands with ghost comments and an rm -rf warning"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Every ghost line above is real Gemma output from a laptop, about half a second each.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Hacktoberfest 2026 · Week 4: Ghost in the Machine&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This is my entry for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26" rel="nofollow"&gt;DEV Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine&lt;/a&gt;. The week asks for a spooky build with open-source AI at its core. Here the ghost &lt;em&gt;is&lt;/em&gt; the open model: Gemma 4, running on your own laptop, gives the…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ankitjha1405/haunted-terminal" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Two files do the work, with no dependencies beyond Python's standard library: &lt;code&gt;ghost.zsh&lt;/code&gt; (the hooks) and &lt;code&gt;ghost&lt;/code&gt; (everything else).&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The architecture is small. &lt;code&gt;ghost.zsh&lt;/code&gt; hooks into zsh in two places. After every command, &lt;code&gt;precmd&lt;/code&gt; hands the command and its exit code to the ghost. Before Enter, a wrapped &lt;code&gt;accept-line&lt;/code&gt; widget runs the safety check. When a terminal opens, it starts the music and plays the intro. The &lt;code&gt;ghost&lt;/code&gt; script talks to llama-server's OpenAI-compatible endpoint, draws the animations, and manages the sound.&lt;/p&gt;

&lt;p&gt;Most of what I learned came from things going wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The ghost that wouldn't speak
&lt;/h3&gt;

&lt;p&gt;That first live run: eight commands, eight empty replies. The raw response showed why. Gemma 4 starts &lt;em&gt;thinking&lt;/em&gt; as soon as it gets a system prompt, and it spent all 60 of its tokens reasoning about how to be a ghost:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"reasoning_content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thinking Process:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;1. **Analyze the Request &amp;amp; Persona:**..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One flag fixed it: &lt;code&gt;"chat_template_kwargs": {"enable_thinking": false}&lt;/code&gt;. A ghost should blurt, not deliberate. There's now a test so this can't quietly come back.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. "Another…"
&lt;/h3&gt;

&lt;p&gt;Once it spoke, it started a lot of lines the same way: &lt;em&gt;Another triumph. Another failure. Another branch lost.&lt;/em&gt; So I measured it. I wrote &lt;a href="https://github.com/ankitjha1405/haunted-terminal/blob/main/eval_ghost.py" rel="noopener noreferrer"&gt;&lt;code&gt;eval_ghost.py&lt;/code&gt;&lt;/a&gt;, which runs 40 everyday commands (git, npm, docker, typos, failed builds) through the ghost three times and checks every reply.&lt;/p&gt;

&lt;p&gt;Then I added four example replies to the prompt, told it to notice one concrete detail of the command, and skipped commands like &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;cd&lt;/code&gt; that aren't worth a ghost's breath. Here's the before and after, 120 replies each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Replied at all&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Under 20 words&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gave no advice&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No emoji, quotes or hashtags&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Didn't open with "Another"&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One sentence&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;88%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median reply time&lt;/td&gt;
&lt;td&gt;0.7 s&lt;/td&gt;
&lt;td&gt;0.7 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of the remaining "two sentence" replies are fragments like &lt;em&gt;"Five commits. Such a brief, pathetic life for code."&lt;/em&gt;, which honestly suit him. The examples cost no speed: llama-server caches the shared prompt, so old and new run at the same median.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The safety check is not the model
&lt;/h3&gt;

&lt;p&gt;A warning before &lt;code&gt;rm -rf&lt;/code&gt; has to be instant and right every time, so it's plain pattern matching. Gemma only does the part where being creative is the point. The same script tests it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Safety check&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dangerous commands caught&lt;/td&gt;
&lt;td&gt;19/19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Harmless look-alikes left alone&lt;/td&gt;
&lt;td&gt;19/19 (was 17/19)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two false alarms were &lt;code&gt;grep -r 'DROP TABLE' migrations&lt;/code&gt; and &lt;code&gt;echo 'drop table' &amp;gt; notes.txt&lt;/code&gt;. Now &lt;code&gt;DROP&lt;/code&gt; only counts inside a database client like &lt;code&gt;psql&lt;/code&gt; or &lt;code&gt;mysql&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Secrets never reach the model
&lt;/h3&gt;

&lt;p&gt;Even a local model shouldn't see your keys, and the ghost could repeat one on screen. Before a command reaches Gemma, anything that looks like a secret is blanked: &lt;code&gt;export OPENAI_API_KEY=sk-...&lt;/code&gt;, &lt;code&gt;--password=...&lt;/code&gt;, &lt;code&gt;Bearer&lt;/code&gt; tokens, &lt;code&gt;https://user:token@...&lt;/code&gt;, and GitHub, Slack and AWS key formats. &lt;code&gt;npm test&lt;/code&gt; stays &lt;code&gt;npm test&lt;/code&gt;. &lt;code&gt;echo $GITHUB_TOKEN&lt;/code&gt; stays too, because a variable name isn't a secret.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. A voice that talked too much
&lt;/h3&gt;

&lt;p&gt;My first version had &lt;strong&gt;ElevenLabs&lt;/strong&gt; read every ghost line aloud. It was too much within a minute. A ghost that talks constantly isn't scary. A sound you didn't expect is.&lt;/p&gt;

&lt;p&gt;So now the shell keeps a counter. After every one to three commands (two on average, which I checked over 30 commands), it plays one of seven horror sounds made with the &lt;strong&gt;ElevenLabs sound effects API&lt;/strong&gt;: a breathy &lt;em&gt;boo&lt;/em&gt;, a wolf howl, a witch's cackle, a creaking door, a moan, dragging chains, overlapping whispers. Each is generated once and cached. After that they cost no credits, work offline, and ElevenLabs never sees a single command.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Colours that didn't exist
&lt;/h3&gt;

&lt;p&gt;The welcome card's title came out garbled on my Mac, with some letters invisible. macOS Terminal.app can't display 24-bit colour, and I had used it for a gradient. The card now uses only the 256-colour palette, with a solid white title and a violet base.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rest
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The ghost is a signed distance field:&lt;/strong&gt; a circle for the head and a box with a wavy hem for the body, drawn in &lt;code&gt;@$%&lt;/code&gt; and lit by a violet and green halo. The website draws its hero with the same math in JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The welcome card&lt;/strong&gt; redraws in place 20 times a second until you press a key, and that key isn't typed into your prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One music player serves every tab.&lt;/strong&gt; An atomic lock file stops two tabs from starting two players. (They did, the first time. Testing caught it.) Each shell registers itself, and the music stops when none are left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No server, no ghost.&lt;/strong&gt; If llama-server is down, the ghost stays silent in milliseconds. It never blocks the shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests:&lt;/strong&gt; 15 unit tests, plus an interactive zsh test that drives a real shell through a pseudo-terminal. It types &lt;code&gt;rm -rf&lt;/code&gt;, presses &lt;code&gt;n&lt;/code&gt;, and checks the folder survived. GitHub Actions runs them on every push.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built this with Claude Code as my pair programmer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A terminal sees everything: file paths, hostnames, branch names, half-typed secrets, the command you ran at 2 a.m. I would never pipe that into a hosted API to get a joke back.&lt;/p&gt;

&lt;p&gt;With an open-weight model I don't have to. Gemma runs on my machine, so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works offline.&lt;/strong&gt; On a plane, in a basement, with Wi-Fi off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;My shell history stays mine.&lt;/strong&gt; No account, no logs on someone else's server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; A ghost that comments hundreds of times a day would be a real bill on a paid API. Here it's zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lock-in.&lt;/strong&gt; &lt;code&gt;GHOST_URL&lt;/code&gt; points at any OpenAI-compatible server. Swapping Gemma for another open model is one flag to llama-server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This only works because open models are now small and good enough to sit next to your shell and answer in under a second. A year ago this would have been a cloud API with a privacy policy. Now it's a file on my disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 4 E2B is the ghost, running locally through llama.cpp, with thinking turned off, example-driven prompting, and a measured before and after.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs:&lt;/strong&gt; seven horror sound effects made with the ElevenLabs sound effects API, played at random every one to three commands and cached so they work offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of GitHub Copilot:&lt;/strong&gt; GitHub Actions runs the unit tests and a zsh syntax check on every push.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Music: "Horror Music" by kiravale, via Pixabay. Code: MIT. Demo video: built with the &lt;a href="https://github.com/feitangyuan" rel="noopener noreferrer"&gt;onetake&lt;/a&gt; motion skill (PolyForm Noncommercial), narrated with the open Kokoro TTS model. The terminal in it is redrawn from the ghost's own code, and every ghost line in it is real Gemma output.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
