cd /news/ai-tools/git-afterlife-i-held-a-seance-for-th… · home › topics › ai-tools › article
[ARTICLE · art-158949] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

git-afterlife: I Held a Séance for the Original flask.py

A developer built git-afterlife, a command-line tool that mines a repository's git history for deleted files and generates an HTML "ofrenda" altar honoring each one with birth and death dates, contributors, the killing commit, and an AI-written epitaph. A séance mode lets users converse with a deleted file's "ghost," which answers in first person based on its real code and history, powered by Gemma 3 4B running locally via Ollama. In a demo, the tool resurrected Flask's original single-file flask.py, deleted in 2010 by a commit reading "out with the old.

by read8 min views2 publishedOct 27, 2026

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

Every repository has a graveyard.

Somewhere in your git log there is a file that was born in a hopeful first commit, survived dozens of refactors, got blamed for bugs it didn't cause, and was finally deleted by someone typing a commit message like cleanup. Nobody lit a candle for it.

git-afterlife does. It is a small command-line tool that digs every deleted file out of a repository's history and builds them an altar: an ofrenda, like the ones families raise on Día de los Muertos so that the people they lost can find their way home for one night. Each file gets a place on the altar with:

Then there is the part that gave me chills the first time it worked: seance. You pick one dead file and talk to its ghost. It answers in first person, from its real code and history.

I pointed it at Flask, and the most famous ghost on the altar is flask.py: the original single-file Flask, born on 2010-04-06 in a commit called Initial checkin of stuff that exists so far., changed in 104 commits in less than three months, and laid to rest on 2010-07-02 by a commit whose entire message was out with the old. That file is where a framework used by millions of people started. git-afterlife gave it a candle.

This is what happened when I asked it why it died:

you › Why did they delete you?

spirit › It was a simple deletion, a regrettable act. Justin Quick, in a commit message stating, "out with the old," removed me from the repository. My final moments were a consequence of that single commit – a forgotten relic, purged from the git history.

Some of the epitaphs Gemma wrote for the altar:

The deceased Epitaph
flask.py "A microframework, purged with a dismissive 'out with the old.'"
tests/flask_tests.py "Served Flask tests faithfully, then vanished with a split."
setup.py "A simple setup, swiftly replaced by a modern plea."
docs/deploying/fastcgi.rst "It guided deployments, then vanished with a rewrite."

The demo is built from scratch by GitHub Actions: a runner installs Ollama, pulls Gemma 3 4B, clones Flask, raises the altar and holds a séance with flask.py, then publishes everything to GitHub Pages.

The altar is a single self-contained HTML page: papel picado swaying at the top, a flickering candle on every grave, marigold petals falling, and tiers like a real ofrenda, with one soul at the top and wider rows below. The first three souls also sat for a short séance, and their conversation is shown on their card. Open any card's portrait to read the file's last source code.

Try it on your own repository in under a minute:

ollama pull gemma3:4b      # or gemma3:1b on an older laptop
git clone https://github.com/PauLopNun/git-afterlife.git
python3 git-afterlife/afterlife.py summon /path/to/your/repo     # writes altar.html
python3 git-afterlife/afterlife.py seance some/deleted/file.py /path/to/your/repo

Or run it on any public repository without installing anything: fork the repo and use Actions → Raise the altar → Run workflow, choosing the repository and the model.

Every repository has a graveyard: files born in a hopeful first commit, carried through dozens of refactors, and finally deleted with a one-line commit message Nobody remembers them.

git-afterlife digs them out of your git history and builds them an altar, an ofrenda the altar families raise on Día de los Muertos to welcome back the ones they lost. Each deleted file gets a place on the altar with its birth date, its death date, the people who touched it, the commit that killed it, and an epitaph with its last words, written by an open-weight model running on your own machine.

You can also hold a séance and talk to the ghost of a deleted file. It remembers its real code, who created it, and why it was removed.

summon seance
Builds a self-contained HTML altar with papel picado, flickering candles, falling marigold petals and recorded séances

The whole tool is one Python file that uses only the standard library, so there is nothing to pip install. MIT licensed.

