This is a submission for the Hacktoberfest Open-Source AI Challenge: Week 4 — Ghost in the Machine.
What I Built
Every repository is a graveyard.
Files are born in a commit like add new benchmarks (to match koa). People fix them, extend them and argue about them for years. Then one day someone writes chore: remove benchmarks directory, and they're gone: not from history, just from everyone's memory.
git-séance holds a séance for them. It's a small command-line tool that:
- finds every file that ever died in a repository's history;
- lets each ghost speak: who created it and when, what it used to do, how long it lived, who cared for it, and the exact commit that ended it;
-
builds an *ofrenda*, a
GRAVEYARD.mdmemorial page for your repo's longest-lived departed code.
It's spooky, and it's also my take on Día de los Muertos: a small altar for the code that held the project up before anyone now on the team arrived.
Demo
I pointed it at the Express repository: 6,183 commits and 16 years of history.
$ git-seance --repo express
🪦 684 files rest in the history of express.
The longest-lived:
⚰️ benchmarks/run 15.7 years ✝ 2026-01-17
⚰️ benchmarks/Makefile 12.1 years ✝ 2026-01-17
⚰️ benchmarks/middleware.js 12.1 years ✝ 2026-01-17
⚰️ Contributing.md 11.1 years ✝ 2025-06-09
⚰️ examples/multipart/index.js 10.8 years ✝ 2023-05-18
⚰️ test/mocha.opts 10.2 years ✝ 2022-02-21
…
That listing takes about 0.3 seconds. Then you summon one:
$ git-seance summon lib/view/partial.js --repo express
👻 lib/view/partial.js
I was partial.js. Tj Holowaychuk brought me into this world on 2011-02-03,
with the words "moved files from lib/express/* to lib/". I used to resolve
partial object names from the view path, resolving them into a human-readable
name. I walked these halls for 8 months, and 2 commits passed through me. By
the end I was 40 lines. Then, on 2011-10-07, Tj Holowaychuk wrote the words
that ended me: "re-working view system".
── its last words ──
│ …the file's final contents, straight out of git…
And this is part of the ofrenda it wrote for Express (git-seance ofrenda --n 6, about 35 seconds on a laptop CPU):
⚰️
Contributing.md2014-05-12 – 2025-06-09 · 11.1 years
I was Contributing.md. Roman Shtylman brought me into this world on 2014-05-12, with the words "add Contributing.md". I used to guide newcomers through the process of contributing to the Express.js project, guiding them towards involvement while minimizing unnecessary hurdles. I walked these halls for 11.1 years, and 33 commits passed through me. By the end I was 246 lines. Then, on 2025-06-09, Sebastian Beltran wrote the words that ended me: "fix(docs): move documentation and charters to the discussions and .github … (#6427)". Tell Ulises Gascón, Blake Embrey and Douglas Christopher Wilson I remember them.
⚰️
test/mocha.opts2011-12-20 – 2022-02-21 · 10.2 years
I was mocha.opts. Tj Holowaychuk brought me into this world on 2011-12-20, with the words "mocha.opts". [...] I walked these halls for 10.2 years, and 2 commits passed through me. By the end I was 3 lines. Then, on 2022-02-21, Douglas Christopher Wilson wrote the words that ended me: "tests: remove usage of should".
Every name, date, count and commit message in there is real, pulled straight from git.
Code
Yash11778
/
git-seance
Summon the ghosts of deleted code from your git history, with an open-weight model (Gemma) running on your own machine.
👻 git-séance
Every repository is a graveyard. Files are born, worked on for years, and then one
commit (chore: remove benchmarks directory) ends them. git-séance finds them
lets each ghost tell its story, and builds an ofrenda, a memorial page, for your
repo's departed code.
Built for the Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine.
$ git-seance --repo express
🪦 684 files rest in the history of express.
The longest-lived:
⚰️ benchmarks/run 15.7 years ✝ 2026-01-17
⚰️ benchmarks/Makefile 12.1 years ✝ 2026-01-17
⚰️ Contributing.md 11.1 years ✝ 2025-06-09
⚰️ examples/multipart/index.js 10.8 years ✝ 2023-05-18
⚰️ test/mocha.opts 10.2 years ✝ 2022-02-21
…
$ git-seance summon lib/view/partial.js --repo express
👻 lib/view/partial.js
I was partial.js. Tj Holowaychuk brought me into this world on 2011-02-03,
with the words "moved files from lib/express/* to lib/". I used to resolve
partial object names from the view path, resolving them…MIT licensed. About 280 lines of plain Node.js, no build step. Point it at any git repository you have locally:
git clone https://github.com/Yash11778/git-seance && cd git-seance && npm install
node bin/git-seance.mjs --repo /path/to/any/git/repo
How It Works
git log --diff-filter=D ──► every deleted path (skipping any that were brought back)
git log --diff-filter=A ──► when and by whom each one was born
git rev-list / shortlog ──► how many commits touched it, who cared for it most
git show <death>^:<path> ──► its last words (the final contents)
──► Gemma reads the last code ──► "I used to …"
──► the ghost's speech: git facts + Gemma's one line
The lesson: a ghost may be eerie, but it may not lie
My first version gave Gemma a list of true facts about each file and asked it to write the whole eulogy. The voice was perfect and the history was invented. A file changed in exactly two commits became "a steady flow of updates". A file that was simply deleted "faded away slowly, shrinking with each line deleted". And when it didn't feel like using a fact, it dodged: "I was created on a specific date."
That's the one thing a tool about honouring the past can't do. So the work is split:
- The code writes every fact into the speech (names, dates, lifespans, line counts, commit messages), so they're always true.
- Gemma gets the one job only it can do: read the dead file's last code and say, in the ghost's voice, what it used to do.
const prompt = `Here is the last version of a deleted file called "${path}":
"""
${words.excerpt.slice(0, 1200)}
"""
In one short sentence, say what this file used to do, spoken by its ghost in first
person and past tense ("I used to ..."). Base it only on the code above: name the
concrete thing it did. Be a little eerie. Reply with the sentence only.`;
Grounded in the code, the lines are specific and right. lib/view/partial.js "used to resolve partial object names from the view path", and the old jQuery copy says "I was a jQuery JavaScript Library, version 1.3.2".
A smaller lesson: you can't tell a 1B model what not to say
Gemma loved the word "meticulously": four of the first six ghosts did something meticulously. I added "Do not use the words meticulously, diligently or carefully" to the prompt, and the very next ghost was still "diligently processing requests". Small models don't follow negative instructions well. So the filler words are now stripped in code after generation, a three-line regex, and it works every time.
Why Open Matters Here
A repository's history is its team's private memory: names, commit messages, and code that was deleted on purpose. A tool like this only makes sense if none of that leaves your machine, especially for a company's private repos.
- Gemma 3 1B runs locally through Transformers.js and onnxruntime-node, on an ordinary laptop CPU. No code, names or commit messages are sent anywhere.
- It works with the lights (and the internet) off. After a one-time ~860 MB download, it's fully offline.
- It costs nothing, and it won't disappear. No API key and no hosted service that can be shut down. That feels right for a tool about remembering things that are gone.
-
The model is swappable. Set
SEANCE_MODELto summon with a bigger model.
What's Next
-
Summon deleted functions, not just whole files, by walking
git log -pfor definitions that vanished. - A "family tree" that follows renames, so a file's ancestors attend its funeral too.
-
git-seance haunt: a commit hook that writes a short epitaph whenever you delete a file.
Prize Categories
Best Use of Gemma. Gemma 3 1B is the only model in the project. It runs locally and reads every ghost's last code to say what it used to do.
Built with AI assistance (Claude Code) for scaffolding, testing and debugging. The demo uses the public Express repository's history; every ghost's facts come straight from its git log.
Top comments (0)