0

πŸš€ Claude Code: From Zero to Hero πŸ€–

A practical, progressive guide to getting serious value out of Claude Code. Each section is short, actionable, and builds on the one before. If you already know the basics, skim the early parts and jump to where it gets interesting β€” the later sections are where most users leave value on the table.

πŸ“– How to read this guide Every section ends with a Try this now box. Do the exercise before moving on. Reading alone will not make you faster; typing will.


Table of contents

🌱 Part 1 β€” Zero

  1. What Claude Code actually is
  2. Install and first run
  3. Your first real task
  4. The interface: commands and shortcuts you need on day one

πŸ”§ Part 2 β€” Apprentice 5. CLAUDE.md β€” teaching Claude about your project 6. Permissions β€” stop approving the same commands over and over 7. Plan mode and review discipline 8. Context hygiene β€” the skill nobody teaches

⚑ Part 3 β€” Journeyman 9. Slash commands β€” your personal shortcuts 10. Subagents β€” delegation and isolation 11. Skills β€” reusable procedures 12. Hooks β€” deterministic automation

πŸ† Part 4 β€” Hero 13. MCP servers β€” connecting external systems 14. Prompting for real work 15. Team setup β€” making Claude Code a shared asset 16. Debugging Claude when it goes sideways 17. The habits that separate heroes from tourists


🌱 Part 1 β€” Zero

1. πŸ€– What Claude Code actually is

Claude Code is an AI coding agent that runs in your terminal (and inside VS Code, JetBrains, etc.). It reads your codebase, writes and edits files, runs shell commands, and iterates on tasks β€” all with your permission.

Three mental models that will save you hours of confusion:

  1. It's a collaborator, not a compiler. You describe intent; it proposes actions and waits for approval on anything risky. Give it context the way you'd brief a new teammate.
  2. It is stateless between sessions, but not between turns. Close the terminal and it forgets the conversation. That's why project memory (CLAUDE.md) exists β€” to carry the important stuff forward.
  3. Every tool call is explicit. Reading a file, editing it, running a shell command β€” these are all visible tool calls. If it's making changes you don't want, you can see exactly where.

What it is not: a chat wrapper. Claude Code has a rich configuration surface β€” permissions, slash commands, subagents, skills, hooks, MCP servers β€” and the difference between a tourist and a power user is almost entirely in how those are set up.


2. πŸ“¦ Install and first run

Install the CLI (one command, no account setup beyond API access):

npm install -g @anthropic-ai/claude-code

Verify:

claude --version

Start it inside a project directory:

cd ~/projects/my-repo
claude

On first run it will walk you through authentication. After that, you're looking at an interactive prompt waiting for input.

πŸ”₯ Try this now Install Claude Code, cd into any project you have, and run claude. Type /help and read the entire help output. Don't skip this β€” 30% of the things people ask me could be answered by reading /help once.


3. 🎯 Your first real task

Don't start with "hello world." Start with something you'd actually ask a teammate.

A good first prompt:

Read the README.md and the top-level directory, then give me a two-paragraph summary of what this project does and how the pieces fit together.

Why this works: it's bounded, read-only, and forces Claude to explore the codebase β€” which is how you'll learn what tools it has.

Watch what happens:

  • It calls Read on README.md
  • It runs ls via Bash
  • Maybe it peeks at a few key files
  • It answers in prose

You'll see tool calls scroll by. Each one is a concrete action. This transparency is the whole point β€” you're not trusting a black box.

Now try something active:

Add a CHANGELOG.md at the repo root with a "Keep a Changelog" template and an Unreleased section.

It will ask permission to write the file. Say yes. Look at the diff it produced. Ask it to change something trivial ("add a link to keepachangelog.com at the top"). Notice how it edits in place rather than re-writing the file.

πŸ”₯ Try this now Pick one real, small task in a real repo β€” not a toy β€” and ask Claude Code to do it end to end. Something like "write me a script that renames all .jpg to .png" or "refactor this function to use async/await." Review every tool call. Reject one thing you don't like and watch it adjust.


4. ⌨️ The interface

