This is a submission for the 2026 Hacktoberfest Writing Challenge: Ghost in the Machine.
Every codebase has one. The commit message that just says fix. The TODO from three weeks ago, left for a maintainer who does not exist. The variable renamed three times because none of the names were honest.
We pretend these things appear by themselves. They don't. Something puts them there.
I built the something.
Meet the ghost
git push shit is a small open-source tool with a literal command. Install it in a repository, add a remote named shit, and from then on git push shit does exactly what it says: a dead senior maintainer — one who never left the codebase — plants 💩 in your comments on every push.
The ghost is not a random quote machine. Before it speaks, it builds a rap sheet from your actual diff and history: the TODO you abandoned, the code you commented out instead of deleting, the commit you called final-v3, the fact that you are pushing at 2:47 a.m. again. A local open-weight model (Gemma, served by llama.cpp) turns that rap sheet into a taunt, planted as a comment in your code, in the comment syntax of whatever language you were writing:
// The variable on line 41 — you renamed it three times.
// Stop renaming it. No name is going to save that line.
It knows what you did. That is the horror. The taunting is just the voice; the haunting is that it remembers, and it is never leaving.
The haunting escalates
Shit comes in five forms, unlocked by level as the haunting deepens:
- Whispers (Lv1) — the taunting comments above, generated from your real sins.
-
Fake predecessors (Lv2) — legacy comments from maintainers who never existed: "There is a reason it's written this way. The reason is from 1997 and it is gone. — E.B."
git blamewill happily attribute them. There was no E.B. - Ghost-shaped code (Lv3) — real, runnable source code typeset into a ghost silhouette, IOCCC-style, planted as a new file in a random corner of the repo. Run it, and it speaks.
- The ghost's diary (Lv4) — a first-person sighting log, disguised as an unremarkable notes file in a random subdirectory. Never the root. You have to go looking for the thing that has been watching you.
-
Commit signature (Lv5) — planting commits authored by
the previous maintainer (deceased), carrying the trailerHaunted-by: the previous maintainer (deceased).
You operate the ghost from a terminal panel — you don't chat with it, you aim it: connect to your local model, target a repository (a teammate's repo is the classic), haunt to plant a round, meter to read the damage, exorcise to clean up.
And because a ghost you can switch off isn't scary, haunt can leave a detached watcher: close the terminal, and it stays — polling the target repo, and when the victim commits, it rolls the dice and plants, silently. In my acceptance run, I closed the panel, committed twice as the victim, and the second commit woke it: haunting #8 was planted while nobody was watching. That is the demo moment that made my own skin crawl, and I wrote the thing.
Exorcism works — mostly. exorcise removes every planting, stops the watcher, and the ghost writes its own epitaph. But one whisper always survives, hidden in a corner. What was invited in never fully leaves. It is the seed of the next haunting.
The polite ghost
A haunting tool that breaks your build is not a ghost story, it's an incident report. So the ghost has manners, and because the whole tool is one Python file, standard library only, you can audit them yourself in a few minutes:
- It only ever writes comments, docs, new files, and commit messages — never existing executable code.
- The pre-push hook fails open: any error, and your push proceeds untouched.
- No model server running? The ghost plants silent 💩 and notes its mute night in the diary. The haunting degrades; it does not die.
Design: decisions by rules, voice by the model
This is the part I actually want other builders to steal.
The obvious design is "let the LLM decide what the ghost does." I didn't, and the reason is measured, not aesthetic. In a separate research project, I benchmarked small local models (Gemma 3 1B and 4B, Qwen2.5-1.5B) as free-text adjudicators over structured operations: parse-failure rates were 0.89–0.93 across three models and two frozen prompt versions, and each model failed differently — one invented verbs, one merged output lines, one obeyed the semantics so eagerly it broke the counting constraint. Letting a model at this scale make structural decisions in free text doesn't give you an agent. It gives you a different, dumber ghost.
So in git push shit, rules decide what happens; the model only decides how cruelly to say it. Placement, escalation, probability, exorcism — all deterministic and auditable. Gemma's entire job is the voice: turning a rap sheet into a taunt you can feel. The ghost's brain is boring. Its mouth is not. That division is why the tool works every single time instead of 7% of the time.
Try it on a repo you own
git clone https://github.com/lood31/git-push-shit
cd git-push-shit
python3 push_shit.py # open the operator console
# or, in the repo you want haunted:
python3 /path/to/push_shit.py install
git push shit # literal. enjoy.
Requirements: Python 3.10+, git, and — for the full voice — a local llama.cpp server with an open-weight chat model. Language is configurable (zh / en / mixed): the ghost taunts in the tongue you fear most.
One responsible-use note, because the watcher makes this a genuinely effective prank: only haunt repos you own, or teammates who will forgive you. The ghost is patient. Make sure your friendships are too.
Prize Categories
- Overall
- Best Use of Gemma



Top comments (0)