DEV Community

Misbah Bagwan
Misbah Bagwan

Posted on Edited on

Command Casperr: a tiny hand-drawn ghost that haunts your PowerShell terminal πŸ‘»

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 built Command Casper, a tiny hand-drawn ghost that floats on your screen and haunts your PowerShell terminal.

You type a command but don't press Enter. You press Alt+G. Casper looks at what you typed and turns green, yellow or red:

  • 🟒 Green: it only reads things.
  • 🟑 Yellow: it changes something, but you can usually undo it (installs, copies, a git commit).
  • πŸ”΄ Red: it destroys something or is hard to undo (deletes, overwrites, --force, download-and-run).

Click the ghost and a speech bubble opens with a plain-English explanation, plus real facts about your actual folder: "this folder has 7 files, all edited today."

The theme gave me a perfect starting point. One of the example ideas on the challenge page was a haunted terminal that "possesses your shell." I wanted a friendly haunting, though. Casper isn't there to scare you. He's the ghost that says "hold up, human bean, think this through" right before you wipe a folder.

I'm fairly new to all of this, so I kept two rules:

  1. It never blocks Enter and never runs your command. It only looks.
  2. The AI never decides the colour. More on that below, because it's the most important design choice in the project.

Fun detail: the ghost is original pixel art I drew myself (witch hat, pumpkin, pink bow). Yes, "Casper" is also a famous cartoon ghost. I'm not affiliated with that character, and the art is mine. That's also why the shell command is spelled casperr.

Demo

Summon him and release him like this:

. D:\ghost\ghost.ps1
casperr summon     # "Casperr has been summoned!"
casperr release    # "Casperr has returned to the ghost realm!"
Enter fullscreen mode Exit fullscreen mode

When summoned, he drops in from above and settles. When released, he does the same thing in reverse and fades away. Green bobs slowly, yellow a bit quicker, and red is frantic, because red should feel a little panicky.

Code

πŸ‘» Command Casperr

A tiny hand-drawn ghost that haunts your PowerShell and warns you before you press Enter.