Key commands (type these at the prompt)

Command What it does
/help Full command reference
/clear Wipe the conversation β€” start fresh without quitting
/model Switch between models (Opus / Sonnet / Haiku)
/init Bootstrap a CLAUDE.md for the current project
/status Show what mode you're in, token usage, etc.
/review Review the current branch's changes
/compact Manually compact conversation context to free room
Esc Interrupt Claude mid-action
Shift+Tab Cycle through permission modes (normal β†’ auto-accept β†’ plan)

Permission modes (the single most useful thing to understand)

Claude Code has three main modes you'll toggle between:

  1. Normal β€” Claude asks before every tool call that isn't pre-approved. Safe default.
  2. Auto-accept (a.k.a. "YOLO mode" or "accept edits") β€” Claude runs without asking. Use when you trust the task and want speed. Never use for destructive or networked operations on a repo you care about.
  3. Plan mode β€” Claude explores and reasons but cannot modify anything until you approve a plan. Use for anything non-trivial. This is the single biggest time-saver most people ignore.

Cycle them with Shift+Tab. The current mode is shown in the status area.

Interrupting

If Claude is going down the wrong path, hit Esc. Don't wait for it to finish and then complain β€” redirect mid-flight. It handles interruption well.

πŸ”₯ Try this now Start a session, press Shift+Tab three times and observe how the mode indicator changes. Then try the same trivial task ("add a blank line to the README") in each mode and feel the difference. Also press Esc while it's mid-action at least once. Getting comfortable with these three keys is worth more than any config.


πŸ”§ Part 2 β€” Apprentice

5. πŸ“„ CLAUDE.md

CLAUDE.md is the single most valuable file in a Claude-Code-enabled repo. It's plain markdown placed at the repo root (and optionally in subdirectories) that Claude reads at the start of every session.

Think of it as the onboarding doc for a new engineer, except the engineer reads it every single day and has perfect recall.

What to put in it

  • Architecture β€” the service boundaries, the data flow, who calls whom
  • How to run things β€” exact commands, copy-paste runnable
  • Conventions that the code alone can't tell you β€” "we prefer functional components," "all errors must be wrapped with fmt.Errorf," etc.
  • Pitfalls β€” things that have burned the team before ("never edit an applied migration")
  • End-to-end checklists for common tasks ("adding a feature touches these 9 layers, in this order")

What to leave out

  • Anything ls or git log can answer
  • Narrative prose, history, aspirations
  • Secrets
  • Step-by-step tutorials (link to them instead)

Layering

You can have nested CLAUDE.md files. When Claude works inside a subdirectory, the nested file is loaded too. Use this for service-specific conventions in a monorepo.

repo/
  CLAUDE.md                  # root β€” cross-cutting context
  backend-go/CLAUDE.md       # Go-specific conventions
  backend-python/CLAUDE.md   # Python-specific conventions
  frontend/CLAUDE.md         # React/TS-specific conventions

There's also ~/.claude/CLAUDE.md β€” personal preferences applied in every project on your machine (e.g., "I prefer tabs over spaces in my personal scripts").

Rules of thumb

  • Every line competes for context budget. Treat it like a tweet β€” if removing a line wouldn't hurt, remove it.
  • Prefer commands over instructions. make test-integration beats a paragraph about integration tests.
  • State constraints explicitly. "Integration tests require Docker." not "We have integration tests."
  • Link, don't duplicate. If your style guide lives elsewhere, link it.

πŸ”₯ Try this now In your project, run /init. Claude will scan the codebase and draft a CLAUDE.md for you. Then read it critically and delete half the content. The short version is usually better. Commit it.


6. πŸ” Permissions

By default, Claude asks before running any shell command or editing any file. That's safe but interrupt-heavy.

Create .claude/settings.json in your repo:

{
  "permissions": {
    "allow": [
      "Bash(go test:*)",
      "Bash(pnpm test:*)",
      "Bash(npm run build:*)",
      "Bash(git status:*)",
      "Bash(git diff:*)",
      "Bash(git log:*)"
    ],
    "deny": [
      "Bash(sudo:*)",
      "Bash(rm -rf /:*)",
      "Bash(git push --force:*)"
    ]
  }
}

