Skip to main content
Guide contents

Guide contents

Time to study: 20 min
#automation#claude_code#cli#terminal#ai_tools
Beginner20 min

Claude Code: The Beginner's Handbook

Complete engineering guide to Claude Code by Anthropic: CLI setup, authentication, permissions management, essential hotkeys, and building your first project.

Published:

Claude Code is the official terminal-based agent developed by Anthropic, capable of reading source code, applying edits, running commands, and managing git workflows directly in your terminal through natural language. Unlike standard web chat interfaces that require manual code copying, Claude Code operates autonomously within your codebase.

This handbook serves as the definitive starting point for developers new to Claude Code. The material is organized into three structured modules:

  • Module 1 — Installation and Core Setup: Global CLI deployment, API key and OAuth authentication, first launch, and configuration files.
  • Module 2 — Working Sessions and Agent Interactions: Managing context windows, keyboard shortcuts, slash commands, non-interactive execution, and token optimization with /compact.
  • Module 3 — Security and Permission Boundaries: Configuring settings.json, building fine-grained allow/deny pattern lists, and sandboxing command executions.

Each module concludes with a practical coding exercise, building and hardening an interactive React / Next.js component.


1. What is Claude Code and System Requirements

1.1. What Claude Code Is and Differences from Web Chat

Claude Code functions as an autonomous terminal assistant integrated directly into your engineering toolchain. Rather than functioning as a passive chat window, the agent leverages concrete tools:

  • Inspection & Search: Recursively traverses directories, inspects files, and conducts fast regex searches (grep) and glob pattern matching (glob).
  • Targeted Code Modifications: Applies precise file patches without rewriting entire large source files.
  • System Command Execution: Runs test runners, compilers, linters, and git operations while actively monitoring output codes and stack traces.

1.2. System Requirements and Environment Preparation

Before installing Claude Code, verify that your environment meets the following prerequisites:

  • Operating System: macOS, modern Linux distributions, or Windows via WSL2.
  • JavaScript Runtime: Node.js version 18.0 or newer (check with node -v).
  • Version Control: Git version 2.20 or newer (check with git --version).
  • Anthropic Access: An active Anthropic Console API key or an account subscribed to Claude Max.

2. Installation and Authentication

2.1. CLI Installation via npm and Package Managers

Claude Code is distributed as a global package via the npm registry. Install it by executing:

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

Verify that the CLI executable is available in your shell:

bash
claude --version

If your terminal reports command not found, your npm global bin directory is not included in your $PATH environment variable. Refer to the diagnostic table in Module 1 for resolution steps.

2.2. Authentication and Anthropic Account Linking

Two authentication methods are supported:

Option A — Anthropic API Key:
Export your credential as an environment variable:

bash
export ANTHROPIC_API_KEY="sk-ant-your-api-key"

To persist the credential across terminal restarts, add it to your shell configuration file:

bash
echo 'export ANTHROPIC_API_KEY="sk-ant-your-api-key"' >> ~/.zshrc source ~/.zshrc

Option B — Claude Max Subscription (OAuth):
Subscribers to Claude Max ($100 or $200/month) can authenticate through their browser without token metering:

bash
claude login

This launches an OAuth consent page in your default browser to authorize your terminal workstation.


3. First Launch and Basic Configuration

3.1. First Run in a Project and Environment Verification

Navigate into any codebase on your machine and launch Claude Code:

bash
cd ~/my-project claude

Upon startup, you will enter the interactive REPL. Submit an initial reconnaissance query:

text
Summarize the structure of this project and list the main technologies used.

Claude will inspect package.json, build manifests, and root directories, returning an executive summary of your stack.

3.2. Baseline Configuration and Initial Troubleshooting

Settings files reside under ~/.claude/:

  • ~/.claude/settings.json — Global tool permissions and execution policies.
  • ~/.claude/CLAUDE.md — Global instructions applied to every session.
  • .claude/settings.json — Repository-scoped settings (committed to Git).
  • CLAUDE.md — Project-level architectural guidelines and coding standards.
Startup IssueRoot CauseEngineering Solution
claude: command not foundGlobal npm bin path missing from PATHExport binary path: export PATH="$(npm config get prefix)/bin:$PATH"
401 UnauthorizedInvalid or expired API credentialsRun claude logout, verify ANTHROPIC_API_KEY, and re-authenticate
Slow initial startupFirst-time repository indexingFirst launch builds project index; subsequent runs use local cache

4. Practice: Build Your First Application

4.1. Step-by-Step Prototype Generation Workflow

The objective of the first exercise is creating a baseline Next.js client component with Claude Code:

  1. Direct Claude to generate a new page file at app/practice/page.tsx.
  2. Instruct the agent to build an interactive button triggering a test asynchronous handler.
  3. Validate functionality by running the local server at http://localhost:3000/practice.

4.2. Starter Code Template and Local Server Verification

Initial component implementation:

tsx
// app/practice/page.tsx 'use client'; import { useState } from 'react'; export default function PracticePage() { const [result, setResult] = useState(''); const [loading, setLoading] = useState(false); async function runTest() { setLoading(true); try { const response = await fetch('/api/test'); const data = await response.json(); setResult(data.message || 'Request completed successfully'); } catch { setResult('Error executing test request'); } finally { setLoading(false); } } return ( <div className="p-8 max-w-2xl mx-auto font-sans"> <h1 className="text-3xl font-bold mb-6">Practice Exercise 1: Prototype</h1> <button onClick={runTest} disabled={loading} className="bg-black text-white px-6 py-3 rounded-lg hover:bg-neutral-800 disabled:opacity-50 transition" > {loading ? 'Running...' : 'Run Test'} </button> {result && ( <div className="mt-6 p-4 bg-neutral-100 rounded-lg border border-neutral-200"> {result} </div> )} </div> ); }

5. Working Session and Dialogue Flow

5.1. Launching the Interactive REPL Session

Start daily development workflows by navigating to your repository and entering the REPL:

bash
cd ~/my-project claude

Claude maintains persistent conversational memory across the session, keeping track of modified files and recent compilation outputs. Interactions proceed in natural developer language.

5.2. The Dialogue Loop: Planning, Tool Execution, and Verification

Agent operations follow a five-stage execution lifecycle:

mermaid
flowchart TD A["Developer specifies task in natural language"] --> B["Claude audits codebase and devises action plan"] B --> C["Agent requests user approval for sensitive actions"] C --> D["Execution of approved tools and diff display"] D --> E["Developer reviews output and provides feedback"]

Typical dialogue progression:

  • Prompt: Add a loading spinner to the dashboard page.
  • Inspection: Claude reads app/dashboard/page.tsx, identifying unhandled loading states.
  • Action: Proposes creating loading.tsx and wrapping data fetches in React Suspense.
  • Approval: Displays a unified diff and pauses for explicit developer confirmation.

6. Hotkeys, Commands, and Operating Modes

6.1. Essential Hotkeys and Context Management Slash Commands

Mastering terminal shortcuts significantly accelerates development velocity:

ShortcutFunction
EnterSubmit current message to the agent
EscapeCancel active response generation or tool execution
Ctrl+CGracefully exit Claude Code
Up / DownTraverse command input history
Shift+TabToggle between single-line and multi-line input modes

Key slash commands for session control:

  • /help — Display available commands and flags.
  • /clear — Wipe current conversation history.
  • /compact — Compress conversation history to recover context capacity without losing essential facts.
  • /model — Switch active model dynamically (e.g., toggling between Sonnet and Opus).
  • /permissions — Inspect active tool execution policies.

6.2. Non-Interactive Mode and Execution Efficiency Tips

For CI scripting, cron jobs, and single-shot terminal tasks, invoke the non-interactive print mode with -p:

bash
# Query repository architecture claude -p "What database does this project use?" # Pipe log output directly for root-cause diagnosis cat error.log | claude -p "Find the root cause of this crash and suggest a patch"

💡 Productivity Guidelines:

  • Provide explicit constraints: write Add debounce to the form submission click handler instead of vague prompts like Fix form.
  • Run /compact periodically whenever dialogue history exceeds 30–40 interaction turns.

7. Practice: Enhance Your Application

7.1. Code Refactoring and Automated Enhancements with Claude

In the second exercise, we will expand the initial component by instructing Claude to harden typing and add animated UI feedback.

Submit the following prompt to Claude Code:

text
Open app/practice/page.tsx. Implement strict TypeScript typings, add try/catch error handling with an alert banner on red background, and render an animated CSS spinner while loading.

7.2. Feature Expansion: Styling, Error Handling, and Loading States

The enhanced component implementation:

tsx
// app/practice/page.tsx - Enhanced Version 'use client'; import { useState } from 'react'; export default function PracticePage() { const [result, setResult] = useState<string | null>(null); const [error, setError] = useState<string | null>(null); const [loading, setLoading] = useState(false); async function runTest() { setLoading(true); setError(null); try { const response = await fetch('/api/test'); if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); const data = await response.json(); setResult(data.message || 'Operation completed successfully'); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Unexpected execution error'); } finally { setLoading(false); } } return ( <div className="p-8 max-w-2xl mx-auto font-sans"> <h1 className="text-3xl font-bold mb-4">Practice Exercise 2: Enhanced</h1> <p className="text-neutral-600 mb-6">Testing interactive feedback and exception handling.</p> <button onClick={runTest} disabled={loading} className="flex items-center gap-2 bg-black text-white px-6 py-3 rounded-lg hover:bg-neutral-800 disabled:opacity-50 transition" > {loading && ( <span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" /> )} {loading ? 'Processing...' : 'Execute Task'} </button> {error && ( <div className="mt-6 p-4 bg-red-50 text-red-700 rounded-lg border border-red-200"> {error} </div> )} {result && ( <div className="mt-6 p-4 bg-neutral-100 text-neutral-800 rounded-lg border border-neutral-200"> {result} </div> )} </div> ); }

