<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: kingmin8768</title>
    <description>The latest articles on DEV Community by kingmin8768 (@kingmin8768).</description>
    <link>https://dev.to/kingmin8768</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1327797%2F0efb0390-fbe6-4c23-b23d-4982526b97c5.png</url>
      <title>DEV Community: kingmin8768</title>
      <link>https://dev.to/kingmin8768</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kingmin8768"/>
    <language>en</language>
    <item>
      <title>Ghost in the Machine: git-spectre — Local AI Digital Séances for Your Haunted Git History</title>
      <dc:creator>kingmin8768</dc:creator>
      <pubDate>Wed, 28 Oct 2026 06:17:26 +0000</pubDate>
      <link>https://dev.to/kingmin8768/ghost-in-the-machine-git-spectre-local-ai-digital-seances-for-your-haunted-git-history-41g6</link>
      <guid>https://dev.to/kingmin8768/ghost-in-the-machine-git-spectre-local-ai-digital-seances-for-your-haunted-git-history-41g6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DEV Hacktoberfest Open-Source AI Challenge — Week 4: "Ghost in the Machine"&lt;/strong&gt; 🎃👻&lt;br&gt;
A submission for the Overall category and &lt;strong&gt;Best Use of Gemma&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/kingmin8768/git-spectre" rel="noopener noreferrer"&gt;https://github.com/kingmin8768/git-spectre&lt;/a&gt; · &lt;strong&gt;License:&lt;/strong&gt; MIT · &lt;strong&gt;Language:&lt;/strong&gt; Python · &lt;strong&gt;AI:&lt;/strong&gt; Google Gemma (open-weight, via Ollama) with a zero-dependency Standalone Haunted Engine fallback&lt;/p&gt;




&lt;h2&gt;
  
  
  👻 The Motivation: Your Commit History Is a Diary. Why Are You Pasting It Into a Chatbot?
&lt;/h2&gt;

&lt;p&gt;Before we get to the ghosts, let's talk about the &lt;em&gt;actual&lt;/em&gt; monster under the bed.&lt;/p&gt;

&lt;p&gt;Every developer's git history is an intimate document. It contains your real name, your email, the hour you actually go to bed, the functions you were ashamed of, the &lt;code&gt;wip&lt;/code&gt; confessions you never cleaned up, and the anatomy of proprietary code your company would rather not see pasted into a hosted LLM's training pipeline "anonymized or otherwise."&lt;/p&gt;

&lt;p&gt;And what does the AI-hype era tell us to do with that history? Paste it into a cloud chatbot for "AI-powered commit insights." That's not a feature; that's a data-leak dressed up in a Halloween costume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;git-spectre takes the opposite deal.&lt;/strong&gt; It summons the ghosts of your repository using a &lt;strong&gt;local, open-weight model — Google's Gemma, served on-device through Ollama&lt;/strong&gt; — and, when no model is installed, a built-in &lt;strong&gt;Standalone Haunted Engine&lt;/strong&gt; that needs nothing but Python. The consequence is the whole point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;strong&gt;Codebase privacy&lt;/strong&gt;: commit messages, authors, diffs, and blame never leave the machine. Not once, not anonymized, not "just the metadata."&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Zero-leakage by architecture&lt;/strong&gt;: there is no API call to make, no endpoint to misconfigure, no vendor to trust. Privacy here is not a policy — it is physics.&lt;/li&gt;
&lt;li&gt;✈️ &lt;strong&gt;Offline dev&lt;/strong&gt;: airplane, bunker, cabin in the woods — the séance works anywhere git works.&lt;/li&gt;
&lt;li&gt;💸 &lt;strong&gt;No keys, no costs, no rate limits&lt;/strong&gt;: no API token in your CI, no meter running on every haunting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open-weight models like Gemma are what make this trade possible: you get the ghost, the wit, and the personality — and the blame stays on your disk, where the ghosts belong.&lt;/p&gt;

