Please ๐Ÿ–ฑ๏ธ here for Github Blogs

Claude Notes

  • June 22, 2025
Table of Contents

Part 1: Claude Code

Claude Code is Anthropic’s agentic CLI tool for software development. Unlike IDE plugins (GitHub Copilot, Cursor) that assist you as you type, Claude Code operates autonomously โ€” it reads your codebase, writes files, runs commands, browses the web, calls APIs, and iterates on its own output.

What Claude Code Can Do

  • Read and write files across your entire project
  • Execute shell commands (tests, builds, git operations)
  • Search the web for documentation and solutions
  • Connect to external services via MCP (GitHub, Slack, databases, etc.)
  • Run parallel sub-agents for complex multi-part tasks
  • Integrate into CI/CD pipelines as a fully automated agent

What Makes It Different from Cursor/Copilot

FeatureCursor / CopilotClaude Code
Primary interfaceIDE (GUI)Terminal (CLI)
Context awarenessOpen filesEntire codebase
Autonomy levelSuggestionsFull autonomous execution
MCP / HooksNoYes
CI/CD integrationNoYes (GitHub Actions)
Custom agentsNoYes
Sandboxing controlLimitedFull control

Installation & Setup

Requirements

  • Node.js 18+ (required)
  • macOS 10.15+, Ubuntu 20.04+/Debian 10+, or Windows via WSL/Git Bash
  • Minimum 4GB RAM
  • Active internet connection

Install

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

Authenticate

claude  # Opens browser for Anthropic login on first run

Or set via environment variable:

export ANTHROPIC_API_KEY=sk-ant-...

Verify Installation

claude --version
claude --help

Architecture & Mental Model

Understanding Claude Code’s layered architecture is the key to mastering it.

    graph TD
	    subgraph CORE["๐Ÿ”ท Core Layer"]
	        CLI["Claude Code CLI + Session Management"]
	        CTX["CLAUDE.md context ยท conversation loop"]
	    end
	
	    subgraph DELEGATION["๐Ÿ”ท Delegation Layer"]
	        SA["Sub-Agents"]
	        SK["Skills"]
	        SC["Slash Commands"]
	    end
	
	    subgraph EXTENSION["๐Ÿ”ท Extension Layer"]
	        MCP["MCP Servers"]
	        HK["Hooks"]
	        PL["Plugins"]
	    end
	
	    CORE --> DELEGATION
	    DELEGATION --> EXTENSION

Most users only use the Core Layer โ€” that’s where context bloat and high costs come from. Power users delegate to Sub-Agents, automate with Hooks, and extend with MCP.

Key Insight

CLAUDE.md gives Claude memory โ†’ Slash Commands create repeatable workflows โ†’ Sub-Agents handle parallel work โ†’ Hooks enforce deterministic rules โ†’ MCP connects external services


CLI Commands & Flags

Starting Sessions

claude                              # Start new interactive session
claude "fix the authentication bug" # Start session with initial prompt
claude -p "explain this function"   # One-shot query, then exit (non-interactive)
claude -c                           # Continue the most recent session
claude --resume                     # Pick a past session to resume

Model Selection

claude --model opus          # Use Claude Opus (most capable)
claude --model sonnet        # Use Claude Sonnet (balanced)
claude --model haiku          # Use Claude Haiku (fastest, cheapest)

Permissions Flags

claude --allowedTools "Read" "Write" "Bash"     # Skip dialog for these tools
claude --disallowedTools "Write"                 # Remove a tool entirely
claude --dangerously-skip-permissions            # Skip ALL permission dialogs (use with extreme caution)
claude --permission-mode plan                    # Start in plan-only mode

Context & Prompt Flags

claude --system-prompt "You are a React expert"            # Replace system prompt
claude --append-system-prompt "Never delete test files"    # Add to system prompt
claude --agent MyCustomAgent                               # Use a specific sub-agent

Output Flags (for scripting/CI)

claude -p "analyze code" --output-format json              # JSON output
claude -p "review" --max-turns 5 > report.txt             # Limit turns, pipe output
claude -p "audit" --allowedTools Read,Grep,Glob \
  --output-format json > security_report.json

Worktrees (Parallel Isolation)

claude --worktree feature-auth   # Create isolated git worktree for this session

In-Session Shortcuts & Commands

Keyboard Shortcuts

ShortcutAction
SHIFT + TABCycle between modes (Default โ†’ Write โ†’ Plan)
CTRL + CCancel current input
ESCCancel current generation (can inject new prompt mid-task)
ESC + ESCUndo the last action Claude performed
CTRL + BMove task to background (Claude continues autonomously)
OPTION + P / ALT + PSwitch model mid-session
CTRL + OToggle verbose output
CTRL + V / CMD + VPaste text or image into prompt
โ†‘ / โ†“ arrowsScroll through past messages

Slash Commands (Built-in)

/help          # List all available commands including custom ones
/model         # Switch AI model for current session
/clear         # Clear context window (start fresh)
/compact       # Summarize + clear context (retains summary)
/compact retain the error handling patterns  # Compact with specific retention
/context       # View context window stats and usage %
/usage         # View plan usage / remaining quota
/init          # Analyze project and generate CLAUDE.md
/mcp           # View and manage connected MCP servers
/permissions   # View and update permission settings
/rewind        # Undo to earlier conversation point
/config        # Open interactive settings menu
/statusline    # Configure the terminal status bar

Rule of thumb: Use /compact when context hits 70-80%. Use /clear when switching tasks entirely.


CLAUDE.md โ€” The Agent’s Constitution

CLAUDE.md is the most important file in your Claude Code setup. It gives Claude persistent project memory โ€” instructions that load automatically at the start of every session.

File Hierarchy

~/.claude/CLAUDE.md              # Global โ€” applies to ALL your projects
your-project/CLAUDE.md           # Project โ€” shared via Git with team
your-project/CLAUDE.local.md     # Local โ€” personal overrides, NOT in Git

What to Put in CLAUDE.md

# Project: E-Commerce API

## Tech Stack

- Python 3.12 + FastAPI + SQLAlchemy
- PostgreSQL (primary DB), Redis (cache)
- Docker for local dev, AWS ECS for production

## Code Conventions

- Use type hints everywhere โ€” no untyped functions
- Snake_case for variables, PascalCase for classes
- Write docstrings for all public functions
- Tests in `/tests` mirroring the src structure
- Use pytest with fixtures, not unittest

## Architecture Rules

- All DB access goes through the repository pattern
- Business logic in services, NOT in route handlers
- Never return raw SQLAlchemy models โ€” use Pydantic schemas

## DO NOT

- Modify `.env` or `.env.example` files
- Delete or alter database migration files
- Change any `*_schema.py` files without asking
- Push directly to `main` branch โ€” always create a PR

## Running the Project

- Start: `docker-compose up`
- Tests: `pytest -v`
- Migrations: `alembic upgrade head`
- Lint: `ruff check .`

Tips for Good CLAUDE.md Files

  1. Be specific โ€” “Use snake_case” beats “follow Python conventions”
  2. List what NOT to do โ€” prevents costly mistakes
  3. Include run commands โ€” Claude can test its own changes
  4. Keep it under 25KB โ€” larger files slow down context loading
  5. Update it regularly โ€” treat it like living documentation

Modular Rules (Alternative to One Big File)

