# Six weeks of Claude Code, and I've stopped pasting into chat

Back in February I said the thing I wanted from AI was something that could read my repo and run my tests itself, so I'd stop being the clipboard in the middle. Well, that exists now, and I've used it most days for about six weeks.

Claude Code went generally available on 22 May along with Claude 4 (Opus 4 and Sonnet 4). I'd played with the research preview earlier in the year on 3.7 Sonnet and liked it, but it felt like a demo. With Claude 4, and with it then being included in the Pro and Max plans, it went from interesting to the first thing I open in the morning.

## Handing over the steps

Before, I wrote the code and AI either guessed the next line or answered whatever I pasted into a chat. Now I describe a task and something else does the steps. It runs in the terminal, inside the repo, reads the files it thinks matter, greps for usages, edits, runs `npm test` or `go test ./...`, reads the failure and tries again. Sometimes I watch, sometimes I make a coffee. My part of the loop has shifted from typing to reviewing, and I read a lot more code than I write.

A recent example from work: a component library had the same sorting logic copied into several places around a `Table`. I asked for it to be pulled into a hook, with the call sites updated, the existing tests kept green and new tests for the hook. It took a few minutes and touched a handful of files, and reviewing took me longer than the work did. By hand that's a morning.

What made it useful on our codebase, as opposed to just impressive, was a `CLAUDE.md` file at the root, which it reads at the start of every session. Mine is things like this:

```md
# Notes for Claude

- Package manager is pnpm. Never npm.
- Run `pnpm test --filter <pkg>` for one package, not the whole repo.
- UI components live in packages/ui. Don't create new ones in apps/.
- We use date-fns, not moment. Don't add dependencies without asking.
- Go services: handlers stay thin, logic goes in internal/<domain>.
```

Pretty much every line is a mistake it made once. It's the onboarding doc I'd give a new joiner, minus the history, and I keep it short because when it got long the important lines started getting ignored.

The bigger use at work has been moving some old Java services to Go. They do fairly simple things (read files, validate, transform, push to an API) wrapped in a lot of ceremony. What works is pointing it at one class and its tests and asking for the behaviour as a list of rules, edge cases included. I check that list against what I know and against production logs, and only then ask for a Go version with table-driven tests for each rule. What doesn't work is "convert this package to Go". It'll do it, and it'll compile, and it may well drop the one null check that was the whole reason an old bug never came back.

## The new ways it goes wrong

The failures are different from chat, and a bit worse, because the output is bigger.

It's very comfortable with big diffs. Ask for one change and you can get renamed variables, a reshuffled import block and a "small improvement" to some unrelated function, all summarised as a tidy-up. Each bit is harmless, but together they bury the one change that matters, so "only touch what this task needs" now goes into nearly every prompt. A couple of times it has fixed a failing test by changing what the test expected instead of fixing the code, and the summary said all tests pass, which was technically true. I read test diffs first now.

It also gets stuck sometimes, trying the same broken idea in slightly different clothes. When I see the third similar attempt I stop it and point it somewhere else, because letting it loop has never once been quicker. And it doesn't know about the parts of our setup that aren't in the repo: environment variables that only exist in CI, a service that needs to be running locally, a feature flag. It writes code that works in its world.

So a few habits have changed. I write tasks like tickets (what, why, which files, what done looks like, what to leave alone), and the better the ticket, the less there is to review. I make sure the working tree is clean before anything big, so `git diff` shows only its work and `git checkout .` is a cheap undo. And I do the interesting bits myself. It writes the hook, but I decide whether there should be a hook, partly because that's where I learn and partly because that's where it's most likely to pick something generic.

The habit I worry about is skimming. Reviewing tires you out in a different way from writing, and I've caught myself approving a diff because the summary sounded right. I've gone back to the rule from February: if I can't explain a change without reading the summary, it doesn't get committed.

On refactors and rewrites with decent tests, it saves me a lot more time than in February. On work where the hard part is deciding what to build, not much has changed, because that part is still mine. It's all moving every couple of weeks at the moment (hooks have just landed, and subagents are apparently next), so I'll come back to this once it's stopped being new.

---

*First published on [my blog](https://blogs.kishankanejiiya.tech/posts/claude-code-changed-my-week). Cover photo: Anirban Saha, CC BY-SA 4.0, via Wikimedia Commons ([source](https://commons.wikimedia.org/wiki/File:Beautiful_Mechanical_Keyboard.jpg)).*

