Every developer has the same folder: a graveyard of side projects that got one weekend of energy and then vanished. todo-app, that-chat-thing, portfolio-v3. You open it, feel a small pang of guilt, and close it.
Rest in Repo turns that folder into an actual graveyard — one spooky static HTML page where each dead project gets a tombstone, a cause of death, and a eulogy written by a local Gemma model. Nothing leaves your machine.
Repo: https://github.com/mayankinkk/rest-in-repo
The rule: code decides the facts, the model only writes the voice
The core design decision is that the model never gets to decide why a project died. Deterministic rules read the git history and classify it:
if facts.lifespan_days <= 3 and facts.commit_count >= 3 and _is_weekend(facts.first_commit):
return _result("weekend_hack", reasons, "medium")
if facts.lifespan_days <= 7 and facts.commit_count >= 8:
rate = facts.commit_count / max(facts.lifespan_days, 1)
if rate >= 3:
return _result("hackathon_orphan", reasons, "medium")
Nine causes of death, from Born Dead (a few commits and gone) to Almost Shipped (deploy config present, then silence) to Hackathon Orphan (built in a blaze over five days, abandoned at the deadline).
The model's only job is to turn those facts into a eulogy. And it is not trusted with numbers.
The number validator
Small models love inventing statistics. The prompt says "use only the facts," but that's a request, not a guarantee. So every eulogy passes through a whitelist check:
allowed = {facts.commit_count, facts.lifespan_days, facts.file_count, ...}
bad = [n for n in numbers_in(eulogy) if n not in allowed]
if bad:
# regenerate with: "Your previous answer invented these numbers: ..."
If the model claims "1,432 commits" for a project with 40, it gets sent back. In testing, gemma3:4b invented a number on 1 of 6 eulogies raw and 0 of 6 after the retry loop; qwen2.5:7b was 0 of 6 raw but roughly twice as slow (~21s vs ~11s per eulogy). Full numbers in MODEL_COMPARISON.md.
What's on a tombstone
Each card carries a cause chip and confidence, the project's own last words used verbatim as its epitaph (a quote-checker refuses to put invented words in its mouth), a commit activity strip, and badges like night owl, "almost quit once (2354d gap)", and leftover TODOs. The time of death is pulled from the final commit — not the clock when the page was generated.
Buttons reveal more: a séance shows the last diff plus a weekday×hour commit heatmap; Resurrect offers a concrete 3-step plan to revive it; Export PNG draws a share card on a canvas. There's a scattered cemetery map view, anonymize mode, and fog drifting behind it all with candles you can blow out.
Why local and open matters here
This tool reads the contents of your private repos — commit messages, file trees, TODO counts, the half-finished diff you never pushed. Sending that to a closed API would be exactly wrong. Running Gemma through Ollama means the eulogies are generated with the lights off and the internet off, and your shame stays on your laptop. It costs nothing and needs no API key, which is the difference between a tool you actually run and one you don't.
Run it
ollama pull gemma3:4b
python3 main.py ~/projects --resurrection -o graveyard.html
20 unit tests over synthetic git fixtures cover the classifier.
Top comments (0)