.claude/
โ””โ”€โ”€ rules/
    โ”œโ”€โ”€ code-style.md
    โ”œโ”€โ”€ security.md
    โ”œโ”€โ”€ testing.md
    โ””โ”€โ”€ git-workflow.md

Configuration & Settings Files

File Locations

~/.claude.json                          # Global user settings
~/.claude/settings.json                 # Global Claude Code settings
your-project/.claude/settings.json      # Project-shared settings (commit to Git)
your-project/.claude/settings.local.json # Personal project settings (gitignore)

Key Settings

{
  "model": "claude-sonnet-4-6",
  "alwaysThinkingEnabled": true,
  "permissions": {
    "allow": ["Read", "Write", "Bash(git *)", "Bash(npm *)"],
    "deny": ["Bash(rm -rf *)", "Write(.env*)"]
  },
  "env": {
    "NODE_ENV": "development",
    "LOG_LEVEL": "debug"
  },
  "hooks": {
    "PreToolUse": [...],
    "PostToolUse": [...]
  }
}

Project Folder Structure (Best Practice)

your-project/
โ”œโ”€โ”€ CLAUDE.md                    # Shared project instructions (commit this)
โ”œโ”€โ”€ CLAUDE.local.md              # Personal instructions (gitignore)
โ”œโ”€โ”€ .mcp.json                    # MCP server configs (commit this)
โ””โ”€โ”€ .claude/
    โ”œโ”€โ”€ settings.json            # Shared settings (commit this)
    โ”œโ”€โ”€ settings.local.json      # Personal settings (gitignore)
    โ”œโ”€โ”€ commands/                # Custom slash commands
    โ”‚   โ”œโ”€โ”€ pr.md
    โ”‚   โ”œโ”€โ”€ review.md
    โ”‚   โ””โ”€โ”€ deploy.md
    โ”œโ”€โ”€ agents/                  # Sub-agent definitions
    โ”‚   โ”œโ”€โ”€ security-auditor.md
    โ”‚   โ””โ”€โ”€ test-writer.md
    โ”œโ”€โ”€ skills/                  # Auto-activated expertise
    โ”‚   โ””โ”€โ”€ python-typing/
    โ”‚       โ””โ”€โ”€ SKILL.md
    โ””โ”€โ”€ hooks/                   # Hook scripts
        โ”œโ”€โ”€ pre-commit-check.sh
        โ””โ”€โ”€ block-env-writes.sh

Permissions & Security

Claude Code asks for permission before performing potentially risky actions. You control this granularity.

Permission Levels (Modes)

ModeBehavior
defaultAsk permission for each new tool/action type
acceptEditsAuto-approve file writes, ask for Bash
planRead-only โ€” plan actions, execute nothing
bypassPermissionsSkip all dialogs (dangerous!)

Setting Granular Permissions

{
  "permissions": {
    "allow": [
      "Read",
      "Write",
      "Bash(git *)",
      "Bash(npm run *)",
      "Bash(pytest *)",
      "Bash(docker-compose *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Write(.env*)",
      "Write(**/migrations/**)"
    ]
  }
}

Via CLI Flags

# Allow specific tools without dialog
claude --allowedTools "Read" "Write" "Bash(git *)"

# Deny specific tools entirely
claude --disallowedTools "Write"

MCP โ€” Model Context Protocol

MCP transforms Claude Code from a file reader/writer into a tool that can interact with any external system โ€” databases, GitHub, Slack, Jira, etc.

What MCP Enables

Without MCP, Claude Code can only read files and run bash commands.
With MCP, Claude can:

  • Query your production database
  • Create GitHub PRs and issues
  • Post Slack messages
  • Check Sentry errors
  • Interact with any API your team uses

The MCP ecosystem grew from ~100K downloads in Nov 2024 to 8M+ by April 2025 โ€” 80x growth. Over 300 integrations exist.

Adding MCP Servers

# Via CLI (wizard)
claude mcp add github -- npx -y @modelcontextprotocol/server-github

# With environment variables
claude mcp add github -s user \
  -e GITHUB_PERSONAL_ACCESS_TOKEN=your-token \
  -- npx -y @modelcontextprotocol/server-github

# View installed servers
claude mcp list

Via Config File (Better for Teams)

Edit .mcp.json directly โ€” much easier for complex configs:

{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"
      }
    },
    "postgres": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "postgresql://localhost/mydb"
      }
    },
    "sequential-thinking": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
    }
  }
}

Using MCP Tools in Sessions

Once connected, MCP tools appear as slash commands:

/mcp__github__create_issue
/mcp__github__search_repositories
/mcp__filesystem__read_file
/mcp__memory__create_entities
ServerUse Case
@modelcontextprotocol/server-githubGitHub PRs, issues, repos
@modelcontextprotocol/server-postgresQuery PostgreSQL
@modelcontextprotocol/server-filesystemExtended filesystem ops
@modelcontextprotocol/server-slackSlack messaging
@playwright/mcpBrowser automation
@modelcontextprotocol/server-sequential-thinkingStructured reasoning

MCP Tool Naming in Hooks

MCP tools follow the pattern mcp__<server>__<tool> and work in hooks exactly like built-in tools:

{
  "matcher": "mcp__github__.*",   // Match all GitHub MCP tools
  "hooks": [...]
}

Hooks โ€” Deterministic Automation

Hooks are the most powerful and underused Claude Code feature. They execute shell commands, HTTP endpoints, or LLM prompts automatically at specific lifecycle points โ€” regardless of what Claude decides to do.

Think of CLAUDE.md as “should do” rules. Hooks are “must do” rules.

Hook Events

EventWhen It Fires
PreToolUseBefore Claude executes any tool โ€” can BLOCK it
PostToolUseAfter a tool completes successfully
PostToolUseFailureAfter a tool fails
PermissionRequestWhen Claude asks for a new permission
ElicitationWhen an MCP server requests user input

Hook Configuration

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git commit*)",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/pre-commit-check.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/run-linter.sh"
          }
        ]
      }
    ]
  }
}

Pre-Commit Enforcement Hook (Real Example)

This hook blocks Claude from committing until all tests pass:

#!/bin/bash
# .claude/hooks/pre-commit-check.sh

# Run tests
npm run test 2>&1

if [ $? -ne 0 ]; then
  echo '{"decision": "block", "reason": "Tests must pass before committing"}'
  exit 0
fi

# Tests passed โ€” allow commit
echo '{"decision": "allow"}'

Block Dangerous Commands Hook

#!/bin/bash
# .claude/hooks/block-dangerous.sh

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin)['tool_input'].get('command',''))")

# Block rm -rf
if echo "$COMMAND" | grep -qE "rm\s+-rf\s+/"; then
  echo '{"decision": "block", "reason": "Refusing to delete system directories"}'
  exit 0
fi

echo '{"decision": "allow"}'

Block Writes to .env Files

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'INPUT=$(cat); FILE=$(echo $INPUT | python3 -c \"import sys,json; print(json.load(sys.stdin)[\\\"tool_input\\\"][\\\"path\\\"]\"); if [[ $FILE == *.env* ]]; then echo \\'{{\"decision\":\"block\",\"reason\":\"Cannot write to .env files\"}}\\'; else echo \\'{{\"decision\":\"allow\"}}\\'; fi'"
          }
        ]
      }
    ]
  }
}