Type a command (don't press Enter), press Alt+G, and Casperr turns green, yellow or red. Click him for a plain-English explanation plus real facts about your folder.

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
















🟒 Green 🟑 Yellow πŸ”΄ Red
Only reads things Changes something, usually recoverable (installs, copies, git commit) Destroys or is hard to undo (deletes, overwrites, --force, download-and-run)

The one rule that matters

The rules decide the colour. The AI never does.

The colour comes from a plain, editable rules.json and a small deterministic engine (aliases, && chains where the worst command wins, quotes, > vs >>, -WhatIf making a command green, unknown commands default to yellow). The AI (Gemma 4, an open-weight model) is told…




How I Built It

The model: Gemma 4 26B (gemma-4-26b-a4b-it), an open-weight model, served through Google AI Studio's free tier. No credit card, no cost.

The most important decision: rules pick the colour, the AI only explains.

My first instinct was "let the model judge the command." But a model that can be talked into a different answer is a bad safety guard. So the colour comes from a plain, editable rules.json and a small rule engine: aliases, && chains (the worst command in the chain wins), quotes, > vs >>, and -WhatIf making a command green. Anything unknown defaults to yellow. It's deterministic: same input, same colour, every time.

I tested the engine on 114 commands (37 green, 33 yellow, 44 red) and all pass. The tests also run automatically on every push with GitHub Actions.

The AI arrives afterwards. The bubble opens instantly with template text, then Gemma's explanation fades in a moment later from a background thread. The prompt tells it the verdict is final:

"The verdict is RED and it is final. Never contradict it, never change it. Use ONLY the facts given below."

It only receives the command, the verdict with its reasons, and counts or sizes ("7 files, 18.6 KB"). Never file contents.

If there's no key, no internet, or the API errors out, the bubble just shows the template text. The tool never breaks.

Other bits: Windows PowerShell 5.1 with one PSReadLine key binding, a small tkinter window, and a plain UDP message to 127.0.0.1 between the two. The hook lives in the current terminal session only, with no $PROFILE edits and nothing installed system-wide. The AI part is pure Python standard library, so there's nothing to pip install. Everything lives in one folder.

What the model says

Same prompt, the rules choose the colour, Gemma 4 26B writes the explanation:

Command Rules said Gemma 4 26B
pip install requests 🟑 "This command installs Python packages by downloading code from the internet. Because it downloads new files to your system, it is marked as YELLOW."
Copy-Item .\rules.json .\rules.bak 🟑 "This command copies the file rules.json, which is 18.6 KB and was edited today, to a new backup file. This action is marked YELLOW because it copies files or folders."
Remove-Item .\art -Recurse -Force πŸ”΄ "This command will delete the folder named .\art and everything inside it. This folder contains 7 files that were edited today. This action is permanent and cannot be undone."
`iwr https://example.com/setup.ps1 \ iex` πŸ”΄

Across a 10-command test, all 10 answers came back in roughly 2 seconds each and none contradicted the rules. (These commands are only analysed, never run.)

Two models, and what went wrong (honest section)

I also tried the bigger Gemma 4 31B on the same free tier. It was a different story:

Model (free hosted tier) Answered
Gemma 4 26B 10 of 10 on every full run, about 2 s each
Gemma 4 31B 1 of 10 on the first run (server errors and timeouts), then 2 of 4 with retries, some taking over 100 s

That's one night, a free tier and small samples, so please don't read it as "the 31B is a worse model." It only says that the free hosted endpoint wasn't dependable for it, when I tried. It's also exactly why the template fallback exists.

Two bugs taught me something:

  • The empty answer. My first test returned nothing. Gemma 4 had spent my whole token budget "thinking" out loud (drafts, constraint checklists) and never reached the answer. I turned its thinking down and gave it more room.
  • The imaginary empty folder. For commands with no file facts, the model sometimes claimed "there are no files in the current folder." My prompt had literally said "Facts: none," and it read that as a statement about the folder. I changed the prompt to say nothing should be claimed about the folder when no facts exist. Because the rules own the colour, this could never have flipped a verdict. Still, it's exactly why I didn't let the model own the colour.

Why Does Open Innovation Matter?

I'll be honest about where open helped and where it didn't.

It helped:

  • Swapping models is one line. The model name lives in a .env setting. Comparing two Gemma sizes took one flag. The code also speaks the common OpenAI-style request format, so pointing it at another provider or a local server should be a config change. I haven't tested other providers yet.
  • It cost nothing. I have a budget of zero and no card, and the whole project runs on a free tier.
  • No lock-in for the important part. The thing that keeps you safe is a JSON file you can read, edit and argue with. The model is a replaceable explainer. If a provider changes its rules, Casper falls back to templates instead of dying.

Open weights are what make that choice mine and not the provider's.

The Spirit of It

Casper is meant to be a gentle kind of spooky. I drew him pixel by pixel, gave him a witch hat and a little pumpkin, and wrote him lines like "Spooky. Are you sure about this?" and "Watch out, mortal!" The goal was a ghost that makes the scary moment of pressing Enter feel a bit less lonely, and maybe makes you pause for one second before the red command.

The lines live in a plain personality.json, so you can rename him and swap "mortal" for anything you like.

Built by
Misbah Β· Dev: @misbah_bagwan

Prize Categories

  • Best Use of Gemma: Gemma 4 26B writes every explanation, through Google AI Studio.
  • Best Use of GitHub Copilot: I used GitHub Copilot in VS Code while building (the repo includes my Copilot instructions file), and the rule tests run automatically on every push with GitHub Actions.

Built with help from AI assistants (Claude and GitHub Copilot). The design decisions, the art, the rules and the testing are mine.

Music credits: nastelbom-halloween-halloween-music-621496 by Nastelbom, from Pixabay

Top comments (0)