Pattern rules

  • Bash(cmd:*) β€” allow cmd followed by any arguments
  • Bash(cmd arg1:*) β€” allow cmd arg1 with anything after
  • Bash(cmd) β€” exact match only
  • deny always wins over allow

Personal vs team

  • .claude/settings.json β€” committed, shared with the team
  • .claude/settings.local.json β€” git-ignored, personal tweaks (your favorite CLIs, local env)
  • ~/.claude/settings.json β€” global, applies to every project on your machine

The golden rule

Never blanket-allow Bash(*). The permission prompt is cheap; a destructive command you didn't mean to run is expensive. Keep the deny list tight and aggressive.

πŸ”₯ Try this now Look back at your last Claude Code session. Which commands did you approve three or more times? Those are your candidates for the allow list. Add them to .claude/settings.json and commit. Do NOT add things you only approved once β€” premature allow-listing is how people accidentally yield too much.


7. πŸ—ΊοΈ Plan mode

For any task that is more than "rename this variable," press Shift+Tab until you're in Plan mode before you start. Then prompt:

Plan out what it would take to add rate limiting to the /api/login endpoint. Don't make any changes β€” just propose the plan.

Claude will explore, read code, think, and produce a concrete plan (files to touch, order of operations, tradeoffs). You review the plan, ask follow-up questions, adjust the approach. When you're happy, you exit plan mode and tell it to execute.

This pattern catches an enormous class of "Claude went off and did the wrong thing" problems. Five minutes of planning saves an hour of re-doing.

When to skip plan mode

  • Trivial edits (typo fix, one-line change)
  • Tasks where "wrong direction" has no cost (exploratory prototyping)
  • When you're already in a detailed prompt-response loop and have alignment

When to always use plan mode

  • Any change touching more than 3 files
  • Any migration or refactor
  • Any task involving external systems (APIs, databases, deploys)
  • Anything where you'd review a PR carefully β€” if it needs review, it needs a plan first

πŸ”₯ Try this now Take a real task on your backlog that you've been putting off. Enter plan mode. Ask for a plan. Read it critically. You'll find that either (a) the plan reveals the task is bigger than you thought β€” which is useful information β€” or (b) you're now ready to execute with confidence.


8. 🧹 Context hygiene

The single most underrated skill. Long conversations accumulate irrelevant context, which degrades Claude's attention and eats your token budget.

Rules

  1. Start a new session for an unrelated task. Don't use the same conversation to fix a bug, add a feature, and then write release notes.
  2. Use /clear aggressively. When you shift focus, clear the conversation. The cost of re-explaining is usually less than the cost of carrying accumulated noise.
  3. Don't paste huge logs. If the full stack trace is 2000 lines, paste the top 20 and let Claude ask for more if needed.
  4. Delegate searches. "Find every place X is used" is a job for a subagent (covered in Part 3), not your main conversation. A subagent can ingest a mountain of search output and return a short summary, keeping your main context clean.
  5. Use /compact when context fills up. It summarizes history and continues with less bloat. Better than letting auto-compaction kick in mid-task.

Signs your context is polluted

  • Claude makes the same small mistake it already corrected earlier
  • It references files that have nothing to do with the current task
  • It proposes solutions that contradict constraints you already set
  • Responses feel generic and hedge-y

When you see these, /clear is almost always the right move.

πŸ”₯ Try this now Next time you finish a task, before starting a new one, run /clear. Build the muscle. Most people keep the conversation running forever and wonder why Claude gets worse over time.


⚑ Part 3 β€” Journeyman

9. ⚑ Slash commands

A slash command is a markdown file in .claude/commands/ that becomes an invocable shortcut. The file body becomes the prompt; $ARGUMENTS is substituted with whatever you type after the command name.

Minimal example

.claude/commands/review.md:

Review the uncommitted changes on this branch.

Focus on:
- Security issues (injection, XSS, unsafe deserialization)
- API contract changes that would break callers
- Missing tests for new code paths
- Unused imports, dead code