&lt;h2&gt;
  
  
  🪦 What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;git-spectre&lt;/strong&gt; — &lt;em&gt;"the haunted git history &amp;amp; digital séance CLI"&lt;/em&gt; — treats every repository as what it truly is: a graveyard. Commits are graves, branches are crypts, TODO comments are voices still whispering under the floorboards. Four rites let you interact with the dead:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;git-spectre haunt&lt;/code&gt; — the ghosts review their own code
&lt;/h3&gt;

&lt;p&gt;It reads recent commits (or one you point at), profiles the &lt;em&gt;crime&lt;/em&gt; behind each one, and summons the departed developer's spirit to comment on it. Ghost personas are chosen from measurable sins:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Persona&lt;/th&gt;
&lt;th&gt;Summons when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🕒 &lt;strong&gt;The 3 AM Poltergeist&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;commits made between 00:00 and 05:00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👹 &lt;strong&gt;The Colossus&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;a single commit of 500+ changed lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🩹 &lt;strong&gt;The Bearer of 'WIP'&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;messages like &lt;code&gt;wip&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;tmp&lt;/code&gt;, &lt;code&gt;asdf&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📅 &lt;strong&gt;The Weekend Wraith&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Friday-and-later commits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👻 &lt;strong&gt;The Forgotten Contributor&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;everything else&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Real output from the demo repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;╭───── 834f3bf · Bob Cursed · 31 Oct 2024 03:14 · "wip" 1 file(s), +6/-0 ──────╮
│ The 3 AM Poltergeist 🕒                                                      │
│    ✦ This was written at 03:14 AM-ish. The dead keep those hours. So,        │
│ apparently, did Bob Cursed.                                                  │
│    ✦ The commit message reads 'wip'. Archaeologists of the future will weep. │
│    ✦ This grave dates to 31 Oct 2024. Whatever problem it solved, the        │
│ problem has since been reborn twice.                                         │
╰──────────────────────────────────────────────────────────────────────────────╯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;code&gt;git-spectre seance &amp;lt;file|commit&amp;gt;&lt;/code&gt; — the digital séance
&lt;/h3&gt;

&lt;p&gt;Light a candle, close the circle, and &lt;strong&gt;interrogate the spirit of whoever wrote a file&lt;/strong&gt;. On a file, git-spectre runs &lt;code&gt;git blame&lt;/code&gt;, identifies the dominant spirit, and puts the questions to &lt;em&gt;them&lt;/em&gt; — with the blame summary entered into evidence. This is the feature that hits hardest in code review culture: before you refactor someone's function, hear them explain themselves.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🕯️ Candle lit. Summoning the spirit of Bob Cursed…

╭───────────────── SÉANCE — Bob Cursed (departed 31 Oct 2024) ─────────────────╮
│ summoned via commit 834f3bf: "wip"                                           │
│                                                                              │
│   Q: Why did you write this?                                                 │
│   A: It was 03:14. I thought I was brilliant. I was merely awake.            │
│   Q: What were you thinking at the time?                                     │
│   A: The build was broken. The coffee was gone. The code wrote itself and I  │
│ signed it.                                                                   │
│   Q: Do you repent?                                                          │
│   A: I repent of nothing at 03:14. Repentance requires consciousness.        │
│   Q: Who else touched what you touched?                                      │
│   A: Top spirit: Bob Cursed holds 6 lines of 'cursed.py'. Their fingerprints │
│ are everywhere. So are mine.                                                 │
╰──────────────────────────────────────────────────────────────────────────────╯

The candle is out. The spirit returns to the blame.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;code&gt;git-spectre graveyard&lt;/code&gt; — Día de los Muertos for your dead code
&lt;/h3&gt;

