cd /news/ai-tools/ofrenda-lighting-a-candle-for-the-fi… · home › topics › ai-tools › article
[ARTICLE · art-161392] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

ofrenda — lighting a candle for the files your repository deleted

A developer built ofrenda, an open-source command-line tool that scans a git repository's history for deleted files and generates a eulogy for each one using a locally run model. The tool reconstructs each file's lifespan from git metadata — the commit that created it, its contributors, and its content at the moment of deletion — then feeds that record to gemma3:4b via Ollama to produce a grounded epitaph and short story, writing the results to a single self-contained HTML page. It ships with flags for limiting output, swapping in smaller models, JSON export, and custom output paths.

by read5 min views1 publishedOct 31, 2026

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

Every git repository is a graveyard, and nobody holds the ceremony.

Somewhere in your history there's a pricing.html that shipped before the

product existed, an app_v2.py from the rewrite that never finished, a

stylesheet in hotpink you were proud of for six hours. git log will tell

you when they died. It will never tell you what they meant — so they rot,

unmourned, while you scroll past their filenames looking for something else.

ofrenda is the ceremony. It's a Día de los Muertos altar for your code:

$ ofrenda examples/graveyard-repo

ofrenda :: 4 departed :: model gemma3:4b

  [1/4] app_v2.py
          “Served 'eventually'. Rest now.”
  [2/4] index.html
          “A valiant start, now dust.”
  [3/4] pricing.html
          “A valiant, if misguided, attempt.”

  4 remembered, 0 unspoken

  ofrenda lit → …/ofrenda.html

The tool walks your history for every deleted file and digs up its whole

life: the commit that created it, the people who touched it, how many

commits it survived — and, on the eve of its death, the literal content it

was still carrying. Then it hands that record to a model running on your own machine and asks it to say a few words. What comes back is one

I interpreted "Ghost in the Machine" this way: the ghosts aren't monsters,

they're the dead we didn't memorialize, and the machine finally gets to

speak for them. Halloween gives you the graveyard; Día de los Muertos tells

you what to do there — remember deliberately, warmly, and with candles.

Who this is for: anyone who has ever rewritten a project "from scratch" and

later wondered what the old version actually did; maintainers doing cleanups

who want a moment of gratitude before the rm; teams onboarding someone who

needs to understand not just what exists, but what was tried and abandoned.

No deployment needed — it's your own machine, and the page it prints is a

single file you can open with the Wi-Fi off.

git clone https://github.com/itzneel05/ofrenda && cd ofrenda
ollama pull gemma3:4b
pip install -e .

python examples/make_demo_repo.py   # grows a small graveyard to mourn
ofrenda examples/graveyard-repo      # writes ofrenda.html

Real captured output — four dead files, four eulogies, straight from

gemma3:4b:

ofrenda :: 4 departed :: model gemma3:4b

  [1/4] app_v2.py
          “Served 'eventually'. Rest now.”
  [2/4] index.html
          “A valiant start, now dust.”
  [3/4] style.css
          “A vibrant blush, now gone.”
  [4/4] pricing.html
          “A valiant, if misguided, attempt.”

  4 remembered, 0 unspoken

  ofrenda lit → C:\...\ofrenda.html

And what the model wrote for pricing.html, verbatim from --json:

{
  "path": "pricing.html",
  "epitaph": "A valiant, if misguided, attempt.",
  "story": "Launched with a bold promise of zero cost, pricing.html bravely represented the nascent product — a testament to early enthusiasm and, frankly, a bit of optimism. Its short existence ended abruptly when the Demo Author deemed its message 'sad'.",
  "cause_of_death": "deleted",
  "beloved": ["Zero cost", "Early optimism", "A brief, memorable moment"]
}

Every claim in that story is grounded in evidence the tool actually fed it:

the file's content (<h1>Only $0 — because nothing works yet</h1>), the

commit that killed it (fix: pricing page was making everyone sad), and

its two-commit lifespan.

Other flags: --limit 10 (ten newest deaths), --model gemma3:1b

(smaller machines), --json (for scripting), --out altar.html.

https://github.com/itzneel05/ofrenda

ofrenda/gitdead.py — the archaeology: git log --diff-filter=D for deaths, --follow for birth/lifespan/contributors, git show <death>^:<path> for the content at death. Parses git's raw record separators byte-carefully (a fun bug: Python's splitlines() treats \x1e as a line break, which silently swallowed every finding until a test caught it).ofrenda/eulogy.py — prompt built from the evidence, plus a tolerant JSON parser for whatever the model decides to wrap it in (fences, chatty prefixes, trailing "Hope that helps!").ofrenda/client.py — stdlib Ollama client. No base-URL flag, no API key: 127.0.0.1:11434 and nowhere else.ofrenda/render.py — the altar itself: one HTML file, zero scripts, zero CDNs, everything escaped.tests/ — 24 tests,

flowchart TD
    A["git log --diff-filter=D<br/>which files died, and who killed them"] --> C["life record per file"]
    B["git log --follow + git show death^:path<br/>birth, lifespan, contributors, final content"] --> C
    C --> D["prompt built from the evidence"]
    D --> E["gemma3:4b on 127.0.0.1:11434<br/>(local, via Ollama)"]
    E --> F["epitaph · story · cause of death · beloved[]"]
    F --> G["HTML-escaped into one self-contained<br/>candle-lit ofrenda page"]

Zero runtime dependencies. Python 3.9+, git, Ollama, done.

Built with AI assistance in OpenCode, with Google's open-weight Gemma 3 running locally through Ollama.

Because the code that gets deleted is often the code you'd least want to

upload. Personal projects with your real name in the history. A client's

proprietary logic you still have an NDA about. The half-finished side

business. A repository that contains a layoff's worth of commit messages.

Asking a cloud API to read every deleted file in your history — and write

about your team while it's at it — is a question you'd never get a yes to,

which is exactly why the tool would be useless if it asked.

With an open-weight model on localhost:

--model gemma3:1b for speed, fine-tune Gemma on I didn't expect this part to land. The demo repo is synthetic — six commits

I wrote ten minutes earlier — and the model still produced, for a

two-line file named app_v2.py that returned the string 'eventually':

"Served 'eventually'. Rest now."

That's a two-line function getting a headstone. I ran it again and got a

different epitaph, same feeling. The point of Día de los Muertos was never

accuracy about the dead — it was the remembering. A tool that makes you stop

and read what your cleanup commit actually destroyed, for eight seconds

per file, on your own machine, is a small machine for exactly that.

gemma3:4b (and gemma3:1b) via Ollama is the sole author: every epitaph, story, cause of death and beloved-trait list comes from the model. There is deliberately no template fallback — if the model is missing, the tool stops, because a mad-libs condolence would miss the entire point.

── more in #ai-tools 4 stories · sorted by recency
── more on @ofrenda 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/ofrenda-lighting-a-c…] indexed:0 read:5min 2026-10-31 · —