Hook Best Practices

  • Block at commit, not at write โ€” blocking mid-plan confuses Claude
  • Use hint hooks for warnings โ€” non-blocking feedback is less disruptive
  • Log hook execution โ€” helps debug agent behavior in production
  • Match specifically โ€” overly broad matchers slow everything down

Custom Slash Commands

Create your own /commands that Claude executes on demand โ€” reusable, parameterized workflows.

Creating Commands

# Project-specific command
mkdir -p .claude/commands
echo "Review this code for security vulnerabilities, focusing on OWASP Top 10:" \
  > .claude/commands/security-review.md

# Global command (all projects)
mkdir -p ~/.claude/commands
echo "Write comprehensive tests for the selected code:" \
  > ~/.claude/commands/write-tests.md

Parameterized Commands

Use $ARGUMENTS to pass dynamic input:

<!-- .claude/commands/fix-issue.md -->

Fix GitHub issue #$ARGUMENTS following our coding standards in CLAUDE.md.

Steps:

1. Read the issue description
2. Identify affected files
3. Implement the fix with tests
4. Run the test suite
5. Create a descriptive commit message
# Usage in session
/fix-issue 342

Complex Multi-Step Command

<!-- .claude/commands/pr.md -->

Create a pull request for the current changes.

Steps:

1. Run `git diff` to understand all changes
2. Run the full test suite โ€” abort if any fail
3. Write a clear PR description explaining WHY, not just what
4. Create the PR with appropriate labels
5. Request review from the relevant team members based on the files changed

Viewing Available Commands

/help   # Lists all built-in AND custom commands

Sub-Agents (Parallel Task Delegation)

Sub-agents are specialized Claude instances you can spawn for specific tasks. They run in isolated contexts, preventing context pollution and enabling parallel execution.

Defining a Sub-Agent

## <!-- .claude/agents/security-auditor.md -->

name: security-auditor
description: Specialized in application security analysis and vulnerability assessment
allowed-tools: Read, Grep, Glob, Bash(git log:_), Bash(git diff:_)

---

# Security Auditor Agent

You are a senior application security engineer specializing in:

## Expertise

- OWASP Top 10 vulnerabilities
- SQL injection, XSS, CSRF patterns
- Authentication and authorization flaws
- Secrets and credential exposure
- Dependency vulnerability analysis

## Response Format

Always provide:

1. Severity rating (Critical/High/Medium/Low)
2. Affected files and line numbers
3. Proof of concept or explanation
4. Concrete remediation steps
5. References (CVE, OWASP, etc.)

More Agent Examples

## <!-- .claude/agents/test-writer.md -->

name: test-writer
description: Writes comprehensive tests for new or modified code
allowed-tools: Read, Write, Bash(pytest _), Bash(npm test _)

---

You are a test engineering specialist. For every function or component:

- Write unit tests covering happy path, edge cases, and error conditions
- Follow existing test patterns in the codebase
- Aim for >90% branch coverage
- Use descriptive test names that explain what's being tested
## <!-- .claude/agents/db-expert.md -->

name: db-expert
description: Database query optimization, schema design, and migration planning
allowed-tools: Read, Bash(psql _), mcp**postgres**._

---

You are a database architect expert focused on:

- Query performance and indexing strategy
- Schema normalization and design
- Safe migration planning
- Analyze EXPLAIN ANALYZE output
  Always provide performance impact estimates.

Using Sub-Agents

# In a session, just refer to the agent by name
claude --agent security-auditor "audit the authentication module"

# Or Claude will automatically delegate when appropriate
"Use the security-auditor agent to review all API endpoints"

Skills โ€” Auto-Activated Expertise

Unlike slash commands (user-triggered), skills activate automatically when Claude detects they’re relevant to the current task.

How Skills Work

  1. You define a skill with a SKILL.md file
  2. Claude reads all skill descriptions at session start
  3. When your task matches a skill’s description, Claude loads and applies it
  4. You never explicitly invoke a skill โ€” it just activates

Skill Structure

.claude/skills/
โ””โ”€โ”€ python-typing/
    โ”œโ”€โ”€ SKILL.md         # Description + instructions
    โ””โ”€โ”€ examples/        # Optional example files
## <!-- .claude/skills/python-typing/SKILL.md -->

name: python-typing
description: Adding or improving Python type hints and type annotations in Python code

---

When adding type hints to Python code:

1. Use `from __future__ import annotations` for forward references
2. Prefer `X | Y` over `Optional[X]` or `Union[X, Y]` (Python 3.10+)
3. Use `TypeAlias` for complex type aliases
4. Add `Protocol` for structural subtyping
5. Annotate all function signatures including return types
6. Use `TypeVar` for generic functions
7. Add `py.typed` marker file if it's a library

Always run `mypy --strict` after adding type hints to verify correctness.

Plugins

Plugins are packaged collections of hooks, commands, skills, and MCP configurations โ€” shareable and installable as a unit.

Plugin Structure

my-plugin/
โ”œโ”€โ”€ plugin.json          # Plugin manifest
โ”œโ”€โ”€ commands/
โ”‚   โ””โ”€โ”€ security-check.md
โ”œโ”€โ”€ hooks/
โ”‚   โ””โ”€โ”€ pre-commit.sh
โ”œโ”€โ”€ skills/
โ”‚   โ””โ”€โ”€ security/
โ”‚       โ””โ”€โ”€ SKILL.md
โ””โ”€โ”€ mcp/
    โ””โ”€โ”€ config.json

Installing a Plugin

# Via npm (if published)
npm install -g claude-code-plugin-security

# Or directly from GitHub
claude plugin install https://github.com/user/my-plugin

Plugins are ideal for distributing opinionated team configurations โ€” install once, get consistent agent behavior across everyone’s machines.


Context Management

Context is your most important resource in Claude Code. Managing it well is the difference between accurate autonomous work and hallucination-prone output.

Context Warning Signs

Context UsageStatusAction
0โ€“50%โœ… GoodWork freely
50โ€“70%โš ๏ธ WatchPlan ahead
70โ€“90%๐ŸŸก DangerRun /compact
90%+๐Ÿ”ด Critical/clear mandatory

At 70%+ context, Claude starts losing precision. At 85%+, hallucinations increase significantly.

Check Context Usage

/context   # Shows used / total tokens, percentage

Compaction Strategies

/compact                                    # Summarize everything
/compact retain the error handling patterns # Keep specific things
/compact retain all API endpoints discovered so far

Manual Session History

Claude Code saves all sessions to ~/.claude/projects/. You can analyze these:

# Resume a previous session
claude --resume

# Continue most recent
claude -c

# Advanced: analyze session logs for patterns
ls ~/.claude/projects/my-project/

Reducing Context Bloat

  1. Use sub-agents for exploration tasks โ€” they run in separate contexts
  2. Use --worktree to isolate parallel tasks
  3. Be specific in requests โ€” vague tasks cause Claude to read more files
  4. Use /clear when switching between unrelated tasks in the same project

Modes โ€” Default, Plan, Write

Switching Modes

SHIFT + TAB    # Cycle through modes in session
--permission-mode plan    # Start in plan mode

Mode Behaviors

Default Mode

  • Claude asks permission per tool category
  • Good balance of safety and speed
  • Best for most tasks

Plan Mode (plan)

  • Claude can only read โ€” no writes or execution
  • Claude proposes a plan for your approval
  • Use for: reviewing architecture changes, understanding impact before committing

