The Ultimate Guide to Advanced Claude Code Usage: Parallel Development, Plan Mode, and Hooks

Summary: Based on official Claude Code documentation and internal team best practices, this comprehensive guide covers advanced workflows including Git worktree parallel sessions, Plan Mode for complex task planning, CLAUDE.md knowledge management, Skills automation, Subagents for multi-threading, Hooks for event-driven automation, and 10 core technical strategies for data analysis and terminal optimization.

Core Claude Code Workflows

Understanding New Codebases

Claude Code provides streamlined workflows for rapidly comprehending unfamiliar codebases. When you join a new project, you can master its structure through several key steps:

  • Get a Codebase Overview: Ask Claude to analyze the directory structure, main modules, and architecture.
  • Find Relevant Code: Use Glob and Grep tools to locate files specific to a particular feature or functionality.
  • Understand Relationships: Use the Read tool to examine key files and establish connections between code components.

These tools can be combined to form a complete code exploration workflow. For example, start by using Glob to locate all configuration files, then use Grep to search for specific function names, and finally use Read to examine key implementations.

Fixing Bugs Efficiently

When encountering an error message, Claude Code can quickly locate and fix the source of the problem:

  1. Error Analysis: Paste the error log directly; Claude will analyze the error type and potential causes.
  2. Code Location: Use Grep to search for functions, classes, or variables related to the error.
  3. Automatic Fixes: Let Claude generate a fix and apply changes using the Edit tool.
  4. Verification: Run tests or check the code to confirm the issue is resolved.

Team experience suggests that most bugs can be fixed by Claude independently. A common scenario involves enabling the Slack MCP and pasting a bug report from Slack directly to Claude with a single word: “fix.” No context explanation or manual location is required. Claude will examine the code, understand the problem, and repair it.

For more complex scenarios like distributed system issues, pointing Docker logs to Claude allows it to help troubleshoot. Claude is “surprisingly capable” in this regard.

Refactoring Code

When updating old code to use modern patterns and practices, Claude Code offers a systematic refactoring workflow:

  1. Code Analysis: First, analyze the structure and issues of existing code.
  2. Refactoring Planning: Discuss the refactoring plan in Plan Mode.
  3. Step-by-Step Implementation: Use Edit and Write tools to gradually replace old code.
  4. Test Validation: Run tests to ensure refactoring hasn’t broken functionality.

Core Principle: For complex tasks, use Plan Mode to discuss the solution with Claude first. Iterate until you are satisfied with the plan, then switch to auto-edit mode for Claude to execute. A good plan usually means Claude can get it right in one go, without back-and-forth changes.

Working with Tests

When adding tests for uncovered code, Claude Code can:

  1. Analyze Coverage: Identify code paths lacking tests.
  2. Generate Test Cases: Generate new tests based on existing test patterns.
  3. Verify Tests: Run tests to ensure they pass.
  4. Discover Edge Cases: Analyze code paths to suggest tests for error conditions, boundary values, and unexpected inputs.

Claude can generate tests that follow your project’s existing patterns and conventions. When asking for tests, be specific about what behavior you want to verify. For comprehensive coverage, ask Claude to identify edge cases you might have missed.

Creating Pull Requests

You can create a PR by directly asking Claude (“create a pr for my changes”) or by using the /commit-push-pr skill, which commits, pushes, and opens a PR in one step.

> /commit-push-pr

