The complete guide to Claude Code. Opus 4.7, Sonnet 4.6, Haiku 4.5. 1M token context window. 27 hook events. 43 production-tested chapters across 6 topical Parts (Foundation, Workflow, Extension, Context Engineering, Advanced, Reference). Three install tiers. CC 2.1.121+ compatible.
Current as of: Claude Code 2.1.111+. Related: Chapter 02 — Rules System, Chapter 05 — Progressive Disclosure, Chapter 06 — Context Governance
Every message you send to Claude Code loads a set of always-on context: your CLAUDE.md, the .claude/rules/ directory, skill descriptions, agent descriptions, and MCP tool schemas. That content is repeated on every turn. The context window is finite — 1M tokens on Opus 4.6/4.7 Max is large, but it’s not free. Quality degrades above 75% utilization, and cache misses on bloated static content get expensive fast.
Anthropic’s skill design guide puts it plainly:
“The context window is a public good. Skills share the context window with everything else.”
This chapter covers the cost hierarchy (what loads when), thresholds (how much is too much), branch-scoped loading (how to shed cost per task), separation patterns (global vs project), and the measurement tools that let you see exactly where tokens are going.
Push content to the cheapest tier that serves its purpose.
| Tier | Per-message cost | Use for |
|---|---|---|
| Hook (shell) | 0 tokens | Enforcement, logging, validation |
| Skill body | 0 until invoked | Procedures, reference material, workflows |
| Path-scoped rule | Conditional on matching path | File-type patterns (paths: CSV format) |
Rule (~/.claude/rules/) |
Every turn (cached) | Universal invariants |
CLAUDE.md |
Every turn (cached) | Critical facts, prime position |
| Skill description | Every turn, subject to 2% budget | Trigger text telling Claude when to invoke |
| Agent description | Every turn, no formal cap | Trigger text for Task() spawns |
| MCP tool schema | Every turn per connected server | Tool name + description + parameters |
Task(). They don’t compete with your main conversation.Level 1: Description (always loaded, ~100-250 chars)
→ Tells the model WHEN to use a skill or agent
Level 2: Skill body (on invocation, ~2-8K chars)
→ Tells the model HOW to execute the task
Level 3: Supporting files (on demand via Read, unlimited)
→ Deep reference data, examples, large configs
A deployment skill with 500 lines of content costs about 2K tokens at Level 2 — but only when triggered. The same content in CLAUDE.md would cost 2K tokens on every message.
Concrete caps per file and per session. These are the numbers the governance system (Chapter 06) enforces.
| Metric | Target | Warning | Critical | Action |
|---|---|---|---|---|
| Single rule file | <2K chars | 2K-4K | >4K (hook blocks) | Condense or split into rule + skill |
| Global rules total | <150K chars | >200K (hook blocks) | >250K | Run /context-optimization |
| Session always-on total | <300K chars | >300K | >400K | Audit CLAUDE.md and skills |
| Skill descriptions total | <16K chars (2% default) | Approaching | Budget exceeded | Trim or disable-model-invocation: true |
| Individual skill description | 80-250 chars | 250-500 | >500 | Rewrite as action verb + trigger |
CLAUDE.md length |
<200 lines | 200-400 | >400 | Relocate to rules |
The 4K per-file cap forces you to split. When a rule wants to grow beyond a single screen, extract the invariant (1-2 KB) and pointer it to a paired skill that holds the detail.
The 200K global cap is enforced by a PreToolUse hook on Edit and Write. Override with CLAUDE_RULE_SIZE_OVERRIDE=1 in emergencies, documented in your global CLAUDE.md so you remember it exists.
Default: 2% of context window ≈ 16,000 characters. Override via environment variable:
# In ~/.bashrc or ~/.zshrc
export SLASH_COMMAND_TOOL_CHAR_BUDGET=40000
Measure before deciding:
total=0
for f in $(find ~/.claude/skills .claude/skills -maxdepth 3 -name "SKILL.md" 2>/dev/null); do
desc=$(sed -n '/^description:/p' "$f" | head -1 | sed 's/^description: *//;s/^"//;s/"$//')
total=$((total + ${#desc}))
done
echo "Total: $total chars (budget: ${SLASH_COMMAND_TOOL_CHAR_BUDGET:-16000})"
At high utilization (>90%), adding a single skill can silently drop others. Four ways to reclaim budget:
~/.claude/skills-disabled/ (not loaded, but recoverable)disable-model-invocation: true for user-only skills (removes from budget entirely)~/.claude/skills/ to .claude/skills/ so they only load per-project# Good (85 chars): action verb + what + when
description: "Deploy to GCP Cloud Run. Use for staging/production deployments and traffic routing."
# Bad (240 chars): prose, details, no trigger signal
description: "This agent is a deployment specialist that handles all aspects of deploying to Google Cloud Platform Cloud Run including staging deployments, production deployments, traffic routing, health checks, timeout configuration, and rollback procedures."
The model needs to know when to pick the skill, not how it works internally.
Loading every rule and every skill for every task wastes tokens. A UI branch doesn’t need database patterns; a database branch doesn’t need UI patterns. Branch-scoped loading cuts always-on context by 30-50% per task on mature projects.
Each branch gets a small JSON manifest defining what to load:
{
"manifest_version": "3.0",
"branch": "dev-data",
"mission": "Schema migrations + query optimization",
"domain": "database",
"ondemand_files": {
"branch_context": [
"CURRENT/dev-data/ROADMAP.md"
],
"domain": [
"memory-bank/ondemand/database/quick-reference.md",
"memory-bank/ondemand/database/patterns.md"
]
},
"estimated_tokens": {
"global_always": 64000,
"ondemand_domain": 11000,
"total_max": 75000
},
"should_NOT_load": {
"deployment/ci-cd.md": "Not managing CI/CD on this branch",
"database/COMPLETE-SCHEMA.md": "Too large — use quick-reference instead"
}
}
The critical detail: the @ symbol only triggers file loading when it’s in CLAUDE.md. A hook that just prints @path to the terminal does nothing. The hook must write the imports into the file.
#!/bin/bash
# .claude/hooks/session-start.sh
current_branch=$(git branch --show-current 2>/dev/null)
manifest="CURRENT/$current_branch/CONTEXT-MANIFEST.json"
# Step 1: cleanup — remove old auto-loaded section so it doesn't accumulate
if [ -f "CLAUDE.md" ] && grep -q "AUTO-LOADED DOMAIN FILES" CLAUDE.md; then
sed -i '/^## AUTO-LOADED DOMAIN FILES/,$d' CLAUDE.md
fi
# Step 2: write @ imports
if [ -f "$manifest" ]; then
cat >> CLAUDE.md <<EOF
---
## AUTO-LOADED DOMAIN FILES (Session-Specific)
**Branch**: $current_branch
**Source**: $manifest
EOF
jq -r '.ondemand_files | to_entries[] | .value[]' "$manifest" 2>/dev/null | while read file; do
[ -z "$file" ] && continue
[ -f "$file" ] && echo "@$file" >> CLAUDE.md
done
fi
echo "@$file" — prints to terminal, files NOT loadedecho "@$file" >> CLAUDE.md — writes to file, files ARE loadedAn example project with 4 active branches and a 113K-token average baseline saw per-branch savings of 30-47% after adopting branch manifests — the UI branch shed database patterns, the database branch shed UI patterns, and the knowledge branch shed deployment files. Actual numbers depend on how cleanly your domains separate; measure before and after with /context.
should_NOT_loadglobal_always + ondemand_domain) in the manifest itself so growth is visibleEverything in ~/.claude/ loads for every project. Skills, rules, and CLAUDE.md content designed for one project become dead weight everywhere else. The fix is to push project-specific content down one level.
1. Project references in global rules. ~/.claude/rules/ should be universal. Over time, project-specific examples creep in:
<!-- ~/.claude/rules/global/context-checking.md (BAD) -->
1. Search context: memory-bank/learned/, ULTIMATE-MINI files # project-specific
2. Use database-context-loader-skill # project-specific
3. Check UNIVERSAL-SYSTEM-MASTER.md for existing APIs # project-specific
Every unrelated project now loads those irrelevant references on every message.
2. Project-specific skills at user level. Skills in ~/.claude/skills/ load their descriptions for all projects. If 25 of 47 user-level skills only apply to one project, every other project’s skill budget carries 25 irrelevant descriptions.
3. Bloated CLAUDE.md. Content useful during development gets left behind even after it’s been moved to rules, skills, or on-demand files.
Phase 1 — Clean global rules. Remove project-specific references from ~/.claude/rules/:
# Audit: find project-specific terms in global rules
grep -rn "MyProject\|specific-tool\|api-name" ~/.claude/rules/
# Fix: replace project-specific items with generic equivalents
| Before (project-specific) | After (universal) |
|---|---|
memory-bank/learned/ |
project documentation |
UNIVERSAL-SYSTEM-MASTER.md |
project system docs |
Sacred Commandment X |
single responsibility principle |
Verify with a zero-hit grep:
grep -rn "MyProject\|specific-tool" ~/.claude/rules/ # expect: no output
Phase 2 — Relocate project-specific skills. Move them from ~/.claude/skills/ to .claude/skills/.
| Level | Location | Loads for | Use when |
|---|---|---|---|
| User (global) | ~/.claude/skills/ |
All projects | Skill is useful everywhere |
| Project | .claude/skills/ |
This project only | Skill is project-specific |
Decision criteria for each skill:
Phase 3 — Trim CLAUDE.md. For each section, ask:
“Would removing this cause Claude to make mistakes?”
If the content exists in .claude/rules/, memory-bank/always/, or any other auto-loaded file, the answer is no. Remove it.
Common duplications to eliminate:
CLAUDE.md section |
Already covered by | Action |
|---|---|---|
| Deployment rules | .claude/rules/deployment/ |
Remove, add 1-line reference |
| Sacred/compliance rules | .claude/rules/sacred/ |
Remove, add 1-line reference |
| Context system explanation | Auto-loaded always/ files | Remove entirely |
| Validation workflow | .claude/rules/global/validation.md |
Remove entirely |
| Historical achievements | Move to learned/ files | Remove entirely |
| Feature status | system-status.json |
Remove entirely |
Keep in CLAUDE.md only:
@ import declarations (if using file imports)| Cleanup | Typical savings | Who benefits |
|---|---|---|
| Project refs in global rules | 500-3,000 chars | All other projects |
| Project skills moved to project level | 2,000-8,000 chars of description budget | All other projects |
CLAUDE.md trim |
5,000-25,000 chars | This project (every message) |
~/.claude/rules/. Project-specific → .claude/rules/.~/.claude/skills/. No → .claude/skills/.CLAUDE.md? “Is this already in a rule file or auto-loaded file?” Yes → don’t add it. No → “Would removing this cause mistakes?” No → don’t add it.Run a quarterly audit:
echo "=== Global Rules ==="
echo "Files: $(find ~/.claude/rules -name '*.md' | wc -l)"
echo "Total chars: $(find ~/.claude/rules -name '*.md' -exec cat {} + | wc -c)"
echo "=== Global Skills ==="
echo "Skills: $(find ~/.claude/skills -name 'SKILL.md' | wc -l)"
echo "=== CLAUDE.md ==="
wc -l CLAUDE.md
You can’t optimize what you can’t measure. Two tools, one manual and one automated.
/context — live session inspectionRun /context during any session to see current utilization: total tokens, per-surface breakdown (CLAUDE.md, skills, MCP tools, conversation), and any warnings about oversized files or excluded skills. This is the fastest way to see if a specific session is bloated.
/context-audit — read-only health reportA skill that produces a full health report in 30 seconds:
CLAUDE.md length over 200 linesRun on a monthly cadence and before any cleanup pass.
# CLAUDE.md token cost
wc -c CLAUDE.md | awk '{printf "CLAUDE.md: %d chars (~%d tokens)\n", $1, $1/4}'
# Global rules cost
find ~/.claude/rules -name "*.md" -exec cat {} + | wc -c | \
awk '{printf "Global rules: %d chars (~%d tokens)\n", $1, $1/4}'
# Find duplicate agent names across user and project levels
comm -12 \
<(ls ~/.claude/agents/*.md 2>/dev/null | xargs -I{} basename {} | sort) \
<(ls .claude/agents/*.md 2>/dev/null | xargs -I{} basename {} | sort)
The right tool depends on the signal.
| Signal | Tool |
|---|---|
/context shows warnings about file size or excluded skills |
/context-audit for a full report |
| Session compaction happens earlier than expected | /context-audit, then /context-optimization |
Adding a new rule or CLAUDE.md section — ask: must this be always-on? |
Move to a skill body or hook |
| Single file over 4K chars | Extract invariant to rule, move detail to paired skill (pointer-rule pattern) |
| Global rules total over 200K | /context-optimization guided 5-phase reduction |
| Monthly cadence | /context-audit → decide action → /context-optimization if needed |
The /context-optimization skill walks you through audit → classify → condense → relocate → verify. For heavy lifting that needs an isolated context window, delegate to the context-optimizer subagent.
The full governance methodology — enforcement hooks, scanners, baseline tags, regression detection, monitoring — is covered in Chapter 06 — Context Governance.
Use this checklist to audit a project’s context costs:
CLAUDE.md under 200 lines? Move details to .claude/rules/ or on-demand files.SLASH_COMMAND_TOOL_CHAR_BUDGET)disable-model-invocation: true?context: fork for isolation?.claude/rules/ instead of agents?SLASH_COMMAND_TOOL_CHAR_BUDGET.~/.claude/ loads for every project. Keep it universal.CLAUDE.md gate test: “Would removing this cause Claude to make mistakes?” If not, remove it./context for live sessions, /context-audit for the full picture.Next: Chapter 05 — Progressive Disclosure Related: Chapter 06 — Context Governance, Chapter 07 — Skill Lifecycle