Building with Claude and Cursor: an AI engineer's workflow
An honest account of how AI coding tools actually fit into my day — where they save real time, where they quietly cost it, and the habits around context, prompting, and review that separate a speedup from a mess.
- Tools
- AI
- Workflow
I use Claude and Cursor every working day, and I want to describe that honestly rather than the way tool demos do. These are not a magic “describe your app and ship it” button, and pretending otherwise is how people end up with a codebase they cannot maintain. Used with some discipline, though, they are a genuine multiplier on the parts of the job that are mechanical rather than hard. The skill is knowing which parts those are.
Where they actually help
The wins are consistent and they cluster around work that is tedious but not conceptually deep:
- Scaffolding. A new API route, a Pydantic model, a React component with the right props, a config file in a format I half remember. This is the strongest use by a wide margin — boilerplate I know exactly how I want, just typed for me in seconds.
- Mechanical refactors. Rename a concept across a module, thread a new parameter through a call chain, convert a callback pattern to async. Tedious, error-prone by hand, and exactly the kind of pattern-matching the model is good at.
- Tests. Give it a function and it drafts a reasonable first pass at the cases — including edge cases I would have gotten to eventually. I still add the ones it misses, but it clears the blank page.
- Exploring unfamiliar code.Dropped into a large codebase I did not write, “where does authentication get enforced, and walk me through the request path” is faster than grepping blind. It is a reading aid as much as a writing one.
Where they don’t
The failures are just as consistent, and they show up wherever the task needs judgement the model does not have. It will happily produce confident, plausible, wrong code — and the danger is precisely that it looks right. Specifically, I do not hand off:
- Architecture.Deciding boundaries, data models, and how services relate is the actual engineering. The model has no view of my system’s constraints or its future, and its suggestions here tend toward generic patterns that fit the average codebase, not mine.
- Anything security- or money-sensitive. Auth flows, permission checks, payment logic, anything touching secrets. Plausible is not good enough when the failure mode is a breach.
- Subtle, context-heavy bugs.When the fix depends on an invariant that lives three files away or in a teammate’s head, the model guesses. Sometimes the guess is a useful hypothesis; it is never the last word.
Context is the whole game
The biggest lever on output quality is what the model can see. A vague request against no context yields generic code; a precise request with the right files in view yields something that fits. In Cursor that means deliberately attaching the relevant files, the type definitions, the neighbouring code that establishes the conventions — not dumping the whole repo and hoping.
Context windows are finite and, just as importantly, more is not always better. A window stuffed with marginally relevant files dilutes attention and invites the model to pattern-match on the wrong thing. I curate: the files that matter, and a clear statement of intent. Managing that deliberately — and starting a fresh session when a conversation has drifted or filled with dead ends rather than fighting a polluted one — is most of what “prompt engineering” means in practice.
# Weak — no context, no constraints, invites a generic guess
"add caching to this"
# Strong — states intent, constraints, and the shape of done
"Add caching to get_user_profile() in services/user.py.
Use the existing Redis client in db/cache.py (see get_client()).
Key by user_id, TTL 5 min, and invalidate in update_profile().
Match the error handling style already used in that file."The loop I run
Day to day, the work settles into a tight cycle. The mistake is treating it as a straight line — prompt, accept, move on. It is a loop, and the review step is not optional.
When a draft is wrong, the instinct to hit “try again” is usually the wrong move. A regenerated guess against the same vague prompt is just a different guess. The productive move is to go back to intent: the model was wrong because I under-specified, so I add the missing constraint or the file it needed, and the next draft is usually right. Refining the prompt beats re-rolling the dice.
The honest bottom line
These tools have made me meaningfully faster, but not by replacing the thinking — by clearing the typing around it so I spend more of my attention on the parts that need a human. The engineers I see get burned are the ones who let the tool make decisions instead of drafts, and stop reading the output. Kept in its lane — a fast, tireless pair-programmer that is often right and confidently wrong just often enough to keep you honest — it is one of the better upgrades to the job in years. The judgement about what to build, and whether the code is actually correct, stays yours. That part does not delegate.