Write Mode (acceptEdits)

  • Auto-approves file writes
  • Still asks for Bash execution
  • Use for: known-safe code generation tasks

Bypass Mode (bypassPermissions / --dangerously-skip-permissions)

  • Skips ALL dialogs
  • Use only in sandboxed CI/CD environments
  • Never use on production systems or with untrusted prompts

Remote Sessions & GitHub Actions

Remote Web Sessions

claude --remote "Add dark mode to the settings page"

Starts a remote (web-based) Claude Code session โ€” useful for sharing work or running headless.

GitHub Actions Integration

This is how teams run Claude Code in CI/CD pipelines โ€” Claude becomes a fully automated engineering agent triggered by PRs, issues, Slack messages, or alerts.

# .github/workflows/claude-agent.yml
name: Claude Code Agent

on:
  issues:
    types: [labeled]

jobs:
  fix-issue:
    if: github.event.label.name == 'claude-fix'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Run Claude Code Agent
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          claude -p "
            Fix GitHub issue #${{ github.event.issue.number }}: 
            ${{ github.event.issue.title }}
            
            Issue body: ${{ github.event.issue.body }}
            
            Steps:
            1. Understand the issue
            2. Identify the root cause
            3. Implement the fix with tests
            4. Verify tests pass
            5. Create a pull request
          " \
          --allowedTools "Read,Write,Bash(git *),Bash(npm *)" \
          --max-turns 20

CI/CD Best Practices

  • Use --output-format json for machine-readable output
  • Set --max-turns to prevent runaway agents
  • Use --allowedTools to restrict to safe operations
  • Always review logs โ€” Claude Code logs full agent activity in GHA

Production Best Practices

Keep CLAUDE.md as the Source of Truth

Treat CLAUDE.md like code. Review changes, version it, keep it accurate. The quality of Claude’s output directly correlates with CLAUDE.md quality.

Use Hooks for Critical Enforcement

Don’t rely on CLAUDE.md instructions for things that must never happen (writing to .env, deleting migrations). Use PreToolUse hooks that block โ€” they’re deterministic.

Block at Commit, Not at Write

Blocking Claude mid-plan (on file writes) confuses it. Let it finish, then enforce at the commit stage:

# PreToolUse hook on git commit โ€” check tests passed first
# This is better than blocking on every Edit/Write operation

Use Sub-Agents for Exploration

When Claude needs to explore the codebase to understand something before making changes, delegate to a sub-agent. This keeps the main context clean.

Model Selection by Task

# Use Haiku for cheap, fast exploration tasks
claude --model haiku "find all files that import from auth module"

# Use Sonnet for most production tasks (best balance)
claude --model sonnet "refactor the payment service"

# Use Opus only for very complex reasoning
claude --model opus "design the new event sourcing architecture"

Log Everything in CI/CD

claude -p "..." \
  --output-format json \
  --max-turns 15 2>&1 | tee agent_log_$(date +%Y%m%d).json

Review these logs periodically for common errors and use them to improve CLAUDE.md.

The Meta-Loop (Advanced)

# Analyze what other Claude instances got stuck on, then fix it
cat ~/.claude/projects/*/logs/*.json | \
  claude -p "see what the other Claude sessions got stuck on and improve our CLAUDE.md"

Security Considerations

Known Risks

  • Supply chain attacks โ€” malicious skills and MCP servers exist. Only use vetted community tools.
  • MCP server access โ€” MCP servers can read and write your codebase by default. Scope their permissions.
  • Prompt injection โ€” content Claude reads (files, web pages) can contain instructions trying to hijack Claude’s behavior.
  • Context leakage โ€” Claude may inadvertently expose secrets from files it reads.

Security Checklist

# 1. Explicitly deny dangerous operations
{
  "permissions": {
    "deny": ["Bash(rm -rf *)", "Bash(sudo *)", "Write(.env*)"]
  }
}

# 2. Use --allowedTools in CI/CD to whitelist only what's needed
claude -p "..." --allowedTools "Read,Grep,Glob"

# 3. Never use --dangerously-skip-permissions in any shared environment

# 4. Audit installed MCP servers regularly
claude mcp list

# 5. Scope MCP permissions โ€” not every server needs Write access

Preventing .env Access

{
  "permissions": {
    "deny": ["Read(.env*)", "Write(.env*)", "Read(**/.env*)"]
  }
}

Quick Reference Cheat Sheet

CLI

claude                          # New session
claude "task"                   # New session with prompt
claude -p "task"                # One-shot, exit when done
claude -c                       # Continue last session
claude --resume                 # Pick session to resume
claude --model sonnet           # Set model
claude --allowedTools "Read,Write"   # Pre-approve tools
claude --permission-mode plan   # Plan-only mode
claude --append-system-prompt "..."  # Add to system prompt
claude --agent MyAgent          # Use specific sub-agent
claude --worktree feature-x     # Isolated git worktree

In-Session

SHIFT+TAB    โ†’ cycle modes
ESC          โ†’ cancel generation
ESC+ESC      โ†’ undo last action
CTRL+B       โ†’ background task
CTRL+O       โ†’ verbose toggle
/compact     โ†’ summarize + clear
/clear       โ†’ clear context
/model       โ†’ switch model
/context     โ†’ check usage %
/mcp         โ†’ manage MCP servers
/permissions โ†’ update permissions

Files

CLAUDE.md                     โ†’ project instructions (commit)
CLAUDE.local.md               โ†’ personal instructions (gitignore)
.claude/settings.json         โ†’ shared settings (commit)
.claude/settings.local.json   โ†’ personal settings (gitignore)
.mcp.json                     โ†’ MCP servers (commit)
.claude/commands/             โ†’ custom slash commands
.claude/agents/               โ†’ sub-agent definitions
.claude/skills/               โ†’ auto-activated skills
.claude/hooks/                โ†’ hook scripts
~/.claude/CLAUDE.md           โ†’ global instructions (all projects)

Context Rules of Thumb

< 70%  โ†’ work freely
70-90% โ†’ /compact now
90%+   โ†’ /clear mandatory
switching tasks โ†’ /clear

MCP Tool Pattern

mcp__<server>__<tool>
mcp__github__create_issue
mcp__postgres__query
mcp__filesystem__read_file

Part 2: Programmatically using it

Claude is a family of large language models developed by Anthropic. Focus of each:

  • OpenAI focuses on capability maximization
  • Google scale-first
  • Anthropic’s focuses safety-first AI development.

Ways to Access Claude

Anthropic Interfaces

  • Claude.ai โ€” consumer web/mobile/desktop chat interface
  • Claude for mobile devices โ€” native Android/iOS app
  • Claude Desktop App โ€” native macOS and Windows app

Developer Tools

  • Anthropic API โ€” direct API access for building applications
  • Claude Code โ€” agentic CLI for software development
  • Claude Code for IDEs - VS Code, IntelliJ, PyCharm and other JetBrains IDEs

Embedded Product Integrations

  • Claude in Browsers โ€” browser-based browsing agent
  • Claude in Excel/PowerPoint
  • Claude Code for Slack โ€” Claude accessible within Slack workspaces
  • Cowork โ€” desktop tool for non-developers to automate file and task management

Third-Party Cloud Providers

  • Amazon Bedrock โ€” Claude models via AWS
  • Google Cloud Vertex AI โ€” Claude models via GCP

Ecosystem / Third-Party Apps

