Today marks my lines of code count to 1 million.
To be fair, roughly 300k lines of code are “hardcore” code, which is still twice as much as I wrote in Google in 3.5 years (roughly 150k LOC).
There are a few interesting facts I’d like to list out:
- I deleted/rejected more code from AI than I accepted.
- I spend more time on thinking than writing.
- I love emoji, as other vibe coders do, but not too much when it becomes messy.
- Most of the code is in Python and Dart, for the love of flutter.
- It’s actually much more intense than the old days of coding.
- Half the code was using Claude Sonnet 3.5, but recently I found myself just loving Gemini 2.5 a lot more (see this post), and more than Claude 4 & Claude Code. I still prefer Cursor over Gemini CLI, but I can see the trend towards fully agentic coding, which is likely a format of Codex / Claude Code / Gemini CLI.
- AI is best at frontend, database operations, boilerplate codes, which likely boosts you 10x.
- Be cautious about the code structure, avoid over-engineering, fast fail to avoid silent failure, and avoid code duplication.
- Start a fresh session after > 10(20) rounds of conversation. Refactor after > 1000 lines of code. Do not write long util / helper files.
- Articulation is the single most important skill to orchestrate the AI.
The debate of Vibe Coding
There are people who are still skeptical about “vibe coding”, and I’d like some thoughts.
First, is vibe coding easy or hard?
TBH, it’s actually much intense than writing code without AI. You have no time to “take a break”, which is usually when you write some boilerplate code that you essentially relax your brain. You need to jump to next task immediately, because AI would finish things in seconds. This will make you feel like you are in a race, and you need to keep up with the pace, because it is pretty obvious that you are the bottleneck. Also, you need to solve problems that even AI can not solve (which is now becoming a compliment).
Second, what exactly is AI good at?
The argument about vibe coding is sometimes about the work that they do, and people are not necessarily talking about the the same thing when talking about vibe coding. So what exactly is AI actually good at?
- Frontend: 10x. Whether it is typescript or javascript, or flutter, AI can just do w.e. you want, in seconds.
- Database: 10x. Most of the time, you just need to spend time to think about the schema (or brainstorm with AI), and AI will do the rest.
- Boilerplate: 10x. When ever you need to read some engineering documents, it is just better to let AI implement or help you read the doc.
- Backend: 1.3x - 2x. The 2x is for me, some people might say lower. This part is actually where things may vary a lot. Some foundational work may find AI is not helpful at all, but it is actually rare. People are surprised to see that AI can write Mojo (the high performance language by Modular AI) and even Lean4 (the formal proof language) code farily well, both of which are the state of the art and relatively new.
So what AI is actually NOT good at?
It’s actually not a good question, because it is after all a tool (for now), and the user needs to be aware of the limitations of the tool, and not complaining about the tool not being omniscient. So this is actually a “be cautious” list.
- Overengineering is the most frastrating problem to me. I usually just hard stop the generation and rewrite my prompts. Even with different ways sayign “don’t over-engineer” or “don’t over-think”, AI sometimes will still generate a lot of redundant code. Be extra careful about this. Simplicity is the ultimate sophistication.
- Error handling. AI tends to hide and errors to avoid exceptions, crashing, etc. This is a big problem of “silent failure” which is the worst kind of failure, as you don’t even know that it is happening. This is basically the “fail fast” engineering principle, to bring attention to critical failures. I also hate when AI wrap a import in a try-catch block, which doesn’t make sense (althought I know the true reason for this, which is a long story).
- Not having enough context and reinventing the wheel, by recreating a new helper functions / files. It happens to me a lot, simply because AI is not always aware of the context.
- Avoid long files (soft limit 500, hard limit 1000). Ideally less than 500 lines. When > 1000 lines, it is usually a good idea to refactor. Context length is still NOT a solved problem and will likely continue to be a problem.
- Avoid long util / helper files. It is usually a good idea to split them into smaller files. Actually, avoid util files in the first place and just give intuitive names to the functions & files.
- Refactor often, just like you do in the old days. With AI, it is much faster and easier to refactor, where you can just paste the error message to AI and it will just figure out.
- Less is more. This is what Andrew Ng calls Lazy Prompting (link).
- There are some pretty obvious bug that I can spot. like string mismatch, where AI surprisingly just can’t figure out. When I point out, AI would just say “You’ve hit the nail on the head” and then fix it. I still don’t know exactly why this happens, but it actually happened a lot.
Context Engineering
The term “vibe coding” is famous and popular, but may not be a great term as it underpins the intellectual challenges that the developers are facing. However, “context engineering” from Andrew Karpathy is actually a great term that captures the essence of the problem of building AI agents, and perfectly replaces the term “prompt engineering”, which is misleadingly alluding to a “wrapper” around ChatGPT.
The key idea is that LLM is capable of a lot things, but it is mostly stateless, and we need to make it stateful, which can be rephrase as the challenge is about memory engineering. By now the most effective for memory engineering is still through plain text, where the difference lies how this plain text is generated and organized. For coding, it remains as the frontier and an open problem about codebase understanding, despite the efforts of Claude, Devin, and Cursor. Honestly, I find my manual blueprint (README for AI) of the codebase is still best for AI to quickly get the structure of the codebase, but it is a fairly tactical work to do, based on my 1000 hours of vibe coding, and takes some iterations with trial and error.
Overall, context engineering is the most important thing to engineer an agent, and to put “just enough” context into LLMs to to the right thing.
Do you need to understand the generated code?
One key question to ponder: Do you need to fully understand the AI-generated code?
My personal philosophy:
- High level: Absolutely yes. You must understand the overall design, flow, architecture, and data structures — otherwise you are flying blind.
- Low level: Let go most part. You don’t need to micro-read every helper function unless it is part of the core algorithm, agent loop, or critical performance path. Those parts demand deep understanding.
For me, the real art is about knowing when to let go, to choose between dive deep and trust AI.
I enjoy discussing architecture and data structure design for hours — that’s where most of the thinking should happen. Once the structure is clear, actual implementation often takes far less time.
So, my daily workflow is usually:
- Design — Discuss ideas with ChatGPT / Gemini, for however long you need.
- Code Architecture — Discuss with Gemini / Claude about the architecture, for 10-15 minutes.
- Implementation — Let AI write the code, usually fast, maybe 30s to 2 minutes. Unless some unexpected code (which I usually blame on my bad instructions).
- Debug — Try paste the error trace into AI first, and if it is a hard bug, open a web page and debug together with Gemini 2.5.
- Go back to 1 and iterate.
Can I still code (without AI)?
I once worried: after relying so heavily on AI for code generation, maybe I couldn’t write code independently anymore.
I was wrong.
I can still write good code, with good quality and good performance.
The proof is that I’m taking the Stanford cs336, building LLM from scratch, a extremly coding intensive course, and recommended not to use AI. I’ve done a fairly good job in doing the assignments.
Some prompts (rules in Cursor) that I found useful
- “Don’t over-engineer. Favor simple logic and common industry solutions.”
- “Help me brainstorm and no code”
- “Make minimal necessary changes.”
- “Use minimal comments and avoid redundancy.”
- Again, “Don’t over-engineer.”