Claude Code best practices: the short version
Per Anthropic's documentation, in most cases your first plain prompt in a fresh session already does the right thing. Setup pays off where your project has something Claude cannot see from the code alone: a deploy process that lives in someone's head, a file it must never read, a check that has to pass, a budget. This page is the short version, with links to the longer guides.
When a session goes wrong, it is usually one of four things
- Claude built something different from what you had in mind, or it rediscovers the same fact every session. It is missing information it cannot get from the repo.
- It said it was done and it was not, usually because it had no way to check its own work.
- It did something that must never happen, or skipped a step that must always happen. A prompt alone cannot guarantee either.
- It got it right, but cost more time, tokens or permission prompts than the task was worth.
Two kinds of instruction
Everything you tell Claude Code is one of two kinds. Claude decides: your prompt, CLAUDE.md, a skill. It usually follows them, but nothing guarantees it. Claude Code enforces: a hook, a deny rule, a managed setting. These apply every time, whatever the model decided. Most of the time you want Claude to decide. Keep the enforced kind for rules with no exceptions. If you keep adding emphasis to a CLAUDE.md line and Claude still misses it, the docs say that line probably belongs in a hook. The reverse holds too: a hook that only enforces a preference should go.
1. Tell Claude what it cannot see
Claude reads your code well, so write down only what it cannot find, or what it would spend time rediscovering every session. A test before you write anything: could it find this by reading the code, and would it actually go and look? If both are yes, leave it out.
- Be specific in the prompt. Name the file, describe the symptom, say what "fixed" looks like. "Fix the export bug" becomes "the export button does nothing for reports over 1,000 rows; the handler is in
src/export/; write a failing test first, then fix it". - Hand things over instead of describing them. Type
@and a path to include a file, paste a screenshot, or pipe output in:cat error.log | claude -p "what is going on here". - If you do not know what you want yet, ask Claude to interview you until it could write the spec, and write it to a file such as
SPEC.md. Then build from that file in a fresh session. - Keep
CLAUDE.mdshort. Every line takes a little attention on every task. Good content: the exact test, typecheck and lint commands, places where the code is misleading, decisions that are not in the repo, anything you had to correct twice./initwrites a starter; the work is then mostly deleting lines. Personal preferences go inCLAUDE.local.md, kept out of git. - Scope rules to one part of the code with a file in
.claude/rules/that has apaths:filter, so it loads only when Claude works there. - Put team procedures in skills. A release checklist in a skill does not weigh on unrelated tasks the way it would in
CLAUDE.md. For a workflow with side effects, adddisable-model-invocation: trueso it only runs when you type it. - Connect what lives elsewhere. A command-line tool you are signed in to (such as
gh) is usually the easiest way in; otherwise add an MCP server. Servers add their tool names to the context even when unused, so turn off the ones you do not need in/mcp.
# Commands
- Run one test file: npm test -- path/to/file.test.js
- Typecheck: npx tsc --noEmit
# Gotchas
- src/legacy/ is still live, but do not copy its patterns into new code
- Integration tests need DATABASE_URL, see .env.example
See the memory guide and how to write a skill.
2. Give Claude a check to run
Claude stops when the work looks done. If it has nothing to run that comes back pass or fail, "looks done" is all it has, and you become the test suite. Give it a test file, a build's exit code, a linter, or a script that compares output with an expected file, and it can make a change, run the check, read what broke and fix it. If your repo already has one, the most useful line in CLAUDE.md is the command that runs it.
You choose how strict to be:
- In the prompt: "run the auth tests afterwards and keep going until they pass". Claude decides when it is satisfied.
- With a goal: recent versions have a
/goalcommand that sets a condition a separate model checks after every turn. It matters mostly for long unattended runs. - With a
Stophook: your script runs whenever Claude tries to finish and sends it back to work if the script exits with code 2. Claude Code enforces this one. After several blocks in a row it lets the turn end, so it cannot loop forever. - With a fresh reviewer: a second session, or a review in a subagent that never saw the conversation, is not swayed by the reasoning that produced the code. Tell it what to check, and to skip style, or it will always find something.
Whichever you pick, ask for evidence: the command it ran and its output. "All tests pass" alone tells you little.
{
"hooks": {
"Stop": [
{ "hooks": [ { "type": "command", "command": "npx tsc --noEmit 1>&2 || exit 2" } ] }
]
}
}
That goes in .claude/settings.json. The compiler output is redirected to stderr because that is what Claude receives as the reason it cannot finish yet. More in three hooks to paste.
3. Enforce the rules that cannot have exceptions
"Never read .env", "always run the formatter", "do not touch the migrations folder": Claude will follow these almost every time. Where "almost" is not good enough, move them out of CLAUDE.md and into configuration that Claude Code applies itself.
- Hooks run your command at fixed points: before or after a tool call, when Claude tries to stop, at session start. A
PostToolUsehook with the matcherEdit|Writecan run your formatter after every edit, whether or not Claude remembers the rule. Use a command or HTTP hook for real enforcement; a hook that asks another model to decide is not deterministic. - Deny rules hold in every permission mode.
"deny": ["Read(./.env)", "Read(./secrets/**)"]in your settings blocks the Read tool and common file-reading commands such ascat .env. Rules match tool calls, not intent: a script that opens the file is not caught, and a domain deny rule on web fetches does nothing aboutcurlunless the sandbox is on. - The sandbox (
/sandbox) limits file and network access at operating-system level. The docs list macOS, Linux and WSL2 as supported. - Auto mode is a classifier, a model judging each action, not a hard rule. Put your "never" rules in deny rules or hooks.
Where a rule lives decides who it applies to: .claude/settings.local.json and ~/.claude/settings.json are yours alone, .claude/settings.json in the repo applies to everyone who works there (its allow rules and hooks wait until each person accepts the folder), and managed settings belong to an organization. Keep the enforced set small; every hook and deny rule will occasionally fire when it should not, and someone has to maintain it. See a starter permissions file, permission modes and which settings file wins.
4. Steer, and keep cost down
- Watch the first minute and press
Escas soon as Claude drifts. It stops mid-action and keeps everything up to that point. /rewind(orEsctwice on an empty prompt) rolls the code, the conversation or both back to an earlier prompt, so trying the bolder approach is low-risk. Checkpoints cover files edited with Claude's file tools, not files only a shell command touched, and they work alongside git, not instead of it.- After two failed corrections,
/clearand write one better prompt that includes what you learned. A third correction mostly adds to a conversation that already holds two failed attempts. /clearbetween unrelated tasks. Every request sends the whole conversation, so a session that has collected three tasks re-reads all three on the fourth./usageshows where your usage went, and/compactaccepts a focus such as "keep the API changes and the test commands".- Name long work.
/rename oauth-migrationin the session, thenclaude --resume oauth-migrationfrom your shell picks it up later.
See undoing changes and using less quota.
Before you leave a run unattended
Go through five questions for that specific task: does it know what done looks like; can it check its own work; what is it allowed to touch; what stops it (a turn or spend cap); and where does the result go, and who signs off. Claude will carry a long task through on its own. The parts that stay with you are starting it, deciding what "done" means this time, and approving the merge. See running from a script and parallel sessions with worktrees.
What you can stop doing
- Shouting in capitals (IMPORTANT, ALWAYS). Current models follow a plainly worded line, and heavy emphasis tends to make Claude over-apply the rule. If a rule cannot bend, make it a hook or a deny rule; if a line gets lost, the file is too long.
- "Think hard" and "be thorough". That is ordinary prompt text. The control for how hard Claude thinks is the effort level.
- "Keep going, do not be lazy". Giving Claude a check to pass is different, and still worth doing.
- Describing your architecture and file layout in
CLAUDE.md. Claude reads the repo itself.
For how the pieces fit together, see how Claude Code works. If something is not behaving, debug your configuration. All the guides are in the guides index.
This follows Anthropic's best practices documentation as we read it in October 2026. We are not affiliated with Anthropic. We wrote this from the documentation and have not tested every case. Commands, defaults and the permission mode a session starts in change between versions, and where this page and the documentation disagree, the documentation wins.
See also: Everyday workflows.
The free loop-stop skill gives long tasks a limit and a stop rule. If you want a second pair of eyes on your CLAUDE.md and settings, the Tune-Up Kit is a checklist for exactly that.