I used to write code. Now I mostly write plans and review.
That sounds like a slogan, but it’s the most honest way I can describe what happened to my day-to-day as an engineer. For a while, Claude Code was “fancy autocomplete” to me: I typed, it guessed, I fixed, and I was still doing all of the thinking. The shift came when I stopped treating it like a tool and started treating it like a **coworker **one with a specific skill set, a cost, and habits I had to learn to manage.
This is the write-up I wish I’d read at the start: the mental model that made everything click, the workflow I actually use now, and the handful of concepts that carry the most weight.
Claude Code is two pieces, and confusing them is the source of most early frustration:
Diagrams in this article are from Lydia Hallie’s Claude Code workshop (Frontend Masters).
The model never edits a file or runs a command directly. It decides what should happen and emits a “tool call” essentially a request and the harness executes it, then feeds the result back. That back-and-forth is the agentic loop, and it’s what makes this an agent instead of a chatbot. The loop ends when the model replies with plain text and no tool call which is exactly the moment your terminal goes quiet and hands control back to you.
Two consequences fall out of this that matter every single day:
Once I internalized “the model plans, the harness executes,” the rest of the features stopped feeling like a grab-bag and started feeling like a system.
I don’t freestyle prompts anymore. I run a pipeline (built on Matt Pocock’s skills):
Working with a teammate?* This pays off even more. Because *to-tickets already splits the work into small, independent issues, you can point Claude at exactly the right slice "only work on the tickets that aren't assigned to my teammate." You each stay in your lane, nothing overlaps, and you sidestep the merge conflicts you'd hit the traditional way, where you're both editing the same thing. It's far more organized.
The magic isn’t any single step, it’s that thinking happens before building, and each stage produces an artifact I can review. My job shifted from typing code to being the product manager and the reviewer.
Three models, and the trade-off is capability vs. speed vs. cost:
The subtlety people miss: there’s also an effort level (low / medium / high / max) how hard the model thinks. When a model gets “lazy” and refuses, it’s often just low effort, not too small a model. When Opus rewrites your whole test suite because you asked for a blue button, it’s often max effort, not too big a model.
My rule: start with Sonnet, escalate to Opus only if it can’t get it right. Defaulting to “always Opus, max effort” burns limits fast.
Before implementing anything, I use Plan Mode (Shift+Tab in the CLI, or just ask it to plan). It flips your role: you review the plan, push back, and then it builds. This is where I catch the most mistakes, the plan reveals assumptions and missing pieces before a single file changes.
And put verification in the loop: give the model something concrete to check against, a screenshot of the intended UI, an existing test, a type-check.
If you find yourself explaining the same procedure twice, make it a **skill, **a Markdown file with a reusable procedure:
---name: deploydescription: Deploy the app to staging or production. Use when wrapping up a release.---
1. Run the tests.2. Bundle the app.3. Deploy to the target environment.
Think of it as: description = when to run it, body = what it does. The mindset shift: we’ve gone from prompt engineering to skill engineering.
Skills shape behavior, but they can’t guarantee anything. When something absolutely must happen, you want a **hook **custom logic bound to a point in the agentic loop, like a Git hook but for Claude Code’s lifecycle. The canonical example: type-checking on every edit.
// .claude/settings.json{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "bun run typecheck" }] } ] }}
Rule of thumb: if it must be enforced, it’s a hook. If it’s a repeatable flow, it’s a skill.
Everything above runs in one conversation, and every tool result piles into that context. The more clutter, the worse the model gets at the original task. Sub-agents fix this.
A sub-agent is a separate loop with its own context, tools, and system prompt. The main agent spawns it, it works in the background, and **only the result comes back, **all the noisy intermediate steps never touch your main conversation.
The catch: sub-agents use a lot of tokens because they re-establish base context from scratch, and people often don’t realize they’re running. Use the right model for them, and check /usage if your bill looks weird.
The context window went from 200K tokens to 1M, and my instinct was to celebrate. Wrong instinct. As the window fills, the model loses the thread — too much irrelevant content — and output quality drops. I now /compact or clear and start fresh far more often than I expected to.
The single most useful reframe: treat it like a teammate, not a search box.
That’s the real change. I write fewer lines of code than I used to and I ship better software because of it.
What’s the one Claude Code habit that changed your workflow? I’d love to hear it.
Why Claude Code Changed My Workflow? was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.