A humorous yet practical guide to AI-assisted development. DON'T PANIC.
View the Project on GitHub HermeticOrmus/hitchhikers-guide-to-vibe-engineering
“The dolphins left Earth just before it was demolished, leaving behind only this message: ‘So long, and thanks for all the fish.’ They knew something humans didn’t: when to leave.”
The hardest skill in vibe coding is knowing when to stop.
The AI will never tell you to stop.
Ask for improvements, it improves. Ask for refactors, it refactors. Ask for more features, it adds them. Ask for edge cases, it handles them. Ask for optimizations, it optimizes.
It has no sense of “enough.” It has no deadline pressure. It has no concept of diminishing returns.
You do. That’s your job.
Karpathy described vibe coding as building where “it’s not really coding—I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.”
The key phrase: “it mostly works.”
Not perfectly. Not completely. Not covering every edge case. Mostly.
For prototypes, personal projects, and experiments, “mostly works” is the finish line. You’re done. Ship it.
Version 1: Works for the happy path
Version 2: Handles main error cases
Version 3: Has basic validation
Version 4: Covers edge cases
Version 5: Optimized for performance
Version 6: Refactored for cleanliness
Version 7: Added comprehensive logging
Version 8: Improved error messages
Version 9: Added more edge cases
Version 10: Still not shipped...
Each version is better. None are necessary beyond a certain point.
Ask yourself: “If I shipped right now, what bad thing would happen?”
You: "Make this cleaner"
AI: [Refactors to pattern A]
You: "Hmm, can you try a different approach?"
AI: [Refactors to pattern B]
You: "Actually, the first way was better in some ways..."
AI: [Refactors to blend of A and B]
You: [Still not satisfied]
If you’re going in circles, you’ve hit diminishing returns. Pick one and move on.
You: "This needs to handle a million records"
Reality: You have 47 records
Solve actual problems, not imagined ones. Ship, measure, then optimize if needed.
You: "Add configuration options for all these values"
You: "Make the error messages more helpful"
You: "Add telemetry for debugging"
You: "Support multiple output formats"
Are users asking for these? Or are you adding them because you can?
The AI will happily explore tangents:
You: "Implement sorting"
AI: "Here's sorting, and here's caching, and here's pagination,
and here's filtering, and here's a complete query builder..."
Stay focused on what you actually need.
Definition: The minimum that proves the concept.
"We need to know if users will use this feature."
→ Ship the simplest version that tests the hypothesis
→ Learn from real usage
→ Iterate or abandon based on data
Definition: Solves the problem without polish.
"We need this functionality by Friday."
→ It works
→ It handles main error cases
→ It's not beautiful but it's correct
→ Ship it, polish later (or never)
Definition: Appropriate for real users at scale.
"This is going to production."
→ Comprehensive error handling
→ Logging and monitoring
→ Performance tested
→ Security reviewed
→ Documentation complete
Definition: You never have to think about this again.
"This is a solved problem."
→ All of production ready, plus:
→ Edge cases handled
→ Well tested
→ Well documented
→ Maintainable by others
Know which victory you’re aiming for. Stop when you achieve it.
When you’re done with a feature, practice gratitude:
Not because it has feelings, but because gratitude shifts your mindset:
"Thanks, this implementation is solid. I'm going to:
1. Run final tests
2. Clean up the commits
3. Submit for review
4. Move on to the next thing"
This explicit closure helps you stop iterating.
You did the work that matters:
The AI generated tokens. You created value.
Weird? Maybe. But acknowledging that the code is “done enough” helps you let go:
git commit -m "feat: implement user authentication
- JWT-based authentication
- Rate limiting included
- Logging configured
Good enough for v1. Known limitations documented in README."
Set a timer. When it rings, assess:
"I have 2 hours for this feature."
[2 hours later]
"What do I have? Is it shippable? If not, what's the minimum to make it shippable?"
Define the scope. Stick to it.
"This PR adds login. It does not add:
- Registration
- Password reset
- OAuth
- Admin features
Those are separate PRs. This one is done when login works."
Explain to someone (or something) what you built:
"This feature allows users to...
It handles these cases...
It doesn't handle these cases because...
I'm confident it works because..."
If you can explain it clearly, you understand it. If you understand it, you can ship it.
Ask: “If I come back tomorrow, will I be confused or confident?”
The dolphins knew when to leave. They didn’t wait for:
They assessed the situation, found it unworkable, and departed with grace and gratitude.
Know when the feature is done: Not perfect. Done.
Know when the approach isn’t working: Sometimes the AI can’t help with this problem. Switch to manual mode.
Know when to start fresh: Long conversations accumulate context errors. New chat, clear prompt.
Know when to ship: Real usage beats theoretical improvement. Get it to users.
Know when to walk away: Not everything needs to be built. Some features should be abandoned.
If this Guide has taught you anything, let it be this:
The AI is powerful. You are essential. Together, you can build things neither could build alone.
But only if you ship.
This Guide will continue to evolve. New entries will be added. Old ones will be revised. The field of vibe coding is young, and we’re all learning.
But the fundamentals won’t change:
Whether you’re building a weekend prototype or production infrastructure, these principles hold.
So long, and thanks for all the code.
May your vibes be good, your diffs be small, and your deploys be green.
Share and Enjoy!
[ ] I know what I'm building
[ ] I know the constraints
[ ] I know what "done" looks like
[ ] I know the risk level
[ ] I'm being specific
[ ] I'm providing context
[ ] I'm reviewing output
[ ] I'm testing as I go
[ ] I understand the code
[ ] I've tested it
[ ] I've committed it
[ ] I've stopped iterating
Stuck? Try:
1. New conversation
2. Simpler prompt
3. Smaller scope
4. Manual mode
5. Take a break
This concludes the main Guide. See the Field Guide Entries for specific topics.
Return to The Beginning if you need to remember not to panic.