What my Claude Code routine looks like a year in
A year after Claude Code went GA, most of what I tried early on has gone, and what's left is planning, small tasks, tests and a lot of careful review.

It's been about a year since Claude Code went GA and I wrote that it had changed how my week looks. The novelty wore off a long time ago. I use it most days, at work and on side projects, and quite a lot of what I tried in those first months didn't last, so I thought it was worth writing down what did, mostly for my own benefit.
Before any code gets written
For anything bigger than a one-file change I start in plan mode. It reads the code, proposes what it's going to do, and I read the plan before a single file changes. I was most tempted to skip this step early on, because it feels slow, but it's where I save the most time. Rejecting a bad plan takes a couple of minutes. Rejecting a bad implementation means reviewing the whole thing first, and then rejecting it anyway.
What I'm looking for in a plan is usually one of three things: it wants to touch files I didn't expect, it wants to add a dependency, or it's about to invent a new pattern when the repo already has one for exactly this. One of those comes up more often than not, and a sentence back usually sorts it out before anything is written.
The other thing that matters before any code is the size of the task. "Add pagination to the meters table, server side, using the existing usePaginatedQuery hook" gets a good result. "Improve the meters page" gets a diff I don't want to read. I break work down the way I would for a new joiner on the team: one behaviour, roughly one PR's worth of change, and a clear idea of what done looks like. If I can't describe done in a sentence, I split it again.
Tests, hooks and the boring rules
On work code the deal is tests first, or at least tests in the same change. I'll often write the cases myself as a list in the prompt, especially the edge cases I actually care about, and let it write the test code around them. Then I read the test diff before the implementation diff, because a model that wants green ticks will occasionally make the test agree with the code rather than the other way round. If the tests are right, the rest is much easier to judge. For UI work I add a Playwright check for the main flow too. It's slower, but it catches the "compiles, renders, button does nothing" sort of bug that unit tests walk straight past.
Hooks run shell commands at points in a session, like after a file edit or before a command runs. I only have a couple. After an edit, the formatter and type checker run on the changed files, so errors show up straight away instead of when I go looking. And before a command, anything that touches .env files or pushes to main gets blocked. That second one isn't really about the model misbehaving. I just don't want something that important to depend on anyone remembering, me included.
Subagents I use for one thing, which is keeping the main conversation clean. "Find every place we format currency and list the patterns" means reading a lot of files, and I'd rather a subagent did that and came back with a short answer. Skills cover the things I repeat: one for our component conventions at work, one for the deploy pattern on my home server. They're just folders with instructions and the odd script, and they only load when they're relevant. I did spend a few weeks building fancier multi-agent setups, and I've stopped. For the kind of work I do, one well-briefed session does better than several agents passing notes to each other.
My CLAUDE.md files are shorter now than they were a year ago, twenty or thirty lines, and each line is something it got wrong at least once, written as an instruction. When one grew to a few hundred lines the important rules got lost in it. Same with memory. It's useful, but I prune it, because an out-of-date note is worse than no note at all (it'll follow an instruction that stopped being true months ago, very confidently).
Reviewing what comes back
I review every diff the way I'd review a pull request from someone smart who joined last week. Good intent, no knowledge of our history.
git diff --stat # did it touch what I expected?
git diff -- '*.test.*' # tests first
git diff # then the rest, file by file
If the stat shows a file I didn't expect, I ask why before reading anything else. Sometimes there's a good reason. Other times it's a drive-by "improvement" that gets reverted. And the rule I set myself last year still stands: if I can't explain a change without reading its summary, it doesn't get committed.
Anything touching auth, user input, file paths, SQL or network calls also gets a second session with one job, which is to review the diff for security problems with fresh context and no attachment to code it just wrote. It finds real things. A path built from user input that wasn't normalised. A server action that checked there was a session but not that the record belonged to that user. A dangerouslySetInnerHTML fed from a CMS field. None of these are exotic, and that's why they slip through when you're tired. Since React2Shell in December I also ask it to check dependency versions against recent advisories whenever package.json changes. That doesn't replace npm audit or Dependabot, but it reads the advisory text, and they don't.
What I still do myself
Data models and API shapes I write by hand, because those decisions outlive the code and the generic answer is usually wrong for us. Anything with tricky concurrency or caching I'll have it explain, but I write it. And the first version of a new pattern is mine too: once it exists in the repo it can copy it well, but if it has to invent one, you get something very average. (Posts like this one are also mine, for what it's worth.)
Cost-wise, a personal plan is a fixed monthly amount, which is fine for side projects. Where I've been careful is API usage in my own automations, because there the bill grows with every call, so cheap work goes to a small model and only the hard part goes to a big one. I'll write that up properly when I do a post on my n8n workflows. At work the maths is simple enough. If it saves a senior engineer a couple of hours a week it has paid for itself many times over, and the cost I actually notice is attention, because reviewing is tiring and a tired reviewer approves things they shouldn't.
It's made me quicker at the parts of the job that were never the hard parts, and, a bit to my surprise, more careful about the rest.
First published on my blog. Cover photo: Shixart1985, CC BY 2.0, via Wikimedia Commons (source).
About the author
- Full stack engineer in London with 5+ years on production web platforms. I lead AI-assisted modernisation at Xanda: React and Go for the UK energy market, a government claims portal, and moving old Java and C++ systems onto the cloud. Outside work I run a small home server behind a Cloudflare Tunnel with a handful of public tools on it: Doorstep (rental alerts across Rightmove, OnTheMarket and OpenRent), SeenSooner (NHS A&E and planned-care waits), GridPulse (live GB grid carbon), Sift (LLM ticket triage that survives model failures) and AI Radar (a news digest written hourly by an n8n workflow). I write here about React and Next.js upgrades, Node, coding with AI agents, and the CVEs I've had to patch. Originals live at blogs.kishankanejiiya.tech.
Comments
Join the discussionNo comments yet. Be the first to comment.




