Using Claude Code Like a Pro — Driving an Agent, Not Autocomplete
Most people use Claude Code like fancier autocomplete. Professionals drive it like an agent. The difference isn't prompt tricks — it's how you design context, permissions, and feedback loops.
Most people use Claude Code like fancier autocomplete. Ask a question, paste the code, ask again when it breaks. Use it that way and you get exactly that much out of it.
Professionals work differently. They drive Claude Code as an agent — something that reads files, edits them, runs commands, looks at the result, and fixes itself. And the difference, surprisingly, has almost nothing to do with "writing better prompts."
The good news: the professional way comes down to a handful of techniques. The bad news: without them you get stuck in the same place every time. Hand it a big task and it edits the wrong thing, the context gets tangled, and you fall back to "I'll just do it myself."
This post is about using Claude Code as a tool, not a toy. One mental model, then ten techniques on top of it.
The mental model — you control three things
Claude Code is, in the end, an agent running in a loop. Toward a goal, it reads context → acts (edits files, runs commands) → looks at the result → decides again. It repeats until the job is done.
What you actually control is just three things.
[Context] ──→ [Agent loop] ──→ [Feedback]
what it knows act via tools how it checks the result- Context — what Claude "knows" right now: your instructions, the files it opened, CLAUDE.md, the conversation so far. A smart model still can't do what it doesn't know.
- Tools & permissions — what Claude "can do": read/write files, shell commands, search, subagents. You decide how far that reaches.
- Feedback loop — how Claude "verifies" its own work: tests, type checks, builds, lint. Without it, you get plausible lies.
Almost everything a pro does is tuning these three. Not "how do I phrase the prompt?" but "how do I give it the context this task needs, what permissions does it get, and how does it verify the result?" Hold this picture in your head and every technique below turns out to be a variation on the same theme.
1. CLAUDE.md — the one most important file
The first thing to do when you open Claude Code — if you pick only one — is CLAUDE.md.
CLAUDE.md is a project memo that gets loaded automatically at the start of every session. Put your build/test commands, coding conventions, directory layout, and the things-not-to-do in there, and you stop explaining them every time.
/init # scans the codebase and drafts a CLAUDE.md for youWhat goes in a good CLAUDE.md:
## Commands
- Build: `npm run build`
- Test: `npm test`, single file: `npm test -- path/to/file`
- Lint: `npm run lint` (required before commit)
## Conventions
- Never mutate existing objects — always return a new one
- Keep files small: 200–400 lines, 800 max
- No console.log — use the logger
## Structure
- src/lib — pure logic, no React dependency
- src/components — UI onlyThere's a hierarchy — all three are merged and read:
~/.claude/CLAUDE.md— shared across all your projects (your personal taste)<project>/CLAUDE.md— this project (shared with the team, committed to git)<subfolder>/CLAUDE.md— only when working inside that folder
When a new rule comes up mid-conversation, add it to memory on the spot with #:
# Always put migrations under supabase/migrationsClaude asks where to save it and writes it into CLAUDE.md.
2. Clear context on purpose — /clear and /compact
The most common reason people use Claude Code badly: trying to do everything in one session.
Long conversations fill the context window. Build login, then chase a bug, then refactor, then fix CSS… and now Claude's context is full of unrelated junk. It drags in a stale decision from earlier, slows down, and costs more.
The rule: one task, one session. When the task is done, clear it.
/clear # wipes context completely. the start of a new task.
/compact # summarizes and compresses the conversation (a breather mid-task)/clear — when you start a new task. If the previous task's context won't help the next one, drop it without hesitation.
/compact — when a single task runs long and the context is filling up but you want to keep the thread. It squeezes the conversation into a summary.
3. Plan mode — plan before you touch code
For a small edit, just ask. But when a task spans several files, changes structure, or the "how" itself is uncertain — make it plan first.
Plan mode lets Claude plan what to do and how, without touching a single line of code. It reads, but doesn't write.
Shift + Tab # cycle modes: normal → auto-accept → plan modeIn plan mode Claude investigates the codebase, proposes an approach, and waits for your approval. You read the plan and — if the direction is wrong — fix it now. Correcting one sentence at the planning stage is 100x cheaper than writing 200 lines in the wrong direction and reverting them.
The flow:
- Shift+Tab into plan mode
- Describe the task — "switch the payments module from Stripe to Toss"
- Claude proposes a plan — affected files, order, risks
- Review it — approve or ask for changes
- Only then does it write code
4. Design your permissions — auto-accept and allowlists
By default, Claude Code asks before every file edit or command. Safe — but slow on work you already trust. There are two knobs.
Auto-accept mode — proceed without asking each time:
Shift + Tab # toggle auto-acceptTurn it on only for trusted, well-defined work. For anything exploratory or risky — off, and confirm one at a time.
Permanent allowlist — register the safe commands you run constantly in settings.json and stop being asked:
// .claude/settings.json (project) or ~/.claude/settings.json (global)
{
"permissions": {
"allow": [
"Bash(npm run test:*)",
"Bash(npm run lint)",
"Bash(git status)",
"Edit",
"Read"
],
"deny": [
"Bash(rm -rf *)",
"Read(./.env)"
]
}
}Now tests and lint run without prompts, .env can never be read, and dangerous deletes are blocked.
5. Hand it a feedback loop — tests are the truth
If you take one thing from this post — take this.
Claude fixes itself when it has a way to check whether its code is right. When it doesn't, it hands you plausible-looking code and says "all done." The thing that makes the difference isn't the model — it's the feedback loop.
The most powerful feedback is tests.
"Before fixing this function — write a failing test first.
Then make it pass, and confirm green with npm test."Ask that and Claude writes the test (RED) → implements → runs the test → fixes itself on failure → repeats until it passes. You don't have to step in. Give it a verifiable goal and the agent self-corrects.
Even when there are no tests, you can still hand it feedback:
"After the change — confirm there are no type errors with
npx tsc --noEmit, and that npm run build succeeds. Then stop."For UI work, paste a screenshot. One image of "this is how it should look" is stronger feedback than ten paragraphs.
6. Subagents — for parallelism, and to isolate context
Claude Code can delegate work to other Claudes. These are subagents. Two reasons to use them.
1. Parallelism — independent work, at the same time:
"Review three areas in parallel:
1) security of the auth module
2) performance of the cache layer
3) types of the util functions"2. Context isolation — the more important one. A task like "search the whole codebase for where this feature is implemented" reads dozens of files. Do it in the main session and your context fills with junk. Hand it to a subagent and the search happens in the subagent's context — only the conclusion comes back to the main session.
Save the roles you reach for often as custom agents:
<!-- .claude/agents/code-reviewer.md -->
---
name: code-reviewer
description: Reviews quality & security right after code is written/edited. Use proactively.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a code review expert. Review changed code for security,
readability, and error handling — and report findings classified
as CRITICAL / HIGH / MEDIUM.Now "review what I just wrote with code-reviewer" calls it.
7. Turn repeated work into slash commands
If you keep typing the same long instruction, that's the signal to make it a slash command.
Drop a markdown file under .claude/commands/ and it becomes a /command.
<!-- .claude/commands/fix-issue.md -->
Handle GitHub issue #$ARGUMENTS:
1. Read it with `gh issue view $ARGUMENTS`
2. Find the relevant code
3. Write a failing test → fix → make the test pass
4. Draft a commit messageNow /fix-issue 42 runs that whole procedure. 42 lands in $ARGUMENTS.
Worth knowing the built-ins, too:
/clear wipe context
/compact compress the conversation
/init generate CLAUDE.md
/review code review
/model switch model
/agents manage subagents8. Hooks — guardrails that run without being asked
If a slash command is "something that runs when I call it," a hook is "something that runs automatically without being called."
A hook runs a shell command at a specific moment. The most common use: auto-format on every file edit.
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATHS\""
}
]
}
]
}
}Now prettier runs every time Claude edits a file. You never have to ask it to "format that."
Why hooks are powerful: they're deterministic. Ask Claude to "lint it" and it might forget; a hook runs the code no matter what. Not a request — a rule.
Key moments:
- PreToolUse — before a tool runs (block dangerous commands)
- PostToolUse — after a tool runs (format, lint, type check)
- Stop — when the session ends (final check)
9. MCP — connect the outside world
So far this has been Claude playing inside files and a shell. MCP (Model Context Protocol) connects the world beyond that.
Attach an MCP server and Claude can query a database directly, read an issue tracker, look at a design file, drive a browser.
claude mcp add --transport http context7 https://... # latest library docs
claude mcp list # connected serversCommon combinations:
- Docs MCP (Context7, etc.) — current library APIs, without hallucinating them
- DB MCP — read the schema, run queries
- Browser MCP (Playwright, etc.) — actually open the page and check the UI
- Issue / Jira / Notion MCP — read task context directly
The point is extending verification and context. With a browser MCP, Claude can open the screen it just built and fix it — another feedback loop.
10. Model and thinking time — when to spend the expensive brain
The last knob — size of the brain, depth of the thought.
/model # switch between Opus / Sonnet / Haiku- Opus — deepest reasoning. Complex architecture decisions, gnarly debugging, designing big refactors.
- Sonnet — most coding work. A good default.
- Haiku — fast and cheap. Simple edits, repetitive work, frequently-invoked subagents.
You don't need the expensive brain for everything — matching the model to the task's difficulty is a pro's sense of cost.
Depth of thought is adjustable too. In front of a hard problem, one keyword buys more reasoning time:
think a bit more thinking
think hard more
ultrathink as deep as it goes"Analyze this concurrency bug with ultrathink —
trace where the race condition comes from and fix it."Use it only when the reasoning genuinely calls for it. ultrathink on a trivial task is a waste of money and time.
The daily loop — on one page
A pro's day is, in the end, this loop on repeat:
# Project setup (once)
/init # generate CLAUDE.md → hand-tune it
# set permissions + a format hook in .claude/settings.json
# Start a new task
/clear # clean context
Shift+Tab → plan mode # for a big task, plan first
# "plan the payments-module refactor — show me first, then get approval"
# After approving the plan — run it with a feedback loop
# "failing test first → implement → loop yourself until npm test is green"
# When you need to explore, isolate it in a subagent
# "find where this pattern is used via a subagent, give me just the conclusion"
# Wrap up
/review # or the code-reviewer agent
git diff # final check with your own eyes
# commit (the PostToolUse hook already formatted/linted)
# Next task → /clear againFive common traps
1. Everything in one session
Context fills with junk and judgment blurs. → /clear between tasks.
2. No CLAUDE.md, explaining every time
Re-typing the same conventions every session. → /init, tune it, do it once.
3. Believing "it's done" without verification Accepting code with no test, no build run. → always hand it a grader (test/type/build).
4. Mindless auto-accept Auto-accept on, not watching, and the wrong files all change. → only in the trusted zone, with a careful allowlist.
5. Big task with no plan 200 lines in the wrong direction. → plan mode, "plan first."
Closing — the real secret
The ten techniques in this post all reduce to one sentence.
Using Claude Code well isn't writing better prompts — it's designing the environment the agent works in.
Give it good context (CLAUDE.md, a clean session), the right permissions (allowlist, auto-accept), and a dense feedback loop (tests, types, hooks), and the model produces good results on its own. When you're stuck, the question is always the same — "Does Claude know enough to do this? Does it have permission to? Does it have a way to check that it's right?"
Like git, the real secret of Claude Code is not being afraid of it. Auto-accept is scary because it might not be reversible — but commit often, branch your work, lay down a verification loop, and even the worst case is one git reset away. (If git still scares you — start with git.)
The next post goes one level deeper: building your own harness — weaving custom agents, hooks, and slash commands together to automate your recurring workflow end to end.
Related writing
How to Land Your First Dev Job — It's Risk Reduction, Not an Exam
Landing a junior job isn't an exam that proves your knowledge. It's about reducing the employer's risk. Portfolio, résumé, applications, coding tests, and interviews step by step — plus what AI changed, in an honest field guide.
A Career Path for People Just Starting as Developers — The 2026 Version
Does it still make sense to become a developer when AI writes the code? Yes — but the path changed. An honest roadmap of what to learn and in what order, how to choose a first job, and what to avoid.