8. Permission Model and Security

8.1. Architecture of the Permission Model and Risk Tiers

Claude Code partitions all operational tool calls into two security tiers based on systemic risk:

Permission TierEligible Tool InvocationsExecution Mechanics
Safe (Read-Only)Read, Grep, Glob, directory listingsExecuted immediately without prompting developer
High Risk (Mutation)Edit, Write, Bash, file deletion, git pushPauses for explicit confirmation before invocation

8.2. Mechanics of Approving and Denying Dangerous Actions

When attempting an operation in the high-risk tier, Claude displays a confirmation dialog:

text
Claude wants to run: npm install express Allow? (y/n/always)

Available response flags:

  • y (yes) — Approve this specific one-time invocation.
  • n (no) — Reject execution, prompting Claude to suggest an alternative.
  • always (or a) — Grant unrestricted permission for this tool until session termination.

9. Settings Files and Access Control

9.1. Global and Project-Level Settings Files (settings.json)

To establish persistent permission rules, author ~/.claude/settings.json:

json
{ "permissions": { "allow": [ "Read", "Glob", "Grep", "Edit", "Write", "Bash(npm run *)", "Bash(git status)" ], "deny": [ "Bash(rm -rf *)", "Bash(sudo *)" ] } }

9.2. Pattern Rules for Bash Commands and Auditing via /permissions

The permissions.allow array supports expressive glob patterns:

  • Bash(npm test *) — Permit test runners without interactive prompts.
  • Bash(git commit *) — Authorize commit creation.
  • Bash(rm -rf *) in deny — Enforces an absolute ban on recursive directory deletion.

Inspect active runtime rules at any point by typing /permissions.


10. Security and Operational Best Practices

10.1. Access Control Strategy: Least Privilege Principle

  • Progressive Permission Expansion: Begin development in fully supervised mode. Add command patterns to the allow array only after validating consistent agent behavior.
  • Ban Unbounded Bash Wildcards: Never add "Bash(*)" to your allowlist; doing so completely dismantles the security sandbox.
  • Enforce Explicit Deny Rules: Hardcode defensive denials for dangerous system utilities (sudo, mkfs, dd) to protect against accidental confirmations.

10.2. Environment Secret Isolation and Rigorous Diff Auditing

  • Secret Variable Isolation: Claude Code inherits environment variables from the parent shell. Avoid launching sessions with active production database connection strings.
  • Review Diffs Before Approval: Inspect patch diffs line-by-line to prevent unintended modifications to adjacent modules.

11. Practice: Final Version of the Application

11.1. Hardened Workflow and Production Security Validation

In the final module, we assemble a complete production-ready dashboard component:

  1. Define strict execution boundaries in .claude/settings.json.
  2. Direct Claude to refactor the component into a resilient production structure with typed API payloads.
  3. Validate compilation integrity with npm run build.

11.2. Final Component Code and Deployment Readiness Checklist

Production-grade component implementation:

tsx
// app/practice/page.tsx - Production-Ready Final Version 'use client'; import { useState } from 'react'; interface ApiResponse { message: string; status: 'ok' | 'error'; timestamp: string; } export default function PracticePage() { const [data, setData] = useState<ApiResponse | null>(null); const [error, setError] = useState<string | null>(null); const [loading, setLoading] = useState(false); async function runTest() { setLoading(true); setError(null); try { const response = await fetch('/api/test'); if (!response.ok) throw new Error(`Server returned ${response.status}`); const payload: ApiResponse = await response.json(); setData(payload); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Unexpected execution failure'); } finally { setLoading(false); } } return ( <main className="min-h-screen bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8 font-sans"> <div className="max-w-xl mx-auto bg-white p-8 rounded-xl shadow-sm border border-neutral-200"> <h1 className="text-2xl font-semibold text-neutral-900 mb-2">Practice Exercise 3: Production Version</h1> <p className="text-sm text-neutral-500 mb-6">Hardened client component optimized and audited via Claude Code.</p> <button onClick={runTest} disabled={loading} className="w-full flex justify-center items-center gap-2 bg-neutral-900 text-white py-3 px-4 rounded-lg font-medium hover:bg-neutral-800 disabled:opacity-50 transition" > {loading && ( <span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" /> )} {loading ? 'Running Verification...' : 'Execute Healthcheck'} </button> {error && ( <div className="mt-6 p-4 bg-red-50 text-red-700 text-sm rounded-lg border border-red-200"> <strong>Error:</strong> {error} </div> )} {data && ( <div className="mt-6 p-4 bg-neutral-50 text-neutral-800 text-sm rounded-lg border border-neutral-200 space-y-1"> <div><strong>Status:</strong> {data.status}</div> <div><strong>Message:</strong> {data.message}</div> <div className="text-xs text-neutral-400"><strong>Timestamp:</strong> {data.timestamp}</div> </div> )} </div> </main> ); }
This guide is completely free. If it saved you an evening, you can support the project's growth.
Support the author