DEV Community

Sagar Maurya
Sagar Maurya

Posted on

Séance: Summon the Ghost of a Dead GitHub Repo

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

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

Every developer has a repo they walked away from. It sits on GitHub with its last commit, its unanswered issues and a README full of plans that never happened. It isn't gone, only silent.

Séance gives it a voice.

You paste the link to an abandoned GitHub repo. Séance reads its description, README, open issues, recent commits, star count and last push date. A local Gemma model then plays the repo's ghost in the first person, and a haunted voice speaks the reply aloud. After that you can keep talking to it, asking why it died, what it was proud of and what it wished someone had finished.

I took "Ghost in the Machine" literally. A dead repo is a ghost in the machine: still there, still addressable, still carrying its own history. Séance turns that history into a story you can listen to.

Demo

Séance dashboard

Code

GitHub logo mauryasagar / seance

Summon the ghost of an abandoned GitHub repo. A local Gemma model plays the dead repo and ElevenLabs gives it a haunted voice. Hacktoberfest 2026.

🕯️ Séance

Summon the ghost of an abandoned GitHub repo.

Paste a dead repo's link and its ghost speaks to you in a haunted voice, telling you how it died. Then you can ask it anything.

An open-weight Gemma model runs locally on your machine and does the thinking, and ElevenLabs gives the ghost its voice.

Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine

Séance screenshot

How it works

  1. You paste a GitHub repo URL.
  2. Séance reads the repo through the GitHub API: the description, README, open issues, recent commits, stars and last push date.
  3. That becomes the ghost's "memories". A local Gemma model plays the dead repo in first person, using only those facts.
  4. The reply is sent to ElevenLabs for a whispery voice, then run through a small reverb and low drone so it sounds like it's coming from a crypt.
  5. You can keep…

How I Built It

The open-source AI. The ghost's brain is gemma4:e4b, an open-weight Gemma model that I run locally through Ollama. The system prompt gives it a persona and a set of rules: speak in the first person, be haunting and a little sad, mention specific details as memories rather than as a report, keep it to three short sentences, and use only the facts provided. Those facts come from four GitHub API calls: repo info, README, open issues and recent commits. Pull requests are filtered out of the issue list, so the ghost mourns real unanswered issues and not merged work.

The voice. The reply goes to ElevenLabs (eleven_v3), which understands expressive tags like [whispers] and [sighs]. I then process the raw audio myself in NumPy. A synthetic crypt-style reverb and a faint low drone sit under a single voice.

The interface. The UI is Streamlit with custom CSS and inline SVG, with no image assets: a blood moon, drifting clouds, bare branches, an owl with glowing red eyes, bats with flapping wings, step cards with torn edges, and a Summon button that drips.

What went wrong first

  • The ghost was slow. Gemma's "thinking" mode wrote out its reasoning before answering. Turning it off, keeping the model loaded in memory and capping the reply length made it feel immediate.
  • The voice wasn't scary. The default voice was clean and friendly. Dropping the pitch, adding a lot of echo and layering a second voice each made it worse. What worked was restraint: one voice, a subtle reverb and a quiet drone.
  • The best voice was behind a paywall. I picked a haunted voice from the ElevenLabs library, but free plans can't use library voices through the API. Shaping a built-in voice myself got me the sound I wanted anyway.
  • Moving files broke my environment. Reorganising the project folder left my virtual environment pointing at a path that no longer existed, so I rebuilt it from scratch. It was a boring bug, but it ate twenty minutes.

Why Does Open Innovation Matter?

Séance only works the way it does because the model is open.

  • No LLM API in the loop. The ghost's brain runs on my own laptop. There is no model bill, no rate limit and no API key for the model, and the repo text is never sent to a third-party LLM service. Only the GitHub fetch and the ghost's short spoken reply (sent to ElevenLabs for the voice) go online.
  • It degrades gracefully. If the voice service fails, the ghost still answers in text, because the thinking never depended on a closed API.
  • The model is swappable. The model name is one line in ghost.py. Pointing it at another open model gives the ghost a different personality, and I could tune the persona without waiting on anyone's roadmap.
  • It can't be switched off. A séance app built on one vendor's hosted model would disappear the day that model is retired. A project about remembering dead software shouldn't depend on a service that could become dead software itself.

I should be upfront about the one closed piece: the voice. The open model carries the project, and the voice is the finishing touch.

The Spirit of It

I summoned mojombo/grit, an old Ruby Git library, and the ghost said:

"I was... a vibrant engine, once powering grand things... Now, only echoes remain of my object-oriented grace..."

A dead project's own history, spoken back in a whisper, hit differently than reading its commit log ever has. Every abandoned repo was once someone's late nights and good intentions. Hearing it talk made me want to go back and finish one of mine.

Prize Categories

  • Best Use of Gemma: Gemma runs locally via Ollama and is the ghost's entire brain: persona, memory of the conversation and every reply.
  • Best Use of ElevenLabs: ElevenLabs text-to-speech gives the ghost its voice, using the expressive eleven_v3 model, with my own audio effects layered on top.

Top comments (0)