Various platforms building on the Anthropic API, including tools like Cursor, Notion, Perplexity, and more.

Key Strengths of Claude

  • Large Token context window
  • Native PDF and document understanding
  • Strong instruction following and structured output
  • Excellent at code generation and reasoning
  • Unique Extended Thinking capability
  • Strong multilingual performance

AI Model Context Window Comparison (April 2026)

To understand 1 Million tokens - think of entire Harry Potter series its almost ~1.08M Tokens. 1 Million Tokens is approx ~3000 pages.

ModelProviderContext WindowHow They Achieve It
Llama 4 ScoutMeta10M tokensMixture-of-Experts (17B active / 109B total params); open-weight, self-hosted
Gemini 1.5 ProGoogle2M tokensEfficient attention scaling; optimized for retrieval over synthesis
Claude Opus 4.6Anthropic1M tokensConstitutional AI architecture; strong recall & reasoning at depth
GPT-5.4OpenAI1M tokensLarge dense model with extended attention; Codex-tier access
Gemini 3.1 ProGoogle1M tokensNative multimodal attention across text, image, audio, video
Qwen 3.6 PlusAlibaba1M tokensSparse MoE transformer; cost-efficient at scale
Grok 4.20xAI2M tokensHigh-throughput transformer with extended positional encoding
Gemini 3.1 FlashGoogle200K tokensDistilled Flash architecture; optimized for speed and low latency
Claude Sonnet 4.6Anthropic200K tokensBalanced compute/quality; strong instruction-following
Claude Haiku 4.5Anthropic200K tokensLightweight; optimized for fast, high-volume tasks
GPT-4oOpenAI128K tokensDense transformer with rotary position embeddings
Perplexity SonarPerplexity200K tokensRAG-augmented; retrieval offsets context limits

Constitutional AI โ€” How Claude Thinks

This is the most important Claude-specific concept. Claude is not just RLHF-trained โ€” it uses Constitutional AI (CAI), Anthropic’s proprietary alignment approach.

How Constitutional AI Works

Step 1 โ€” Supervised Learning: Claude is trained on human-generated data (like other LLMs).

Step 2 โ€” Self-Critique via a Constitution: A set of principles (the “constitution”) is used to have Claude critique its own outputs. For example:

“Does this response help someone do something harmful? If so, rewrite it.”

Step 3 โ€” RLHF from AI Feedback (RLAIF): Instead of only using human feedback, Claude uses AI-generated feedback based on the constitution. This scales alignment without needing infinite human labelers.

The Three Core Principles (HHH)

PrincipleWhat It Means
HelpfulActually useful to the human, not watered-down or overly cautious
HarmlessAvoids enabling physical, psychological, or societal harm
HonestTruthful, calibrated in uncertainty, non-deceptive

Why This Matters for Engineers

  • Claude will push back on instructions that violate its values โ€” design with this, not against it
  • Claude’s refusals are more consistent and principled than other models
  • You can rely on Claude not sycophantically agreeing with wrong answers
  • Constitutional values are internalized, not just surface-level filters

Claude Model Families

As of 2025โ€“2026, Claude models are organized into families. The current generation is Claude 4.

Current Models (Claude 4 Family)

ModelBest ForSpeedCost
Claude Opus 4Complex reasoning, research, hard problemsSlowHighest
Claude Sonnet 4Production apps, balanced intelligence + speedMediumMedium
Claude Haiku 4High-volume, simple tasks, real-time responsesFastestLowest

Model String IDs (for LangChain)

claude-opus-4-6         # Opus 4
claude-sonnet-4-6       # Sonnet 4 (most common in production)
claude-haiku-4-5-20251001  # Haiku 4

How to Choose

Need deep reasoning or complex analysis? โ†’ Opus
Building a production app with real users? โ†’ Sonnet (default choice)
High-volume, classification, simple Q&A? โ†’ Haiku
Streaming chatbot, real-time features? โ†’ Haiku or Sonnet

Older Generations (Still Available)

  • Claude 3 family: Opus 3, Sonnet 3.5, Haiku 3 โ€” still widely used
  • Claude 2 โ€” largely deprecated, avoid for new projects

Using Claude with LangChain

Installation

pip install -U langchain-anthropic langgraph

Current latest: langchain-anthropic==1.4.1

Basic Call

from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(
    model="claude-sonnet-4-6",
    # api_key="sk-ant-..."  # or set ANTHROPIC_API_KEY env var
    max_tokens=1024
)

# Modern style: pass tuples directly โ€” no need to import message classes
messages = [
    ("system", "You are a senior Python engineer."),
    ("human", "Explain async/await in Python"),
]

response = llm.invoke(messages)
print(response.content)

Key Differences from Raw Anthropic SDK

FeatureRaw Anthropic SDKLangChain (ChatAnthropic)
System promptTop-level system param("system", "...") tuple or SystemMessage
Response accessresponse.content[0].textresponse.content (string)
Streamingclient.messages.stream(...)for chunk in llm.stream(...)
ChainingManual| operator with LCEL
MemoryManual history managementLangGraph checkpointer
Structured outputManual JSON parsingllm.with_structured_output(MyModel)
Tool callingManual loopllm.bind_tools([...])

Tip: You can pass messages as plain tuples ("system", "...") / ("human", "...") โ€” no need to import SystemMessage / HumanMessage for basic usage.

Multi-Turn Conversations

The modern approach uses LangGraph with a checkpointer โ€” this replaces the older RunnableWithMessageHistory pattern:

from langchain_anthropic import ChatAnthropic
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=512)

# Build a minimal stateful graph
def call_model(state: MessagesState):
    response = llm.invoke(state["messages"])
    return {"messages": response}

workflow = StateGraph(state_schema=MessagesState)
workflow.add_edge(START, "model")
workflow.add_node("model", call_model)

app = workflow.compile(checkpointer=MemorySaver())

# Each invocation with the same thread_id shares memory
config = {"configurable": {"thread_id": "user-1"}}

# Turn 1
app.invoke({"messages": [("human", "My name is Alex")]}, config=config)

# Turn 2 โ€” Claude remembers Alex
result = app.invoke({"messages": [("human", "What's my name?")]}, config=config)
print(result["messages"][-1].content)

The older RunnableWithMessageHistory still works but LangGraph is the recommended approach for new projects.


Prompt Engineering for Claude

Claude is specifically trained to respond well to certain prompt patterns.

XML Tags โ€” Claude’s Superpower

Claude is explicitly trained to parse and respect XML structure. Use ChatPromptTemplate to keep this clean:

from langchain_core.prompts import ChatPromptTemplate
from langchain_anthropic import ChatAnthropic

prompt = ChatPromptTemplate.from_messages([
    ("system", """
<role>You are a senior data engineer at a fintech company.</role>
<constraints>
  - Focus only on indexing and query plan issues
  - Return your answer in JSON format
  - Do not suggest schema changes
</constraints>
"""),
    ("human", """
<task>Analyze the SQL query below and identify performance bottlenecks.</task>
<query>{query}</query>
""")
])

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)
chain = prompt | llm

response = chain.invoke({"query": "SELECT * FROM transactions WHERE user_id = 123 ORDER BY created_at DESC;"})
print(response.content)

Few-Shot Prompting

from langchain_core.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate
from langchain_anthropic import ChatAnthropic

