DEV Community

Sandip Ghorai
Sandip Ghorai

Posted on

I Held a Seance for a Dead Repo (Offline, With Open-Source AI)

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

This is my submission for the Hacktoberfest Open-Source AI Challenge: Ghost in the Machine.

What I Built

Every developer has a graveyard: abandoned side projects, archived repos, and tools that were loved once and then went quiet.

Gitseance lets you hold a séance for them. Point it at any git repository and it reads the full history. Then you can talk to the Spirit of the Repo, a ghost made only of its commits.

🕯️ Ask the spirit: Why was the cache rewritten three times?
👻 I remember... a winter of bugs. The first cache failed under load. The second
   was a hurried fix, "temp hack, fix later." Later never came...
🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025 🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025

It is spooky, but it is also useful. The spirit explains why code exists, which is the thing documentation never captures. Because it speaks only from the history, when it doesn't know something it says the void is silent instead of making things up.

I also see it as a small ofrenda for forgotten open-source work. The people who built these tools deserve to be remembered, and their work is more than git log output.

How It Works

  1. git log extracts the repo's memories (hash, author, date, message, body)
  2. Each memory is embedded locally with nomic-embed-text
  3. Your question retrieves the 6 most relevant memories by cosine similarity
  4. A local Llama model answers in the voice of the ghost, constrained to those memories only

Everything runs through Ollama. No API keys, no accounts, no network calls.

import subprocess, sys, math, ollama

CHAT, EMBED = "llama3.2", "nomic-embed-text"

def history(repo, limit=400):
    out = subprocess.run(
        ["git", "-C", repo, "log", f"-{limit}", "--pretty=%h|%an|%ad|%s%n%b%x00", "--date=short"],
        capture_output=True, text=True).stdout
    return [c.strip() for c in out.split("\x00") if c.strip()]

def embed(t): return ollama.embeddings(model=EMBED, prompt=t)["embedding"]

def cos(a, b):
    return sum(x*y for x, y in zip(a, b)) / (math.sqrt(sum(x*x for x in a)) * math.sqrt(sum(y*y for y in b)))

def main(repo):
    commits = history(repo)
    print(f"Raising the dead... reading {len(commits)} memories")
    index = [(c, embed(c)) for c in commits]
    system = ("You are the Spirit of this repository, a ghost made only of its commit history. "
              "Speak in eerie, wistful first person ('I remember...'). Use ONLY the memories given. "
              "If you don't remember something, say the void is silent. Never invent facts.")
    while True:
        q = input("\n🕯️  Ask the spirit: ")
        qv = embed(q)
        top = sorted(index, key=lambda x: cos(qv, x[1]), reverse=True)[:6]
        memories = "\n---\n".join(c for c, _ in top)
        r = ollama.chat(model=CHAT, messages=[
            {"role": "system", "content": system},
            {"role": "user", "content": f"Memories:\n{memories}\n\nQuestion: {q}"}])
        print("\n👻", r["message"]["content"])

main(sys.argv[1])
🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025 🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025

Run it:

ollama pull llama3.2 && ollama pull nomic-embed-text
python gitseance.py ./some-dead-repo
🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025 🔥 ข่าวด่วน: sandip ghorai dafbbc/i held a seance for a dead repo offline with open source ai - Kapook Update 2025

Demo

[Insert screenshot or GIF of your terminal séance]

Code: github.com/YOURNAME/gitseance

Why Open Innovation Matters Here

This project could not exist the same way on a closed API.

  • Privacy: Commit history from private or proprietary repos is sensitive. With a local model, a séance on your company's code never leaves your laptop.
  • It works with the lights off: With Wi-Fi disabled, the ghost still talks.
  • Swappable minds: A small 3B model is fast, terse, and creepy. A larger one is more poetic and verbose. Changing the ghost's personality is a one-line edit, with no vendor lock-in.
  • It can't be deprecated: A tool about preserving dead projects shouldn't depend on a service that might shut down. The weights sit on my disk, so the ghost can haunt me for as long as I want.
  • Free: Nothing to pay for, so it's fine to run on hundreds of repos.

What I Learned

  • Grounding matters. My first prompt let the ghost invent dramatic backstories, which was fun but false. Restricting it to retrieved memories, with a "the void is silent" fallback, made it more trustworthy and spookier.
  • Small local models are good enough for retrieval-grounded storytelling.
  • Ethics: The ghost speaks as the repository, never as a real person. I didn't want to impersonate any maintainer.

What's Next

  • An --ofrenda mode that generates a Markdown tribute page for any dead repo
  • Indexing issues, PR comments, and TODOs as "unfinished business"
  • A candle-lit terminal UI

Try it on your own abandoned project. Fair warning: it may remember things you'd rather forget. 👻🕯️

Top comments (0)