# Using Claude Code Better: The Beginner's Guide

> Most people use Claude Code like fancy autocomplete and leave 90% of it on the table. It's a terminal agent that reads your repo, runs your commands, and checks its own work. Here's how to actually drive it.
>
> Published: 2026.07.28 · 12 min · AI, CLAUDE CODE, AGENTS, GUIDE
> Canonical: https://cyperx.dev/blog/using-claude-code-better-beginner

---
You installed Claude Code. You typed a question. It gave you a decent answer. You copied the code into your editor, ran it, it half-worked, you typed another question. Congratulations — you just used a race car to drive to the mailbox.

Claude Code isn't a chatbot that happens to live in your terminal. It's an agent. It reads your whole repo, runs your commands, edits your files, runs your tests, and checks its own work before it hands anything back. If you're using it like autocomplete with extra steps, you're leaving about 90% of it on the table.

This is the guide I wish someone had handed me on day one. By the end you'll stop typing "how do I..." and start typing "do this, and here's how you'll know it worked." That shift is the whole game.

![A lone developer at a terminal while a swarm of agent nodes fans out in parallel across the frame](/images/blog/cc-hero.webp)

## What Claude Code actually is

Most tools you've used are text-in, text-out. You ask, they answer, you do the work. Claude Code closes that loop. It's a terminal-native agent with real hands: it can list your files, grep across the codebase, open and edit any of them, run shell commands, spin up your dev server, and read the output that comes back.

That last part matters more than the editing. An agent that can *only* write code is a fancy autocomplete. An agent that can write code, run it, see it fail, and fix it — that's a different kind of tool. It doesn't need you to be the copy-paste middleman between it and reality.

So the mental model isn't "smart search box." It's "a junior dev who's read the entire codebase in the time it took you to read this sentence, never gets bored, and will happily run the test suite forty times." Your job stops being *typing the code*. It becomes *directing the work and defining what "done" means*. More on that — it's the core of everything.

![Animated Claude Code agent loop — read the repository, run commands, edit files, test changes, inspect results, then repeat](/images/blog/cc-beginner-agent-loop.svg)

## Your first real session

Open a terminal, `cd` into an actual project, and run:

```bash
claude
```

That drops you into the interactive REPL. Not a web tab, not a sidebar — a prompt sitting inside your repo, with your files and your git history right there. First thing to do in any new project:

```
/init
```

This scans your codebase and generates a `CLAUDE.md` at the repo root — a short brief on what the project is, how it's built, how to run it and test it. We'll come back to this file because it's one of your biggest levers. Let it write a first draft, then you trim it.

Now give it something real. As it works, you'll hit permission prompts — Claude wants to run a command or edit a file and asks first. This is the safety rail, and how you answer shapes your whole experience.

- **Reads and searches** (ls, grep, cat, reading files) — safe. Allow them.
- **Edits inside the repo** — this is the job. Allow, and lean on git as your undo button.
- **`npm test`, `go test`, `cargo build`, your linter** — the good stuff. You *want* it running these. Allow.
- **`rm -rf`, `git push`, anything that force-pushes, deletes, or leaves your machine** — read it. Every time. This is where you actually pay attention.

You can approve one-off, approve-for-session, or run in a skip-permissions mode (don't, not while learning — that's how you find out what "it deleted the wrong branch" feels like). There are permission modes too: `default` asks as it goes, `acceptEdits` stops nagging you about file writes but still gates commands, and `plan` mode makes it think through an approach and show you *before* touching anything. Plan mode is great when you don't fully trust the ask yet — you get the strategy, approve it, then it executes.

The reflex to build: skim what it wants to do, allow the boring stuff freely, actually read the dangerous stuff. Rubber-stamping a `git push --force` because you've been mashing "yes" for ten minutes is a self-inflicted wound.

## CLAUDE.md — the file that does the most work