Don't modify files β€” review only. Output a punch list.

Invoke with /review.

With arguments

.claude/commands/test.md:

Run the test suite for the specified service. Argument: $ARGUMENTS

Rules:
- If argument is "go": `cd backend-go && go test ./... -race -count=1`
- If argument is "python": `cd backend-python && uv run pytest -v`
- If argument is "frontend": `cd frontend && pnpm test`
- If argument is "all" or empty: run all three, stop on first failure

Invoke with /test go or /test all.

Frontmatter (optional)

---
description: Open a PR for the current branch with auto-generated title and body
argument-hint: "[issue-number]"
allowed-tools: ["Bash", "Read", "Write"]
model: opus
---

Steps:
1. Ensure branch is pushed
2. Read commits since diverging from main
3. Draft a PR title and body based on the commits
4. Run `gh pr create` with the drafted content
5. If $ARGUMENTS is present, add "Closes #$ARGUMENTS" to the body

Gotchas

  • Flat namespace. .claude/commands/git/commit.md becomes /commit, not /git:commit. Name files carefully.
  • No code execution in the markdown file itself β€” the body is sent as a prompt. Claude then decides what to run.
  • Keep them focused. If a command tries to do too much, split it.

Slash command vs skill vs subagent

Use when
Slash command User explicitly triggers a workflow (/test, /lint, /pr)
Skill Reusable procedure Claude should apply when relevant (user doesn't type it)
Subagent You want an isolated context / fresh conversation for a big sub-task

πŸ”₯ Try this now Identify the three prompts you most commonly type. Turn each into a slash command. You'll feel the productivity gain immediately.


10. 🀝 Subagents

Subagents are specialized Claude instances that run in a separate conversation with their own system prompt and tool permissions. The main agent delegates work to them.

Why this matters:

  1. Context isolation. The subagent doesn't see your main conversation. Great for independent reviews β€” it can't be biased by your prior reasoning.
  2. Parallelism. The main agent can run multiple subagents concurrently. Perfect for "check A, B, and C independently."
  3. Tool scoping. A "reviewer" subagent can be given read-only tools, so it literally can't write files even if asked.

Defining a subagent

Create .claude/agents/migration-reviewer.md:

---
description: Review SQL migrations for safety. Use proactively whenever a migration file is added or modified.
tools: ["Read", "Bash", "Grep"]
model: opus
---

You are a database migration safety reviewer. For any migration under `backend-go/migrations/`, check:

1. Does it have both Up and Down blocks?
2. Are NOT NULL columns added with a default, or is there a backfill step?
3. Are indexes created CONCURRENTLY on large tables?
4. Is there anything irreversible (DROP COLUMN, DROP TABLE) that needs a rollback plan?

Report findings as a punch list. Do not modify files.

The main agent will now auto-invoke this whenever a migration changes (because of the "Use proactively" phrasing).

Built-in agent types

Claude Code ships with a few built-in agent types you can use without defining your own:

  • Explore β€” fast codebase search, great for "find every place X is used"
  • general-purpose β€” the default, for any research task

When to use a subagent

  • Research/exploration that will generate lots of output you don't want in your main context
  • Independent review where you want an unbiased second opinion
  • Parallelizable work β€” three questions that don't depend on each other

When NOT to use a subagent

  • Small targeted tasks β€” spawning a subagent has overhead; for a 30-second task, just do it yourself
  • Tasks where you want to stay in conversation β€” the subagent returns one message and is gone; you can't iterate with it

πŸ”₯ Try this now Next time you need to understand an unfamiliar area of your codebase, prompt the main agent: "Spawn an Explore subagent to find every place authenticate() is called, what it returns, and who handles its errors. Give me a short report." Notice how your main context stays clean.


11. πŸ’‘ Skills

Skills are reusable procedures that Claude loads when relevant. Unlike slash commands (user-triggered) or subagents (fresh-context delegation), skills layer procedural knowledge onto your current conversation.

Directory layout

.claude/skills/
  release-notes/
    SKILL.md          ← required
    template.md       ← optional supporting files
    scripts/
      extract.sh      ← optional helper scripts

SKILL.md format

---
description: Generate release notes from git log since the last tag. Invoke when the user asks for a changelog, release notes, or summary of recent changes.
---

# Release Notes Skill

When invoked:

1. Find the last tag: `git describe --tags --abbrev=0`
2. Run `git log <tag>..HEAD --pretty=format:'%h %s (%an)' --no-merges`
3. Group commits by conventional prefix (feat/fix/chore/docs/refactor)
4. Format using `template.md` in this skill directory
5. Output the final markdown β€” do not write to a file unless asked

Auto-discovery

Claude reads the description of every available skill at session start. When your prompt matches a skill's description, it's invoked automatically.

This is why the description matters more than anything else in the skill. Write it like a trigger: when should this fire?

Bad: "Release notes generator." Good: "Generate release notes from commits since the last git tag. Invoke when the user asks for a changelog, release notes, or summary of changes since vX.Y.Z."

Skill vs slash command β€” the quick heuristic

Ask: "Will the user explicitly type /skill-name?"

  • Yes β†’ make it a slash command
  • No, but Claude should apply it when a situation arises β†’ make it a skill

Built-in skills

Claude Code ships with several built-in skills (update-config, simplify, pr, lint, test, gen, build, migrate, review, security-review, etc.). Run /help to see what's currently registered.

πŸ”₯ Try this now Pick a procedure your team does routinely β€” releasing a version, writing a migration, auditing a feature β€” and turn it into a skill. Craft the description carefully so Claude auto-invokes it.


12. πŸͺ Hooks

Hooks are shell commands the harness (not Claude) runs in response to events. They run outside Claude's decision loop, which makes them the right tool for:

  • Enforcing something deterministically (auto-format after edit)
  • Injecting context (show branch name on session start)
  • Blocking unsafe actions (refuse writes to /etc/)

A memory instruction like "always format Go files" is advisory β€” Claude might forget. A hook is a hard guarantee.

Shape

Hooks live in .claude/settings.json:

{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<pattern>",
        "hooks": [
          { "type": "command", "command": "<shell>" }
        ]
      }
    ]
  }
}

