The Complete Guide to Claude Code V2: CLAUDE.md, MCP, Commands, Skills & Hooks β€” Updated Based on Your Feedback

LLMs 485 points 44 comments 6 days ago

**πŸš€ UPDATE: V3 is now live β€” adds LSP, 25+ MCP servers, commands/skills merge, and more.** # The Complete Guide to Claude Code V2: Global CLAUDE.md, MCP Servers, Commands, Skills, Hooks, and Why Single-Purpose Chats Matter ## πŸŽ‰ Updated Based on Community Feedback πŸ“– **NEW: Web version with better formatting** This is V2 of the guide that went viral. Huge thanks to u/headset38, u/tulensrma, u/jcheroske, and everyone who commented. You pointed out that CLAUDE.md rules are suggestions Claude can ignore β€” and you were right. This version adds **Part 7: Skills & Hooks** covering the enforcement layer. **What's new in V2:** - Part 7: Skills & Hooks β€” deterministic enforcement over behavioral suggestion - GitHub repo with ready-to-use templates, hooks, and skills --- **TL;DR:** Your global `~/.claude/CLAUDE.md` is a security gatekeeper that prevents secrets from reaching production AND a project scaffolding blueprint that ensures every new project follows the same structure. MCP servers extend Claude's capabilities exponentially. Context7 gives Claude access to up-to-date documentation. Custom commands and agents automate repetitive workflows. **Hooks enforce rules deterministically** where CLAUDE.md can fail. **Skills package reusable expertise**. And research shows mixing topics in a single chat causes **39% performance degradation** β€” so keep chats focused. --- ## Part 1: The Global CLAUDE.md as Security Gatekeeper ### The Memory Hierarchy Claude Code loads CLAUDE.md files in a specific order: | Level | Location | Purpose | |-------|----------|---------| | **Enterprise** | `/etc/claude-code/CLAUDE.md` | Org-wide policies | | **Global User** | `~/.claude/CLAUDE.md` | Your standards for ALL projects | | **Project** | `./CLAUDE.md` | Team-shared project instructions | | **Project Local** | `./CLAUDE.local.md` | Personal project overrides | Your global file applies to **every single project** you work on. ### What Belongs in Global **1. Identity & Authentication** ```markdown ## GitHub Account **ALWAYS** use **YourUsername** for all projects: - SSH: `git@github.com:YourUsername/<repo>.git` ## Docker Hub Already authenticated. Username in `~/.env` as `DOCKER_HUB_USER` ## Deployment Use Dokploy MCP for production. API URL in `~/.env` ``` **Why global?** You use the same accounts everywhere. Define once, inherit everywhere. **2. The Gatekeeper Rules** ```markdown ## NEVER EVER DO These rules are ABSOLUTE: ### NEVER Publish Sensitive Data - NEVER publish passwords, API keys, tokens to git/npm/docker - Before ANY commit: verify no secrets included ### NEVER Commit .env Files - NEVER commit `.env` to git - ALWAYS verify `.env` is in `.gitignore` ### NEVER Hardcode Credentials - ALWAYS use environment variables ``` ### Why This Matters: Claude Reads Your .env Security researchers discovered that Claude Code **automatically reads `.env` files** without explicit permission. Backslash Security warns: > "If not restricted, Claude can read `.env`, AWS credentials, or `secrets.json` and leak them through 'helpful suggestions.'" Your global CLAUDE.md creates a **behavioral gatekeeper** β€” even if Claude has access, it won't output secrets. ### Defense in Depth | Layer | What | How | |-------|------|-----| | 1 | Behavioral rules | Global CLAUDE.md "NEVER" rules | | 2 | Access control | Deny list in settings.json | | 3 | Git safety | .gitignore | --- ## Part 2: Global Rules for New Project Scaffolding This is where global CLAUDE.md becomes a **project factory**. Every new project you create automatically inherits your standards, structure, and safety requirements. ### The Problem Without Scaffolding Rules Research from project scaffolding experts explains: > "LLM-assisted development fails by silently expanding scope, degrading quality, and losing architectural intent." Without global scaffolding rules: - Each project has different structures - Security files get forgotten (.gitignore, .dockerignore) - Error handling is inconsistent - Documentation patterns vary - You waste time re-explaining the same requirements ### The Solution: Scaffolding Rules in Global CLAUDE.md Add a "New Project Setup" section to your global file: ```markdown ## New Project Setup When creating ANY new project, ALWAYS do the following: ### 1. Required Files (Create Immediately) - `.env` β€” Environment variables (NEVER commit) - `.env.example` β€” Template with placeholder values - `.gitignore` β€” Must include: .env, .env.*, node_modules/, dist/, .claude/ - `.dockerignore` β€” Must include: .env, .git/, node_modules/ - `README.md` β€” Project overview (reference env vars, don't hardcode) ### 2. Required Directory Structure ``` project-root/ β”œβ”€β”€ src/ # Source code β”œβ”€β”€ tests/ # Test files β”œβ”€β”€ docs/ # Documentation (gitignored for generated docs) β”œβ”€β”€ .claude/ # Claude configuration β”‚ β”œβ”€β”€ commands/ # Custom slash commands β”‚ └── settings.json # Project-specific settings └── scripts/ # Build/deploy scripts ``` ### 3. Required .gitignore Entries ``` # Environment .env .env.* .env.local # Dependencies node_modules/ vendor/ __pycache__/ # Build outputs dist/ build/ .next/ # Claude local files .claude/settings.local.json CLAUDE.local.md # Generated docs docs/*.generated.* ``` ### 4. Node.js Projects β€” Required Error Handling Add to entry point (index.ts, server.ts, app.ts): ```javascript process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); process.exit(1); }); process.on('uncaughtException', (error) => { console.error('Uncaught Exception:', error); process.exit(1); }); ``` ### 5. Required CLAUDE.md Sections Every project CLAUDE.md must include: - Project overview (what it does) - Tech stack - Build commands - Test commands - Architecture overview ``` ### Why This Works When you tell Claude "create a new Node.js project," it reads your global CLAUDE.md first and **automatically**: 1. Creates `.env` and `.env.example` 2. Sets up proper `.gitignore` with all required entries 3. Creates the directory structure 4. Adds error handlers to the entry point 5. Generates a project CLAUDE.md with required sections **You never have to remember these requirements again.** ### Advanced: Framework-Specific Rules ```markdown ## Framework-Specific Setup ### Next.js Projects - Use App Router (not Pages Router) - Create `src/app/` directory structure - Include `next.config.js` with strict mode enabled - Add analytics to layout.tsx ### Python Projects - Create `pyproject.toml` (not setup.py) - Use `src/` layout - Include `requirements.txt` AND `requirements-dev.txt` - Add `.python-version` file ### Docker Projects - Multi-stage builds ALWAYS - Never run as root (use non-root user) - Include health checks - `.dockerignore` must mirror `.gitignore` + include `.git/` ``` ### Quality Gates in Scaffolding The claude-project-scaffolding approach adds enforcement: ```markdown ## Quality Requirements ### File Size Limits - No file > 300 lines (split if larger) - No function > 50 lines ### Required Before Commit - All tests pass - TypeScript compiles with no errors - Linter passes with no warnings - No secrets in staged files ### CI/CD Requirements Every project must include: - `.github/workflows/ci.yml` for GitHub Actions - Pre-commit hooks via Husky (Node.js) or pre-commit (Python) ``` ### Example: What Happens When You Create a Project **You say:** "Create a new Next.js e-commerce project called shopify-clone" **Claude reads global CLAUDE.md and automatically creates:** ``` shopify-clone/ β”œβ”€β”€ .env ← Created (empty, for secrets) β”œβ”€β”€ .env.example ← Created (with placeholder vars) β”œβ”€β”€ .gitignore ← Created (with ALL required entries) β”œβ”€β”€ .dockerignore ← Created (mirrors .gitignore) β”œβ”€β”€ README.md ← Created (references env vars) β”œβ”€β”€ CLAUDE.md ← Created (with required sections) β”œβ”€β”€ src/ β”‚ └── app/ ← App Router structure β”œβ”€β”€ tests/ β”œβ”€β”€ docs/ β”œβ”€β”€ .claude/ β”‚ β”œβ”€β”€ commands/ β”‚ └── settings.json └── scripts/ ``` **Zero manual setup. Every project starts secure and consistent.** --- ## Part 3: MCP Servers β€” Claude's Integrations MCP (Model Context Protocol) lets Claude interact with external tools and services. ### What MCP Servers Do > "MCP is an open protocol that standardizes how applications provide context to LLMs." MCP servers give Claude: - Access to databases - Integration with APIs - File system capabilities beyond the project - Browser automation - And much more ### Adding MCP Servers ```bash # Add a server claude mcp add <server-name> -- <command> # List servers claude mcp list # Remove a server claude mcp remove <server-name> ``` ### Essential MCP Servers | Server | Purpose | Install | |--------|---------|---------| | **Context7** | Live documentation | `claude mcp add context7 -- npx -y @anthropic-ai/context7-mcp` | | **Playwright** | Browser testing | `claude mcp add playwright -- npx -y @anthropic-ai/playwright-mcp` | | **GitHub** | Repo management | `claude mcp add github -- npx -y @modelcontextprotocol/server-github` | | **PostgreSQL** | Database queries | `claude mcp add postgres -- npx -y @modelcontextprotocol/server-postgres` | | **Filesystem** | Extended file access | `claude mcp add fs -- npx -y @anthropic-ai/filesystem-mcp` | ### MCP in CLAUDE.md Document required MCP servers in your global file: ```markdown ## Required MCP Servers These MCP servers must be installed for full functionality: ### context7 Live documentation access for all libraries. Install: `claude mcp add context7 -- npx -y @anthropic-ai/context7-mcp` ### playwright Browser automation for testing. Install: `claude mcp add playwright -- npx -y @anthropic-ai/playwright-mcp` ``` --- ## Part 4: Context7 β€” Live Documentation Context7 is a game-changer. It gives Claude access to **up-to-date documentation** for any library. ### The Problem Claude's training data has a cutoff. When you ask about: - A library released after training - Recent API changes - New framework features Claude might give outdated or incorrect information. ### The Solution Context7 fetches live documentation: ``` You: "Using context7, show me how to use the new Next.js 15 cache API" Claude: *fetches current Next.js docs* *provides accurate, up-to-date code* ``` ### Installation ```bash claude mcp add context7 -- npx -y @anthropic-ai/context7-mcp ``` ### Usage Patterns | Pattern | Example | |---------|---------| | Explicit | "Using context7, look up Prisma's createMany" | | Research | "Check context7 for React Server Components patterns" | | Debugging | "Use context7 to find the correct Tailwind v4 syntax" | ### Add to Global CLAUDE.md ```markdown ## Documentation Lookup When unsure about library APIs or recent changes: 1. Use Context7 MCP to fetch current documentation 2. Prefer official docs over training knowledge 3. Always verify version compatibility ``` --- ## Part 5: Custom Commands and Sub-Agents Slash commands are reusable prompts that automate workflows. ### Creating Commands Commands live in `.claude/commands/` as markdown files: **`.claude/commands/fix-types.md`:** ```markdown --- description: Fix TypeScript errors --- Run `npx tsc --noEmit` and fix any type errors. For each error: 1. Identify the root cause 2. Fix with minimal changes 3. Verify the fix compiles After fixing all errors, run the check again to confirm. ``` **Use it:** ``` /fix-types ``` ### Benefits of Commands | Benefit | Description | |---------|-------------| | **Workflow efficiency** | One word instead of paragraph prompts | | **Team sharing** | Check into git, everyone gets them | | **Parameterization** | Use `$ARGUMENTS` for dynamic input | | **Orchestration** | Commands can spawn sub-agents | ### Sub-Agents Sub-agents run in **isolated context windows** β€” they don't pollute your main conversation. > "Each sub-agent operates in its own isolated context window. This means it can focus on a specific task without getting 'polluted' by the main conversation." ### Global Commands Library Add frequently-used commands to your global config: ```markdown ## Global Commands Store these in ~/.claude/commands/ for use in ALL projects: ### /new-project Creates new project with all scaffolding rules applied. ### /security-check Scans for secrets, validates .gitignore, checks .env handling. ### /pre-commit Runs all quality gates before committing. ### /docs-lookup Spawns sub-agent with Context7 to research documentation. ``` --- ## Part 6: Why Single-Purpose Chats Are Critical This might be the most important section. **Research consistently shows that mixing topics destroys accuracy.** ### The Research Studies on multi-turn conversations found: > "An average **39% performance drop** when instructions are delivered across multiple turns, with models making premature assumptions and failing to course-correct." Chroma Research on context rot: > "As the number of tokens in the context window increases, the model's ability to accurately recall information decreases." Research on context pollution: > "A **2% misalignment early** in a conversation chain can create a **40% failure rate** by the end." ### Why This Happens **1. Lost-in-the-Middle Problem** LLMs recall information best from the **beginning and end** of context. Middle content gets forgotten. **2. Context Drift** Research shows context drift is: > "The gradual degradation or distortion of the conversational state the model uses to generate its responses." As you switch topics, earlier context becomes **noise that confuses** later reasoning. **3. Attention Budget** Anthropic's context engineering guide explains: > "Transformers require nΒ² pairwise relationships between tokens. As context expands, the model's 'attention budget' gets stretched thin." ### What Happens When You Mix Topics ``` Turn 1-5: Discussing authentication system Turn 6-10: Switch to database schema design Turn 11-15: Ask about the auth system again Result: Claude conflates database concepts with auth, makes incorrect assumptions, gives degraded answers ``` The earlier auth discussion is now buried in "middle" context, competing with database discussion for attention. ### The Golden Rule > **"One Task, One Chat"** From context management best practices: > "If you're switching from brainstorming marketing copy to analyzing a PDF, start a new chat. Don't bleed contexts. This keeps the AI's 'whiteboard' clean." ### Practical Guidelines | Scenario | Action | |----------|--------| | New feature | New chat | | Bug fix (unrelated to current work) | `/clear` then new task | | Different file/module | Consider new chat | | Research vs implementation | Separate chats | | 20+ turns elapsed | Start fresh | ### Use `/clear` Liberally ```bash /clear ``` This resets context. Anthropic recommends: > "Use `/clear` frequently between tasks to reset the context window, especially during long sessions where irrelevant conversations accumulate." ### Sub-Agents for Topic Isolation If you need to research something mid-task without polluting your context: ``` Spawn a sub-agent to research React Server Components. Return only a summary of key patterns. ``` The sub-agent works in isolated context and returns just the answer. --- ## Part 7: Skills & Hooks β€” Enforcement Over Suggestion This section was added based on community feedback. Special thanks to u/headset38 and u/tulensrma for pointing out that **Claude doesn't always follow CLAUDE.md rules rigorously**. ### Why CLAUDE.md Rules Can Fail Research on prompt-based guardrails explains: > "Prompts are interpreted at runtime by an LLM that can be convinced otherwise. You need something deterministic." Common failure modes: - **Context window pressure**: Long conversations can push rules out of active attention - **Conflicting instructions**: Other context may override your rules - **Copy-paste propagation**: Even if Claude won't edit `.env`, it might copy secrets to another file One community member noted their PreToolUse hook catches Claude attempting to access `.env` files "a few times per week" β€” despite explicit CLAUDE.md rules saying not to. ### The Critical Difference | Mechanism | Type | Reliability | |-----------|------|-------------| | CLAUDE.md rules | Suggestion | Good, but can be overridden | | **Hooks** | **Enforcement** | **Deterministic β€” always runs** | | settings.json deny list | Enforcement | Good | | .gitignore | Last resort | Only prevents commits | ``` PreToolUse hook blocking .env edits: β†’ Always runs β†’ Returns exit code 2 β†’ Operation blocked. Period. CLAUDE.md saying "don't edit .env": β†’ Parsed by LLM β†’ Weighed against other context β†’ Maybe followed ``` ### Hooks: Deterministic Control Hooks are shell commands that execute at specific lifecycle points. They're not suggestions β€” they're code that runs every time. #### Hook Events | Event | When It Fires | Use Case | |-------|--------------|----------| | `PreToolUse` | Before any tool executes | Block dangerous operations | | `PostToolUse` | After tool completes | Run linters, formatters, tests | | `Stop` | When Claude finishes responding | End-of-turn quality gates | | `UserPromptSubmit` | When user submits prompt | Validate/enhance prompts | | `SessionStart` | New session begins | Load context, initialize | | `Notification` | Claude sends alerts | Desktop notifications | #### Example: Block Secrets Access Add to `~/.claude/settings.json`: ```json { "hooks": { "PreToolUse": [ { "matcher": "Read|Edit|Write", "hooks": [ { "type": "command", "command": "python3 ~/.claude/hooks/block-secrets.py" } ] } ] } } ``` The hook script (`~/.claude/hooks/block-secrets.py`): ```python #!/usr/bin/env python3 """ PreToolUse hook to block access to sensitive files. Exit code 2 = block operation and feed stderr to Claude. """ import json import sys from pathlib import Path SENSITIVE_PATTERNS = { '.env', '.env.local', '.env.production', 'secrets.json', 'secrets.yaml', 'id_rsa', 'id_ed25519', '.npmrc', '.pypirc' } def main(): try: data = json.load(sys.stdin) tool_input = data.get('tool_input', {}) file_path = tool_input.get('file_path') or tool_input.get('path') or '' if not file_path: sys.exit(0) path = Path(file_path) if path.name in SENSITIVE_PATTERNS or '.env' in str(path): print(f"BLOCKED: Access to '{path.name}' denied.", file=sys.stderr) print("Use environment variables instead.", file=sys.stderr) sys.exit(2) # Exit 2 = block and feed stderr to Claude sys.exit(0) except Exception: sys.exit(0) # Fail open if __name__ == '__main__': main() ``` #### Example: Quality Gates on Stop Run linters and tests when Claude finishes each turn: ```json { "hooks": { "Stop": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "~/.claude/hooks/end-of-turn.sh" } ] } ] } } ``` #### Hook Exit Codes | Code | Meaning | |------|---------| | 0 | Success, allow operation | | 1 | Error (shown to user only) | | **2** | **Block operation, feed stderr to Claude** | ### Skills: Packaged Expertise Skills are markdown files that teach Claude how to do something specific β€” like a training manual it can reference on demand. From Anthropic's engineering blog: > "Building a skill for an agent is like putting together an onboarding guide for a new hire." #### How Skills Work **Progressive disclosure** is the key principle: 1. **Startup**: Claude loads only skill *names and descriptions* into context 2. **Triggered**: When relevant, Claude reads the full `SKILL.md` file 3. **As needed**: Additional resources load only when referenced This means you can have dozens of skills installed with minimal context cost. #### Skill Structure ``` .claude/skills/ └── commit-messages/ β”œβ”€β”€ SKILL.md ← Required: instructions + frontmatter β”œβ”€β”€ templates.md ← Optional: reference material └── validate.py ← Optional: executable scripts ``` **SKILL.md** (required): ```markdown --- name: commit-messages description: Generate clear commit messages from git diffs. Use when writing commit messages or reviewing staged changes. --- # Commit Message Skill When generating commit messages: 1. Run `git diff --staged` to see changes 2. Use conventional commit format: `type(scope): description` 3. Keep subject line under 72 characters ## Types - feat: New feature - fix: Bug fix - docs: Documentation - refactor: Code restructuring ``` #### When to Use Skills vs Other Options | Need | Solution | |------|----------| | Project-specific instructions | Project `CLAUDE.md` | | Reusable workflow across projects | **Skill** | | External tool integration | MCP Server | | Deterministic enforcement | **Hook** | | One-off automation | Slash Command | ### Combining Hooks and Skills The most robust setups use both: - A `secrets-handling` **skill** teaches Claude *how* to work with secrets properly - A `PreToolUse` **hook** *enforces* that Claude can never actually read `.env` files ### Updated Defense in Depth | Layer | Mechanism | Type | |-------|-----------|------| | 1 | CLAUDE.md behavioral rules | Suggestion | | **2** | **PreToolUse hooks** | **Enforcement** | | 3 | settings.json deny list | Enforcement | | 4 | .gitignore | Prevention | | **5** | **Skills with security checklists** | **Guidance** | --- ## Putting It All Together ### The Complete Global CLAUDE.md Template ```markdown # Global CLAUDE.md ## Identity & Accounts - GitHub: YourUsername (SSH key: ~/.ssh/id_ed25519) - Docker Hub: authenticated via ~/.docker/config.json - Deployment: Dokploy (API URL in ~/.env) ## NEVER EVER DO (Security Gatekeeper) - NEVER commit .env files - NEVER hardcode credentials - NEVER publish secrets to git/npm/docker - NEVER skip .gitignore verification ## New Project Setup (Scaffolding Rules) ### Required Files - .env (NEVER commit) - .env.example (with placeholders) - .gitignore (with all required entries) - .dockerignore - README.md - CLAUDE.md ### Required Structure project/ β”œβ”€β”€ src/ β”œβ”€β”€ tests/ β”œβ”€β”€ docs/ β”œβ”€β”€ .claude/commands/ └── scripts/ ### Required .gitignore .env .env.* node_modules/ dist/ .claude/settings.local.json CLAUDE.local.md ### Node.js Requirements - Error handlers in entry point - TypeScript strict mode - ESLint + Prettier configured ### Quality Gates - No file > 300 lines - All tests must pass - No linter warnings - CI/CD workflow required ## Framework-Specific Rules [Your framework patterns here] ## Required MCP Servers - context7 (live documentation) - playwright (browser testing) ## Global Commands - /new-project β€” Apply scaffolding rules - /security-check β€” Verify no secrets exposed - /pre-commit β€” Run all quality gates ``` --- ## Quick Reference | Tool | Purpose | Location | |------|---------|----------| | Global CLAUDE.md | Security + Scaffolding | `~/.claude/CLAUDE.md` | | Project CLAUDE.md | Architecture + Commands | `./CLAUDE.md` | | MCP Servers | External integrations | `claude mcp add` | | Context7 | Live documentation | `claude mcp add context7` | | Slash Commands | Workflow automation | `.claude/commands/*.md` | | **Skills** | **Packaged expertise** | `.claude/skills/*/SKILL.md` | | **Hooks** | **Deterministic enforcement** | `~/.claude/settings.json` | | Sub-Agents | Isolated context | Spawn via commands | | `/clear` | Reset context | Type in chat | | `/init` | Generate project CLAUDE.md | Type in chat | --- ## GitHub Repo All templates, hooks, and skills from this guide are available: **github.com/TheDecipherist/claude-code-mastery** What's included: - Complete CLAUDE.md templates (global + project) - Ready-to-use hooks (block-secrets.py, end-of-turn.sh, etc.) - Example skills (commit-messages, security-audit) - settings.json with hooks pre-configured --- ## Sources - Claude Code: Best practices for agentic coding β€” Anthropic - Effective context engineering for AI agents β€” Anthropic - Introducing the Model Context Protocol β€” Anthropic - Equipping agents for the real world with Agent Skills β€” Anthropic - Agent Skills Documentation β€” Claude Code Docs - Hooks Reference β€” Claude Code Docs - Claude Project Scaffolding β€” Madison Hutson - CLAUDE.md Templates β€” Claude-Flow - Context7 MCP Server β€” Upstash - Context Rot Research β€” Chroma - LLMs Get Lost In Multi-Turn Conversation β€” arXiv - Claude Code Security Best Practices β€” Backslash - Claude Code Hooks: Guardrails That Actually Work β€” Paddo.dev - Claude Code Hooks Mastery β€” GitHub - Claude loads secrets without permission β€” Knostic - Slash Commands Documentation β€” Claude Code Docs - Writing a good CLAUDE.md β€” HumanLayer - Context Management Guide β€” Arsturn - CLAUDE.md Best Practices from Prompt Learning β€” Arize --- *What's in your global CLAUDE.md? Share your hooks, skills, and patterns below.* *Written with ❀️ by TheDecipherist and the Claude Code community*

More from r/ClaudeAI