How to use Claude Code: a complete guide for developers
A hands-on guide to Claude Code: install it, run your first session, and use plan mode, CLAUDE.md, subagents, hooks and headless mode on real projects.
Claude Code is an agent that works in your terminal. You point it at a repository, describe what you want in plain English, and it reads files, edits them, runs your tests and commits the result. It is not autocomplete with a bigger window, and treating it like autocomplete is the fastest way to be disappointed by it.
I have used it daily for the past several months on a production TypeScript codebase, on this blog, and on side projects. This guide is what I would tell a colleague on their first day with it: how to install it, the loop that actually works, the handful of features worth learning early, and the mistakes that waste the most time.
What Claude Code actually is
The mental model that matters: Claude Code is a coding agent with tools, running in a loop, inside your project.
When you ask it to fix a bug, it does not answer from a snapshot of your file. It searches the repo, reads the files it decides are relevant, forms a plan, edits code, runs the test suite, reads the failure, and edits again. You approve the actions that touch your machine. That loop is the product.
It ships in four places, all backed by the same agent:
- The CLI (
claude) — the terminal interface this guide covers. - IDE extensions for VS Code and JetBrains.
- A desktop app for macOS, Windows and Linux, if you would rather not live in a terminal.
- The web app at claude.ai/code, for sessions that run in the cloud.
You need a Claude Pro, Max, Team, Enterprise or Console account. The free Claude.ai plan does not include Claude Code. You can also point it at Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry if your company routes AI traffic through one of those.
Install Claude Code
The native installer is the recommended route, and it keeps itself updated in the background.
macOS, Linux, WSL:
curl -fsSL https://claude.ai/install.sh | bashWindows PowerShell:
irm https://claude.ai/install.ps1 | iexIf you prefer a package manager, brew install --cask claude-code on macOS and winget install Anthropic.ClaudeCode on Windows both work — neither auto-updates, so you will need to upgrade them yourself. There are signed apt, dnf and apk repositories too.
npm still works and installs the same native binary:
npm install -g @anthropic-ai/claude-codeCheck it worked:
claude --version
claude doctorclaude doctor prints read-only diagnostics — install health, settings-file errors, warnings with suggested fixes — without starting a session. It is the first thing to run when something behaves strangely.
Then open a terminal in a project and start it:
claudeThe first run sends you to a browser to log in. After that you are in an interactive session.
A note for Windows users
Claude Code runs natively on Windows, no WSL required. Two things are worth knowing:
- Installing Git for Windows is optional but recommended, because it gives Claude a Bash tool via Git Bash. Without it, shell commands run through PowerShell instead — which works, but a lot of community advice assumes POSIX shell syntax.
- Sandboxed command execution is only supported under WSL 2. If you want Claude running commands in isolation, that is the reason to use WSL.
Your first session
Start in a repository you know well, so you can judge the output. Then ask for something small and specific.
The single biggest predictor of a good result is whether your prompt contains the information a new contractor would need. Compare:
fix the login bugagainst:
Users with an expired session get a 500 instead of a redirect to /login.
It reproduces on any request to /dashboard with a stale cookie.
Look at the auth middleware and the session helper, and add a test.The second is not longer for the sake of it. It names the symptom, the reproduction, the suspected area, and the definition of done. Claude is good at finding things; it cannot guess which of four plausible bugs you meant.
Three input tricks worth learning in the first ten minutes:
@mentions a file. Typing@src/lib/auth.tsputs that path in front of Claude directly instead of making it search.!runs a shell command. Prefixing your message with!runs it in the session, so the output lands in the conversation. Useful for handing over a failing test run or agit log.#writes to memory. Starting a message with#saves the instruction for future sessions instead of just this one.
The loop that works: explore, plan, code, verify
Almost every frustrating Claude Code session comes from skipping straight to "write the code." The loop that consistently works has four steps, and you can stop at any of them.
1. Explore. Ask it to read before it writes. "Read the checkout flow and explain how a discount code is applied, including where the totals are computed. Do not change anything yet." You get a map of the code and, more importantly, you find out whether it has understood the right part of the repo before it starts editing.
2. Plan. Ask for the approach, not the diff. This is what plan mode is for (below). Reviewing a five-bullet plan costs you thirty seconds; reviewing a 400-line diff built on the wrong assumption costs you an afternoon.
3. Code. Let it implement the approved plan. Keep the unit of work small enough that you can still review it — one behaviour, not one epic.
4. Verify. This is the step people skip, and it is the one that makes agents trustworthy. Give Claude a way to check its own work: a test command, a type check, a linter, a script that hits the endpoint. An agent that can run your test suite will iterate until it passes. An agent with no feedback loop is guessing.
If your project has a reliable way to build and run itself, tell Claude about it once in CLAUDE.md and every future session inherits it.
Plan mode and permission modes
Shift+Tab cycles the session's permission mode. This is the most important key in the tool.
The modes, in cycle order:
| Mode | What it does | When to use it |
|---|---|---|
default (shown as Manual) | Asks before each action that writes or runs | Normal work |
acceptEdits | Auto-approves file edits, still asks for commands | A refactor you have already scoped |
plan | Read-only. Investigates and proposes, cannot edit | Anything you have not fully specified |
bypassPermissions | Asks for nothing | Throwaway sandboxes only |
auto | Classifies actions and only asks for the risky ones | Longer autonomous runs |
Plan mode earns its keep on anything non-trivial. Claude can read everything and run nothing, so it comes back with an approach instead of a fait accompli. You then approve, redirect, or throw it away having lost nothing. Start a session there with:
claude --permission-mode planYou can also pre-approve narrow permissions rather than living in prompts or turning them all off:
claude --allowed-tools "Read" "Bash(git log *)" "Bash(npm test *)"/permissions manages the persistent allow/ask/deny rules for a project. Spending five minutes there — allowing your test command, denying anything that touches production — pays for itself within a day.
CLAUDE.md: the file that stops you repeating yourself
Every session starts with a fresh context window. CLAUDE.md is how project knowledge survives that.
Run /init in a new project and Claude writes a starting CLAUDE.md by exploring the codebase — build commands, test commands, the conventions it can infer. If one already exists, /init suggests improvements instead of overwriting it.
Files load from broadest to most specific, and all of them are concatenated rather than overriding each other:
| Location | Scope |
|---|---|
~/.claude/CLAUDE.md | You, in every project |
./CLAUDE.md or ./.claude/CLAUDE.md | The project, committed for the team |
./CLAUDE.local.md | You, in this project — gitignore it |
What belongs in it: build and test commands, architectural decisions, naming conventions, and the rules a new teammate would need told. What does not: anything Claude can read off the codebase itself. A directory listing in CLAUDE.md is context you pay for on every single session, to tell Claude something ls would have told it for free.
Two rules of thumb that make a real difference:
- Keep it under 200 lines. Longer files consume more context and get followed less reliably. If yours is growing, that is a signal to move things out, not to keep appending.
- Be specific enough to verify. "Use 2-space indentation" works. "Format code properly" does not. "Run
npm testbefore committing" works. "Test your changes" does not.
Add to it at the moment you notice yourself explaining something for the second time. That is the entire heuristic.
For larger projects, .claude/rules/ splits instructions into topic files, and a rule can be scoped so it only loads when relevant:
---
paths:
- "src/api/**/*.ts"
---
# API rules
- Every endpoint validates its input with the shared schema helper.
- Errors use the standard error response shape.That rule costs nothing until Claude touches a file under src/api/.
Claude also keeps its own auto memory per repository — notes it writes about your corrections and preferences, separate from the CLAUDE.md you write. /memory lets you browse, edit or delete any of it, and toggle the feature off.
Context is the resource you manage
The context window is finite, and a long session fills it with things that stopped being relevant twenty turns ago. Managing it is most of the skill.
/contextshows what is currently in the window as a grid, including which memory files loaded. Run it when a session starts feeling stupid./clearstarts fresh. Use it between unrelated tasks — a new bug in a new area does not benefit from the previous feature's history, it is diluted by it./compactsummarises the conversation to free space while keeping the thread. Reach for it mid-task; reach for/clearbetween tasks.
One task per session is the habit worth building. Ten small focused sessions beat one sprawling one, every time.
Sessions persist, so ending one is cheap:
claude -c # continue the most recent session here
claude -r "auth-refactor" # resume a session by name or id
claude -n "auth-refactor" # name the session you are startingAnd when a change goes the wrong way, Esc Esc on an empty prompt opens the rewind menu, which restores code and conversation to an earlier checkpoint. /rewind does the same thing from the command menu. This is a real undo for the agent's edits, and knowing it exists makes you braver about letting Claude try things.
Commands and shortcuts worth memorising
You can get by with /help, but these are the ones I use constantly.
| Shortcut | What it does |
|---|---|
Shift+Tab | Cycle permission modes (this is the plan mode key) |
Esc | Interrupt mid-turn, keeping the work so far |
Esc Esc | Clear the draft, or open the rewind menu on an empty prompt |
Shift+Enter or Ctrl+J | Newline without sending |
Ctrl+O | Toggle the transcript viewer to see full tool calls |
Ctrl+R | Reverse-search your prompt history |
Ctrl+B | Send a running command or agent to the background |
Ctrl+T | Toggle Claude's task checklist |
Ctrl+G | Edit your prompt in your real editor |
| Command | What it does |
|---|---|
/init | Generate a starting CLAUDE.md |
/clear, /compact, /context | Manage the context window |
/model | Switch model and save it as the default |
/code-review | Review the current diff or a PR |
/permissions | Edit allow / ask / deny rules |
/memory | Browse and edit memory files |
/agents, /mcp, /hooks | Configure subagents, MCP servers, hooks |
/resume, /rewind | Go back to an earlier session or checkpoint |
/usage | Current usage and cost |
/doctor | Diagnose setup problems |
On models: use the most capable one for design, debugging and anything requiring judgement, and a faster one for mechanical work. /model switches mid-session, and --fallback-model keeps a long run alive if you hit a limit.
Customise it: skills, subagents, hooks
Once the basics are habit, these are what turn Claude Code from a tool into your tool. All three are files in your repo, which means they are reviewable and shared with your team.
Skills (and custom commands)
A skill is a folder with a SKILL.md in it. The folder name becomes the command:
.claude/skills/
└── release-notes/
└── SKILL.md → /release-notesThe file is YAML frontmatter plus markdown instructions:
---
name: release-notes
description: Draft release notes from commits since the last tag
allowed-tools: Read, Grep, Bash(git log *)
---
Read the commits since the most recent git tag and group them into
Added / Changed / Fixed. Skip dependency bumps and merge commits.
Write the result to CHANGELOG.md under a new version heading.Write a skill the moment you notice yourself pasting the same instructions into chat for the third time. Crucially, a skill's body only loads when it is used — so a long procedure costs almost nothing until you invoke it, unlike the same text sitting in CLAUDE.md.
Custom commands and skills have converged: .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both give you /deploy. Existing command files keep working; new work is better as a skill, which can carry supporting files alongside it.
There are useful bundled ones too — /code-review, /debug, and /run and /verify for building and driving your app.
Subagents
A subagent is a separate context window with its own prompt and tool access, managed with /agents and stored in .claude/agents/. Two things make them worth it:
- Isolation. A subagent that reads forty files to answer one question returns the answer, not the forty files. Your main context stays clean.
- Parallelism. Independent work — reviewing four modules, searching several subsystems — runs concurrently.
The rule of thumb: delegate when the work is searching or reading broadly and you only want the conclusion. Do it yourself when you already know the file.
Hooks
Hooks are shell commands that fire at fixed lifecycle events, configured with /hooks. They are the answer to "Claude keeps forgetting to do X."
The distinction that matters: CLAUDE.md is guidance and Claude may not follow it perfectly. A hook is deterministic — it runs regardless of what the model decides. If a rule genuinely must hold every time, write a hook, not a paragraph.
The obvious first one is a PostToolUse hook that runs your formatter after every edit. Then you never think about formatting again.
MCP: giving Claude your other tools
Model Context Protocol servers let Claude reach systems outside your repo — a database, GitHub, Sentry, a design tool, an internal API.
claude mcp add # add a server/mcp manages connections and OAuth in-session, and project servers live in .mcp.json so the team shares them. The value is obvious the first time you ask Claude to reproduce a bug and it reads the actual failing trace instead of your paraphrase of it.
Add them deliberately, though. Every connected server puts more tool definitions in your context window whether you use them that session or not.
Headless mode and CI
claude -p runs a prompt and exits, which makes Claude Code scriptable:
claude -p "Summarise what changed in this diff" --output-format jsonUseful flags for automation:
--output-format jsonfor parseable output, or--json-schemato force a shape you define.--max-turnsto bound the agentic loop.--allowed-toolsto grant exactly the tools the job needs and nothing more.--max-budget-usdto cap spend on an unattended run.claude setup-tokento generate a long-lived token for CI.
It also reads stdin, which is where a lot of everyday value hides:
git diff main | claude -p "Review this diff for bugs. Be specific about failure cases."Common uses: a PR reviewer in CI, triaging failures on a nightly build, or a scheduled job that keeps a changelog current.
Five mistakes that waste the most time
1. Asking for code before asking for a plan. The fix is Shift+Tab into plan mode. A wrong plan costs a minute; a wrong implementation costs an afternoon.
2. One session for everything. Context fills with irrelevant history and quality drops in a way that feels like the model got worse. /clear between tasks.
3. No verification loop. If Claude cannot run something to check its work, it is guessing and you are the test suite. Give it a command that tells it whether it succeeded.
4. Repeating yourself instead of writing it down. The third time you explain a convention, put it in CLAUDE.md. The third time you paste a procedure, make it a skill.
5. Approving diffs you have not read. It is an agent working on your codebase, not a coworker whose judgement you have spent years calibrating. Small units of work exist so that reviewing them stays possible.
Where to go next
Install it, run /init in a project you know, and give it one real bug in plan mode. That is a fifteen-minute investment and it teaches you more than any guide.
After that, the two changes with the highest return are a CLAUDE.md that actually reflects how your project works, and one hook or skill that removes something you keep repeating. Everything else is refinement.
The official documentation is at code.claude.com/docs and is genuinely worth reading — particularly the pages on permissions, hooks and skills, which are where the real leverage is.
Frequently asked questions
Is Claude Code free?
No. It requires a Claude Pro, Max, Team, Enterprise or Console account, or access through Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry. The free Claude.ai tier does not include it. /usage shows where you stand against your limits.
Does Claude Code work on Windows without WSL?
Yes, natively on Windows 10 1809+ and Windows Server 2019+. Installing Git for Windows is optional but recommended, since it gives Claude a Bash tool instead of PowerShell. Sandboxed command execution requires WSL 2.
Can Claude Code see my whole codebase?
Not all at once, and that is the point. It searches and reads the files it needs, which is why it works on repositories far larger than any context window. Help it by naming files with @ when you already know where the problem is.
How is this different from an autocomplete extension?
Autocomplete suggests the next few lines inside the file you have open. Claude Code takes a goal, searches the repo, edits multiple files, runs your tests and iterates on the failures. Different unit of work, and a different way of prompting.
Will it commit or push without asking?
Not in the default permission mode — writes and commands need approval. That changes if you allowlist those commands, use bypassPermissions, or pass --dangerously-skip-permissions, which is exactly why the last one deserves the name it has.
What if it edits something it should not have?
Press Esc Esc on an empty prompt to open the rewind menu, or run /rewind. Both restore code and conversation to an earlier checkpoint. Working on a branch is still the sensible baseline.