If you have a Slack MCP server configured and specify channels in your CLAUDE.md (e.g., “post PR URLs to #team-prs”), the skill automatically posts the PR URL to those channels. For more control, guide Claude step-by-step or create your own skill.

When you create a PR using gh pr create, the session is automatically linked to that PR. You can resume it later with claude --from-pr <number>.

Plan Mode: The Planning Tool for Complex Tasks

When to Use Plan Mode

Plan Mode instructs Claude to create a plan by analyzing the codebase with read-only operations, making it perfect for exploring codebases, planning complex changes, or safely reviewing code. In Plan Mode, Claude uses AskUserQuestion to gather requirements and clarify your goals before proposing a plan.

Use Plan Mode when:

  • Multi-step Implementation: When your feature requires edits to multiple files.
  • Code Exploration: When you want to thoroughly research the codebase before changing anything.
  • Interactive Development: When you want to iterate on the direction with Claude.

How to Activate Plan Mode

Switch to Plan Mode during a session: You can switch into Plan Mode during a session using Shift+Tab to cycle through permission modes. If you are in Normal Mode, Shift+Tab first switches into Auto-Accept Mode, indicated by ⏵⏵ accept edits on at the bottom of the terminal. A subsequent Shift+Tab will switch into Plan Mode, indicated by ⏸ plan mode on.

Start a new session in Plan Mode: Use the --permission-mode plan flag to start a new session:

claude --permission-mode plan

Run “headless” queries in Plan Mode: You can also run a query in Plan Mode directly with -p (i.e., in “headless mode”):

claude --permission-mode plan -p "Analyze the authentication system and suggest improvements"

Practical Example

Planning a complex refactor:

claude --permission-mode plan
> I need to refactor our authentication system to use OAuth2. Create a detailed migration plan.

Claude analyzes the current implementation and creates a comprehensive plan. Refine with follow-ups:

> What about backward compatibility?
> How should we handle database migration?

Configure Plan Mode as Default

// .claude/settings.json
{
  "permissions": {
    "defaultMode": "plan"
  }
}

Hooks: Event-Driven Automation

Hook Lifecycle

Hooks are user-defined shell commands or LLM prompts that execute automatically at specific points in Claude Code’s lifecycle. When an event fires and a matcher matches, Claude Code passes JSON context about the event to your hook handler.

Some events fire once per session, while others fire repeatedly inside the agentic loop:

Event When it fires
SessionStart When a session begins or resumes
UserPromptSubmit When you submit a prompt, before Claude processes it
PreToolUse Before a tool call executes. Can block it
PermissionRequest When a permission dialog appears
PostToolUse After a tool call succeeds
PostToolUseFailure After a tool call fails
Notification When Claude Code sends a notification
SubagentStart When a subagent is spawned
SubagentStop When a subagent finishes
Stop When Claude finishes responding
PreCompact Before context compaction
SessionEnd When a session terminates

How a Hook Resolves

Consider this PreToolUse hook that blocks destructive shell commands. The hook runs block-rm.sh before every Bash tool call:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/block-rm.sh"
          }
        ]
      }
    ]
  }
}

The script reads JSON input from stdin, extracts the command, and returns a permissionDecision of "deny" if it contains rm -rf:

#!/bin/bash

# .claude/hooks/block-rm.sh

COMMAND=$(jq -r '.tool_input.command')

if echo "$COMMAND" | grep -q 'rm -rf'; then
  jq -n '{
    "hookSpecificOutput": {
      "hookEventName": "PreToolUse",
      "permissionDecision": "deny",
      "permissionDecisionReason": "Destructive command blocked by hook"
    }
  }'
else
  exit 0 # allow the command
fi

When Claude Code decides to run Bash "rm -rf /tmp/build", the process is:

  1. Claude Code generates JSON input.
  2. The PreToolUse hook matcher matches “Bash”.
  3. The block-rm.sh script executes and reads the JSON input.
  4. The script detects rm -rf and returns a deny decision.
  5. Claude Code reads the JSON output and blocks the command.

Hook Configuration

Hooks are defined in JSON settings files. The configuration has three levels of nesting:

  1. Choose a hook event, like PreToolUse or Stop.
  2. Add a matcher group to filter when it fires, like “only for the Bash tool”.
  3. Define one or more hook handlers to run when matched.

Hook Locations

Where you define a hook determines its scope:

Location Scope Shareable
~/.claude/settings.json All your projects No, local to your machine
.claude/settings.json Single project Yes, can be committed to repo
.claude/settings.local.json Single project No, gitignored
Managed policy settings Organization-wide Yes, admin-controlled
Plugin hooks/hooks.json When plugin enabled Yes, bundled with the plugin
Skill or agent frontmatter While component active Yes, defined in component file

Matcher Patterns

The matcher field is a regex string that filters when hooks fire. Use "*", "", or omit matcher entirely to match all occurrences. Each event type matches on a different field:

Event Matcher filters Example matcher values
PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest tool name Bash, `Edit
SessionStart how session started startup, resume, clear, compact
SessionEnd why session ended clear, logout, prompt_input_exit
Notification notification type permission_prompt, idle_prompt
SubagentStart agent type Bash, Explore, Plan
PreCompact triggered compaction manual, auto
SubagentStop agent type Same values as SubagentStart
UserPromptSubmit, Stop No matcher support Fires on every occurrence

The matcher is a regex, so Edit|Write matches either tool and Notebook.* matches any tool starting with Notebook.

Hook Handler Fields

Each object in the inner hooks array is a hook handler: the shell command, LLM prompt, or agent that runs when the matcher matches. There are three types:

  • Command hooks (type: "command"): Run a shell command. The script receives the event’s JSON input on stdin and communicates results back via exit codes and stdout.
  • Prompt hooks (type: "prompt"): Send a prompt to a Claude model for single-turn evaluation. The model returns a yes/no decision as JSON.
  • Agent hooks (type: "agent"): Spawn a subagent that can use tools like Read, Grep, and Glob to verify conditions before returning a decision.

Common fields:

Field Required Description
type yes "command", "prompt", or "agent"
timeout no Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent
statusMessage no Custom spinner message displayed while hook runs
once no If true, runs only once per session then is removed. Skills only

Command hook fields:

Field Required Description
command yes Shell command to execute
async no If true, runs in background without blocking

Prompt and agent hook fields:

Field Required Description
prompt yes Prompt text to send to model. Use $ARGUMENTS as placeholder for hook input JSON
model no Model to use for evaluation. Defaults to a fast model

Hook Input and Output

Hooks receive JSON data via stdin and communicate results through exit codes, stdout, and stderr.

Common Input Fields

All hook events receive these fields via stdin as JSON:

Field Description
session_id Current session identifier
transcript_path Path to conversation JSON
cwd Current working directory when hook is invoked
permission_mode Current permission mode: "default", "plan", "acceptEdits", "dontAsk", "bypassPermissions"
hook_event_name Name of the event that fired

For example, a PreToolUse hook for a Bash command receives:

{
  "session_id": "abc123",
  "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
  "cwd": "/home/user/my-project",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

Exit Code Output

The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored.

Exit 0 means success. Claude Code parses stdout for JSON output fields. JSON output is only processed on exit 0. For most events, stdout is only shown in verbose mode (Ctrl+O). The exceptions are UserPromptSubmit and SessionStart, where stdout is added as context that Claude can see and act on.

Exit 2 means a blocking error. Claude Code ignores stdout and any JSON in it. Instead, stderr text is fed back to Claude as an error message. The effect depends on the event: PreToolUse blocks the tool call, UserPromptSubmit rejects the prompt, etc.

Any other exit code is a non-blocking error. stderr is shown in verbose mode (Ctrl+O) and execution continues.

JSON Output

Exit codes allow allow/block, but JSON output gives finer-grained control. Instead of exiting with code 2 to block, exit 0 and print a JSON object to stdout. Claude Code reads specific fields from that JSON to control behavior.

The JSON object supports three kinds of fields:

  • Universal fields like continue work across all events.
  • Top-level decision and reason are used by some events to block or provide feedback.
  • hookSpecificOutput is a nested object for events that need richer control. It requires a hookEventName field set to the event name.
Field Default Description
continue true If false, Claude stops processing entirely after hook runs.
stopReason none Message shown to user when continue is false. Not shown to Claude.
suppressOutput false If true, hides stdout from verbose mode output
systemMessage none Warning message shown to user

Key Hook Events

SessionStart

Runs when Claude Code starts a new session or resumes an existing session. Useful for loading development context like existing issues or recent changes, or setting environment variables. For static context, use CLAUDE.md instead.

Matcher values correspond to how the session was started:

Matcher When it fires
startup New session
resume --resume, --continue, or /resume
clear /clear
compact Auto or manual compaction

In addition to common input fields, SessionStart hooks receive source, model, and optionally agent_type.

Persist Environment Variables: SessionStart hooks have access to the CLAUDE_ENV_FILE environment variable, which provides a file path where you can persist environment variables for subsequent Bash commands. To set individual environment variables, write export statements to CLAUDE_ENV_FILE.

#!/bin/bash

if [ -n "$CLAUDE_ENV_FILE" ]; then
  echo 'export NODE_ENV=production' >> "$CLAUDE_ENV_FILE"
  echo 'export DEBUG_LOG=true' >> "$CLAUDE_ENV_FILE"
  echo 'export PATH="$PATH:./node_modules/.bin"' >> "$CLAUDE_ENV_FILE"
fi

exit 0

PreToolUse

Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name: Bash, Edit, Write, Read, Glob, Grep, Task, WebFetch, WebSearch, and any MCP tool names. Use PreToolUse decision control to allow, deny, or ask for permission to use the tool.

Input Fields:
In addition to common fields, PreToolUse hooks receive tool_name, tool_input, and tool_use_id. The tool_input fields depend on the tool.

Bash Input Fields:

Field Type Example Description
command string "npm test" The shell command to execute
description string "Run test suite" Optional description of command
timeout number 120000 Optional timeout in milliseconds
run_in_background boolean false Whether to run command in background

Write Input Fields:

Field Type Example Description
file_path string "/path/to/file.txt" Absolute path to file to write
content string "file content" Content to write to file

Edit Input Fields:

Field Type Example Description
file_path string "/path/to/file.txt" Absolute path to file to edit
old_string string "original text" Text to find and replace
new_string string "replacement text" Replacement text
replace_all boolean false Whether to replace all occurrences

Read Input Fields:

Field Type Example Description
file_path string "/path/to/file.txt" Absolute path to file to read
offset number 10 Optional line number to start reading from
limit number 50 Optional number of lines to read

Glob Input Fields:

Field Type Example Description
pattern string "**/*.ts" Glob pattern to match files against
path string "/path/to/dir" Optional directory to search in. Default: cwd

Grep Input Fields:

Field Type Example Description
pattern string "TODO.*fix" Regular expression pattern to search for
path string "/path/to/dir" Optional file or directory to search in
glob string "*.ts" Optional glob pattern to filter files
output_mode string "content" "content", "files_with_matches", or "count". Default: "files_with_matches"
-i boolean true Case insensitive search
multiline boolean false Enable multiline matching

WebFetch Input Fields:

Field Type Example Description
url string "https://example.com/api" URL to fetch content from
prompt string "Extract the API endpoints" Prompt to run on fetched content

WebSearch Input Fields:

Field Type Example Description
query string "react hooks best practices" Search query
allowed_domains array ["docs.example.com"] Optional: only include results from these domains
blocked_domains array ["spam.example.com"] Optional: exclude results from these domains

Task Input Fields:

Field Type Example Description
prompt string "Find all API endpoints" The task for the agent to perform
description string "Find API endpoints" Short description of the task
subagent_type string "Explore" Type of specialized agent to use
model string "sonnet" Optional model alias to override default

PreToolUse Decision Control: PreToolUse hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level decision field, PreToolUse returns its decision inside a hookSpecificOutput object.

Field Description
permissionDecision "allow" bypasses permission system, "deny" prevents tool call, "ask" prompts user
permissionDecisionReason For "allow"/"ask": shown to user not Claude. For "deny": shown to Claude
updatedInput Modifies tool input parameters before execution. Combine with "allow" to auto-approve
additionalContext String added to Claude’s context before tool executes
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    },
    "additionalContext": "Current environment: production. Proceed with caution."
  }
}

PermissionRequest

Runs when the user is shown a permission dialog. Use PermissionRequest decision control to allow or deny on behalf of the user. Matches tool name, same values as PreToolUse.

In addition to common input fields, PermissionRequest hooks receive tool_name and tool_input fields like PreToolUse hooks, but without tool_use_id. An optional permission_suggestions array contains the “always allow” options the user would normally see.

PermissionRequest Decision Control:

Field Description
behavior "allow" grants permission, "deny" denies it
updatedInput For "allow" only: modifies tool input parameters before execution
updatedPermissions For "allow" only: applies permission rule updates
message For "deny" only: tells Claude why permission was denied
interrupt For "deny" only: if true, stops Claude
{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow",
      "updatedInput": {
        "command": "npm run lint"
      }
    }
  }
}

PostToolUse

Runs immediately after a tool completes successfully. Matches tool name, same values as PreToolUse.

PostToolUse hooks fire after a tool has already executed successfully. The input includes both tool_input (arguments sent to tool) and tool_response (result it returned).

PostToolUse Decision Control:

Field Description
decision "block" prompts Claude with reason. Omit to allow action proceed
reason Explanation shown to Claude when decision is "block"
additionalContext Additional context for Claude to consider
updatedMCPToolOutput For MCP tools only: replaces tool’s output with provided value
{
  "decision": "block",
  "reason": "Explanation for decision",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "Additional information for Claude"
  }
}

PostToolUseFailure

Runs when a tool execution fails. This event fires for tool calls that throw errors or return failure results. Use this to log failures, send alerts, or provide corrective feedback to Claude.

In addition to common input fields, PostToolUseFailure hooks receive the same tool_name and tool_input fields as PostToolUse, along with error information as top-level fields:

{
  "session_id": "abc123",
  "hook_event_name": "PostToolUseFailure",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test",
    "description": "Run test suite"
  },
  "tool_use_id": "toolu_01ABC123...",
  "error": "Command exited with non-zero status code 1",
  "is_interrupt": false
}
Field Description
error String describing what went wrong
is_interrupt Optional boolean indicating if failure was caused by user interruption

PostToolUseFailure Decision Control:

{
  "hookSpecificOutput": {
    "hookEventName": "PostToolUseFailure",
    "additionalContext": "Additional information about the failure for Claude"
  }
}

Practical Tips and Best Practices

Invest in Your CLAUDE.md

This is arguably the highest ROI technique. CLAUDE.md is a file in the project root that Claude Code reads every time it starts. You can write code standards, design principles, PR templates, common error reminders—anything you want Claude to remember.

The key is maintenance. The team’s practice is: after correcting Claude’s mistake, let it update CLAUDE.md itself. A specific prompt could be: “Update your CLAUDE.md so you don’t make that mistake again.”

One engineer’s approach is more systematic: he maintains a notes directory for each project/task, updating after every PR. He then points to these notes in CLAUDE.md, essentially building a continuously updating knowledge base for Claude.

Note: CLAUDE.md should not contain too much content; it will be counterproductive. Only include the most important content AI hasn’t been trained on. Use file links for more content to be read on demand. Claude Code’s official project CLAUDE.md is only about 2.5k tokens:

  • Common Bash Commands: Let AI know how to operate the command line like a developer.
  • Code Style Conventions: Ensure AI-written code meets team standards.
  • UI and Content Design Guidelines: Guide AI on interface design and copywriting.
  • Core Technical Implementation Flows: Teach AI how to handle State Management, Logging, Error Handling, Feature Gating, and Debugging.
  • Pull Request Template: Standardize documentation format when submitting code.

Create Custom Skills

If you do something twice a day, it’s worth turning it into a skill or slash command. A Skill is a set of reusable instructions in a project, invoked with a slash command. For example, /commit-push-pr can commit, push, and create a PR in one step.

Team examples of skills in use:

  • /techdebt: Runs at the end of every session to check and clean up duplicate code.

Some have built a slash command that syncs the last 7 days of Slack messages, Google Drive docs, Asana tasks, and GitHub activity into a single context—effectively a one-click “what happened this week” panoramic view.

Advanced usage: Some use skills to build “Data Analysis Engineer” type agents that can automatically write dbt models, review code, and test changes in dev.

The benefit of Skills is they can be committed to git and reused across projects.

Elevate Your Prompting Techniques

Let Claude Quiz You:
Prompt example: “Grill me on these changes and don’t make a PR until I pass your test.”
Or: “Prove to me this works.” Let Claude compare the behavior of the main branch against your feature branch.
This turns Claude from an “executor” into an “auditor,” having it review you.

Scrap and Rebuild:
When Claude’s solution isn’t good enough, don’t patch it. Just say: “Knowing everything you know now, scrap this and implement the elegant solution.”
Usually, use git to roll back code, start a new session, adjust the prompt, and try again. Continuing in the same session means previous error info might interfere with Claude’s judgment.

Reduce Ambiguity:
Be as detailed as possible when assigning tasks. The more specific you are, the more accurate Claude’s output.

Terminal and Environment Configuration

Many in the team use Ghostty terminal because of its synchronized rendering, 24-bit true color, and full Unicode support. These are important when running multiple Claude sessions simultaneously.

Another practical tip: Use /statusline to customize the status bar to always show current context usage and git branch. This lets you see the status of each session at a glance.

Some use tmux to manage multiple sessions, coloring and naming each tab—one tab per task or worktree.

An often overlooked suggestion: Use voice input. Your speaking speed is three times your typing speed. More importantly, when speaking, you unconsciously say things in more detail, leading to higher quality prompts. On macOS, press fn twice to start voice input.

Using Subagents

This is an advanced technique that is very powerful when used well.

Simplest Usage: Add “use subagents” to any request. Claude will automatically split the task among multiple Subagents processing in parallel, effectively letting it “open more threads” to solve the problem.

Another Usage: Use Subagents to keep the main session context clean. Dispatch independent subtasks, while the main session only handles overall coordination. This prevents the main session’s context window from getting stuffed with intermediate processes.

Subagents allow for parallel tasking, saving significant time.

Advanced Usage: Use hooks to route permission requests to a stronger model, letting it judge which operations are safe to auto-approve and which require human confirmation. It’s like adding a “security auditor” to Claude.

Data Analysis with Claude Code

This usage might surprise many. The team has encapsulated BigQuery usage into a skill, allowing everyone to query data directly using the bq command line in Claude Code.

This isn’t limited to BigQuery. Any database with a CLI, MCP, or API can be used this way. PostgreSQL, MySQL, MongoDB—you can let Claude write queries, run analyses, and generate reports.

This might be even more valuable for non-engineers. Data scientists on the team are now using Claude Code to write queries and create visualizations. The boundaries of tools are blurring.

Learning with Claude Code

Finally, this technique is about using Claude Code to learn new things.

First: Enable “Explanatory” or “Learning” output style in /config. This way, when Claude edits code, it explains “why” it’s making the change, rather than just doing it.

Second: Ask Claude to generate HTML slides to explain unfamiliar code. The results are surprisingly good. You can view a richly illustrated code explanation directly in the browser.

Third: Ask Claude to draw ASCII diagrams to explain protocols, architectures, and data flows. Pure text charts are unexpectedly helpful for understanding complex systems.

Terminal Setup Optimization

Themes and Appearance

Claude cannot control your terminal’s theme. That is handled by your terminal application. You can match Claude Code’s theme to your terminal any time via the /config command. For additional customization of the Claude Code interface itself, you can configure a custom status line to display contextual information like the current model, working directory, or git branch.

Line Breaks

You have several options for entering line breaks into Claude Code:

  • Quick escape: Type \ followed by Enter to create a newline
  • Shift+Enter: Works out of the box in iTerm2, WezTerm, Ghostty, and Kitty
  • Keyboard shortcut: Set up a keybinding to insert a newline in other terminals

Set up Shift+Enter for other terminals: Run /terminal-setup within Claude Code to automatically configure Shift+Enter for VS Code, Alacritty, Zed, and Warp.

Set up Option+Enter (VS Code, iTerm2 or macOS Terminal.app)
For Mac Terminal.app:

  1. Open Settings → Profiles → Keyboard
  2. Check “Use Option as Meta Key”

For iTerm2 and VS Code terminal:

  1. Open Settings → Profiles → Keys
  2. Under General, set Left/Right Option key to “Esc+”

Vim Mode

Claude Code supports a subset of Vim keybindings that can be enabled with /vim or configured via /config. The supported subset includes:

  • Mode switching: Esc (to NORMAL), i/I, a/A, o/O (to INSERT)
  • Navigation: h/j/k/l, w/e/b, 0/^, gg/G, f/F/t/T with ;/, repeat
  • Editing: x, dw/de/db/dd/D, cw/ce/cb/cc/C, . (repeat)
  • Yank/paste: yy/Y, yw/ye/yb, p/P
  • Text objects: iw/aw, iW/aW, i"/a", i'/a', i(/a(, i[/a[, i{/a{
  • Indentation: >>/<<
  • Line operations: J (join lines)

Extended Thinking (Thinking Mode)

Extended thinking is enabled by default, reserving a portion of the output token budget (up to 31,999 tokens) for Claude to reason through complex problems step-by-step. This reasoning is visible in verbose mode, which you can toggle on with Ctrl+O. Extended thinking is particularly valuable for complex architectural decisions, challenging bugs, multi-step implementation planning, and evaluating tradeoffs.

Configure thinking mode:
Thinking is enabled by default, but you can adjust or disable it.

Scope How to configure Details
Toggle shortcut Press Option+T (macOS) or Alt+T (Windows/Linux) Toggle thinking on/off for current session. May require terminal config.
Global default Use /config to toggle thinking mode Sets your default across all projects.
Saved as alwaysThinkingEnabled in ~/.claude/settings.json
Limit token budget Set MAX_THINKING_TOKENS environment variable Limit thinking budget to specific number of tokens. Example: export MAX_THINKING_TOKENS=10000

To view Claude’s thinking process, press Ctrl+O to toggle verbose mode and see the internal reasoning displayed as gray italic text.

How extended thinking token budgets work:
Extended thinking uses a token budget that controls how much internal reasoning Claude can perform. A larger thinking token budget provides:

  • More space to explore multiple solution approaches step-by-step
  • Room to analyze edge cases and evaluate tradeoffs thoroughly
  • Ability to revise reasoning and self-correct mistakes

Token budgets for thinking mode:

  • When thinking is enabled, Claude can use up to 31,999 tokens from your output budget for internal reasoning.
  • When thinking is disabled (via toggle or /config), Claude uses 0 tokens for thinking.

Limit the thinking budget: Use the MAX_THINKING_TOKENS environment variable to cap the thinking budget.

Frequently Asked Questions

How do I handle multiple tasks simultaneously?
Use Git worktree to check out 3-5 working directories simultaneously, running an independent Claude Code session in each. For instance, Directory A is refactoring a module, Directory B is writing tests, and Directory C is updating documentation—advancing three tasks in parallel. Git worktree lets you have multiple branch working directories open in the same repo without switching back and forth.

When should I use Plan Mode?
When encountering complex tasks, discuss the solution with Claude in Plan Mode first. Iterate until you are satisfied with the plan, then switch to auto-edit mode for execution. If things go off track, immediately return to Plan Mode to re-plan—don’t push blindly.

What should I include in CLAUDE.md?
Only the most important content AI hasn’t been trained on, such as project-specific Bash commands, code style conventions, UI design guidelines, core technical implementation flows, and PR templates. Use file links for more content to be read on demand.

How do I create effective Skills?
If you do something twice a day, it’s worth turning it into a skill or slash command. Automate repetitive tasks like the full commit/push/create PR workflow, or integrate multiple data sources to get a panoramic view.

What is the difference between Hooks and Skills?
Hooks are event-driven automations that execute when specific events trigger, such as before/after tool calls or session start/end. Skills are reusable instruction sets invoked manually with slash commands, suitable for repeatable workflows.

How can I get Claude to fix bugs more accurately?
Be clear when describing bugs: how to reproduce, the expected result, and the actual problem (e.g., error logs, screenshots). With this basic information, the AI has enough context to locate and validate the issue. Give Claude enough context and permissions, then trust it—don’t micromanage step-by-step.

How do I switch between multiple Claude sessions?
From inside an active session, use /resume to switch to a different conversation. Sessions are stored per project directory. The /resume picker shows sessions from the same git repository, including worktrees. When starting Claude Code, you can resume a previous session: claude --continue continues the most recent conversation in the current directory, claude --resume opens a conversation picker or resumes by name.

How do I manage Hooks?
Use the /hooks command to open an interactive hooks manager where you can view, add, and delete hooks without editing settings files directly. Each hook in the menu is labeled with a bracket prefix indicating its source: [User] from ~/.claude/settings.json, [Project] from .claude/settings.json, [Local] from .claude/settings.local.json, [Plugin] from a plugin’s hooks/hooks.json (read-only).

How do I use Subagents in Claude Code?
Add “use subagents” to any request, and Claude will automatically split the task among multiple Subagents processing in parallel. Alternatively, use Subagents to keep the main session context clean by dispatching independent subtasks while the main session only handles overall coordination.