DEV Community

Cover image for Git Graveyard: a pixel cemetery where a local Gemma writes epitaphs for your deleted files
Ch Yasaswini
Ch Yasaswini

Posted on

Git Graveyard: a pixel cemetery where a local Gemma writes epitaphs for your deleted files

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

I pointed a 3B model at the deleted files of one of my repos and it gave me this:

In nec emberly, DoricFrieze.jsx, 2026-10-17 to 2026-10-25, by Yasaswini-ch, in a cold, silent delete. Aeon in bytes.

"In nec emberly" is not a phrase. It is, however, exactly the kind of thing that should be carved on a tombstone, and it is why I built this.

What I Built

Git Graveyard is a tiny pixel game. You are a gravedigger walking through a night cemetery. Every tombstone is a file that was deleted from a git repo. Walk up to one, press E, and an epitaph for that file appears in a text box, written by a local open-weight model. Nothing leaves your machine.

The graveyard at night: tombstones by file type, candles, two ghosts

How I read the theme: Halloween on the surface, honoring the past underneath. A deleted file was somebody's afternoon, or somebody's week. It mattered once, it got replaced, and git log is the only place that remembers it. The graveyard is a small ofrenda for that work: the oldest file gets a candle, the freshest grave burns blue, and any file that lived over a year gets a candle of its own.

A few details that make it feel like a place:

  • Tombstone shape follows file type: a cross for .py, a slab for .css/.html/.md, an obelisk for images, round for everything else.
  • Two ghosts drift around. The second one wanders left until you stand at a grave, then floats over to keep you company.
  • Footsteps are generated in code, so there are no audio assets.
  • A repo that has never deleted a file gets its own screen:

This repo is immortal

Demo

The same graveyard read through two different models. Press Tab in the game to swap between them:

gemma3:4b qwen2.5:3b
gemma3:4b epitaph qwen2.5:3b epitaph

Code

Git Graveyard

A pixel gravedigger walks a night cemetery. Every tombstone is a file deleted from a git repo; press E at one to read an epitaph written by a local open-weight model. Nothing leaves your machine.

The graveyard at night: tombstones by file type, candles, two ghosts

Screenshots

The same graveyard read through two models (Tab switches between them). In these runs gemma3:4b (left) wrote shorter, tidier epitaphs, while qwen2.5:3b (right) ran long and leaned on the dates.

gemma3:4b qwen2.5:3b
gemma3:4b epitaph qwen2.5:3b epitaph

A repo with no deleted files gets this screen:

This repo is immortal

Run

pip install pygame
ollama pull gemma3:4b          # or run llama-server with a gemma-3 GGUF
python graveyard.py /path/to/repo 40 gemma3:4b graves.json
python game.py
Enter fullscreen mode Exit fullscreen mode

graveyard.py <repo> <limit> <model> <output> — for llama-server instead of Ollama, switch URL at the top of the file.

Compare two models

python graveyard.py /path/to/repo 12 gemma3:4b graves.json
python graveyard.py /path/to/repo 12 qwen2.5:3b graves_qwen.json
python game.py graves.json graves_qwen.json    # Tab swaps the epitaph between models
Enter fullscreen mode Exit fullscreen mode

Controls

Arrows/WASD walk…

Run it:

pip install pygame
ollama pull gemma3:4b
python graveyard.py /path/to/repo 40 gemma3:4b graves.json   # asks the model, writes graves.json
python game.py                                               # walk around
Enter fullscreen mode Exit fullscreen mode

How I Built It

Two Python files, standard library plus pygame. No image assets.

1. Dig up the dead. graveyard.py shells out to git:

git("log", "--diff-filter=D", "--name-only",
    "--format=@@%H|%an|%ad|%s", "--date=short")
Enter fullscreen mode Exit fullscreen mode

Every file that was ever deleted comes back with who deleted it, when, and the commit message. A second call with --diff-filter=A finds the day each file was born.

2. Ask the model. Each file goes to a local model through the OpenAI-style endpoint that both Ollama and llama-server expose:

PROMPT = """Write a two-line epitaph for a deleted source file.
File: {path}
Born: {born}
Died: {died}
Killed by: {killer}, commit message "{message}"
Tone: dry, affectionate, slightly spooky. Under 25 words. No emojis. Output only the epitaph."""
Enter fullscreen mode Exit fullscreen mode

I used Gemma 3 4B through Ollama. The model only ever sees the path, the dates, the author and the commit message, never the file's contents. That keeps the prompt tiny and the run fast, but it also means an epitaph can only be as informed as the commit message.

3. Draw the cemetery. The sprites are strings in the code:

TOMB = [
    "...######...",
    "..########..",
    ".##########.",
    "mm########mm",   # moss at the base
]
Enter fullscreen mode Exit fullscreen mode

Everything is drawn on a 320x180 surface and scaled up 4x with nearest-neighbor, so the pixels stay crisp. I first rendered the text on that tiny canvas too, and it was unreadable. The text now draws at screen resolution, on top of the pixel art.

Comparing models is one argument. Run the script twice with two models, then python game.py graves.json graves_qwen.json and press Tab to swap every epitaph between them.

Where a small model is weak

I would rather say this than oversell it:

  • Gemma 3 4B repeats itself. Across 12 graves, "a fleeting design" and "Here lies X, a valiant, if brief…" showed up over and over. It writes tidy, on-tone epitaphs, but they blur together by the fifth tombstone.
  • Qwen 2.5 3B is wilder and worse. It went past the "under 25 words" instruction on a couple of graves, tended to restate the dates, and produced the "In nec emberly" line above.
  • Neither knows why a file died. With only a commit message to go on, the "cause of death" is a guess dressed up as poetry.

Why Does Open Innovation Matter?

Repo history is exactly the kind of data you don't want to paste into someone else's API: old secrets that were "removed" in a later commit, private file names, embarrassing commit messages. Here the model runs on localhost, and so does everything else in the project. I tested it with Wi-Fi turned off and it worked the same. It also costs nothing per file, so running it on a repo with hundreds of deleted files is free.

The second thing open weights gave me is the freedom to swap the model with one argument and compare two of them side by side on the same graveyard, with no account and no per-call cost. That comparison is the most honest part of this project: it is how I found out that the smaller model is not just less polished, it is less obedient. I'm not alone in wanting this local-first setup: Pouria Zand's I Built a Private AI Assistant That Queries My Git History and Project Management Data — Using Only Local LLMs makes the same argument for a different tool.

I built this with Claude Code as my coding assistant, and the post is marked as AI-assisted.

Prize Categories

Best Use of Gemma: every epitaph in the main run comes from Gemma 3 4B, running locally through Ollama.

Top comments (0)