`CLAUDE.md` is project memory. Claude reads it automatically at the start of every session, so it's where you write down the things you'd otherwise repeat a hundred times: how to run the app, how to test, conventions the code follows, landmines to avoid.

There are two levels. `~/.claude/CLAUDE.md` is global — your personal preferences across every project. A `CLAUDE.md` at a repo root is project-specific and should live in git so your whole team shares it.

Here's a real, lean starter for a TypeScript project:

```markdown
# Project: acme-api

REST API for the Acme dashboard. Node + TypeScript + Postgres.

## Commands
- Install: `pnpm install`
- Dev server: `pnpm dev` (localhost:3000)
- Test: `pnpm test` (Vitest)
- Test one file: `pnpm test src/routes/users.test.ts`
- Typecheck: `pnpm typecheck`
- Lint: `pnpm lint --fix`

## Conventions
- Strict TypeScript. No `any`. No non-null `!` assertions.
- Routes in `src/routes/`, one file per resource, colocated `.test.ts`.
- DB access only through `src/db/`. Never write raw SQL in a route.
- Errors: throw `AppError`, never bare strings.

## Gotchas
- Migrations run automatically on `pnpm dev`. Don't hand-edit the DB.
- `pnpm test` needs a running Postgres — `docker compose up -d db` first.

## Definition of done
- `pnpm typecheck` and `pnpm test` both pass.
- New endpoints have a test covering the happy path and one failure case.
```

Notice what's *not* there. No essay on your architecture philosophy. No pasted style guide. No history of the project. Keep it lean — everything in this file gets read on every turn, and a bloated `CLAUDE.md` both wastes context and buries the rules that matter. If a line isn't something you'd genuinely repeat out loud to a new teammate on day one, cut it.

That "Definition of done" section at the bottom is doing quiet, heavy lifting. Hold that thought.

![Reference card for a useful Claude Code task: goal, context, verification and exit criteria](/images/blog/cc-beginner-session-card.svg)

## The core loop: give a goal, not a recipe

Here's the single biggest habit change, and it comes straight from how the people who built this thing think about it. Boris Cherny — who created Claude Code — talks about "unhobbling" the model: getting out of its way. The old instinct is to hand an AI tiny, over-specified steps because you don't trust it. That instinct actively makes the output worse now. You're constraining a thing that plans better than your step list does.

Watch the difference.

**The bad prompt — micromanaging:**

```
Open src/routes/users.ts. Add a function called getUserById.
Make it take an id parameter. Query the database. Return the user.
Then add a route for GET /users/:id. Then write a test.
```

You just did the architecture in your head and made Claude your typist. If your plan has a flaw, you baked the flaw in. And you had to think about `getUserById` existing at all — that was *your* job to figure out, not the tool's.

**The good prompt — goal plus definition of done:**

```
Add an endpoint to fetch a single user by ID.

Follow the patterns already in src/routes/ and src/db/.
Return 404 with an AppError if the user doesn't exist.

Done when: `pnpm typecheck` and `pnpm test` pass, and there's a
test covering both the found and not-found cases.
```

You said *what* you want and *how you'll know it's right*. You left the *how* to the agent — which function names, which files, how to wire the DB call, whether there's an existing helper you forgot about. It'll go read `src/routes/` and `src/db/`, match your conventions, and quite often do it better than your step list would have, because it can see the whole codebase and you're working from memory.

Goals scale. Recipes don't. The moment your task is bigger than a paragraph of steps, the recipe approach collapses and the goal approach keeps going.

There's a fun bit of proof here. When Claude's underlying model got upgraded, the team deleted something like 80% of Claude Code's own system prompt — all the careful hand-holding instructions — because the better model did *worse* with the scaffolding than without it. Delete-first. If your prompt is a wall of "do this, then this, then this," you're probably the scaffolding now.

## Verification is the whole thing

If you take one idea from this post, take this one. Per Cherny, the number one factor in whether an agent succeeds at a *long* task isn't how smart it is — it's whether it can check its own work. A model that can verify can grind on a hard problem for hours and climb toward correct. A model that can't verify is just guessing with confidence.

