This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine 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.
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.
Two things are kept strictly apart:
scan.py reads the working tree and the git history and reports: a secret in a file, a…
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.
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.
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.