AI Developer Tools Workflow Claude

How I Stay Efficient with Claude Code — My Setup and Tools

May 14, 2026

I’ve been using Claude Code as my primary development environment for long enough now that I don’t really think about it anymore. It’s just how I work. But that invisibility took a while to achieve — there was a period where I was fighting the tool, working around it, or just not using it well.

This is an account of what actually changed. Not the features. The practices.


The wrong way to start

The first mistake most people make with Claude Code — I made it too — is treating it like a better autocomplete. You describe a function, it writes the function, you review and accept. Repeat.

That works. It’s useful. But it’s not the thing that changes how you build software.

The thing that changes how you build software is using Claude Code as a thinking partner with persistent context — one that knows your codebase, your constraints, and your standards, and can hold that context across an entire feature rather than a single function.

Getting there required three shifts: project instructions, hooks, and intentional delegation.


Shift one: CLAUDE.md files

Every project I work on has a CLAUDE.md at the root. Claude Code reads this at the start of every session.

This isn’t documentation for humans. It’s instructions for Claude — and they override defaults. I use it to capture decisions that don’t live in the code but that Claude needs to respect:

  • Stack decisions (“don’t suggest Vercel, we’re on Cloudflare Pages”)
  • Tone (“TypeScript everywhere, no plain JS files”)
  • Constraints (“CSS via Tailwind only — no inline styles except for dynamic values”)
  • Domain context (“the robot is the hero project — give it the most prominent placement”)
  • Patterns that don’t surface naturally from reading the code

Without CLAUDE.md, Claude reads the codebase and makes reasonable inferences. Those inferences are usually fine. But “fine” isn’t the same as “aligned with what I’ve already decided.” The first time Claude suggests a library you explicitly evaluated and rejected three months ago, you understand why the instructions file matters.

The key insight is that CLAUDE.md turns Claude from a capable-but-general assistant into a capable-and-specific collaborator. It’s the difference between hiring a contractor who can do anything and one who knows your house.

I also write per-directory CLAUDE.md files for complex projects. The root-level file covers the whole project. A src/lib/chatbot/CLAUDE.md might cover specific conventions for how that subsystem works — the shape of tool definitions, what not to cache, why a particular design decision was made. Claude reads all of them, innermost taking precedence.


Shift two: hooks

Hooks are shell commands that Claude Code runs automatically in response to tool events. They’re configured in .claude/settings.json and they run outside Claude’s awareness — the harness executes them directly.

I use hooks for a few things that used to require discipline to remember:

Post-edit formatting. Any time Claude edits a TypeScript or CSS file, a hook runs prettier --write on it. I don’t think about formatting. It just happens. Claude writes the code, the hook formats it, the result is clean.

Pre-commit validation. Before Claude runs a git commit, a hook runs my linter and type checker. If either fails, the commit doesn’t happen. This sounds obvious, but without the hook, Claude would sometimes create a commit after fixing a bug, not realizing it had introduced a type error in a nearby file. The hook makes that impossible.

Notification on task completion. Long agentic tasks — the ones where I’ve asked Claude to implement a whole feature and gone to make coffee — end with a desktop notification so I know to come back. This is a small thing but it means I don’t have to babysit the terminal.

The mental model for hooks: they’re for behaviors that should always happen, regardless of whether you remembered to ask. Anything you’ve said to Claude more than twice — “format the file,” “run the linter,” “check types” — is a candidate for a hook.

Hooks also expose a useful property: they let you enforce invariants that Claude can’t override even if it tries. Claude doesn’t decide whether to run the linter before committing. The harness does. That separation is worth something when you’re relying on Claude to do autonomous work.


Shift three: parallel agents for independent work

The moment I started using parallel subagents was the moment Claude Code stopped feeling like a fast typist and started feeling like a team.

The pattern is straightforward: when I have two or more independent pieces of work, I spawn agents to run them simultaneously rather than doing them sequentially. The agents don’t share context — each one gets a self-contained brief — and they run in parallel.

A real example from this portfolio project: I needed to (a) write three blog posts, (b) audit the Cloudflare Worker routes for a missing rate limit, and (c) update the chatbot system prompt with new project details. Those three things have no dependencies on each other. Done sequentially, they’d take three times as long. Done in parallel, they take as long as the slowest one.