The story that makes this land: an app rewrite where the agent screenshotted the UI and pixel-diffed it against the original, over and over, for two weeks — using the visual diff as the signal for "am I there yet." It didn't need a human in the loop for every step because it had a way to *know* if it was right.

You get this almost for free, and most people skip it. The trick is to always hand Claude a way to check itself, right there in the prompt.

Weak:

```
Fix the bug where the total doesn't include tax.
```

Strong:

```
Fix the bug where the cart total doesn't include tax.

There's a failing test in src/cart/total.test.ts that reproduces it.
Make that test pass without breaking the others.
Run `pnpm test src/cart` and show me it's green before you're done.
```

Now Claude has a referee that isn't you. It'll run the test, watch it fail, fix, re-run, and keep going until it's actually green — instead of announcing "Fixed!" and leaving you to discover it wasn't.

The pattern generalizes to everything:

- UI change? "Start the dev server and confirm the page loads without console errors."
- API change? "Hit the endpoint with curl and show me the response."
- Refactor? "Run the full test suite and the typechecker; nothing should regress."
- CLI tool? "Run it with `--help` and with a real example, paste the output."

The magic phrase is basically *"and prove it."* An agent that has to prove it can't hand you a confident lie. This is the difference between an intern who says "yeah it's done" and one who says "it's done, here's the passing test run." Only one of those you can trust.

## Context hygiene: `/clear` between tasks

Claude Code keeps everything from your current session in context — every file it read, every command, every message. Great for one focused task. Poison across five unrelated ones.

If you fix a login bug, then start a database migration in the same session, all that login noise is still sitting in context. It muddies the new task and burns your window. So between unrelated tasks:

```
/clear
```

Wipes the slate. Fresh start, same repo. Cheap habit, big payoff — think of it like closing tabs. And when a *single* task runs so long the history gets huge, `/compact` summarizes the session down so you can keep going without hitting the wall. Rule of thumb: `/clear` when you switch jobs, `/compact` when one job runs long.

New task, `/clear`. Say it with me.

## Going further (just so you know it's there)

Once the loop above is muscle memory, there's more — I'll point, not lecture, because you don't need it yet.

**Custom slash commands.** Drop a markdown file in `.claude/commands/` and it becomes a `/command`. Say you review PRs the same way every time:

```markdown
---
description: Review the current diff for bugs and missing tests
---

Review the staged git diff. Focus on:
- Logic bugs and unhandled edge cases
- Missing test coverage
- Anything that violates the conventions in CLAUDE.md

Give me a short list, most important first. Don't fix anything yet.
```

Save that as `.claude/commands/review.md` and now `/review` runs your exact checklist any time. Your repeated prompts want to become commands.

**Subagents.** Claude can spin up a separate agent (via its Task tool, with definitions living in `.claude/agents/`) to go do a focused chunk of work in its own clean context and report back — handy for parallel work or keeping a big search from polluting your main thread.

**MCP servers.** `claude mcp add` connects Claude to outside tools and data — a database, a browser, an issue tracker, your own services. It's how the agent reaches past the repo.

**Hooks and settings** live in `.claude/settings.json` — run a command automatically after every edit (auto-format, say), or pre-approve a set of safe commands so you stop getting prompted for `pnpm test`.

That's the map. Don't chase it today. Nail the goal-then-verify loop first; the rest only pays off once that's automatic.

## One full run, done right

Let's do a real one end to end so you can see the rhythm. Task: a `/health` endpoint that checks the database is reachable and returns JSON. Same project as the `CLAUDE.md` above.

**1. Clear and set the goal.**

```
/clear
```

