What Is Vibe Coding? (And Why I Finally Gave In)
If you've been anywhere near the AI coding scene in the past year, you've heard the term "vibe coding." Coined by Andrej Karpathy in early 2025, it describes a style of programming where you describe what you want in natural language, let an AI generate the code, and trust the result without fully understanding every line. The phrase immediately resonated – and sparked heated debates. Some called it the end of software engineering; others dismissed it as a recipe for unmaintainable spaghetti.
I fell firmly into the skeptic camp. As someone who built production systems from scratch for over a decade, I believed that real code required real thinking. But by mid-2026, the tools had matured to a point where ignoring them felt like professional negligence. So I decided to run a controlled experiment: build a real, useful tool from scratch using only vibe coding – no manual debugging, no Stack Overflow, just conversations with AI.
This is the story of GitGlow, a GitHub contribution heatmap customizer that lets you paint your commit history in any pattern or colour palette. More importantly, it's what I learned about where vibe coding shines, where it falls apart, and how to make it work without shooting yourself in the foot.
The Idea: Why GitGlow?
I've always been fascinated by GitHub's contribution graph – those green squares that visualise your coding activity. But the default green scale is boring. Wouldn't it be fun to turn your history into a pixel art canvas? I wanted a CLI tool that could:
- Read your commit history from GitHub
- Let you define a pattern (e.g., a logo, text, or gradient)
- Generate commits in the past (with timestamps) to fill that pattern on the graph
- Be safe and ethical – only for personal repos, with clear warnings
This wasn't a simple CRUD app. It required Git interaction, date manipulation, rate limiting, and careful UX around rewriting history. Perfect for stress-testing vibe coding.
The Setup: Tools and Prompts
I used three tools:
| Tool | Role |
|---|---|
| Cursor IDE (with Claude 4 as default model) | Main coding environment |
| Claude Chat (via API) | For high-level design discussions |
| GitHub CLI | Final testing and deployment |
No manual coding – only prompts. Here's the initial prompt I typed into Cursor:
"Build a Python CLI tool called
gitglow. It should accept a GitHub username, a pattern definition (either a file or inline string), and a date range. The tool will generate a series of commits in a selected repository so that the contribution graph displays the pattern. Use the GitHub API to fetch and push commits. Assume the user has authenticated via a token. Include a--dry-runflag that only shows what would be created."
The AI returned a main.py with 487 lines in about 30 seconds. I didn't read it carefully – I just ran it. And it crashed immediately.
The Iterative Loop: From Broken to Working
This is where vibe coding becomes a dance. You don't debug manually; you copy the error back to the AI and ask for a fix. Over the next four hours, I went through about 40 iterations. Here are the concrete patterns I observed:
1. The AI Is Overconfident
It generated code that called GitHub API v4 (GraphQL) but used REST endpoints for mutation – a mismatch that caused silent failures. I pasted the error and it apologised and fixed it. This happened at least six times.
2. Context Window Is the Real Bottleneck
Once the file grew past 800 lines, Cursor's Claude started forgetting earlier decisions. It would reintroduce bugs it had fixed two prompts ago. I learned to periodically ask for a summary of the architecture: "Write a brief design doc explaining the current architecture, file structure, and key functions." Then I'd feed that back as context for subsequent requests. This dramatically improved consistency.
3. Good Prompting Is a Skill, Not Magic
Vague prompts produced vague code. When I said "improve error handling", it added generic try-except blocks that swallowed real errors. When I said "handle rate limiting by checking X-RateLimit-Remaining header and sleeping for the reset time", it implemented exactly that. Precision in prompts = precision in output.
4. Testing Is Not Optional
I asked the AI to write tests after the core logic was done. It generated 150 lines of pytest code, but the tests were tautological – testing that the functions returned what they claimed, not that the logic was correct. I had to prompt: "Write integration tests that actually call the GitHub API (using a test repo) and verify the contribution graph changes." Only then did I catch a bug where commits were created but with the wrong email, so they didn't count toward the graph.
The Result: GitGlow v1.0
After about eight hours of total vibe-coding time (spread over two days), I had a working CLI tool. Key stats:
- 1,342 lines of Python across 4 files
- 92% test coverage (integration tests only)
- 3 major bugs discovered after deployment, all fixed in under 15 minutes via prompts
- One ethical bug: the AI initially omitted the
--dry-runflag for destructive operations. I had to explicitly add a safety prompt.
Here's a snippet of the final prompt pattern – not hand-crafted, but generated by the AI after I described the requirement:
# Generated by Claude after prompt:
# "Write a function that takes a pattern matrix (list of lists of 0/1) and a date range,
# and returns a list of commit dates that would draw the pattern on a contribution graph."
def generate_commit_dates(pattern, start_date, end_date, intensity=1):
"""
Args:
pattern: list of list of ints (0 or 1), where 1 = commit
start_date: datetime
end_date: datetime
intensity: number of commits per cell (default 1)
Returns:
list of datetime objects
"""
from datetime import timedelta
import itertools
weeks = len(pattern)
days = len(pattern[0]) if weeks > 0 else 7
# Ensure date range covers enough weeks
total_days = (end_date - start_date).days
if total_days < weeks * 7 - 1:
raise ValueError(f"Date range too short: need at least {weeks*7} days")
dates = []
for w in range(weeks):
for d in range(days):
if pattern[w][d] == 1:
for _ in range(intensity):
commit_date = start_date + timedelta(weeks=w, days=d)
dates.append(commit_date)
return dates
This code ran correctly on the first deployment. The AI had learned from earlier iterations to include validation and documentation.
Three Things Vibe Coding Got Right (and Two It Got Wrong)
✅ Speed of Prototyping
Building GitGlow from scratch would have taken me at least a week, given that I'd need to research GitHub API date handling, test Git hooks, and write boilerplate. Vibe coding compressed that to eight hours. For one-off tools, internal scripts, or experimental projects, the speed is unmatched.
✅ Creative Exploration
I wouldn't have thought of adding a "pixel art" mode where you can upload an image and the tool converts it to a pattern. The AI suggested it after I said "the pattern definition is tedious". That feature added 2 hours of development but made GitGlow ten times cooler.
✅ Learning by Doing
Reading the AI-generated code taught me how to use the GitHub GraphQL API for mutation – something I'd never done before. I still had to understand the code to fix bugs, but the AI gave me a working baseline to study.
❌ Maintainability at Scale
The code was clean for a prototype, but not production-ready. No logging framework, no configuration management, no documentation beyond docstrings. When I asked the AI to add those, it introduced new bugs. Vibe coding produces prototypes, not production software – unless you're willing to iterate heavily on non-functional requirements.
❌ Security Blind Spots
The AI once suggested storing the GitHub token in the script itself (hard-coded). I had to prompt for environment variables. It also forgot to validate the --repo argument, which could lead to accidental pushes to the wrong repo. A human with security instincts catches these early; the AI needs explicit guidance.
Practical Tips for Your Own Vibe Coding Project
Based on my experience, here's a framework to get the best results:
| Phase | Approach | Example Prompt |
|---|---|---|
| Design | Describe the high-level architecture and constraints first | "Design a CLI tool that modifies Git history. List the files, each function's responsibility, and the data flow. Don't write code yet." |
| Implementation | Generate one function at a time, not the whole file | "Write the function that validates the date range. It should raise clear errors if dates are out of order or too short." |
| Debugging | Paste the full error message + stack trace | "I get 'HTTP 403' when calling /repos/.../commits. Here's the error JSON: [paste]. What's wrong?" |
| Refinement | Ask for specific improvements, not vague ones | "Add a --dry-run flag that prints the commits that would be created instead of actually pushing them." |
| Testing | Require tests that actually run against a sandbox | "Write integration tests that use a test GitHub repo (create one if needed) and verify the contribution graph pattern appears." |
Where Vibe Coding Fits in 2026
I now integrate vibe coding into my workflow as a deliberate strategy. I use it for:
- Rapid prototyping: Test an idea before committing to a full implementation
- One-off scripts: Data transformations, file system operations, API wrappers
- Learning new APIs: Let AI generate the boilerplate, then read the docs
I avoid it for:
- Security-critical code: Authentication, encryption, payment processing – these need human review
- Performance-sensitive systems: The AI doesn't reason about algorithmic complexity unless explicitly prompted
- Long-lived production services: Vibe-coded code lacks the architectural documentation and error handling needed for maintenance
The Real Lesson
Vibe coding didn't replace my programming skills – it amplified them. The code I got was never perfect, but it was always a starting point. I still had to review, understand, and modify it. But I did it in hours instead of days.
GitGlow is now on my GitHub (public repo: gitglow). I've used it to turn my contribution graph into a rainbow gradient. It's silly, but it taught me more about Git internals than any tutorial ever did.
If you haven't tried vibe coding yet, I recommend you pick a small, well-defined project and go all in. Ignore the best practices for a day. Just talk to the AI. Break things. Fix them with natural language. You'll come out with a working tool and a much clearer picture of where AI fits in your craft.
"The best way to predict the future is to generate it one prompt at a time." – modified from Alan Kay, now applicable to code.
P.S. If you're building tools that integrate with GitHub, you might find ASI Biont useful. ASI Biont supports connection to GitHub via API — learn more at asibiont.com/courses.
Comments