Events you'll actually use

Event Fires when
PreToolUse Before a tool runs. Exit 2 blocks it.
PostToolUse After a tool succeeds. Good for auto-format.
UserPromptSubmit After user sends a prompt. Can inject context.
SessionStart Session boot.
Stop End of Claude's turn.

Exit codes and I/O

  • 0 β€” success; stdout becomes context for Claude
  • 2 β€” blocking; stderr is shown to Claude as the reason to retry/adjust
  • other β€” non-blocking error; logged and ignored

Hooks receive the event payload as JSON on stdin. Parse with jq:

file=$(jq -r '.tool_input.file_path // empty')

Example 1 β€” auto-format after edit

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "file=$(jq -r '.tool_input.file_path // empty'); [[ \"$file\" == *.go ]] && gofmt -w \"$file\"; [[ \"$file\" == *.py ]] && ruff format \"$file\"; true"
          }
        ]
      }
    ]
  }
}

Example 2 β€” block writes to generated files

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "file=$(jq -r '.tool_input.file_path // empty'); if [[ \"$file\" == *generated/* ]]; then echo 'Do not edit generated files β€” re-run code generation instead.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}

Example 3 β€” inject branch info at session start

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          { "type": "command", "command": "echo \"Branch: $(git branch --show-current)\"" }
        ]
      }
    ]
  }
}

When hooks are the wrong tool

  • "Remind Claude to write tests" β†’ put it in CLAUDE.md, not a hook
  • "Run tests only when I say" β†’ slash command, not a hook
  • "Apply procedure X in situation Y" β†’ skill, not a hook

Hooks are for the things the harness must enforce regardless of what Claude decides.

πŸ”₯ Try this now Add a PostToolUse hook that auto-formats any file Claude edits in your project's language. One concrete step that will improve every future session.


πŸ† Part 4 β€” Hero

13. πŸ”Œ MCP servers