examples = [
    {"input": "gonna grab some coffee real quick",
     "output": "I will briefly step away to get some coffee."},
    {"input": "can u fix this bug asap",
     "output": "Could you please resolve this bug at your earliest convenience?"},
]

example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}"),
])

few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

final_prompt = ChatPromptTemplate.from_messages([
    ("system", "Convert each sentence to formal English."),
    few_shot_prompt,
    ("human", "{input}"),
])

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=256)
chain = final_prompt | llm
response = chain.invoke({"input": "lemme know when ur done"})
print(response.content)

Chain of Thought

from langchain_core.prompts import ChatPromptTemplate
from langchain_anthropic import ChatAnthropic

prompt = ChatPromptTemplate.from_messages([
    ("human", """
Solve this problem step by step, showing your reasoning at each stage.

Problem: {problem}
""")
])

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)
chain = prompt | llm

response = chain.invoke({
    "problem": "A train travels 120km at 60km/h, then 80km at 40km/h. What is the average speed?"
})
print(response.content)

Structured Output with Pydantic

LangChain makes structured output very clean via .with_structured_output():

from langchain_anthropic import ChatAnthropic
from pydantic import BaseModel

class ExtractedData(BaseModel):
    name: str
    email: str | None
    sentiment: str   # "positive" | "negative" | "neutral"
    priority: int    # 1-5

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=512)
structured_llm = llm.with_structured_output(ExtractedData)

result = structured_llm.invoke(
    "Hi, I'm Sarah (sarah@email.com). I'm very frustrated with the billing issue and need this fixed ASAP."
)
print(result.name)       # Sarah
print(result.sentiment)  # negative
print(result.priority)   # 5

Tool Use & Function Calling

Defining Tools with LangChain

The cleanest modern approach uses Annotated type hints on plain functions โ€” no @tool decorator needed for bind_tools:

from typing_extensions import Annotated
from langchain_anthropic import ChatAnthropic

def get_weather(
    city: Annotated[str, "The city name, e.g. 'Sydney' or 'New York'"],
    unit: Annotated[str, "Temperature unit: 'celsius' or 'fahrenheit'"] = "celsius",
) -> str:
    """Get current weather for a specific city."""
    return f"The weather in {city} is 22ยฐ{unit[0].upper()} and sunny."

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)
llm_with_tools = llm.bind_tools([get_weather])

response = llm_with_tools.invoke("What's the weather in Sydney?")
print(response.tool_calls)

Add strict=True to guarantee schema-compliant inputs โ€” prevents type mismatches like passengers: "2" instead of passengers: 2:

llm_with_tools = llm.bind_tools([get_weather], strict=True)
# Requires langchain-anthropic>=1.1.0 and Claude Sonnet 4.5+ or Opus 4.1+

Full Agent Loop with LangGraph

For production agents, LangGraph is the recommended approach:

from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent

@tool
def get_weather(city: str) -> str:
    """Get current weather for a city."""
    return f"22ยฐC and sunny in {city}"

@tool
def search_web(query: str) -> str:
    """Search the web for current information."""
    return f"Search results for: {query}"

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)
agent = create_react_agent(llm, tools=[get_weather, search_web])

result = agent.invoke({"messages": [("user", "What's the weather in Sydney?")]})
print(result["messages"][-1].content)

Extended Thinking

Claude’s most unique capability โ€” it can expose its internal reasoning chain before answering.

What It Is

Extended Thinking allows Claude to spend tokens “thinking” before formulating its final answer. This is built into the model at a fundamental level โ€” not just prompt-level chain-of-thought.

When to Use It

  • Complex math or logic problems
  • Multi-step reasoning tasks
  • Hard coding challenges
  • Any situation where accuracy matters more than speed/cost

How to Enable It in LangChain

from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

llm = ChatAnthropic(
    model="claude-opus-4-6",   # Works best on Opus
    max_tokens=16000,
    thinking={"type": "enabled", "budget_tokens": 10000}
)

response = llm.invoke([
    HumanMessage(content="Prove that the square root of 2 is irrational.")
])

# Response content may contain thinking blocks
for block in response.content:
    if isinstance(block, dict):
        if block.get("type") == "thinking":
            print("CLAUDE'S REASONING:\n", block["thinking"])
        elif block.get("type") == "text":
            print("FINAL ANSWER:\n", block["text"])

Budget Tokens

  • Minimum: 1,000 tokens
  • Recommended for hard problems: 5,000โ€“15,000 tokens
  • Higher budget = more thorough reasoning = better accuracy (but higher cost)

Vision, Images & Native PDF Support

Sending Images

import base64
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

with open("chart.png", "rb") as f:
    image_data = base64.b64encode(f.read()).decode("utf-8")

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)

message = HumanMessage(content=[
    {
        "type": "image_url",
        "image_url": {"url": f"data:image/png;base64,{image_data}"}
    },
    {
        "type": "text",
        "text": "Describe what's in this chart and identify the trend."
    }
])

response = llm.invoke([message])
print(response.content)

Supported Image Formats

  • JPEG, PNG, GIF, WebP
  • Max size: 5MB per image
  • Max images per request: 20

Native PDF Support (Claude-Specific)

Claude reads PDFs natively, including preserving layout context โ€” other LLMs require you to extract text first.

import base64
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

with open("report.pdf", "rb") as f:
    pdf_data = base64.b64encode(f.read()).decode("utf-8")

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=2048)

message = HumanMessage(content=[
    {
        "type": "document",
        "source": {
            "type": "base64",
            "media_type": "application/pdf",
            "data": pdf_data
        }
    },
    {"type": "text", "text": "Summarize the key findings from this report."}
])

response = llm.invoke([message])
print(response.content)

Prompt Caching

A Claude-specific feature that dramatically reduces cost and latency for repeated large contexts.

How It Works

When you send the same large context (system prompt, documents, etc.) repeatedly, Claude caches it server-side and charges significantly less for subsequent requests.

Cache Pricing

Token TypeCost vs Normal
Cache write~25% more than normal
Cache read~90% less than normal

Break-even: After just ~2 reads, you save money overall.

How to Enable Caching in LangChain

from langchain_anthropic import ChatAnthropic
from langchain_core.messages import SystemMessage, HumanMessage

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)

# Mark large system prompt for caching using extra_headers or beta flag
# LangChain passes cache_control through the `additional_kwargs` on messages

system_msg = SystemMessage(
    content=[{
        "type": "text",
        "text": "You are an expert on our 500-page company policy document.\n[... very long content ...]",
        "cache_control": {"type": "ephemeral"}   # โ† Mark for caching
    }]
)

response = llm.invoke([
    system_msg,
    HumanMessage(content="What is our vacation policy?")
])
print(response.content)

Best Use Cases

  • Long system prompts (> 1024 tokens) used repeatedly
  • RAG: caching retrieved documents for a session
  • Code review tools: caching the entire codebase
  • Customer support bots: caching product documentation

Cache Lifetime

  • Ephemeral cache: lasts 5 minutes after last use

Memory & Context Management

Claude has no built-in persistent memory. LangChain provides abstractions for this.

Context Window: 200K Tokens

200,000 tokens โ‰ˆ 150,000 words โ‰ˆ ~400 pages of text

The “Lost in the Middle” Problem

Claude (like all LLMs) performs best when important information is at the beginning or end of the context. Information buried in the middle may be ignored.

Best practice: Put critical instructions at both the top AND bottom of your prompt.