The open pieces: Gemma 3, Google's open-weight model, served by Ollama. git-afterlife talks to Ollama's HTTP API on localhost with plain urllib. There is no SDK and no cloud endpoint anywhere in the code.

1. Git archaeology. git log --diff-filter=D lists every deletion in the history. Files that were later resurrected at HEAD are skipped, and so are binaries. To decide who gets a place on the altar, one more git log --name-only counts how many commits touched each path, so the longest-lived source files are raised first while lock files and configs are left to rest. For each soul:

git log -- <path> up to the death commit gives its birth, its lifespan in commits and its mourners,git show <death>^:<path> recovers its final source code, 2. Grounding a small model. My first run with Gemma 3 1B worked end to end, and it was bad. Every epitaph was some variation of "lost in the digital dust, a silent plea", asking for another language with --lang was mostly ignored, and in the séance flask.py claimed it had been deleted because of "a subtle bug". That was invented: the commit says out with the old.

Three changes fixed most of it:

dateutil only appeared in my example. Every ofrenda has one guest who talks too much. 3. Recorded séances. summon --seances 3 interviews the first three souls with the same grounded prompt as the interactive séance, and prints the conversation on their card, so you can meet the ghosts without opening a terminal.

4. Don't trust a ghost that won't stop talking. Epitaphs are requested in Ollama's JSON mode ("format": "json"), but valid JSON is not the same as a sane answer. In one demo run, two epitaphs finished their sentence and then kept going: stray closing braces, a timestamp and a long run of nineteen-digit numbers, all inside a perfectly valid JSON string, printed on the altar. Now every answer has a token cap (num_predict), and any epitaph that is too long or contains braces or long digit runs is thrown away and asked for again. There is a test for exactly that ghost.

5. The altar. The HTML is generated with plain string templates and CSS animations: no JavaScript framework and no external requests, so the page works offline too.

6. Tests and the demo pipeline. The test suite builds a tiny real repository with births, deaths, a binary and a file that comes back to life, and swaps the model for a fake medium, so it checks every step in a fraction of a second without Ollama. It also caught a real bug while I was adding séances to the altar. GitHub Actions runs the tests on every push. The demo is built on demand, because model output changes on every run: the workflow installs Ollama on a standard ubuntu-latest runner, pulls Gemma 3 4B, runs everything on CPU, takes the screenshots in this post with headless Chrome, records the séance GIF with VHS and deploys it all to GitHub Pages.

Because the thing git-afterlife reads is your source code, and source code is the one thing many of us are explicitly not allowed to paste into a cloud chatbot. The repositories with the richest graveyards, a ten-year-old monolith at work or a client project, are exactly the ones whose code must not leave the building. With an open-weight model on localhost, it doesn't. You can hold a séance for your company's legacy billing module without sending a single line of it anywhere.

It also means:

--model takes any Ollama model: 1B on an old laptop, 4B for nicer prose, or something much larger on a GPU. Nothing in the code is tied to one vendor. The moment it landed was the last question of the séance. I asked the original flask.py, dead since July 2010, whether it had a message for the developers who use Flask today. It had answered every question with facts: Armin Ronacher created it, Justin Quick deleted it, it held Request, Response and Session. Then it turned its own cause of death back on us:

spirit › I whisper a warning: remember the roots! My design, born of Armin's meticulous work, still echoes within Flask. Respect the foundations, the careful layering of Werkzeug and Jinja2. My premature demise serves as a reminder – progress must be thoughtful, not simply… "out with the old."

That is the whole idea of Día de los Muertos, said by a Python file. The people who are gone stay alive while someone remembers them. Our code works the same way: almost everything we write will be deleted one day, often by us. The work still mattered, because the thing that replaced it was built on top of it. Flask is in production all over the world today because a 1,573-line file existed for 87 days in 2010.

Run it on your oldest repository. You will probably find a file you had forgotten you wrote. Light it a candle.

This post and the project were made with the help of AI coding tools. I reviewed, ran and tested everything that is described here.

── more in #ai-tools 4 stories · sorted by recency
── more on @git-afterlife 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/git-afterlife-i-held…] indexed:0 read:8min 2026-10-27 · —