{"slug": "ofrenda-lighting-a-candle-for-the-files-your-repository-deleted", "title": "ofrenda — lighting a candle for the files your repository deleted", "summary": "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.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine](https://dev.to/challenges/hacktoberfest-week4-2026-10-26)*\n\n**Every git repository is a graveyard, and nobody holds the ceremony.**\n\nSomewhere in your history there's a `pricing.html` that shipped before the\n\nproduct existed, an `app_v2.py` from the rewrite that never finished, a\n\nstylesheet in hotpink you were proud of for six hours. `git log` will tell\n\nyou *when* they died. It will never tell you what they meant — so they rot,\n\nunmourned, while you scroll past their filenames looking for something else.\n\n**ofrenda** is the ceremony. It's a Día de los Muertos altar for your code:\n\n``` bash\n$ ofrenda examples/graveyard-repo\n\nofrenda :: 4 departed :: model gemma3:4b\n\n  [1/4] app_v2.py\n          “Served 'eventually'. Rest now.”\n  [2/4] index.html\n          “A valiant start, now dust.”\n  [3/4] pricing.html\n          “A valiant, if misguided, attempt.”\n\n  4 remembered, 0 unspoken\n\n  ofrenda lit → …/ofrenda.html\n```\n\nThe tool walks your history for every deleted file and digs up its whole\n\nlife: the commit that created it, the people who touched it, how many\n\ncommits it survived — and, on the eve of its death, the literal content it\n\nwas 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\n\nI interpreted \"Ghost in the Machine\" this way: the ghosts aren't monsters,\n\nthey're *the dead we didn't memorialize*, and the machine finally gets to\n\nspeak for them. Halloween gives you the graveyard; Día de los Muertos tells\n\nyou what to do there — remember deliberately, warmly, and with candles.\n\nWho this is for: anyone who has ever rewritten a project \"from scratch\" and\n\nlater wondered what the old version actually did; maintainers doing cleanups\n\nwho want a moment of gratitude before the `rm`; teams onboarding someone who\n\nneeds to understand not just what exists, but what was tried and abandoned.\n\nNo deployment needed — it's your own machine, and the page it prints is a\n\nsingle file you can open with the Wi-Fi off.\n\n```\ngit clone https://github.com/itzneel05/ofrenda && cd ofrenda\nollama pull gemma3:4b\npip install -e .\n\npython examples/make_demo_repo.py   # grows a small graveyard to mourn\nofrenda examples/graveyard-repo      # writes ofrenda.html\n```\n\nReal captured output — four dead files, four eulogies, straight from\n\n`gemma3:4b`:\n\n```\nofrenda :: 4 departed :: model gemma3:4b\n\n  [1/4] app_v2.py\n          “Served 'eventually'. Rest now.”\n  [2/4] index.html\n          “A valiant start, now dust.”\n  [3/4] style.css\n          “A vibrant blush, now gone.”\n  [4/4] pricing.html\n          “A valiant, if misguided, attempt.”\n\n  4 remembered, 0 unspoken\n\n  ofrenda lit → C:\\...\\ofrenda.html\n```\n\nAnd what the model wrote for `pricing.html`, verbatim from `--json`:\n\n```\n{\n  \"path\": \"pricing.html\",\n  \"epitaph\": \"A valiant, if misguided, attempt.\",\n  \"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'.\",\n  \"cause_of_death\": \"deleted\",\n  \"beloved\": [\"Zero cost\", \"Early optimism\", \"A brief, memorable moment\"]\n}\n```\n\nEvery claim in that story is grounded in evidence the tool actually fed it:\n\nthe file's content (`<h1>Only $0 — because nothing works yet</h1>`), the\n\ncommit that killed it (`fix: pricing page was making everyone sad`), and\n\nits two-commit lifespan.\n\nOther flags: `--limit 10` (ten newest deaths), `--model gemma3:1b`\n\n(smaller machines), `--json` (for scripting), `--out altar.html`.\n\n[https://github.com/itzneel05/ofrenda](https://github.com/itzneel05/ofrenda)\n\n`ofrenda/gitdead.py` — the archaeology: `git log --diff-filter=D` for\ndeaths, `--follow` for birth/lifespan/contributors, `git show <death>^:<path>`\nfor the content at death. Parses git's raw record separators byte-carefully\n(a fun bug: Python's `splitlines()` treats `\\x1e` as a line break, which\nsilently swallowed every finding until a test caught it).`ofrenda/eulogy.py` — prompt built from the evidence, plus a tolerant JSON\nparser for whatever the model decides to wrap it in (fences, chatty\nprefixes, trailing \"Hope that helps!\").`ofrenda/client.py` — stdlib Ollama client. No base-URL flag, no API key:\n`127.0.0.1:11434` and nowhere else.`ofrenda/render.py` — the altar itself: one HTML file, zero scripts, zero\nCDNs, everything escaped.`tests/` — 24 tests, \n\n```\nflowchart TD\n    A[\"git log --diff-filter=D<br/>which files died, and who killed them\"] --> C[\"life record per file\"]\n    B[\"git log --follow + git show death^:path<br/>birth, lifespan, contributors, final content\"] --> C\n    C --> D[\"prompt built from the evidence\"]\n    D --> E[\"gemma3:4b on 127.0.0.1:11434<br/>(local, via Ollama)\"]\n    E --> F[\"epitaph · story · cause of death · beloved[]\"]\n    F --> G[\"HTML-escaped into one self-contained<br/>candle-lit ofrenda page\"]\n```\n\nZero runtime dependencies. Python 3.9+, `git`, Ollama, done.\n\nBuilt with AI assistance in OpenCode, with Google's open-weight Gemma 3 running locally through Ollama.\n\nBecause the code that gets deleted is often the code you'd least want to\n\nupload. Personal projects with your real name in the history. A client's\n\nproprietary logic you still have an NDA about. The half-finished side\n\nbusiness. A repository that contains a layoff's worth of commit messages.\n\nAsking a cloud API to read every deleted file in your history — and write\n\nabout your team while it's at it — is a question you'd never get a yes to,\n\nwhich is exactly why the tool would be useless if it asked.\n\nWith an open-weight model on localhost:\n\n`--model gemma3:1b` for speed, fine-tune\nGemma on I didn't expect this part to land. The demo repo is synthetic — six commits\n\nI wrote ten minutes earlier — and the model still produced, for a\n\ntwo-line file named `app_v2.py` that returned the string `'eventually'`:\n\n*\"Served 'eventually'. Rest now.\"*\n\nThat's a two-line function getting a headstone. I ran it again and got a\n\ndifferent epitaph, same feeling. The point of Día de los Muertos was never\n\naccuracy about the dead — it was the remembering. A tool that makes you stop\n\nand read what your `cleanup` commit actually destroyed, for eight seconds\n\nper file, on your own machine, is a small machine for exactly that.\n\n`gemma3:4b` (and `gemma3:1b`) via Ollama is the\nsole author: every epitaph, story, cause of death and beloved-trait list\ncomes from the model. There is deliberately no template fallback — if the\nmodel is missing, the tool stops, because a mad-libs condolence would\nmiss the entire point.", "url": "https://wpnews.pro/news/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted", "canonical_source": "https://dev.to/justchill/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted-4fn", "published_at": "2026-10-31 06:40:30+00:00", "updated_at": "2026-10-31 06:49:40.410886+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "generative-ai", "large-language-models"], "entities": ["ofrenda", "Ollama", "gemma3:4b", "GitHub", "Hacktoberfest"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted", "markdown": "https://wpnews.pro/news/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted.md", "text": "https://wpnews.pro/news/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted.txt", "jsonld": "https://wpnews.pro/news/ofrenda-lighting-a-candle-for-the-files-your-repository-deleted.jsonld"}}