The skill in using parallel agents is writing good briefs. The agent starts cold — it knows nothing about what you’ve been doing or why. If you write “fix the rate limiting issue,” the agent will have to explore the codebase, figure out what you mean, possibly go in the wrong direction. If you write “the Cloudflare Worker at src/pages/api/chat.ts is missing a rate limit check; it should check the KV namespace rate_limits using the IP from request.headers.get('CF-Connecting-IP'), allow 10 requests per minute, and return 429 with a specific JSON body if exceeded” — the agent executes.

The brief should prove that you understood the problem. If writing the brief feels like too much work, you probably haven’t thought through the problem clearly enough yet.

I’ve also started using what I call a research agent: a subagent I spawn purely to explore a codebase or read documentation, with the explicit instruction to search and report back in under 200 words. It protects my main conversation context from getting flooded with file contents when I’m trying to answer a specific question. The result comes back as a tight summary, and I make the decision with that summary rather than raw file dumps.


What I’ve stopped doing

I stopped reviewing every line Claude writes. This sounds dangerous. It’s actually rational. When Claude is operating within a well-specified context — good CLAUDE.md, well-defined task, clear constraints — the output is almost always right. Reviewing every line was a habit from when I didn’t trust the tool. I now trust the tool and verify at the seams: does the feature work end-to-end? Does the type checker pass? Does the UI look correct? If yes, ship it.

I stopped using Claude Code for things that need thinking. Claude Code is a powerful executor. The thinking still has to come from me. I don’t ask Claude what architecture to use, what tradeoffs to accept, what features to build. I figure that out first — sometimes on paper, sometimes just in my head — and then I use Claude to implement it. “What should I build?” is not a Claude Code question. “Build what I described” is.

I stopped writing tasks for Claude to pick up. This is specific to how some people use agentic workflows — leaving a list of tasks and letting Claude work through them. It sounds like delegation. In practice, it’s abdication. The task list becomes stale, the priorities shift, Claude does work in the wrong order or on the wrong thing. I keep the steering wheel. I decide what to do next. Claude does it.


The meta-skill: writing good briefs

Every good Claude Code interaction I’ve had starts with a good brief. Every frustrating one starts with a vague one.

A good brief has:

  • Context: what’s the broader goal, what’s the current state
  • Scope: what’s in and what’s explicitly out
  • Constraints: what can’t be changed, what must be preserved
  • Success criterion: how will I know when it’s done

“Add dark mode” is not a brief. “Add a dark mode toggle to the nav that stores the preference in localStorage and applies a dark class to the <html> element; existing Tailwind dark: variants are already in place, so it’s just the toggle and persistence; don’t touch the color values in global.css” is a brief.

The additional 30 seconds writing the brief saves you five minutes of review and correction. It also forces you to actually understand the task before handing it off, which surfaces a surprising number of cases where you didn’t understand the task as well as you thought.


Hardware note: run Claude Code on something fast

This is practical advice that nobody talks about. Claude Code streams tokens to your terminal. The terminal rendering is fast. But if you’re running it on an underpowered machine or over a slow network, the experience degrades.

I run Claude Code locally on a machine with a fast SSD and enough RAM to hold the project in editor memory. When I’m away from my desk and on a laptop with a throttled connection, I notice. The tool works but the experience is worse.

This is not a knock on the tool. It’s a reminder that your development environment is a physical system with physical constraints, not just software. Optimize accordingly.


What this actually looks like

A typical session:

  1. Claude Code opens, reads CLAUDE.md, knows the project.
  2. I describe the task — one clear paragraph, or a few bullet points.
  3. If there are parallel independent pieces, I spawn agents.
  4. I watch the output loosely — not reviewing every line, but checking that the approach is right.
  5. Hooks handle formatting and validation automatically.
  6. I test the feature end-to-end.
  7. Done.

The thing that took the longest to accept: most of what I was doing manually wasn’t adding value. Formatting, linting, boilerplate, repetitive structure — none of that requires my judgment. Freeing that time for the parts that do require judgment — architecture, product thinking, debugging subtle behavior — is the actual efficiency gain.

Claude Code doesn’t make you a faster programmer. It makes your judgment the bottleneck, which is where the bottleneck should be.


Final note

The setup I’ve described took months to arrive at. There were a lot of sessions where I was fighting the tool, over-specifying, under-specifying, using it for the wrong things, not using it for the right things.

The sessions that feel effortless now are the ones where I’ve done the thinking and Claude is executing. The sessions that feel frustrating are the ones where I haven’t done the thinking and I’m hoping Claude will do it for me.

That’s not a limitation of the tool. That’s just how building software works.