Most of what I've read about AI-assisted development is either uncritically enthusiastic or uncritically skeptical. I want to write something more measured because I think the reality is interesting in ways that don't fit either camp.
I've been working with Claude Code as my primary development partner for four months on a production CRM and marketing platform I'm building in TypeScript on Next.js. It is, as of this writing, the largest single project I've worked on alone. I want to describe what working this way is actually like, in concrete terms, with what's good and what's hard kept separate.
The shape of the collaboration
The collaboration is asymmetric. I bring the context: the domain knowledge, the architectural intent, the judgment about what's worth building. Claude Code brings raw fluency in TypeScript, exhaustive familiarity with Next.js patterns, and the willingness to write a hundred lines of test scaffolding without complaint. Neither of us could do this work alone in this timeframe.
The pattern that works for me has four steps:
- I describe the problem in full sentences. Not "add a booking form," but "add a three-step booking wizard with cross-step validation, session persistence, and conditional fields that change based on package selection."
- Claude Code drafts an implementation. The first draft is usually wrong in some way, but in the right neighborhood. It looks like the kind of code I'd write if I were typing fast.
- I read the draft carefully. This is the step most discussions of AI coding skip. The draft is not a finished thing; it is a proposal that needs to be evaluated.
- I push back, refine, or accept. Sometimes I rewrite parts by hand because the model's pattern doesn't match the rest of the codebase. Sometimes the draft is exactly right and I commit it. Most often, I refine: pointing out what's wrong, suggesting a different abstraction, asking for a smaller change.
The rejection-and-revision loop is normal. It is the work, not a sign that the tool is failing.
What makes a draft good or bad
I've gotten better at reading drafts critically. The drafts that ship without modification share a few properties:
- The function does one thing, and the boundaries are clear.
- The error handling matches what's already in the codebase, not the model's defaults.
- The naming aligns with conventions established earlier in the project.
- There are no redundant helpers, no defensive validation for inputs that come from internal code.
The drafts that need work tend to have one of these problems:
- The implementation is plausibly correct, but the off-by-one or the missed edge case is hidden in plain sight.
- The code reaches for a pattern from a different codebase (a new abstraction, a different naming convention) instead of matching what already exists.
- The error handling is overgrown: try/catch around things that can't fail, fallbacks for scenarios that don't happen.
- The comment says what the code obviously does, instead of why.
These aren't syntactic errors. They are intent errors. Catching them is the part of the work that doesn't get easier.
The productivity question
I'm going to be careful here, because I think the productivity question is where most accounts of AI-assisted development get sloppy.
In rough terms, my experience is this: for things with well-known patterns (auth flows, form validation, REST endpoints, test scaffolding), the cost of an additional feature drops substantially. Not by a small amount; by enough that the calculus of what makes it into v1 changes. For things that require novel logic, where the pattern doesn't exist in some other codebase, the gain is much smaller, and sometimes there isn't one.
I cannot give you precise numbers. I haven't done the controlled experiment, and the experience is too noisy for an honest single-number summary. What I can say is that the projects I'm willing to attempt have changed. I'm building things I would have ruled out as too expensive a year ago. That's the change that matters; line counts are a secondary signal at best.
Where the leverage doesn't reach
It does not help with product decisions. It does not help with pricing strategy, content strategy, or what to build next. It does not help when the codebase is unusual, when the patterns are bespoke, the model's defaults fight the conventions I've established, and the back-and-forth becomes friction instead of velocity.
It also does not help with the parts that require domain context the model doesn't have. When I needed to model how a Tanzanian safari business actually quotes prices across multiple parks, multiple seasons, multiple permit fees, and four currencies, Claude Code could implement what I described, but I had to do the modeling. The structure of the domain came from me.
The discipline this requires
The single most important skill I've developed working with Claude Code is reading code carefully. Not for syntax, but for intent. Most of the bugs I've shipped came from drafts I half-read. The cost of moving fast with AI tools is that the bug surface area per unit time goes up. If you skip review, you ship bugs faster.
The pattern that keeps me honest is treating each draft as if a colleague had submitted it to me for review. I read it, I push back where I disagree, and I don't commit anything I haven't understood. That sounds simple. It is not always easy when the draft looks right at a glance and the next problem is waiting.
What I think is coming
I think the divide will be between people who use these tools well and people who don't. The people who use them well will look like clear thinkers who can specify problems precisely, read drafts critically, and maintain architectural coherence across a codebase that's growing faster than their typing speed. The people who use them badly will ship more bugs, faster.
This is not a prediction about AI replacing engineers. It is a prediction about the floor rising and the ceiling rising too. The work that distinguishes a good engineer from an average one (judgment, taste, the ability to read code for intent) becomes more valuable, not less, when typing is no longer the bottleneck.
I have more to say about specific patterns: how I structure context for long conversations, how I keep architectural consistency across a few hundred files, what I do when the model's pattern fights mine. Those are the next posts.