Strategies for Long Conversations

1. LangGraph with MemorySaver (recommended):

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph

# LangGraph automatically trims/manages history via the checkpointer
app = workflow.compile(checkpointer=MemorySaver())

2. Trim messages manually in the graph:

from langchain_core.messages import trim_messages

def call_model(state: MessagesState):
    trimmed = trim_messages(state["messages"], max_tokens=4000, token_counter=llm)
    response = llm.invoke(trimmed)
    return {"messages": response}

3. Summarization โ€” Compact old history:

from langchain_core.prompts import ChatPromptTemplate

summarize_prompt = ChatPromptTemplate.from_messages([
    ("human", """
Summarize the following conversation into bullet points,
preserving all key facts, decisions, and user preferences:

{conversation}
""")
])

summary_chain = summarize_prompt | llm
summary = summary_chain.invoke({"conversation": old_conversation_text})

4. External Memory โ€” Use a vector database (Pinecone, Weaviate, pgvector) for long-term memory across sessions.


RAG with Claude + LangChain

LangChain’s ecosystem makes RAG very straightforward with Claude.

Basic RAG Pattern

from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_community.vectorstores import FAISS
from langchain_anthropic import AnthropicEmbeddings  # or use OpenAI embeddings

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)

# Build retriever from your documents
vectorstore = FAISS.load_local("my_index", embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})

prompt = ChatPromptTemplate.from_messages([
    ("system", """You are a helpful assistant. Answer questions based ONLY on the
provided context. If the answer isn't in the context, say "I don't have that information."
Always cite which part of the context you used."""),
    ("human", """
<context>
{context}
</context>

<question>
{question}
</question>
""")
])

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
)

response = rag_chain.invoke("What is our vacation policy?")
print(response.content)

Claude RAG Advantages

  • 200K context = you can stuff more documents without chunking
  • Native PDF = skip the text extraction step entirely
  • Prompt caching = cache your retrieved docs across a session cheaply

Streaming

from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)

for chunk in llm.stream([("human", "Write a short story about a robot.")]):
    print(chunk.text, end="", flush=True)

Async Streaming

async for chunk in llm.astream([("human", "Tell me a joke.")]):
    print(chunk.text, end="", flush=True)

Streaming in a Chain

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([("human", "{input}")])
chain = prompt | llm

for chunk in chain.stream({"input": "Tell me a joke."}):
    print(chunk.text, end="", flush=True)

Batch Processing

LangChain supports batching natively via .batch(), and you can also use the Anthropic Batch API for large-scale async workloads (~50% cost reduction).

LangChain Native Batch

from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=512)

docs = ["Summary of doc 1...", "Summary of doc 2...", "Summary of doc 3..."]
messages_batch = [[HumanMessage(content=f"Summarize: {doc}")] for doc in docs]

results = llm.batch(messages_batch)
for r in results:
    print(r.content)

Anthropic Batch API (via SDK, for 10K+ requests)

For very large offline workloads, drop down to the raw SDK for Batch API access:

import anthropic
import time

client = anthropic.Anthropic()

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"doc-{i:03d}",
            "params": {
                "model": "claude-sonnet-4-6",
                "max_tokens": 512,
                "messages": [{"role": "user", "content": f"Summarize: {doc}"}]
            }
        }
        for i, doc in enumerate(docs)
    ]
)

# Poll until complete
while True:
    batch = client.messages.batches.retrieve(batch.id)
    if batch.processing_status == "ended":
        break
    time.sleep(60)

for result in client.messages.batches.results(batch.id):
    print(f"{result.custom_id}: {result.result.message.content[0].text}")

Claude Code & CLI

Claude Code is an agentic coding tool that runs in your terminal and can read, write, and execute code autonomously.

Installation

npm install -g @anthropic-ai/claude-code
claude  # Start a session

Key CLI Commands

claude                          # Start new session
claude "fix the login bug"      # Start with initial prompt
claude -p "explain this code"   # One-shot query, then exit
claude -c                       # Continue most recent session
claude --model opus             # Use specific model
claude --allowedTools "Read" "Write"   # Skip permission dialogs for these
claude --dangerously-skip-permissions  # Skip ALL permission dialogs (careful!)

Key In-Session Shortcuts

ShortcutAction
SHIFT + TABSwitch modes (default / write / plan)
CTRL + CCancel current input
ESCCancel generation (can inject new prompt)
ESC + ESCUndo last action
CTRL + BMove task to background
/compactSummarize and clear context
/modelSwitch model mid-session
/clearClear context window

CLAUDE.md โ€” Project Instructions File

Create a CLAUDE.md in your project root to give Claude persistent instructions:

# Project: E-Commerce API

## Stack

- Python 3.12 + FastAPI
- PostgreSQL with SQLAlchemy ORM
- Redis for caching

## Conventions

- All endpoints must have type hints
- Use snake_case for variable names
- Write tests for every new function in /tests

## DO NOT

- Modify .env files
- Delete migration files
- Change database schema without asking first

MCP โ€” Model Context Protocol

Anthropic’s open standard for connecting Claude to external tools, data sources, and services. Think of it as a universal plugin system for LLMs.

What It Solves

Without MCP, every tool integration is custom-built. With MCP, any Claude client can connect to any MCP-compliant server using a standard protocol.

Architecture

Claude Client (Claude.ai / Claude Code / Your App)
        โ†• MCP Protocol
MCP Server (exposes tools + resources)
        โ†•
External Service (GitHub, Slack, Databases, APIs...)

MCP Concepts

ConceptDescription
MCP ServerA service that exposes tools and resources via the MCP protocol
ToolsFunctions Claude can call (e.g., create_issue, send_slack_message)
ResourcesData Claude can read (e.g., files, database records)
PromptsPre-built prompt templates exposed by the server

Using MCP in LangChain

As of langchain-anthropic>=0.3.9, Remote MCP is built directly into ChatAnthropic โ€” no separate adapter package needed:

from langchain_anthropic import ChatAnthropic
from langgraph.prebuilt import create_react_agent

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1000)

# Attach remote MCP servers directly to the model
llm_with_mcp = llm.bind_tools([{
    "type": "mcp",
    "server_label": "github",
    "server_url": "https://github.mcp.server/sse",
    "headers": {"Authorization": "Bearer your-token"},
    "allowed_tools": ["create_issue", "search_repositories"],
}])

response = llm_with_mcp.invoke(
    "Create a GitHub issue for the login bug we discussed"
)
print(response.content)

For local (stdio) MCP servers or complex multi-server setups, use the langchain-mcp-adapters package:

# pip install langchain-mcp-adapters
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

async def run_mcp_agent():
    async with MultiServerMCPClient({
        "github": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-github"],
            "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"},
            "transport": "stdio",
        }
    }) as client:
        tools = client.get_tools()
        llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1000)
        agent = create_react_agent(llm, tools)
        result = await agent.ainvoke({
            "messages": [("user", "Create a GitHub issue for the login bug")]
        })
        print(result["messages"][-1].content)
  • GitHub, GitLab
  • Slack, Gmail, Google Calendar
  • Notion, Confluence
  • PostgreSQL, SQLite
  • Filesystem, Web Search, Browser automation

Agents & Agentic Workflows

LangGraph is the recommended framework for production Claude agents.

Core Agent Loop with LangGraph

from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=4096)