```
Add a GET /health endpoint.

It should check the database connection and return:
- 200 { "status": "ok", "db": "up" } when the DB responds
- 503 { "status": "degraded", "db": "down" } when it doesn't

Follow the existing patterns in src/routes/ and src/db/.

Done when:
- `pnpm typecheck` passes
- there's a test in src/routes/health.test.ts covering both the
  healthy and the DB-down case (mock the DB failure)
- `pnpm test src/routes/health` is green
```

Goal, shape of the output, and a hard definition of done with its own referee. I didn't name a single function.

**2. Watch it work.** It reads `src/routes/` to match the style, checks `src/db/` for how connections are exposed, writes the route, writes the test. Permission prompts show up for the file edits — allow. Then it asks to run `pnpm typecheck` and `pnpm test` — that's the whole point, allow.

**3. Let verification run.** It runs the typecheck. Passes. Runs the test. And say one fails — the DB-down mock is throwing where the code expected a rejected promise. Here's the part people miss: *I don't touch anything.* It sees the failure in the test output, reads it, adjusts the error handling, re-runs. Green. It did the debug loop itself because I gave it a test to check against.

**4. Correct if needed.** It reports back with the passing run. I glance at the diff and notice it returns a bare `{ status }` on error instead of using our `AppError` pattern. One line:

```
Looks good, but the 503 path should go through AppError like the
rest of src/routes/. Fix that and re-run the test.
```

It adjusts, re-runs, still green. Now it's done — and "done" means typecheck passes, both test cases pass, and it matches our conventions, because that's what I *defined* done as up front. Not "done" as in "it printed some code."

Total human effort: two prompts and one correction. Notice I never wrote a line of the endpoint, never ran a test myself, never played copy-paste courier. I directed and I verified. That's the job now.

## The bigger picture (per the interview)

The worked example is the small version of something that scales scary far. Cherny frames it as *algebra for agents* — you compose agents like operations. Sequential (do A, then B), parallel (do A and B at once), fan-out (split a big job across many). The referee that makes it safe to run them loose is the same thing you just used on the health endpoint: a test suite.

The example he gives: rewriting a ~100k-line Bun component from Zig to Rust in about 11 days, with the existing test suite acting as the referee the whole way. The agents could run hard and parallel *because* passing tests defined correct. No test suite, no referee, no trust, no scale. It's the pixel-diff idea again — a machine-checkable definition of done is what lets an agent run long without a human babysitting every step.

He splits recurring work into *loops vs routines* too — some jobs loop locally while you watch, others run as scheduled routines in the cloud. One that stuck with me: an "Abstraction Police" job that periodically scans the codebase for premature abstractions and flags them. Boring, valuable, runs on its own. Once you trust the loop, you start pointing it at recurring chores.

And forward-looking — treat this as *from the interview*, not gospel — the claim is that with the next model jump (they talk about an Opus 5), the leash gets longer again and even more of the hand-holding falls away. Which is the through-line of this whole post: the tool keeps rewarding people who *get out of its way* and punishing people who micromanage.

The mindset underneath all of it is empirical. Try something. Watch it fail. Adjust. And — this is the underrated part — *retry things that failed before*, because the model underneath you keeps getting better. That prompt that flopped three months ago might just work now. Don't cache your old "Claude can't do X." Re-test it.

## Do this today

Enough reading. Concrete steps, right now:

1. `cd` into a real project and run `claude`.
2. Run `/init`. Read the generated `CLAUDE.md`, then trim it to the lean shape above — add your real test and run commands and a "Definition of done."
3. Pick one small, real task. Write it as a **goal + definition of done**, not steps. Include how it should verify itself — a test to pass, the app to start, a command to run.
4. Let it work. When it wants to run your tests, say yes. Watch it verify. Don't jump in to fix things it can fix itself.
5. Correct with one sentence if the output's off. Then `/clear` before the next task.
6. Take your most-repeated prompt and save it as `.claude/commands/whatever.md`.

That's the whole shift. Stop asking Claude Code questions. Start handing it goals with a finish line it can see for itself, and let it run to the line. You brought a race car — quit idling in the driveway.