====== Claude Code — Working Reference ======**Scope:** current behaviour as of late Oct 2026 (release line v2.1.3xx). Built from the official docs at code.claude.com and the 7-part listening series. Version-specific details drift fast: check ''%%/release-notes%%'' or the changelog when something behaves differently. **Conventions on this page:** ''%%monospace%%'' = literal command, flag, file or setting. "Agent" = the model doing the work. "Harness" = Claude Code itself (the program that runs tools, hooks and permission checks). ~~TOC~~ ---- ===== 1. Mental model ===== ==== 1.1 Two kinds of instruction ====Every instruction is either read by the model (which may decide otherwise) or enforced by the harness (which always applies it). ^ Concern ^ Non-deterministic: model decides ^ Deterministic: harness enforces ^| What to do | prompt, CLAUDE.md, skills the model picks up | hooks; skills only a user can start || What it can touch | auto-mode classifier | deny rules, sandbox in strict mode, managed settings || When it is done | request for evidence, ''%%/goal%%'', ''%%/code-review%%'' | tests, typecheck, ''%%Stop%%'' hook, CI || How much it spends | effort level, the model's own pacing | ''%%--max-turns%%'', ''%%--max-budget-usd%%'' (with ''%%-p%%''), spend limits || Final word | the agent's own summary | branch protection, a human approving the merge | **Rules of thumb**  * Default to letting the model decide. Most guidelines have exceptions and the model, with the code in front of it, judges them better than a rule written in advance.  * Use the deterministic layer for the few things that must //always// or //never// happen.  * If you keep adding emphasis to a CLAUDE.md line and it is still missed, the line belongs in a hook.  * The reverse also holds: hooks that encode mere preferences should be deleted. ==== 1.2 Four failure modes ====^ Symptom ^ Cause ^ Fix (section) ^| Built the wrong thing, or rediscovers the same fact every session | missing information that is not in the repo | write it down: CLAUDE.md, rules, skills (6, 7) || Said "done" and was not | no way to check its own work | give it a pass/fail check (3) || Did something forbidden, or skipped a mandatory step | a prompt cannot guarantee either | hooks, deny rules, sandbox (4, 8) || Correct but too slow, costly or prompt-heavy | a default does not fit the task | change mode, effort, model, subagent use (1.4, 8, 9) | ==== 1.3 What the defaults already do ====  * Interactive terminal and VS Code sessions start in **auto mode**: a classifier reviews risky actions instead of prompting you.  * Model: **Opus 5.5 at medium effort** on most plans and providers.  * Delegates to subagents when it sees a reason (Explore for wide searches, forks for side tasks), in the background by default.  * Compacts the conversation automatically before the context window fills (1M-token window on most current models). ==== 1.4 Effort, model, wording ====  * **Effort is the thinking control.** ''%%/effort low|medium|high|xhigh|max%%''.    * ''%%high%%''/''%%xhigh%%'': easy-to-overlook cases — bugs in unfamiliar code, flaky tests, schema changes with many readers.    * ''%%low%%'': rapid back-and-forth you review anyway — brainstorming, sketches, small renames.    * ''%%max%%'': hard unattended problems (e.g. vulnerability hunting). Overthinks ordinary tasks.    * ''%%ultrathink%%'' in a prompt: deeper reasoning for that one turn without changing the setting.  * "think hard", "be thorough", "step by step" are ordinary text. They nudge within the effort level, never above it.  * **"be ambitious"** still helps: it tells the agent about **scope** (edge cases, error states, follow-ons), which only you know.  * Models: Opus 5.5 default; Sonnet cheaper for routine work; Haiku for simple subagent jobs; Fable 5.1 only when selected explicitly (''%%/model fable%%''). ==== 1.5 Advice you can drop ====^ Old advice ^ Why it is obsolete ^| Manage the context window aggressively | 1M window plus auto-compaction. Still ''%%/clear%%'' between unrelated tasks for focus and cost. || IMPORTANT / ALL CAPS | Current models follow plain wording; emphasis causes over-application. Unbendable rule -> hook or deny. || Subagents to protect context | Rarely the constraint now. Use them for parallelism, noise isolation, independent review. || Delegate for a better answer | Same or smaller model, same task. A //fresh reviewer// helps; delegation alone does not. || "think harder" keywords | Effort is the control; ''%%ultrathink%%'' for one turn. || "keep going / don't be lazy" | Causes over-work. Give a check instead; use ''%%/goal%%'' or a ''%%Stop%%'' hook for unattended runs. || Describe architecture in CLAUDE.md | The agent reads the repo. Only write what is not there. | ==== 1.6 Steering a live session ====  * Watch the first minute. ''%%Esc%%'' stops mid-action and keeps work so far.  * ''%%/rewind%%'' (or ''%%Esc%%'' twice on an empty prompt): roll code, conversation, or both back to an earlier prompt. Makes the bold attempt cheap.    * Checkpoints only cover edits made with the file tools in the main conversation. Files changed by Bash are **not** restored. Not a git replacement.  * After two failed corrections: ''%%/clear%%'' and write one better prompt instead of a third correction.  * ''%%/btw%%'': quick side question, not added to history.  * ''%%/rename %%'' then ''%%claude --resume %%'' for multi-day work; ''%%claude --continue%%'' resumes the latest.  * ''%%/usage%%'': where tokens went (by skill, subagent, plugin, MCP server).  * ''%%/compact %%'': summarise with a focus. Expensive on a long session with a cold cache.  * Prompt cache lasts about 1 hour on a subscription, 5 minutes on API keys/cloud providers/subagents. ---- ===== 2. Giving it the right information ===== ==== 2.1 The test for what to write down ====  - Could it find this by reading the code?  - Would it actually go and look?If both are yes, leave it out. Write down what was never in the repo (a meeting decision, a deploy process in someone's head, a required env var) and what takes minutes of digging every session. ==== 2.2 Specific prompts ====^ Instead of ^ Try ^| "fix the login bug" | "users report login fails after session timeout. look at token refresh in src/auth/, write a failing test that reproduces it, then fix it" || "add a calendar widget" | "follow the pattern in HotDogWidget.php, build a calendar widget with month picker and year paging. no new libraries" |  * Hand over material instead of describing it: ''%%@path%%'' includes a file; paste screenshots; pipe output (''%%cat error.log | claude -p "what's going on"%%'').  * State your preference between two reasonable approaches up front.  * Vague prompts are fine when exploring; expect more correction. ==== 2.3 Interview first, then build ====I want to add rate limiting to the public API but haven't thought it through.Interview me until you could write the spec, then write it to SPEC.md.Then start a **fresh session** to build from ''%%SPEC.md%%'': clean context plus a written definition of done that a reviewer can check against later. ==== 2.4 Connecting other systems ====  * Prefer a CLI when one exists (''%%gh%%'' signed in = PRs and review comments with no explanation). For unfamiliar CLIs, point at ''%%--help%%''.  * Otherwise MCP: ''%%claude mcp add --transport http notion https://mcp.notion.com/mcp%%''; manage in ''%%/mcp%%''.  * Connected MCP servers add tool definitions to context even when unused: disable the ones you do not need.  * Typed languages: a code-intelligence plugin lets it jump to definitions instead of reading many files. ---- ===== 3. Proving the work is done ===== ==== 3.1 Why "done" fails ====The agent stops when the work //looks// done. Without something to run that returns pass/fail, you become the test suite. Give it a check and it closes the loop itself: change -> run check -> read failure -> fix -> rerun. Valid checks: a test file, a build exit code, a linter, a script diffing output against a fixture, a browser screenshot beside the mockup. **The single most useful line in CLAUDE.md is the command that runs your check.** ==== 3.2 Strictness ladder ====^ Rung ^ Mechanism ^ Who decides done ^| 1 | In the prompt: "run the auth tests and keep going until they pass" | the working model || 2 | ''%%/goal %%'' | a separate evaluator model, every turn || 3 | ''%%Stop%%'' hook (command type) | your script; harness enforces || 4 | ''%%/code-review%%'' or a reviewer subagent | a fresh context that never saw the reasoning | ==== 3.3 /goal in detail ====  * ''%%/goal all tests in test/auth pass and the lint step is clean%%'' — starts a turn immediately; the condition is the instruction.  * After each turn, the configured **small fast model** (Haiku by default on the Anthropic API) judges the condition against the transcript and returns:    * **not yet met** — work continues; the reason becomes guidance for the next turn.    * **met** — goal clears; "achieved" entry recorded.    * **impossible** — goal clears; "failed" entry with the reason.  * Implemented as a **session-scoped prompt-based Stop hook**. So it is model-judged (soft), not deterministic.  * **The evaluator does not run commands or read files.** It only sees what the agent surfaced in the conversation. Write conditions the agent's own output can prove.  * Strong condition = **one measurable end state** + **a stated check** (''%%npm test exits 0%%'', ''%%git status is clean%%'') + **constraints** (''%%no other test file is modified%%'').  * Max 4,000 characters. Bound the run with a clause: ''%%or stop after 20 turns%%''.  * ''%%/goal%%'' (no args) = status: condition, elapsed time, turns, token spend, last reason. ''%%Ctrl+O%%'' shows each verdict's reasoning.  * ''%%/goal clear%%'' (aliases: stop, off, reset, none, cancel). ''%%/clear%%'' also removes it. Resuming a session restores an active goal (counters reset).  * Does **not** change the permission mode. For unattended turns run it in auto mode; in Manual mode it waits on prompts.  * Headless: ''%%claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"%%''. Add ''%%--output-format stream-json --verbose%%'' to see progress.  * **Clears the goal** (you must fix): auth failure (when Claude Code manages credentials), exhausted credit, unrecoverable context overflow, model unavailable.  * **Keeps the goal**: transient errors retry up to 3 times, then pause; rate/usage limits pause; resumes when a usage limit resets if auto-continue is on.  * Background work (subagent, background shell) defers evaluation. After 30 min waiting, a check-in asks the agent to inspect running tasks; later check-ins back off (×2, capped at ×4). ''%%CLAUDE_CODE_GOAL_CHECKIN_MINUTES%%'' changes the interval; ''%%0%%'' disables check-ins and auto-retries.  * Stall guard: several turns with no tool use -> loop stops, goal stays set.  * Unavailable when ''%%disableAllHooks%%'' is true or ''%%allowManagedHooksOnly%%'' is set; subject to workspace trust like hooks.  * Official view: rarely needed interactively; valuable for long background runs where the agent ends a turn with a progress summary while items remain. ==== 3.4 Keeping a session running: compare ====^ Mechanism ^ Next turn starts when ^ Stops when ^ Scope ^| ''%%/goal%%'' | previous turn finishes (or check-in/retry) | evaluator says met/impossible, error you must fix, or ''%%/goal clear%%'' | this session || ''%%/loop%%'' | a time interval elapses | you stop it, or the agent decides it is done | this session || ''%%Stop%%'' hook | previous turn finishes | your script or prompt decides | every session in its settings scope |Auto mode removes per-tool prompts; ''%%/goal%%'' removes per-turn prompts. They are complementary. ==== 3.5 Stop hook that enforces a typecheck ===={  "hooks": {    "Stop": [      { "hooks": [        { "type": "command", "command": "pnpm tsc --noEmit 1>&2 || exit 2" }      ] }    ]  }}  * Exit 2 blocks the stop; stderr is sent back as the reason (hence ''%%1>&2%%'').  * Override after 8 consecutive blocks with no tool call between them. Raise with ''%%CLAUDE_CODE_STOP_HOOK_BLOCK_CAP%%''. ==== 3.6 Evidence and review ====  * Always ask for evidence: the command run and its output, or the screenshot. For unwatched sessions it is the only evidence.  * ''%%/verify%%'': builds and runs the app and checks the change against the running app, not just tests.  * ''%%/code-review%%'': reviews the diff in a fresh subagent.  * Review against intent:use a subagent to review the rate limiter diff against SPEC.md, check every requirementis implemented and the listed edge cases have tests, report gaps that affect correctnessand skip style  * Keep "skip style": a reviewer asked to find problems always finds some; fixing all of them adds abstraction and impossible-case tests. ---- ===== 4. Hooks ===== ==== 4.1 What a hook is ====A user-defined handler the **harness** runs at a fixed lifecycle point. The model does not choose to run it and cannot skip it. Used for: enforcing rules, automating repetitive steps, integrating tools. ==== 4.2 Configuration shape ====Three nesting levels in a settings file:  - **Event** — lifecycle point (''%%PreToolUse%%'', ''%%Stop%%''…).  - **Matcher group** — filter (e.g. only the ''%%Bash%%'' tool).  - **Handler(s)** — what runs.Optional per-handler ''%%if%%'' (permission-rule syntax, tool events only) skips spawning unless the call matches, e.g. ''%%"if": "Bash(git *)"%%'' or ''%%"if": "Edit(*.ts)"%%''. {  "hooks": {    "PreToolUse": [      {        "matcher": "Bash",        "hooks": [          { "type": "command",            "if": "Bash(rm *)",            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",            "args": [] }        ]      }    ]  }} **Matcher rules**  * ''%%*%%'', empty or omitted = match all.  * Only letters/digits/_/-/space/comma/pipe = exact name or list (''%%Edit|Write%%'', ''%%Edit, Write%%'').  * Anything else = unanchored JavaScript regex (''%%Edit.*%%'' also matches ''%%NotebookEdit%%''; anchor with ''%%^…$%%'').  * MCP tools: ''%%mcp____%%''. All tools of a server: ''%%mcp__memory__.*%%'' (the ''%%.*%%'' is required). ==== 4.3 Events ====Cadence: per session (''%%SessionStart%%'', ''%%SessionEnd%%''); per turn (''%%UserPromptSubmit%%'', ''%%Stop%%'', ''%%StopFailure%%''); per tool call (''%%PreToolUse%%'', ''%%PostToolUse%%''). ^ Event ^ Fires ^ Can block? ^| ''%%SessionStart%%'' | new session, resume, ''%%/clear%%'', compaction, fork (matcher: startup/resume/clear/compact/fork) | no (adds context) || ''%%UserPromptSubmit%%'' | before a prompt reaches the model (also scheduled/loop turns) | yes || ''%%PreToolUse%%'' | before a tool runs | yes || ''%%PermissionRequest%%'' | when a call would prompt you | via JSON decision only || ''%%PermissionDenied%%'' | auto mode denied a call | no (can allow retry) || ''%%PostToolUse%%'' | after a tool succeeds | no (tool already ran; stderr shown to agent) || ''%%PostToolUseFailure%%'' | after a tool fails | no || ''%%PostToolBatch%%'' | after a batch of parallel calls | yes (stops loop) || ''%%Stop%%'' | agent finishes responding | yes (forces continuation) || ''%%SubagentStart%%'' / ''%%SubagentStop%%'' | subagent spawned / finished | Stop variant can block || ''%%PreCompact%%'' / ''%%PostCompact%%'' | around compaction | Pre can block || ''%%Notification%%'' | agent needs attention (permission_prompt, idle_prompt…) | no || ''%%InstructionsLoaded%%'' | a CLAUDE.md or rules file loads | no (good for debugging) || ''%%ConfigChange%%'' | a config file changes mid-session | yes || ''%%CwdChanged%%'' / ''%%FileChanged%%'' | directory change / watched file change | no || ''%%WorktreeCreate%%'' / ''%%WorktreeRemove%%'' | worktree lifecycle | yes || ''%%SessionEnd%%'' | session terminates | no |Others: ''%%Setup%%'', ''%%UserPromptExpansion%%'', ''%%TaskCreated%%'', ''%%TaskCompleted%%'', ''%%TeammateIdle%%'', ''%%PreModelSwitch%%'', ''%%PostModelSwitch%%'', ''%%Elicitation%%'', ''%%ElicitationResult%%'', ''%%DirectoryAdded%%'', ''%%MessageDisplay%%''. About 30 in total. ==== 4.4 Handler types ====^ Type ^ What it does ^ Deterministic? ^ Default timeout ^| ''%%command%%'' | shell command; JSON on stdin | yes | 600 s || ''%%http%%'' | POSTs the JSON to a URL | yes | 600 s || ''%%mcp_tool%%'' | calls a tool on a configured MCP server | yes | 600 s || ''%%prompt%%'' | single-turn model judgement | no | 30 s || ''%%agent%%'' | subagent with read/search tools judges (experimental) | no | 60 s |  * ''%%UserPromptSubmit%%'' handlers default to 30 s (they block every prompt). ''%%SessionEnd%%'' hooks share a 1.5 s budget.  * Matching hooks run **in parallel**. One hook's deny does not stop sibling hooks from running.  * **For real enforcement use command or http.** ==== 4.5 Input contract ====JSON on stdin (command) or as the POST body (http). Common fields: ''%%session_id%%'', ''%%prompt_id%%'', ''%%transcript_path%%'', ''%%cwd%%'', ''%%permission_mode%%'', ''%%effort%%'', ''%%hook_event_name%%''; plus ''%%agent_id%%''/''%%agent_type%%'' inside subagents. Tool events add ''%%tool_name%%'', ''%%tool_input%%'', ''%%tool_use_id%%''.{ "session_id": "abc123", "cwd": "/home/me/proj", "permission_mode": "default",  "hook_event_name": "PreToolUse", "tool_name": "Bash",  "tool_input": { "command": "npm test" } }Note: ''%%transcript_path%%'' may lag the current turn; on Stop use ''%%last_assistant_message%%''. Manual mode arrives as ''%%"default"%%''. ==== 4.6 Output contract: exit codes ====  * **Exit 0** = success / no objection. Any valid JSON on stdout is applied. On ''%%PreToolUse%%'', exit 0 is **not approval** — the normal permission flow still runs.  * **Exit 2** = blocking error on events that can block. **stderr** goes back as the reason. This feedback loop is what lets the agent adapt.  * **Any other code (including 1)** = non-blocking error; the action **proceeds**. A policy script that exits 1 enforces nothing.  * On ''%%UserPromptSubmit%%'', ''%%SessionStart%%'', ''%%UserPromptExpansion%%'' and ''%%PostModelSwitch%%'', plain-text stdout on exit 0 is added to the agent's context. ==== 4.7 Output contract: JSON ====Exit 0 and print exactly one JSON object (nothing else on stdout).  * Universal: ''%%continue: false%%'' + ''%%stopReason%%'' (halt entirely); ''%%systemMessage%%'' (warning to user); ''%%terminalSequence%%'' (desktop notification/title/bell via allowed OSC sequences).  * ''%%PreToolUse%%'' via ''%%hookSpecificOutput%%'':{ "hookSpecificOutput": {    "hookEventName": "PreToolUse",    "permissionDecision": "deny",    "permissionDecisionReason": "Database writes are not allowed" } }    * ''%%permissionDecision%%'': ''%%allow%%'' (skip prompt) / ''%%deny%%'' / ''%%ask%%'' (force prompt) / ''%%defer%%'' (''%%-p%%'' only, for SDK wrappers).    * Multiple hooks: most restrictive wins — deny > defer > ask > allow.    * A hook's **allow does not override deny or ask rules** in settings. A hook's **deny holds in every mode**, including ''%%bypassPermissions%%''.    * ''%%updatedInput%%'' rewrites tool arguments before execution (avoid two hooks rewriting the same tool).  * ''%%PostToolUse%%'': ''%%updatedToolOutput%%'' replaces the result (redaction point); top-level ''%%decision: "block"%%'' + ''%%reason%%''.  * ''%%Stop%%''/''%%SubagentStop%%'': ''%%decision: "block"%%'' + ''%%reason%%'' to continue.  * ''%%PermissionRequest%%'': ''%%hookSpecificOutput.decision.behavior%%'' allow/deny, optional ''%%updatedPermissions%%''.  * ''%%additionalContext%%'' (inside ''%%hookSpecificOutput%%'') injects a system reminder: SessionStart/SubagentStart (start), UserPromptSubmit (with prompt), tool events (beside result), Stop (end of turn).    * Write it as plain facts ("Deploy target is staging"), not system-style commands — those can trip prompt-injection defences.    * Strings over 10,000 chars are spilled to a file; only a 2,000-char preview stays. ==== 4.8 Failure semantics (critical) ====  * **Hooks fail open by default.** Script missing, crash, timeout, invalid JSON -> the action goes ahead (non-blocking error notice).  * For guards, set ''%%"onFailure": "block"%%'' on ''%%command%%'' or ''%%http%%'' hooks: any failure then acts like exit 2 (on ''%%PermissionRequest%%'', denies).  * Not applicable to ''%%Stop%%''/''%%SubagentStop%%''/''%%TaskCompleted%%''/''%%TeammateIdle%%'' or async hooks.  * The ''%%if%%'' filter is best-effort: when the harness cannot parse what a shell command runs, the hook fires anyway. **Use permission rules, not hooks, for hard allow/deny on commands.**  * A hook that decides in a background process must print its decision first and redirect the background process's output. ==== 4.9 Where hooks live ====^ Location ^ Scope ^ Shared ^| ''%%~/.claude/settings.json%%'' | all your projects | no || ''%%.claude/settings.json%%'' | project | yes (commit) || ''%%.claude/settings.local.json%%'' | project | no || managed policy settings | organisation | admin-controlled || plugin ''%%hooks/hooks.json%%'' | while plugin enabled | yes || skill frontmatter | rest of session after invocation (''%%once: true%%'' for single run) | yes || subagent frontmatter | while that subagent runs (''%%Stop%%'' becomes ''%%SubagentStop%%'') | yes |  * Hooks merge across levels; managed hooks cannot be disabled from lower levels.  * ''%%"disableAllHooks": true%%'' disables all (no per-hook disable). Per run: ''%%--settings '{"disableAllHooks": true}' %%''.  * Project hooks only run after the folder's workspace trust is accepted (but see ''%%-p%%'' caveats in 8.10).  * ''%%/hooks%%'' = read-only browser showing each hook and its source. ==== 4.10 Patterns ====**Auto-format after edits** (''%%.claude/settings.json%%''):{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write",  "hooks": [ { "type": "command",    "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" } ] } ] } } **Protect files** (''%%.claude/hooks/protect-files.sh%%'', registered on ''%%PreToolUse%%'' matcher ''%%Edit|Write%%''):#!/bin/bashINPUT=$(cat)FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')for p in ".env" "package-lock.json" ".git/"; do  if [[ "$FILE_PATH" == *"$p"* ]]; then    echo "Blocked: $FILE_PATH matches protected pattern '$p'" >&2    exit 2  fidoneexit 0''%%chmod +x%%'' it; a non-executable script is a silent non-blocking failure. **Desktop notification when input is needed** (''%%~/.claude/settings.json%%''):{ "hooks": { "Notification": [ { "matcher": "",  "hooks": [ { "type": "command",    "command": "notify-send 'Claude Code' 'Needs your attention'" } ] } ] } } **Re-inject context after compaction**:{ "hooks": { "SessionStart": [ { "matcher": "compact",  "hooks": [ { "type": "command",    "command": "echo 'Reminder: use Bun, not npm. Run bun test before committing.'" } ] } ] } } **Load direnv into the agent's shell**: ''%%SessionStart%%'' and ''%%CwdChanged%%'' hooks running ''%%direnv export bash > "$CLAUDE_ENV_FILE"%%''. The env file is sourced before every Bash command. **Stop hook loop guard**:INPUT=$(cat)[ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ] && exit 0 **Auto-approve one prompt type** (keep the matcher narrow):{ "hooks": { "PermissionRequest": [ { "matcher": "ExitPlanMode",  "hooks": [ { "type": "command",    "command": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}'" } ] } ] } } ==== 4.11 Debugging ====  * ''%%/hooks%%'' — is it listed under the right event?  * Pipe sample JSON by hand: ''%%echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | ./my-hook.sh; echo $?%%''  * ''%%claude --debug-file /tmp/claude.log%%'' then ''%%tail -f%%''; or ''%%/debug%%'' mid-session.  * ''%%Ctrl+O%%'' transcript view shows hook outcomes.  * Silent failure 1: shell profile echoes text before the JSON -> output treated as plain text. Guard echoes with ''%%if [[ $- == *i* ]]%%''.  * Silent failure 2: decision fields placed at top level instead of inside ''%%hookSpecificOutput%%'' -> ignored. Debug log says "unrecognized keys".  * Use absolute paths or ''%%${CLAUDE_PROJECT_DIR}%%''; exec form (''%%"args": []%%'') avoids shell quoting. ---- ===== 5. Folders and files ===== ==== 5.1 Project folder (commit to git) ====^ Path ^ Purpose ^| ''%%CLAUDE.md%%'' or ''%%.claude/CLAUDE.md%%'' | instructions loaded every session || ''%%CLAUDE.local.md%%'' | private per-project instructions; add to ''%%.gitignore%%'' || ''%%.claude/settings.json%%'' | permissions, hooks, env vars, model defaults (shared) || ''%%.claude/settings.local.json%%'' | personal overrides; "don't ask again" approvals land here || ''%%.claude/rules/*.md%%'' | topic rules, optionally path-scoped || ''%%.claude/skills//SKILL.md%%'' | skills || ''%%.claude/commands/*.md%%'' | older single-file commands (same mechanism as skills) || ''%%.claude/agents/*.md%%'' | custom subagents || ''%%.claude/workflows/*.js%%'' | dynamic workflow scripts; each becomes ''%%/%%'' || ''%%.claude/output-styles/*.md%%'' | response-shaping instruction sets || ''%%.claude/agent-memory//%%'' | subagent persistent memory (project scope) || ''%%.mcp.json%%'' | team-shared MCP servers || ''%%.worktreeinclude%%'' | gitignored files to copy into new worktrees | ==== 5.2 Home folder ''%%~/.claude/%%'' ====  * Personal equivalents: ''%%CLAUDE.md%%'', ''%%settings.json%%'', ''%%rules/%%'', ''%%skills/%%'', ''%%agents/%%'', ''%%output-styles/%%'', ''%%keybindings.json%%'', ''%%themes/%%''.  * ''%%~/.claude.json%%'': app state, account, UI toggles, personal MCP servers, per-project trust.  * ''%%plugins/%%'': installed plugins and marketplaces.  * ''%%CLAUDE_CONFIG_DIR%%'' relocates everything. ==== 5.3 The projects subfolder ====''%%~/.claude/projects//%%''  * ''%%.jsonl%%'' — full transcript: every message, tool call, tool result. Powers resume, continue, rewind.  * ''%%/subagents/agent-.jsonl%%'' — subagent transcripts (+ ''%%.meta.json%%'').  * ''%%/tool-results/%%'' — large outputs spilled from context.  * ''%%memory/%%'' — auto memory (''%%MEMORY.md%%'' + topic files). **Retention and privacy**  * Transcripts and most session data are deleted after ''%%cleanupPeriodDays%%'' (default 30, minimum 1). Memory is exempt.  * **Plaintext, not encrypted.** If a tool reads ''%%.env%%'' or a command prints a token, it is on disk. Mitigate: lower retention, ''%%CLAUDE_CODE_SKIP_PROMPT_HISTORY%%'', ''%%--no-session-persistence%%'' with ''%%-p%%'', deny reads of secret files.  * ''%%claude purge [--dry-run] [--yes] [--all] [-i]%%'' — deletes a project's transcripts, memory, matching history and config entry; shows the plan first.  * Other data: ''%%history.jsonl%%'' (prompt recall, Ctrl+R), ''%%file-history/%%'' (checkpoint snapshots), ''%%plans/%%'', ''%%debug/%%'', ''%%paste-cache/%%'', ''%%tasks/%%''.  * Per-session **scratchpad** lives under the temp dir (''%%/tmp/claude-///scratchpad/%%'' on Linux): throwaway files, no permission prompts, removed with the transcript. ---- ===== 6. Instructions and memory ===== ==== 6.1 CLAUDE.md locations and load order ====^ Scope ^ Location ^ Shared with ^| Managed policy | Linux/WSL ''%%/etc/claude-code/CLAUDE.md%%''; macOS ''%%/Library/Application Support/ClaudeCode/CLAUDE.md%%'' | everyone on the machine; cannot be excluded || User | ''%%~/.claude/CLAUDE.md%%'' | you, all projects || Project | ''%%./CLAUDE.md%%'' or ''%%./.claude/CLAUDE.md%%'' | team via git || Local | ''%%./CLAUDE.local.md%%'' | you, this project |  * Loaded from the working directory **and every parent**; **concatenated**, not overriding. Ordered root -> cwd, so the nearest file is read last; ''%%CLAUDE.local.md%%'' follows ''%%CLAUDE.md%%'' at each level.  * Subdirectory CLAUDE.md files load **lazily**, when the agent reads/edits a file there.  * Delivered as a user message after the system prompt: context, not enforced configuration.  * After ''%%/compact%%'', the root CLAUDE.md is re-read from disk. Instructions given only in chat can be lost.  * ''%%claudeMdExcludes%%'' (glob list, any settings layer) skips other teams' files in monorepos.  * ''%%--add-dir%%'' directories' CLAUDE.md load only with ''%%CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1%%''. ==== 6.2 AGENTS.md ====  * No CLAUDE.md/CLAUDE.local.md in cwd or above -> AGENTS.md is read automatically.  * Both present -> only CLAUDE.md (default ''%%claude-md-or-agents-md%%''). Change via ''%%/config%%'' -> **Project instructions**: ''%%claude-md-and-agents-md%%'', ''%%claude-md%%'', ''%%managed-only%%''.  * Portable alternative: a CLAUDE.md containing ''%%@AGENTS.md%%'' plus Claude-specific lines. ==== 6.3 What to write ====Add a line when: the same mistake happens twice; a code review catches something it should have known; you type the same correction as last session; a new teammate would need it. Good content:  * How to confirm work: exact test/typecheck/lint commands; how to run one test file.  * Misleading code: legacy patterns not to copy; directories that look dead but are live.  * Decisions not in the repo: chosen error helper, deploy flow, migration review rules.  * Anything corrected twice.# Commands- Install: pnpm install- Run one test file: pnpm vitest run path/to/file.test.ts- Typecheck: pnpm tsc --noEmit # Conventions- Use the error helpers in src/lib/errors.ts, never throw raw strings- src/legacy/ is still live but don't copy its patterns into new code # Gotchas- Integration tests need DATABASE_URL set, see .env.example**Style:** under 200 lines; concrete and verifiable ("2-space indentation", not "format nicely"); grouped under headers; no contradictions (the model may pick either side). **Mechanics**  * ''%%@path/to/file%%'' imports (relative to the importing file; max depth 4). Organisation only — no context saving. Paths outside the project need one-time approval. Backticks keep a path literal.  * Block HTML comments are stripped before injection: free maintainer notes.  * ''%%/init%%'' drafts a starting file (or proposes improvements). ''%%CLAUDE_CODE_NEW_INIT=1%%'' for an interactive flow covering CLAUDE.md, skills and hooks.  * ''%%/doctor%%'' proposes trims; ''%%/doctor prompt-audit%%'' flags stale, broken or contradictory instructions across CLAUDE.md, rules, skills, agents.  * Files over 4 MiB are skipped entirely. ==== 6.4 Path-scoped rules ====  * ''%%.claude/rules/*.md%%'' (recursive). One topic per file.  * No frontmatter = loads at session start like CLAUDE.md.  * ''%%paths:%%'' frontmatter = loads only when the agent reads/writes/edits a matching file.---paths:  - "src/api/**/*.ts"---- Validate request bodies with the zod schemas in src/api/schemas/- Every new endpoint needs an entry in openapi.yaml, CI fails without it  * Globs support brace expansion: ''%%src/**/*.{ts,tsx}%%''.  * User rules in ''%%~/.claude/rules/%%'' load before project rules; neither overrides — keep consistent.  * Symlinked shared rule dirs work; targets outside the project need approval.  * On-demand files over a per-file limit (40k chars on 200K context; 150k on 1M with current models) are truncated with a "read the rest" note. ==== 6.5 Auto memory ====  * The agent writes notes for itself: ''%%user%%'' (role, expertise, preferences), ''%%feedback%%'' (corrections, confirmed approaches), ''%%project%%'' (decisions/deadlines not derivable from code), ''%%reference%%'' (where external info lives). Skips anything derivable from code or already in CLAUDE.md.  * Location ''%%~/.claude/projects//memory/%%''; keyed on the git repo, so **all worktrees share it**. Machine-local.  * ''%%MEMORY.md%%'' index, one line per memory; first **200 lines or 25 KB** load each session. Topic files are read on demand.  * "Remember X" -> auto memory. "Add X to CLAUDE.md" -> the shared file.  * ''%%/memory%%'': list/open all instruction files and the memory folder; toggle auto memory. Per project: ''%%"autoMemoryEnabled": false%%''. Env: ''%%CLAUDE_CODE_DISABLE_AUTO_MEMORY=1%%''. ==== 6.6 Debugging instructions ====  - ''%%/context%%'' — is the file under **Memory files**?  - Too long? The line gets lost.  - Contradicted elsewhere (other CLAUDE.md, rules)?  - Vague? Make it concrete.  - Must it always hold? -> hook or deny rule.  - Conflicts with built-in git guidance? ''%%includeGitInstructions%%'', ''%%attribution%%'' settings.  * ''%%InstructionsLoaded%%'' hook logs exactly which files loaded, when, and why. ---- ===== 7. Skills ===== ==== 7.1 What and why ====A folder with ''%%SKILL.md%%'' (YAML frontmatter + markdown body) plus optional supporting files. Follows the open Agent Skills standard. Custom commands are merged into skills (''%%.claude/commands/deploy.md%%'' and ''%%.claude/skills/deploy/SKILL.md%%'' both create ''%%/deploy%%''). **Progressive disclosure:** only name + description sit in context every session; the body loads when invoked (by ''%%/name%%'' or by the agent judging it relevant). ^ Put it in ^ When ^| CLAUDE.md | facts true for every task || rules with ''%%paths:%%'' | facts for one part of the codebase || skill | procedures and task-specific knowledge (release, runbook, doc style) | **Write one when** you keep pasting the same instructions/checklist, or a CLAUDE.md section has become a procedure. **Do not** write one for what the model already does well — it adds context and can degrade output. Measure (7.11). ==== 7.2 Locations and precedence ====^ Location ^ Path ^ Loads in ^| Enterprise | managed settings dir ''%%.claude/skills/%%'' | all users on managed machines || Personal | ''%%~/.claude/skills//SKILL.md%%'' | your local projects (not cloud/Cowork) || Project | ''%%.claude/skills//SKILL.md%%'' | this repo (commit for team) || Nested | ''%%/.claude/skills/%%'' | once the agent works in that subdir || Plugin | ''%%/skills//SKILL.md%%'' | as ''%%/plugin:skill%%'' || claude.ai account | synced to ''%%~/.claude/skills/synced/%%'' | Cowork, cloud, signed-in terminal sessions |  * Name clashes: enterprise > personal > project. A local skill replaces a bundled command of the same name (not its aliases).  * **Cloud sessions and cloud scheduled tasks do not read ''%%~/.claude/skills/%%''.** Enable the skill on your account or commit it to the repo.  * Edits to ''%%SKILL.md%%'' are picked up live; new top-level dirs need ''%%/reload-skills%%''. ==== 7.3 Frontmatter ====^ Field ^ Use ^| ''%%description%%'' | **most important**: what and when; main use case first; words users would say. With ''%%when_to_use%%'' capped at 1,536 chars in the listing || ''%%name%%'' | command name (defaults to folder name) || ''%%disable-model-invocation: true%%'' | only you can run it (deploy, commit, send). Also hides description from context || ''%%user-invocable: false%%'' | only the agent can load it (background knowledge) || ''%%allowed-tools%%'' | pre-approves tools for the invoking turn only; not a restriction || ''%%disallowed-tools%%'' | removes tools while active || ''%%model%%'', ''%%effort%%'' | override for that turn || ''%%paths%%'' | auto-activate only for matching files || ''%%hooks%%'' | register hooks for the rest of the session || ''%%context: fork%%'' + ''%%agent%%'' | run as a subagent (7.8) || ''%%arguments%%'', ''%%argument-hint%%'' | named arguments and autocomplete hint || ''%%shell%%'' | ''%%bash%%'' or ''%%powershell%%'' for injected commands | **Security note:** ''%%allowed-tools%%'' is **not gated by workspace trust** — a skill committed to a cloned repo can grant itself broad access, even in ''%%-p%%'' runs. Read the ''%%allowed-tools%%'' of repo skills before running there. Managed ''%%allowManagedPermissionRulesOnly%%'' neutralises it. Example (user-only, side-effecting):---name: releasedescription: Cut a new release. Bumps version, writes changelog, tags and pushes so CI publishes.disable-model-invocation: trueallowed-tools: Bash(git add *) Bash(git commit *) Bash(git tag *) Bash(git push *)---1. Ensure you are on main with a clean tree. If not, stop and ask.2. Run `pnpm changeset version` and commit the result.3. Summarise PRs merged since the last tag into CHANGELOG.md, one line each.4. Tag `v` and push the tag. CI publishes; never publish locally. ==== 7.4 Invocation control ====^ Frontmatter ^ You invoke ^ Agent invokes ^ In context ^| default | yes | yes | description always; body on invoke || ''%%disable-model-invocation: true%%'' | yes | no | nothing until invoked || ''%%user-invocable: false%%'' | no | yes | description always; body on invoke |''%%/name args%%'' at the start of a message runs it directly; mid-sentence ''%%/name%%'' only permits the agent to run it. ==== 7.5 Content lifecycle ====  * On invocation the rendered body enters the conversation **once** and stays; it is **not re-read** on later turns. Write **standing instructions** ("run tests after every edit"), not one-time steps.  * Re-invoking with identical content adds only a note; changed content (new args/injected output) appends the full body again.  * **Compaction** re-attaches each invoked skill's **first 5,000 tokens**, sharing a **25,000-token** budget filled from the most recent. Put critical lines at the top; re-invoke after compaction if it drifts.  * Absolute rules -> a hook (can live in the skill's ''%%hooks%%'' frontmatter). ==== 7.6 Arguments and substitutions ====  * ''%%$ARGUMENTS%%'' (all), ''%%$ARGUMENTS[N]%%'' / ''%%$N%%'' (0-based, shell-style quoting), ''%%$name%%'' (from ''%%arguments:%%'').  * No placeholder present -> ''%%ARGUMENTS: %%'' is appended.  * ''%%${CLAUDE_SKILL_DIR}%%'', ''%%${CLAUDE_PROJECT_DIR}%%'', ''%%${CLAUDE_SESSION_ID}%%'', ''%%${CLAUDE_EFFORT}%%'', plugin ''%%${CLAUDE_PLUGIN_ROOT}%%''/''%%${CLAUDE_PLUGIN_DATA}%%''.  * Escape a literal with backslash: ''%%\$1.00%%''. ==== 7.7 Injecting live data ====''%%!`command`%%'' (or a fenced block opened with ''%%```!%%'') runs **before** the model sees the skill; output replaces the placeholder.---name: pr-summarydescription: Summarize changes in a pull requestcontext: forkagent: Exploreallowed-tools: Bash(gh *)---- PR diff: !`gh pr diff`- PR comments: !`gh pr view --comments`Summarize this pull request...  * **Any non-zero exit aborts the whole invocation** (except exit 1 from search/compare commands). Append ''%%|| true%%'' where non-zero is normal.  * Each command is checked against permission rules; one that would prompt aborts the skill (outside auto mode) — pre-approve via ''%%allowed-tools%%''.  * Runs in the session shell's cwd, 2-minute timeout, large output spilled to file.  * Not executed locally for skills synced from claude.ai. ''%%disableSkillShellExecution%%'' turns it off (managed). ==== 7.8 Forked skills ====  * ''%%context: fork%%'' runs the body as a new subagent's prompt. **No conversation history** — instructions must stand alone; a conventions-only skill gives it nothing to do.  * Runs in the **background** by default; ''%%background: false%%'' to wait.  * ''%%agent: Explore%%'' or ''%%Plan%%'' start without CLAUDE.md — put everything needed in the skill.  * Background forks edit outside checkpoints; ''%%/rewind%%'' will not undo them. ==== 7.9 Supporting files ====my-skill/├── SKILL.md        (overview + navigation, < 500 lines)├── reference.md    (loaded when needed)├── examples.md└── scripts/helper.py  (executed, not loaded)Link files from ''%%SKILL.md%%'' so the agent knows when to read them. Pair ''%%${CLAUDE_SKILL_DIR}/scripts/x.sh%%'' in the body with ''%%allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/x.sh *)%%'' to run without a prompt. ==== 7.10 Bundled skills ====''%%/doctor%%'' (setup checkup, fixes on confirmation), ''%%/doctor prompt-audit%%'', ''%%/code-review%%'', ''%%/batch%%'', ''%%/debug%%'', ''%%/loop%%'', ''%%/claude-api%%'' (migrate, upgrade, cost-optimize, build-eval…), ''%%/run%%'', ''%%/verify%%'', ''%%/run-skill-generator%%'' (records your launch recipe as ''%%.claude/skills/run-/%%'').If a project skill named ''%%verify%%'' or ''%%simplify%%'' exists at session start, built-in commit instructions tell the agent to run it before each commit. ==== 7.11 Managing and measuring ====  * Skill listing budget ~1% of context; overflow drops descriptions of least-used skills first.  * ''%%/skills%%'' — set each to on / name-only / user-only / off (writes ''%%skillOverrides%%'' to ''%%settings.local.json%%'').  * ''%%/skill-doctor%%'' — context cost vs actual use; prune unused.  * Permission rules: ''%%Skill(name)%%'', ''%%Skill(name *)%%''; deny ''%%Skill%%'' to disable all.  * **Evaluate:** realistic prompts, each in a fresh session with the skill on and with it off; compare. Tools: skill-creator plugin (''%%/plugin install skill-creator@claude-plugins-official%%''), ''%%claude plugin eval%%'' for plugin skills (CI gate).  * Troubleshoot: not triggering -> description keywords, YAML parse (''%%claude plugin validate .claude/skills%%''); triggers too often -> narrow description or user-only; drifts -> standing wording, re-invoke, hook. ---- ===== 8. Permissions, modes and the sandbox ===== ==== 8.1 Three layers ====  * **Rules** — which tools/commands/files/domains are allowed, prompted or refused.  * **Modes** — the baseline for everything the rules do not decide.  * **Sandbox** — OS-level confinement of shell commands (filesystem + network), independent of intent.Permissions are enforced by the harness. Prompts and CLAUDE.md shape what the agent //tries//, not what it is //allowed//. ==== 8.2 Rule evaluation ====  * Lists: ''%%allow%%'', ''%%ask%%'', ''%%deny%%'' under ''%%permissions%%''. Manage with ''%%/permissions%%''.  * Order: **deny -> ask -> allow; first match wins; specificity does not matter.** (Unlike a line-ordered ACL, ordering is by verdict class.) A broad deny beats a narrow allow; an ask beats a narrower allow.  * Across scopes: a deny anywhere beats an allow anywhere. Managed settings beat everything, including CLI flags.  * Bare tool name in deny (''%%Bash%%'') **removes the tool** from context. Scoped (''%%Bash(rm *)%%'') blocks matching calls only.{ "permissions": {    "allow": ["Bash(npm run *)", "Bash(git commit *)"],    "ask":   ["Bash(git push *)"],    "deny":  ["Read(./.env)", "Read(./.env.local)", "Read(./secrets/**)"] } } ==== 8.3 Bash rule syntax ====^ Rule ^ Matches ^ Does not match ^| ''%%Bash(npm run build)%%'' | exactly that | ''%%npm run build --watch%%'' || ''%%Bash(npm run *)%%'' | ''%%npm run build%%'', ''%%npm run%%'' | ''%%npm install%%'' || ''%%Bash(git log *)%%'' | all ''%%git log%%'' | ''%%git push%%'' || ''%%Bash(git *)%%'' | **every** git command, incl. ''%%git -c core.fsmonitor=