We've all been there:
Your script just died with a 50-line traceback. You're tired, you've been staring at the screen for three hours, and you make the mistake of dumping the error into ChatGPT hoping for a fast answer.
What do you get? A polite, rambling 6-paragraph corporate email:
"I'd be glad to help you resolve this issue! This error typically indicates that you are attempting to access a key that does not exist in the dictionary. To prevent this, consider using defensive coding practices..."
Nobody needs a therapy session when their code is broken. Nobody needs a generic lecture on defensive programming. Just tell me what stupid line I wrote, show me the 2-line diff, and let me move on with my day.
Even worse? A while back, I set up a local script with an LLM API to auto-retry failed test runs. The script got stuck in a recursive error loop while I walked away to grab a coffee, burning through \$40+ in API credits from my personal card before I realized what happened.
That was the breaking point. I realized two things were terribly broken with current AI coding tools:
- They treat developers like fragile children with endless polite filler instead of giving direct, unfiltered technical feedback.
- If you automate them locally, you live in constant paranoia of a runaway script draining your personal wallet.
So over the weekend, I built git-oops.
It’s an open-source terminal tool designed with zero fluff:
- It roasts your sloppy syntax with zero filter.
- It shows you an exact unified git diff and applies it to your file in 1 keystroke.
- It has a hard \$1.00 daily circuit breaker that physically kills API calls before your wallet gets drained.
Here’s how it works.
What It Actually Feels Like to Use
Say you wrote this piece of rushed code in broken.py:
def get_user_profile(payload):
# Trusting dictionary keys like a naive child
user_id = payload["user_id"]
return f"Fetching profile for {user_id}"
get_user_profile({"session_id": "xyz987"})
Instead of opening a browser tab, copy-pasting code, and waiting for an essay, you just run:
git-oops --file broken.py --error "KeyError: 'user_id'"
Within a second, your terminal spits out:
____ ___ _____ ___ ___ ____ ____
/ ___|_ _|_ _| / _ \ / _ \| _ \/ ___|
| | _ | | | |____| | | | | | | |_) \___ \
| |_| || | | |____| |_| | |_| | __/ ___) |
\____|___| |_| \___/ \___/|_| |____/
⚡ Automated Crash-to-Patch Synthesizer │ Staff Critic │ Circuit Breaker
╭─ CRITIC ROAST (STAFF) ───────────────────────────────────────────────────╮
│ "Congratulations! You treated an optional dictionary key like it was │
│ guaranteed by the Geneva Conventions, then acted shocked when Python │
│ slapped you with a KeyError. Classic hasty code." │
╰──────────────────────────────────────────────────────────────────────────╯
╭─ DIAGNOSTIC ANALYSIS & FINANCIAL METRICS ────────────────────────────────╮
│ Root Cause : Unchecked dictionary subscription without .get() guard. │
│ Target File : broken.py │
│ Query Cost : $0.00012 USD │ Today's Total: $0.0034 USD │
│ Safety Check : Circuit Breaker Passed (Limit: $1.00) │
╰──────────────────────────────────────────────────────────────────────────╯
PROPOSED SURGICAL GIT PATCH:
--- a/broken.py
+++ b/broken.py
@@ -2,2 +2,3 @@
- user_id = payload["user_id"]
+ user_id = payload.get("user_id")
+ if not user_id:
+ raise ValueError("Missing required user_id in payload")
? Apply this patch to 'broken.py' right now? [y/N]: y
╭─ PATCH APPLIED SUCCESSFULLY ─────────────────────────────────────────────╮
│ File 'broken.py' updated safely. │
│ Run `git-oops --undo broken.py` if you wish to roll back. │
╰──────────────────────────────────────────────────────────────────────────╯
You press y. Enter. The file is modified on disk. Comments and formatting stay intact. Done.
If the patch ends up being unwanted? Type git-oops --undo broken.py and it instantly restores the backup snapshot.
Choose Who Roasts You (--personality)
Everyone has a different tolerance for technical pain, so I baked in 4 caustic archetypes:
-
staff(Default): The cynical, overworked Principal Engineer who looks at your code with pure disappointment. -
kernel: The unhinged OS kernel mailing list maintainer shouting about "brain-damaged architecture". -
chef: Gordon Ramsay in Hell's Kitchen: "LOOK AT THIS KEYERROR! IT'S RAW! AN IDIOT SANDWICH COULD WRITE BETTER DICTIONARY ACCESS!" -
passive_aggressive: The toxic coworker: "Per my previous 15 reviews, dictionaries can be empty. Hope you enjoy debugging this 😊"
You can permanently lock in your preferred flavor of abuse:
git-oops --set-personality chef
Now you don't even have to pass flags. Every crash gets yelled at by an angry Michelin-star chef by default.
The $1.00 Circuit Breaker: Why You Need One
We've all seen the horror stories online: someone hooked up an autonomous agent or test script to "auto-fix my code", forgot about it, and woke up to an accidental \$300+ bill on their personal card.
I refuse to let a CLI tool bankrupt me.
Every time git-oops runs, it tracks token usage in a local JSON ledger (~/.git_oops/spend_ledger.json). If today's accumulated spend reaches your threshold (default: \$1.00), it trips a hard circuit breaker:
def check_circuit_breaker(spend_limit_usd: float = 1.0) -> bool:
spent = get_daily_spend()
if spent >= spend_limit_usd:
raise PermissionError(
f"🚨 [CIRCUIT BREAKER TRIGGERED] Daily budget of ${spend_limit_usd:.2f} exceeded! "
f"(Spent today: ${spent:.4f}). Requests blocked to protect your wallet."
)
return True
It doesn't warn you. It doesn't send an email. It physically halts the network request.
You can check your status anytime:
git-oops --status
It tells you exactly what you spent today down to five decimal places.
Don't Pay for the Same Bug Twice (Local SHA-256 Cache)
When you're debugging, you often run the exact same failing command 3 or 4 times while tweaking configs or environment variables.
Why pay token costs 4 times for the exact same bug?
git-oops hashes filepath + error + code_content using SHA-256. If you re-run against the same crash, it pulls the diagnosis straight from your local cache:
- Cost: \$0.00000
- Latency: 0 ms
- Cloud requests: Zero
No Heavy C-Extensions, No 500MB Virtualenvs
I hate CLI tools that require PyTorch, heavy vector DBs, or 400MB of compiled wheels just to print text to a console.
git-oops is built with pure, standard-library Python plus requests for the REST handshake:
- Zero compile steps.
- Works offline (built-in deterministic offline engine if you don't have an API key).
- Line-ending agnostic (CRLF / LF normalized so it never garbles Windows or Unix files).
- 100% test coverage across Python 3.9 through 3.12.
Give It a Spin
If you want to stop getting babied by LLMs and just want surgical git diffs with honest commentary:
👉 GitHub Repository:
Hao610
/
git-oops
Turn terminal crashes into 1-click git patches. Roasted by a staff engineer, protected by a $1 API circuit breaker.
⚡ git-oops
Turn Any Terminal Crash into a 1-Click Git Patch — Roasted by a Staff Engineer, Protected by an LLM Circuit Breaker.
😤 Why git-oops?
We've all been there:
- Your script crashes with a 50-line Python or Node stack trace.
- You copy-paste it into ChatGPT hoping for a quick fix.
- You get a polite, rambling 6-paragraph essay starting with "I'd be glad to help! The issue appears to be..." just to find 2 changed lines of code buried at the bottom.
- You hook up a local script or agent to auto-retry, hit a recursive exception loop, and get slapped with a surprise cloud API bill.
git-oops replaces that entire mess with a single terminal command:
git-oops --file broken.py --error "KeyError: 'user_id'"
⚡ What You Get in 1.5 Seconds
⚡ [GIT-OOPS] Analyzing crash & invoking staff-level critic
💀 THE ROAST:
"Congratulations! You treated an optional dictionary key…# Clone and install
git clone https://github.com/Hao610/git-oops.git
cd git-oops
pip install -r requirements.txt
# Set your Gemini key (or test offline!)
export GEMINI_API_KEY="your-api-key"
# Catch crashes live on any script
git-oops --run "python my_buggy_script.py"
Let me know in the comments: Do you prefer your code reviewer brutally blunt, or are you actually reading those 5 paragraphs of polite filler? 😂

Top comments (0)