Model Context Protocol (MCP) servers extend Claude with external tools β€” Slack, Linear, Sentry, Postgres, your internal APIs. Configure them in .claude/settings.json:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgres://dev:dev@localhost:5432/app"]
    }
  }
}

Popular servers: postgres, github, slack, linear, sentry, puppeteer, fetch. See the MCP server directory.

Before adding an MCP server, ask:

"Would a shell command work?"

A psql invocation in your permission allowlist is simpler than a Postgres MCP server 90% of the time. MCP is right when:

  • The tool requires stateful auth (OAuth flows, API keys that rotate)
  • The output is richly structured (JSON APIs where Claude needs field-level access)
  • You want Claude to call the tool across many turns without re-establishing connection

If you're adding an MCP server "because I saw one for X," check whether curl, gh, psql, or aws already solves the problem.


14. ✍️ Prompting for real work

Prompting advice is often generic. Here's what actually matters for Claude Code specifically:

1. Scope bounded, context explicit

Bad: "Fix the tests." Good: "Fix the flaky test in backend-go/internal/service/user_test.go. It fails about one run in ten. The last failure log is in /tmp/test-output.log."

The more of the context you provide up front, the less Claude has to spend tokens discovering.

2. State constraints before action

  • "Don't change the public API."
  • "Only modify files under frontend/src/components/."
  • "If the fix requires more than 50 lines of changes, stop and tell me β€” don't barrel through."

These constraints prevent whole classes of "this isn't what I wanted" outcomes.

3. Ask for a plan first on anything non-trivial

Covered in section 7. Plan mode is free; re-doing work is expensive.

4. Be honest about your knowledge

"I don't know this codebase well; help me understand X before we change it" produces better results than pretending to know.

5. Push back on mediocre output

If Claude produces something that works but isn't good, say so: "That works, but it has three issues: (a) ..., (b) ..., (c) .... Please revise." Don't accept first-draft output on things that matter.

6. Use "one-shot" framing for tightly-scoped tasks

"Write a bash script that does X. One shot β€” no back-and-forth. Output the whole script." forces a more thorough first response than open-ended prompting.

7. For debugging, state the hypothesis

Bad: "Why is this broken?" Good: "I think this is broken because the deploy step doesn't wait for the DB migration to finish, but I'm not sure. Verify or refute that hypothesis first."

Hypothesis-first debugging is 3Γ— faster than open-ended investigation.


15. πŸ‘₯ Team setup

Taking Claude Code from "a tool each person uses" to "a shared team asset" is high-leverage. Here's the checklist:

Committed to the repo

  • CLAUDE.md at root, per-service where useful
  • .claude/settings.json β€” shared permissions and hooks
  • .claude/commands/ β€” team slash commands (/test, /lint, /pr, /review, /deploy-staging)
  • .claude/agents/ β€” team subagents (reviewers, explorers)
  • .claude/skills/ β€” team procedures (release notes, migration review, on-call runbook)

Gitignored

  • .claude/settings.local.json β€” personal overrides
  • .env β€” secrets

Onboarding new engineers

Every new hire spends the first 30 minutes of day one:

  1. Reading CLAUDE.md and every nested CLAUDE.md
  2. Skimming .claude/commands/ β€” what shortcuts exist
  3. Copying .env.example β†’ .env
  4. Running make dev (or equivalent) to verify the stack boots
  5. Adding personal approvals to .claude/settings.local.json (not the shared file)

Keeping it fresh

  • Review CLAUDE.md quarterly. Stale guidance is worse than no guidance.
  • Add a pitfall every time someone gets burned. Post-incident: "update CLAUDE.md?" should be on the checklist.
  • Prune. If a slash command isn't used in a month, delete it. If CLAUDE.md has grown past ~300 lines, split it.

16. πŸ› Debugging Claude

When things go wrong, the problem is almost always one of these:

