Kuyō 為已刪除程式碼舉行葬禮,由本機 Gemma 撰寫墓誌
Kuyō: a funeral for the code you deleted, written by a local Gemma
Mauricio Andrade 開發 Kuyō,掃描 Git 儲存庫中曾被刪除的檔案,按檔案壽命、刪除提交等資料計算死因與不安程度,再由本機 Ollama 執行的 Gemma 撰寫墓誌,生成單一 HTML 墓園。
This is a submission for the DEV Hacktoberfest 2026 Challenge, week 4: Ghost in the Machine.
EmailService.java, who managed the dispatch of status notifications for eleven days, met a swift end. It was decommissioned by the decree: "chore: remover EmailService (código morto, email de status não será usado)". May the unnecessary transmissions it once managed now find eternal silence.
I deleted that class myself, in a commit whose message calls it dead code. I never thought about it again until a Gemma model running on my own machine wrote it an epitaph.
Walk through the cemetery → (hover or tap a grave)
What I Built
In Japan, kuyō (供養) is a memorial service for objects that served well. Needles, dolls, brushes and even eyeglasses are thanked and laid to rest instead of just being thrown away.
Kuyō does the same for source code. You point it at a git repository and it:
- exhumes every file that was ever deleted, following renames so that a moved file isn't counted as dead;
- examines each death: how long the file lived, the hour it died, how large the commit that killed it was, whether any test witnessed it, and what its last words were (the commit message);
- scores its restlessness from 0 to 1 and decides the cause of death: violent, premature, forgotten or natural;
- asks Gemma, running locally on Ollama, to write an epitaph from those facts;
- renders a cemetery: one self-contained HTML file where restless souls haunt their graves.
It can also ask a code reviewer for an autopsy of each dead Java file, haunt your shell so that deleted files whisper back, and run as a GitHub Action that reburies your repository on every push.
kuyo scan path/to/repo # the dead and their cause of death, no LLM
kuyo bury path/to/repo # epitaphs + cemetery.html
kuyo seance path/to/repo EmailService.java # talk to a dead file
kuyo bury path/to/repo --autopsy # plus the Shishō's autopsy
kuyo haunt >> ~/.bashrc # deleted files whisper back
Demo
The cemetery above comes from stocklentes-hub, a private repository of mine: 137 deleted files in five months. The page shows only names, dates, commit messages and Gemma's epitaphs, and the code never left my machine.
- It is a Japanese cemetery: every file gets a granite family grave with its name carved in gold, sotoba slats behind it and incense in front.
- The facts are the scene. Pillar height follows the file's lifespan, and the hitodama (spirit flames) above each grave show how restless it is, from one calm blue flame to three trembling violet ones. Violent graves lean and a yūrei rises behind them, forgotten ones grow moss, and premature ones get a small Jizō with a red bib, as children's graves do in Japan.
- Approach a grave and its epitaph is brushed onto a washi strip, stamped with the cause of death as a vermilion seal (横死 violent, 夭折 premature, 無縁 forgotten, 天寿 natural).
- Turn the sound on for wind, crickets and an orin bell whose tone follows the cause of death, all synthesized in the browser.
Each terrace is a day or a month of deaths. When one commit took many souls at once, the terrace says so. In that private repo, 33 files fell together to a commit called fix: backend. Gemma noticed:
Frontend/src/assets/react.svg, who represented the spirit for eighteen short hours, vanished without fanfare. Its final word was the pragmatic "fix: backend", a most unpoetic exit.
Talking to the dead
kuyo seance summons one file's ghost. It answers in first person, remembering only its last contents and the facts of its life, so I went back to that EmailService:
> What did you do when you were alive? Be specific.
EmailService.java: My primary function was to send status change notifications via email.
I held a method, `enviarMudancaStatus`, which asynchronously dispatched messages detailing
updates to a specific order's status. I used a `JavaMailSender` to accomplish this task.
> Who was the president of Brazil when you died?
EmailService.java: The dead do not know such things.
The second answer is the one I'm proudest of. A ghost that makes things up would be a much worse ghost.
A haunted shell
kuyo haunt possesses your terminal. It prints a few lines of shell for your .bashrc or .zshrc, and from then on, deleting a tracked file has consequences:
$ rm src/main/java/dev/kuyo/haunt/Lines.java
$
霊 Lines, a mere four hours of existence, still trembles in the shadow of that `rm` command. Don't delete me yet; I have so much to say.
there is still time: git restore -SW -- ':/src/main/java/dev/kuyo/haunt/Lines.java'
That's Kuyō's own Lines.java, the file that holds what ghosts say when Gemma is away, begging for its life four hours after it was born.
The whisper arrives a few seconds after the prompt comes back, because Kuyō runs in the background while Gemma writes it. The file is examined as if it died right now, with your shell command as its last words. git reset --hard, git push --force and their friends get a line too, and every other command gets silence.
The Shishō's autopsy
Epitaphs are kind, but autopsies are not. Earlier this month I built Shishō (師匠, "master"), a reviewer that reads Java code the way a sensei reads a student's work. With --autopsy, every dead .java file goes on its table.
Kuyō rebuilds the file next to the pom.xml or build.gradle it lived with, as of the commit before it died, and carves the Shishō's lessons on the grave under a vermilion 師:
師 The Shishō's autopsy: medium · No centralized error handling (line 21)
That one is from SpikeResource.java, a spike endpoint in another project of mine that lived nine hours. When the Shishō finds nothing, the washi says the body died clean, and that was the verdict for EmailService. As with restlessness, no model is involved: the autopsy is deterministic.
Burying on every push
Kuyō is also a GitHub Action. Any repository can hold its funerals in CI:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: mauricioandrade/kuyo@main
with:
output: _site/index.html
Gemma runs on the runner itself, so the code still never goes to a third-party API, and cached epitaphs mean each push only pays for its new deaths.
Kuyō buries itself on every push, and its own cemetery already has a mass grave. Midway through the challenge I translated the codebase from Portuguese to English, and 24 files fell together in one commit: Legista.java (the coroner), Exumador.java (the exhumer), Falecido.java (the deceased) and the rest of their family, all killed by "refactor: write the code in English". The tool now holds funerals for its own past.
Code
mauricioandrade
/
kuyo
供養 A funeral for the code that's gone. Reads your git history, diagnoses how each deleted file died, and has a local Gemma model write its epitaph in a haunted HTML cemetery. Runs offline.
English · Português
In Japan, kuyō (供養) is a memorial service for objects that served well: needles, dolls, brushes, even eyeglasses. They are thanked and laid to rest instead of just thrown away.
Kuyō does the same for source code. It reads a repository's git history, finds every file that was deleted, and holds a funeral for each one: how it lived, how it died, and how restless its soul is. A local open-weight model writes the epitaphs, and the result is a cemetery in a single HTML page, where restless souls haunt their graves.
🔒 Your code never leaves your machine. Everything runs offline, with a model you control.
Built for the DEV Hacktoberfest 2026 challenge, week 4: Ghost in the Machine.
The demo cemetery comes from stocklentes-hub, a private repository of mine: 137 deleted files over five months. Its code stays…
How I Built It
Java 25 + Quarkus (picocli) for the CLI, JGit to read history without shelling out to git, LangChain4j to talk to Ollama, and Qute for the template.
The facts are Java's, the words are Gemma's
I wanted a hard rule: the model never decides anything. Restlessness is computed deterministically from five factors:
| Factor | Weight |
|---|---|
| Size of the death commit (log scale, maxes out at 50 files or 2,000 lines) | 0.30 |
| Hour of death, in the author's own timezone (midnight to 5 a.m.) | 0.15 |
Last words: empty, or remove, wip, hotfix, cleanup, oops… |
0.20 |
| No test touched in the commit (code files only) | 0.15 |
| Short life (log scale in hours) | 0.20 |
My first draft used linear scales with a seven-day cutoff for a "premature" death. When I ran it against 175 real deaths from nine of my repos, almost every file came out premature and tormented. In practice files die young and in mass graves: half of mine lived less than a day, and most died in commits touching 20 to 120 files. Log scales fixed the spread. The rename threshold also had to match git's 50%, because JGit defaults to 60% and was turning my refactors into deaths.
Gemma then receives only the result (file, lifespan, authors, cause, last words, hour, how many died alongside it) with one instruction: dry humor, and never invent a fact.
Three things that bit me
-
Gemma 4 thinks by default. My first request took 51 seconds and returned an empty epitaph: the model had spent its whole token budget reasoning. With
think: falseit takes about a second per epitaph. -
The Quarkus Ollama extension fixes the model id at build time. That contradicted the whole "swap the model" promise, so the chat model is built at runtime through a
Supplierinstead.KUYO_MODEL=whateverworks without a rebuild. -
Chrome groups
@font-faceby weight before it appliesunicode-range. My embedded kanji subset rendered as empty boxes until I declared it once per weight.
Everything stays in one file
The cemetery makes no network requests: every grave, lantern and flame is hand-drawn CSS and SVG, the typeface is embedded as small base64 subsets, and prefers-reduced-motion turns every animation off.
Why Does Open Innovation Matter?
Because the most interesting history is usually the one you can't share.
Proprietary code can't be pasted into a closed API, and that is exactly the code whose ghosts I wanted to meet. With an open-weight model on my own machine:
- Nothing leaves the machine. The demo above comes from a private repo, and that was never a problem.
- It costs nothing per run, so burying 137 files is a non-event.
- It works offline.
- The model is just a setting. Gemma today, whatever open model you prefer tomorrow.
Open tools made the rest possible: JGit, Quarkus, LangChain4j, Ollama, and an OFL typeface from the Shippori Mincho Project.
The Spirit of It
In Brazil, November 2nd is Finados, the day we visit our dead. It falls right after this challenge ends.
Every file in these cemeteries did a job once. Some lived eighteen hours to hold up a screen that changed the next morning, some were placeholders whose only purpose was to be replaced. The projects I work on today stand on all of them. Kuyō is a small way to say thank you before moving on.
Prize Categories
-
Best Use of Gemma: Gemma 4 (
gemma4:e4b) runs locally on Ollama and writes every epitaph from facts computed in Java, so private code stays private.
Credits
- Shippori Mincho B1 by the Shippori Mincho Project Authors, SIL Open Font License 1.1.
- Built with Quarkus, JGit, LangChain4j and Ollama.
- Reaction GIFs belong to their respective anime and shows.
- Pair-programmed with Claude Code. Every epitaph and every ghost's answer is Gemma's.
來源:DEV Community · dev.to