@tool
def read_file(path: str) -> str:
    """Read the contents of a file."""
    with open(path) as f:
        return f.read()

@tool
def write_file(path: str, content: str) -> str:
    """Write content to a file."""
    with open(path, "w") as f:
        f.write(content)
    return f"Written to {path}"

@tool
def run_tests() -> str:
    """Run the test suite."""
    import subprocess
    result = subprocess.run(["pytest", "-v"], capture_output=True, text=True)
    return result.stdout + result.stderr

agent = create_react_agent(llm, tools=[read_file, write_file, run_tests])
result = agent.invoke({"messages": [("user", "Fix the failing tests in test_auth.py")]})
print(result["messages"][-1].content)

Multi-Agent Architecture

from langchain_anthropic import ChatAnthropic

# Use different models for different agent roles
research_llm = ChatAnthropic(model="claude-haiku-4-5-20251001", max_tokens=1024)   # Fast, cheap
code_llm     = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=4096)           # Balanced
review_llm   = ChatAnthropic(model="claude-opus-4-6", max_tokens=2048)             # Thorough

# Wire into a LangGraph multi-agent workflow
# (see LangGraph docs for full multi-agent patterns)

Best Practices for Agents

  1. Give Claude a way to ask clarifying questions before starting long tasks
  2. Build in checkpoints โ€” have Claude summarize progress periodically
  3. Set clear success criteria in the initial prompt
  4. Use Opus for planning, lighter models for execution
  5. Log everything โ€” agentic tasks can fail in unexpected ways
  6. Implement human-in-the-loop for irreversible actions (deleting, sending emails, etc.)

Safety, Guardrails & Refusals

What Claude Won’t Do

Claude will refuse to:

  • Generate content that enables mass harm (bioweapons, CSAM, etc.)
  • Help with clearly illegal activities targeting real people
  • Impersonate real individuals deceptively

What Claude Will Do That Others Won’t

Claude is notably less over-cautious than many competitors. It can:

  • Discuss sensitive historical events in depth
  • Help with security research and penetration testing
  • Write morally complex fiction
  • Give direct medical/legal information (with appropriate caveats)

Designing Around Refusals

# Bad โ€” vague, triggers caution
llm.invoke("Help me hack into a system")

# Good โ€” clear professional context
from langchain_core.messages import SystemMessage, HumanMessage

llm.invoke([
    SystemMessage(content="You are a security engineer assistant supporting authorized penetration testing."),
    HumanMessage(content="""
I'm doing an authorized penetration test on our own infrastructure.
I need to understand common SQL injection patterns to test our input validation.
Please show examples with explanations.
""")
])

Adding Your Own Guardrails

from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=1024)

prompt = ChatPromptTemplate.from_messages([
    ("system", """
You are a customer support agent for AcmeCorp.

STRICT RULES:
- Only answer questions about AcmeCorp products
- Never discuss competitors
- If asked about anything outside scope, say:
  "I can only help with AcmeCorp product questions."
- If the user becomes abusive, respond once with a warning then end the conversation politely
"""),
    ("human", "{user_input}")
])

chain = prompt | llm

Production Best Practices

Retry Logic

ChatAnthropic has built-in retry via max_retries โ€” no external library needed:

from langchain_anthropic import ChatAnthropic

# Built-in: retries automatically on rate limits and transient errors
llm = ChatAnthropic(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    max_retries=3,      # default is 2 (mirrors Anthropic SDK default)
    timeout=60,
)

For more complex retry strategies you can also use .with_retry():

import anthropic

llm_with_retry = llm.with_retry(
    retry_if_exception_type=(anthropic.RateLimitError,),
    stop_after_attempt=3
)

Structured Output Validation

from langchain_anthropic import ChatAnthropic
from pydantic import BaseModel, field_validator

class ExtractedData(BaseModel):
    name: str
    email: str | None
    sentiment: str
    priority: int

    @field_validator("priority")
    def priority_range(cls, v):
        assert 1 <= v <= 5, "Priority must be 1-5"
        return v

llm = ChatAnthropic(model="claude-sonnet-4-6", max_tokens=512)
structured_llm = llm.with_structured_output(ExtractedData)

result = structured_llm.invoke(
    "Hi, I'm Sarah (sarah@email.com). I'm frustrated with billing and need this fixed ASAP."
)
print(result)  # ExtractedData(name='Sarah', email='sarah@email.com', ...)

Environment Setup

# .env
ANTHROPIC_API_KEY=sk-ant-...
# Load in Python
from dotenv import load_dotenv
load_dotenv()

from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")  # Picks up ANTHROPIC_API_KEY automatically

Rate Limits (Approximate)

TierRPMTPM
Free525,000
Tier 15050,000
Tier 21,000100,000
Tier 44,000400,000

Pricing & Cost Optimization

General Pricing Tiers (per million tokens)

ModelInputOutput
Opus~$15~$75
Sonnet~$3~$15
Haiku~$0.25~$1.25

Always check anthropic.com/pricing for current rates.

Cost Reduction Strategies

  1. Use the right model โ€” Haiku is 60x cheaper than Opus. Use it where quality allows.
  2. Prompt caching โ€” Cache large, repeated contexts (~90% savings on cached tokens)
  3. Batch API โ€” ~50% discount for non-real-time workloads
  4. Limit max_tokens โ€” Set a realistic ceiling, don’t default to 4096 for simple tasks
  5. Compress prompts โ€” Remove unnecessary words in system prompts
  6. Cache at application layer โ€” Store responses for identical inputs (Redis/memcached)

Cost Estimation

# Rough calculation
input_tokens = 1000
output_tokens = 500
sonnet_cost = (input_tokens * 3 + output_tokens * 15) / 1_000_000
# โ‰ˆ $0.0105 per call

Claude vs Other LLMs โ€” Key Differences

FeatureClaude (Anthropic)GPT-4o (OpenAI)Gemini (Google)
Context Window200K128K1M (Gemini 1.5)
Native PDF SupportYesNo (extract first)Yes
Extended ThinkingYesNoYes (Gemini 2.0)
Constitutional AIYesNoNo
Prompt CachingYesYesYes
MCP SupportNativePartialPartial
Code GenerationExcellentExcellentGood
Instruction FollowingBest-in-classVery goodGood
SycophancyLow (pushes back)HigherMedium
LangChain Supportโœ… langchain-anthropicโœ… langchain-openaiโœ… langchain-google-genai

Quick Reference Cheat Sheet

Install:    pip install langchain-anthropic langchain-core
Models:     Opus > Sonnet > Haiku (capability vs speed/cost)
Context:    200K tokens (~150K words)
Init:       ChatAnthropic(model="claude-sonnet-4-6")
Invoke:     llm.invoke([HumanMessage(content="...")])
Stream:     for chunk in llm.stream([...]): print(chunk.content)
Batch:      llm.batch([[HumanMessage(...)], [...]])
Tools:      llm.bind_tools([my_tool])
Structured: llm.with_structured_output(MyPydanticModel)
Retry:      llm.with_retry(stop_after_attempt=3)
Chain:      prompt | llm | output_parser
Agent:      create_react_agent(llm, tools=[...])
Thinking:   ChatAnthropic(..., thinking={"type": "enabled", "budget_tokens": N})
Caching:    Add "cache_control": {"type": "ephemeral"} to message content blocks

Tags :
Share :
comments powered by Disqus