Claude Code can make a capable engineer feel briefly superhuman. A task that used to require an afternoon of searching, wiring, testing, and cleaning up can become a conversation followed by a diff. That speed is real. So is the danger hiding inside it.
The problem is not that an AI tool writes bad code. Often, it writes perfectly reasonable code. The problem is that reasonable code can still be wrong for the system around it. It can introduce a second way to do the same thing, put policy in the wrong layer, blur an ownership boundary, or turn a temporary shortcut into the permanent shape of the product.
The first failure is usually not the model
When an AI-assisted codebase becomes difficult to change, the instinct is to blame the tool. That is convenient, but incomplete. The tool did not decide that every feature should reach directly into the database. It did not decide that business rules belong in route handlers, that errors should be swallowed, or that three almost-identical utility modules are close enough.
Those decisions usually come from a team that has stopped making decisions explicitly. Give a tool a vague request and an inconsistent repository, and it will infer a local answer from the evidence available to it. It will follow nearby patterns, including the accidental ones. It will optimize for a completed change, not for the architecture you meant to have six months from now.
Keep the shape of the system human-owned
The most important skill in AI-assisted engineering is not prompt writing. It is being able to describe the shape of a system before asking for implementation. What are the boundaries? Which module owns the rule? What is allowed to depend on what? Where does data become trusted? What must remain replaceable? Matt Pocock’s skills repository is useful here because it turns that discipline into a repeatable workflow for Claude Code instead of leaving it to the quality of a single prompt.
These questions sound slower than “build the feature,” but they are not ceremony. Set the skills up once for the repository, then start new work with /grill-with-docs so the agent tests the idea against the codebase and its domain docs. For a small change, use /implement. For work that spans sessions, use /to-spec to preserve the decisions, /to-tickets to break the spec into small vertical slices, /implement one ticket at a time, and /code-review in a fresh context. The point is not to worship a workflow. It is to turn assumptions into plans, specs, and diffs that a human can inspect before they harden into architecture.
The human should own the irreversible choices: the data model, the public API, the security boundary, the failure semantics, and the split between domain logic and infrastructure. Let the tool fill in the reversible parts. If a generated function can be deleted and rewritten without changing the system’s contract, it is a good candidate for delegation. If changing it would force a migration, a client rewrite, or a new security review, slow down and make the decision yourself.
Use AI where reversibility is high
A useful rule is to match the tool’s autonomy to the cost of being wrong. AI is excellent at translating an existing decision into code: writing a test from an example, adapting a parser to a known schema, explaining an unfamiliar module, or preparing a small refactor with a clear before-and-after condition.
It is much less trustworthy as the sole author of a new boundary. “Add authentication” is not one task. It contains choices about sessions, tokens, recovery, permissions, auditability, and what happens when a dependency is unavailable. “Add a repository interface for this existing query and cover it with tests” is a task with a shape. The more of the shape you provide, the less the tool has to invent.
- Ask for a plan and file list before asking for a large implementation.
- Give the tool invariants, forbidden dependencies, and failure cases.
- Keep generated changes small enough to review as a single idea.
- Require tests that describe behavior, not just lines touched.
- Delete speculative abstractions when the second use case never arrives.
The architecture review still matters
AI tools make code review more important, not less. A green test suite can tell you that the new path works. It cannot tell you whether the path belongs in that package, whether the new abstraction has the right owner, or whether the implementation quietly creates a second source of truth.
Review the diff in two passes. First ask whether it works. Then ask a less comfortable set of questions: Did this change introduce a new concept that already exists elsewhere? Did it move a decision into a layer that cannot enforce it? Does the error path preserve useful information? Will the next engineer know which code is authoritative? A tool can help answer these questions, but it should not be the only reviewer asking them.
The skill is knowing when to stop
There is a particular kind of AI-assisted mess that looks productive right up until the first serious change. The repository contains more code, more helpers, more comments, and more tests, but fewer obvious places to put the next requirement. Every answer created another question. Every shortcut became a precedent.
Real engineering is often the interruption. Stop the generation. Remove the duplicate. Refuse the abstraction that has no owner. Rewrite the small part that is now harder to understand than it was before. Claude Code can help you get through the mechanical work, but it cannot give you permission to leave a bad design in place just because the diff is impressive.
The best teams will not be the ones that generate the most code. They will be the ones that preserve the ability to explain their systems, change their minds, and remove what no longer belongs. Use the tools. Keep the architecture yours.
**Github Repository: ** https://github.com/mattpocock/skills
.jpg)