&lt;p&gt;For the Day of the Dead side of the challenge window, &lt;code&gt;graveyard&lt;/code&gt; excavates four kinds of remains — &lt;strong&gt;TODO ghosts&lt;/strong&gt; 🕯️, &lt;strong&gt;commented-out corpses&lt;/strong&gt; 🥀, &lt;strong&gt;deprecated tombstones&lt;/strong&gt; 🪦, and &lt;strong&gt;zombie branches&lt;/strong&gt; 🧟 (unmerged, 90+ days cold, found via &lt;code&gt;merge-base --is-ancestor&lt;/code&gt;) — and raises an actual &lt;strong&gt;ofrenda&lt;/strong&gt;: a markdown altar, &lt;code&gt;OFRENDA.md&lt;/code&gt;, with ASCII tombstones, marigolds, pan de código, and &lt;em&gt;Rites of Resurrection&lt;/em&gt; that tell you how each kind of dead can either cross over or be laid to rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exhumation complete: 6 soul(s) found in 'demo-spectre'.

┃ 🕯️ todo           │ cursed.py:1 │ # TODO: fix this before the demo
┃ 🥀 commented_code │ cursed.py:2 │ # def old_summoning():
┃ 🪦 deprecated     │ cursed.py:4 │ @deprecated
┃ 🧟 zombie_branch  │ doomed      │ doomed

The altar has been raised: OFRENDA.md
Haunt Index: 34/100 — Actively Haunted 😱 — cold spots in the blame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the generated &lt;code&gt;OFRENDA.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        ╔═══════════════════════╗
        ║         R. I. P.      ║
        ║                       ║
        ║      TODO: fix th     ║
        ║                       ║
        ║   cursed.py:1         ║
        ╚═══════════════════════╝

&amp;gt; *"TODO: fix this before the demo"*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. &lt;code&gt;git-spectre diagnose&lt;/code&gt; — the Haunt Index
&lt;/h3&gt;

&lt;p&gt;One number for how haunted your repository is, from 🕯️ &lt;em&gt;Pristinely Poltergeist-Free&lt;/em&gt; to 💀 &lt;em&gt;Fully Possessed&lt;/em&gt;. It weighs witching-hour commits, cursed brief messages, colossal commits, all four kinds of dead code, and sole-author graveyards (a repository haunted by exactly one restless soul is its own kind of sad).&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Tech Stack &amp;amp; Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Python 3.9+ · Typer · Rich · the &lt;code&gt;git&lt;/code&gt; binary · Google Gemma (open-weight) via Ollama · a hash-seedable Standalone engine · pytest&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌────────────────────────────────────────────────────────────┐
│                      cli.py (typer + rich)                 │
│        haunt · seance · graveyard · diagnose · epitaph     │
└───────────────┬────────────────────────────┬───────────────┘
                │                            │
┌───────────────▼──────────────┐  ┌──────────▼─────────────────────┐
│      git_scanner.py          │  │       ghost_engine.py          │
│  (read-only exhumation)      │  │  dual-mode voices of the dead  │
│  · commit log + numstat      │  │  ┌──────────────────────────┐  │
│  · line-porcelain blame      │  │  │ OllamaGemmaEngine        │  │
│  · branch merge-base check   │  │  │  (Gemma via ollama run)  │  │
│  · dead-code excavator       │  │  ├──────────────────────────┤  │
│    TODO / FIXME / HACK / XXX │  │  │ StandaloneHauntedEngine  │  │
│    commented-out code        │  │  │  (hash-seeded personas,  │  │
│    @deprecated tombstones    │  │  │   zero dependencies)     │  │
│    zombie branches (90d)     │  │  └──────────────────────────┘  │
└───────────────┬──────────────┘  └──────────┬─────────────────────┘
                │                            │
