How I use Claude Code every day, and how I check its work

5 min read

Updated October 27, 2026

Claude Code does most of the typing on what I build now, and my part has moved to the two ends of each task. Before it starts, I say exactly what I want and what done looks like. After it finishes, I check the evidence. The middle is its problem.

This site and my homelab are both maintained with it. (I still open Cursor when I want my hands on the code myself.)

Frame the task like a ticket for a new teammate

The agent is fast and literal, and it knows nothing about why you want something. So I write tasks the way I’d write a ticket for a capable new hire: the outcome, where it lives, the constraints, what not to touch, and how we’ll both know it’s finished.

Add the talk at <URL> to src/content/speaking.ts.
Use the event date, not the upload date.
Don't touch any other file.
Done when `npm run check` passes and the talk shows on /speaking.

The last line does most of the work. With a finish line it can test, the agent runs the check itself and keeps going until it passes, instead of stopping when the code merely looks right.

For anything bigger than a small fix, I ask for a plan first (Claude Code has a plan mode for exactly this) and read it before a single file changes. Correcting a plan costs one message. Correcting a finished run costs a lot more.

Write the rules down once: CLAUDE.md and AGENTS.md

Claude Code reads a CLAUDE.md file from the repo at the start of every session. This site’s CLAUDE.md is a single line, @AGENTS.md, which pulls in a shared AGENTS.md, so every agent and every human reads the same guide.

That guide opens with a TL;DR that includes the definition of done, then a table of commands, a map of the source tree, recipes for the common edits (“add a talk” is one object in one file), conventions, and a list of gotchas. The gotchas are the most valuable part, because each one comes with its reason. Fonts are self-hosted, for example, because builds in sandboxes without network access fail, and a past upgrade silently dropped the font because of it. An agent that knows the reason doesn’t “fix” it back.

There’s also a rule no linter could enforce: this is a public site about a real person, so never add private data, even if it’s in a CV you were given.

If you’re starting from nothing, this much is already useful:

## Before you say you're done

- Run `npm run check` (lint, typecheck, build). It must pass.
- UI changes: run the app, check light and dark, at 390px and 1280px.
- Don't add a dependency without saying why.
- Never commit secrets, tokens or personal data.

When the agent gets something wrong in a way one sentence would have prevented, add the sentence.

Verification is most of the work

An agent saying it’s finished is a claim, and I treat it like one. On this site, npm run check runs lint, the typecheck and a production build, exactly like CI. Then npm run smoke crawls the running site: every page has to return 200, and the feeds, the social card image, the sitemap and the 404 page get checked too. CI runs both on every pull request, so an agent’s branch gets the same treatment as mine.

Pixels need eyes. The AGENTS.md checklist for UI changes lists the pages to open in both themes, at phone and desktop widths, plus the mobile menu and the command palette. When this site moved to Tailwind CSS v4, the bar was zero visual change, and the upgrade was checked against 62 screenshots (every route, light and dark, mobile and desktop) that came out pixel-identical to the old build.

Then I read the diff. Every file name always; every line of anything that touches config, dependencies, auth or the network. I’m looking for files that shouldn’t be in the diff at all, deleted or skipped tests, loosened types, a stray any, new dependencies, numbers hard-coded that should be computed, and anything that quietly “fixes” a gotcha AGENTS.md explains.

MCP: connect the context instead of pasting it

MCP servers give Claude Code tools beyond the terminal: an issue tracker, a hosting dashboard, a database, a browser. Instead of pasting an error log into the chat, the agent reads it where it lives. It’s also what a lot of the teams at the Tokyo AI Hackathon, which I co-organized with Anthropic, Raycast and Supabase, spent the day building.

Start read-only, because an MCP server acts with whatever credentials you gave it. And add servers one at a time, because every tool you connect is one more thing the agent might decide to use.

Long runs, and how I check them

Long autonomous runs (an upgrade, a migration, the same change across dozens of files) are where the agent saves the most time. They only work with a finish line it can test on its own, so I set one before I start: the commands that must pass, the screenshots I want, and what it must not touch.

When I come back, the code is the last thing I read. First comes the evidence: its summary of what it ran and what it skipped, the commit list, the CI result, the screenshots. If the summary says a check was skipped, that’s the first thing I rerun. Only then do I open the diff, starting with the riskiest file.

The homelab, and a Discord assistant on a Mac mini

The same approach runs my homelab: old laptops rebuilt as thin terminals, a NAS running Immich, Jellyfin, Paperless and Home Assistant, and two Evangelion-style Next.js dashboards that show the state of every machine in the house. The dashboards are ordinary Next.js apps, so they get checked like one. The rest has no CI, so the smoke test is Uptime Kuma: if a change leaves a service not answering, I hear about it.

The odd one out is a Claude-powered Discord assistant, self-hosted on a headless Mac mini that’s always on. There, Claude isn’t writing code for me; it is the program that’s running. If you build one, the checklist changes: give it only the tools it needs, keep a log of what it did, and keep its keys out of the repo.

What I keep, and how trust works

I don’t hand over what to build and why; the agent is good at the how. I don’t hand over secrets, or anything that changes what’s exposed to the internet (my machines reach each other over Tailscale without a single open port, and an agent doesn’t get to change that). And I don’t hand over the merge. An agent can open the pull request; deciding that it ships is my job.

Everything else is trusted the way a new teammate is: per kind of task, on a record. Content edits on this site have a long record of passing check and smoke, so I skim them. Dependency upgrades have a shorter one, so I read them. Anything that touches auth or the network starts from zero every time.

When a run goes wrong, the fix goes in two places: the code, and a line in AGENTS.md, so the next session starts out knowing it.

Stay up to date

Get notified when I publish something new, and unsubscribe at any time.