This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
The Fool is an AI that lives in your git repo and looks broken on purpose. Its brain loads to 12% and stays there. Ask it something easy and it sometimes answers with obvious nonsense. Then, out of nowhere, it interrupts, jumps your code view to a file and line, and tells you about a real mistake you made: the TODO you wrote 40 days ago, the file you edited and never committed, the commit you made at 3 AM.
The scary part is meant to be the gap between how stupid it acts and how much it actually knows. I wanted a fool that is not a fool.
It runs entirely on your machine with Gemma (through Ollama). It is read-only: it never changes your repo and never runs your code.
Demo
Code
The Fool
My entry for Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine.
The Fool is an AI that lives in your git repo. It looks broken and unfinished on purpose: it stutters, it loads its brain to 12% and stays there, and when you ask it something it sometimes says something obviously stupid. But it has read every file in your project, and every now and then, out of nowhere, it interrupts to point out a mistake you made. A real one, with the file, the line and the date.
It runs entirely on your machine with a small open model (Gemma through Ollama). It is read-only: it never changes your repo and never runs your code.
How it works
Two things are kept strictly apart:
-
Code finds the mistakes.
scan.pyreads the working tree and the git history and reports: a secret in a file, a…
How I Built It
The whole design rests on one split: the model suggests, code verifies.
Code finds the mistakes. scan.py reads the files and the git history and reports secrets (including ones you deleted but git remembers), tracked .env files, syntax errors, leftover debuggers and print("here"), bare except:, old TODOs, empty files, stub functions, unused imports, files edited and never committed, and commits after midnight. Every finding has an exact file, line, time and quote. A small language model is bad at counting days or noticing line 214, so I did not ask it to.
The model only talks. When you chat, Gemma answers from the three most relevant snippets of the repo and has to cite file and line. Code then checks every citation against the real files and drops the ones that do not exist. Haunts are worded by templates by default. With --phrase model, Gemma can reword them, but only if its line still contains the file name and every number from the finding.
The "stupid" answers never come from the model. They are fixed lines, and the interface labels them "glitch, not an answer". A real wrong answer from a model is a bug. A staged one is a character, and I did not want the two to be confusable.
Finding the right file was the hard part. My first search was plain word matching. On 20 questions I wrote about my own project, in my own words, it put the right file in the top 3 snippets 65% of the time. Asking "where is the average duration calculated" does not match a function called avg_dur. I added synonyms, prefix and typo matching, a boost for definition lines and a penalty for README files, which took it to 70%. An optional step where Gemma first guesses likely code names took it to 80% (16 of 20), at the cost of one extra model call per question.
What the numbers do and do not show
- Scanner on planted mistakes: 67 of 67 found, no false alarms, on 12 sample repos. This is a sanity test. I wrote the mistakes and the scanner, so it proves the scanner does what I meant and nothing more.
- Scanner on real code. I ran it on click, requests and my own unfinished project. The first run flagged test certificates as secrets, so I excluded test folders and cut noisy stub and import rules. I tuned those rules after seeing real output, so they are heuristics, not a benchmark. On my own project it found 15 things (5 uncommitted files, one untouched for 138 days; 2 after-midnight commits; 8 unused imports). All were real.
- Q&A on my 20 questions: retrieval 65% → 70% → 80% as above. That is 20 questions, so each one is 5 points, and I tuned the default rules after seeing it fail on these same questions, so 70% is not a clean result. It still misses 4 of 20.
- Citations prove a line exists, not that the answer is right. 19 of 20 answers had a real file:line receipt, but some of those pointed at the wrong file.
- Most checks are Python-specific. On my laptop (8 GB RAM, no GPU) Gemma 3 4B takes about 60 seconds per answer.
Why Does Open Innovation Matter?
A tool that reads your private code and your git history should not need to send either to a server. Because Gemma is open and small enough to run locally, the haunting stays on your machine, and you can read every rule in scan.py to see exactly what it will accuse you of. Being open also let me limit what the model is allowed to do, which is the point of the project.
My Agent Session
I built The Fool in conversation with Claude. The idea and the character are mine: an AI that looks stupid and glitchy but secretly knows everything, and haunts you with a real mistake. Claude helped turn that into a design and wrote most of the code. I directed it, ran everything on my own machine and repo, and decided what went in.
How the session actually went:
Design pushback. I started with a vague “spooky AI”. Claude proposed a design where code finds the mistakes and the model only talks. I kept that design because it made the haunts trustworthy.
Real-world testing found problems. I ran the scanner on my own unfinished project. It found 15 things, and I felt called out. Early Gemma answers took 100 to 160 seconds, and one answer looped. We fixed these by shrinking the context and cutting repeated text.
My own evaluation exposed a weakness. I wrote 20 questions about my own repo in natural wording. The first search scored 65%. That drove the search rules and the optional --expand step, which reached 80%.
My feedback changed the interface. I disliked the first chat-only UI, so we rebuilt it as a code viewer where haunts fly in over the exact line and fade out.
Claude made mistakes too. It got the deadline time and the weekdays wrong, and I corrected it. Its sample tests were circular, which is why the post calls them sanity tests.
What I did myself: the concept, running and testing on real repos, writing the 20 questions, choosing what to keep, recording the demo and writing the final post.
The Spirit of It
I did not want an AI that is merely creepy. I wanted one that is wrong in a way you can see and right in a way you can check. The fool's nonsense is labeled and staged. The haunts come with receipts. When I ran it on my own half-finished project and it told me a file had sat uncommitted for 138 days, it felt like being called out, and I could not argue, because it was right.
Prize Categories
- Best Use of Gemma: Gemma 3 4B runs locally through Ollama. It answers questions about the repo and can reword haunts. Its output is never trusted without a code check.
- Best Use of ElevenLabs: the narration in the demo video is generated with ElevenLabs. The app itself does not use ElevenLabs: its optional "speak aloud" uses the browser's built-in local voice, so nothing from your repo is sent to a cloud service.


Top comments (0)