Skip to main content

Blog

Tagged “best-practices”

7 posts.

  • When to stop vibe coding and take the wheel yourself

    Stop vibe coding the moment the code starts holding something you cannot afford to lose: real users, real data or real money. In day-to-day terms the crossing point shows up as five signals: debugging starts taking longer than building, the app begins storing information that belongs to someone else, you can no longer say what a file does without asking the model, the same defect keeps returning in a new shape, and a second person needs to work in the code. Taking the wheel does not mean closing the tools. It means moving from accepting output to reading it and deciding.

  • Testing AI-generated code without writing every test

    You can test AI-generated code without writing every test by hand, as long as the checks do not come from the model that wrote the code. That is the whole constraint, and everything practical follows from it: you write the specification and the invariants yourself, because they encode what the code should do; you let a model produce the bulk of the example tests, because they encode what the code does; and you put something external in between to tell the two apart, whether that is a mutation testing run, a property-based check, a type system, a security scanner, or a review by a model from a different provider. Get that split right and the volume of test code stops being your problem. Get it wrong and you end up with a green suite that agrees with the bug.

  • Guardrails that stop an AI agent breaking your app

    Guardrails stop an AI agent breaking your app when they live in the runtime rather than in the prompt. That means the agent's credentials, the environment it can reach, the tools it is allowed to call, the actions that require a human to approve, and the spend and time limits on its loop, all enforced by systems that do not depend on the model cooperating. An instruction like "do not touch production" is a request: the model can read it, agree with it, and still issue the write, because nothing in the execution path stopped it. So the work of adding guardrails is mostly unglamorous permissions and plumbing, plus a short list of actions you decide a person has to sign off before they happen.

  • Small iterations beat big rewrites in vibe coding

    Small iterations win: ask for one change you can run, read and commit, rather than a rewrite you cannot review. The reason is measurable rather than aesthetic. A large-scale study of agentic pull requests on GitHub found that being too large was among the top three reasons reviewers rejected them, with the authors recommending that such work be split into smaller, easier-to-review submissions. Failed agent pull requests skew towards larger change sets, more touched files and failing CI. A big rewrite also fights the tool itself, because model output quality falls as the context window fills. Rewrites are not always wrong, but they are only cheap when the plan is written down, the tests exist and everything is already in git.

  • Reading the diff is the review vibe coding lacks

    Reading the diff means checking the added and removed lines an AI agent produced before you accept them, and vibe coding needs it because vibe coding is defined by not doing it. Andrej Karpathy's original description of the practice included the line "I 'Accept All' always, I don't read the diffs anymore", and the measured consequence is well documented: studies of AI-generated code put the share containing at least one security flaw somewhere between roughly a third and a half, depending on language and method. The strongest argument for the review step is newer and stranger than the vulnerability counts. A 2026 formal-verification study fed models their own proven-vulnerable code and asked them to review it, and they correctly identified the flaw in 70 of 89 cases. The knowledge was there. It simply was not applied while the code was being written, which is exactly the gap a diff read fills.

  • Reading the diff is the habit vibe coding needs

    Reading the diff means going through the exact lines an AI coding tool changed, before you accept them, and forming a view on each one. Vibe coding as it was first described did the opposite: Andrej Karpathy's February 2025 post described accepting AI-generated changes without reading the diffs at all. That works for a throwaway weekend project and stops working the moment the code holds real data, real money or real users, because the two things an unread diff hides best are quiet architectural damage and quiet data exposure. Both now have evidence behind them: GitClear's analysis of hundreds of millions of lines shows duplication and rework climbing year after year, and 2026 security scans have found AI-built apps leaking sensitive data through the same small set of mistakes. Reading the diff is the cheapest correction available, and it is a skill, not a virtue.

  • How to write a clear prompt for an AI coding tool

    A clear prompt for an AI coding tool states the goal in one sentence, then adds the context the tool cannot see, the constraints it must respect, and at least one concrete example of the input and output you expect. GitHub's own guidance describes the shape as starting general and then getting specific: a broad description of the scenario first, followed by the specific requirements. The reason vague prompts fail is not that the model is weak, it is that the gaps get filled with assumptions, so "build a login form" produces code that looks right and matches nobody's stack. Everything else worth doing follows from that: keep the slice small enough to review, show the pattern with an example or a test rather than describing it, say what you do not want, and rewrite the prompt rather than arguing with the output.