┌───────────────▼────────────────────────────▼───────────────┐
│                     graveyard.py                           │
│   Día de los Muertos renderer → OFRENDA.md + terminal wake │
└────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The dual-mode engine is the technical heart.&lt;/strong&gt; &lt;code&gt;ghost_engine.py&lt;/code&gt; exposes one interface with two implementations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;OllamaGemmaEngine&lt;/code&gt;&lt;/strong&gt; — detects any pulled Gemma-family model with &lt;code&gt;ollama list&lt;/code&gt; (no network), builds a character prompt from commit metadata (author, hour, size, message) and lets Gemma improvise the ghost. When it narrates, the panel is stamped &lt;code&gt;via gemma2:2b&lt;/code&gt; so you always know whose voice you're hearing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;StandaloneHauntedEngine&lt;/code&gt;&lt;/strong&gt; — a deterministic, hash-seeded template engine. Each persona is selected from measurable properties of the commit (hour band, size band, message laziness, weekday), and the flavor lines are chosen with a RNG seeded by the commit sha — so the same ghost always says the same thing, which makes output reproducible for docs, demos, and CI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fallback is seamless and automatic: if Ollama exists but has no Gemma, or fails mid-séance, the standalone engine finishes the haunting and nobody notices the curtain move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The scanner is strictly read-only.&lt;/strong&gt; git-spectre never commits, never rewrites history, never touches a ref. The only file it creates is the altar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing:&lt;/strong&gt; 38 pytest tests build &lt;em&gt;real&lt;/em&gt; temporary git repositories — a 3 AM &lt;code&gt;wip&lt;/code&gt; commit, a cursed file, a zombie branch abandoned in 2020 — and run every command end-to-end against them, scanner to altar. All 38 pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎬 Demo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;git-spectre    &lt;span class="c"&gt;# or: pip install . from a clone&lt;/span&gt;
ollama pull gemma2:2b      &lt;span class="c"&gt;# optional — the standalone engine works without it&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;your-most-haunted-repo

git-spectre haunt          &lt;span class="c"&gt;# the dead review their own diffs&lt;/span&gt;
git-spectre seance src/    &lt;span class="c"&gt;# interrogate the spirit of a file's author&lt;/span&gt;
git-spectre graveyard      &lt;span class="c"&gt;# raise the OFRENDA.md altar for Día de los Muertos&lt;/span&gt;
git-spectre diagnose       &lt;span class="c"&gt;# how haunted is this repository, really?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full captured terminal sessions, including a complete &lt;code&gt;OFRENDA.md&lt;/code&gt; altar, are in the repository under &lt;a href="https://github.com/kingmin8768/git-spectre/tree/main/demo" rel="noopener noreferrer"&gt;&lt;code&gt;demo/&lt;/code&gt;&lt;/a&gt;. The README carries an extended, copy-pasteable transcript of every rite.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎃 How It Connects to the Theme
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Ghost in the Machine&lt;/em&gt; asks what it means for the past to keep living inside our tools. Here's the thing: it already does.&lt;/p&gt;

&lt;p&gt;The person who wrote a function at 3 AM in 2021 is still in every line they touched. They answer for it every single time someone runs &lt;code&gt;git blame&lt;/code&gt;. Their habits, their shortcuts, their one terrible Friday — all of it persists in the machine, silent, until summoned.&lt;/p&gt;

&lt;p&gt;Halloween gives those ghosts a &lt;strong&gt;voice&lt;/strong&gt;: &lt;code&gt;haunt&lt;/code&gt; and &lt;code&gt;seance&lt;/code&gt; let the departed explain, deflect, and complain about your refactoring plans. Día de los Muertos gives them an &lt;strong&gt;altar&lt;/strong&gt;: &lt;code&gt;graveyard&lt;/code&gt; treats dead code not as garbage to delete in shame but as &lt;em&gt;familiares&lt;/em&gt; worth honoring before you let them cross over — with marigolds, candles, and rites of resurrection instead of &lt;code&gt;rm -rf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And the AI twist that makes it all work: the ghost in the machine is running &lt;em&gt;in&lt;/em&gt; the machine. A local Gemma model channels your repository's actual dead without a single byte of them leaving the séance room. The ghost was never a metaphor. It was the blame.&lt;/p&gt;

&lt;h2&gt;
  
  
  📄 Repository &amp;amp; License
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kingmin8768/git-spectre" rel="noopener noreferrer"&gt;https://github.com/kingmin8768/git-spectre&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;🕯️ &lt;em&gt;Light a candle before you run &lt;code&gt;git blame&lt;/code&gt; next time.&lt;/em&gt; 🕯️&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>hacktoberfest</category>
      <category>ai</category>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