Symptom Likely cause Fix
Claude keeps asking to run a command I want pre-approved Not in permissions.allow, or pattern too narrow Add Bash(cmd:*) to .claude/settings.json
My hook isn't firing Wrong event name, wrong matcher, or bad JSON Validate JSON; re-check event name; test the command in isolation
Claude edits files but skips formatting PostToolUse hook crashed silently End hook command with || true; add echo for visibility
Slash command not found File naming collision (flat namespace) Rename file; put it directly in .claude/commands/
~/.claude/CLAUDE.md isn't being read It is β€” but per-project CLAUDE.md takes precedence for overlapping topics Split clearly: global in ~/.claude, project in repo
Subagent gives a different answer than main agent Expected β€” it has isolated context by design If you want shared context, don't use a subagent
Claude forgets between sessions Facts were only in chat, not in CLAUDE.md Move enduring facts to CLAUDE.md
Hook blocks every command unexpectedly Exit code 2 is a hard block Reserve exit 2 for real blocks; use 0 for non-blocking
Claude keeps making the same mistake Context is polluted with contradictory info /clear and re-prompt with explicit constraints
Response is generic and useless Claude lacks context to answer well Give it a file to read, a command to run, or narrow the scope

Using --debug

Run Claude Code with --debug to see detailed logs β€” hook invocations, tool calls, timing. Essential when something silent is misbehaving.

The "read it back" trick

When Claude produces output you disagree with, prompt: "Read back to me your understanding of what I asked for." Usually reveals the specific misinterpretation in seconds. Cheaper than re-arguing.


17. πŸ’ͺ Habits

A list of habits that separate the heroes from the tourists. None of them are secret. All of them are practiced, not learned.

βœ… Do

  • Plan before you build. For any non-trivial task, use plan mode or ask for a plan.
  • Review every diff before accepting. Claude is fast; a fast wrong change is still wrong.
  • Clear context aggressively. Start new sessions for unrelated work.
  • Update CLAUDE.md when you get burned. The next person (or your future self) shouldn't repeat the mistake.
  • Use subagents for exploration. Keep your main context clean.
  • Push back on mediocre output. Say "that's not quite right because X; revise."
  • Commit your .claude/ configuration. It's team infrastructure, not personal config.
  • Keep denies aggressive, allows minimal. sudo, rm -rf /, git push --force should always be blocked.

❌ Don't

  • Don't blanket-allow Bash(*). The cost of permission prompts is much less than the cost of one accidental destructive command.
  • Don't paste 2000-line logs. Paste the relevant 20 lines.
  • Don't accept first-draft output on things that matter. Iterate.
  • Don't keep one session running forever. Context rot is real.
  • Don't put secrets in CLAUDE.md or the chat. Ever.
  • Don't skip hooks (--no-verify) without a specific reason. Fix the real issue.
  • Don't build elaborate configuration before you've used the defaults for a week. Start simple. Add surfaces when you feel the pain.

πŸ“ˆ The progression

You're a tourist if you:

  • Type freeform prompts, approve everything one by one, never configure anything

You're an apprentice if you:

  • Have a CLAUDE.md, permission allow list, and use plan mode regularly

You're a journeyman if you:

  • Have slash commands for your common workflows, use subagents for exploration, and have at least one hook enforcing a guarantee

You're a hero if you:

  • Treat .claude/ as team infrastructure, prune it regularly, and notice when you're using the wrong surface (skill when it should be a command, hook when it should be memory)

πŸ“š Further reading


πŸ“‹ One-page summary

If you remember nothing else:

  1. Put enduring facts in CLAUDE.md. Keep it tight.
  2. Pre-approve your common commands in .claude/settings.json. Never Bash(*).
  3. Use plan mode (Shift+Tab) before any non-trivial task.
  4. Clear context between unrelated tasks (/clear).
  5. Turn your repeat prompts into slash commands.
  6. Use subagents for big searches and independent reviews.
  7. Use skills for procedures Claude should apply automatically.
  8. Use hooks when you need a hard guarantee, not a polite suggestion.
  9. Review every diff. Push back on mediocre output.
  10. Update configuration when you get burned β€” once, not twice.

🚒 Happy shipping.


If you found this helpful, let me know by leaving a πŸ‘ or a comment!, or if you think this post could help someone, feel free to share it! Thank you very much! πŸ˜ƒ


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.