SpyBara
Go Premium

Documentation 2026-03-26 21:07 UTC to 2026-03-27 21:09 UTC

19 files changed +3,227 −66. View all changes and history on the product overview
2026
Tue 31 21:09 Mon 30 21:13 Sat 28 18:04 Fri 27 21:09 Thu 26 21:07 Wed 25 21:08 Tue 24 18:15 Mon 23 21:08 Sun 22 18:04 Sat 21 18:03 Fri 20 21:05 Thu 19 06:17 Wed 18 18:16 Tue 17 21:10 Mon 16 21:10 Sat 14 03:44 Fri 13 21:07 Thu 12 21:07 Wed 11 03:43 Tue 10 03:43 Mon 9 21:06 Sat 7 03:37 Fri 6 06:10 Thu 5 06:12 Wed 4 21:06 Sun 1 06:10

agent-teams.md +1 −1

Details

101 `tmux` has known limitations on certain operating systems and traditionally works best on macOS. Using `tmux -CC` in iTerm2 is the suggested entrypoint into `tmux`.101 `tmux` has known limitations on certain operating systems and traditionally works best on macOS. Using `tmux -CC` in iTerm2 is the suggested entrypoint into `tmux`.

102</Note>102</Note>

103 103 

104The default is `"auto"`, which uses split panes if you're already running inside a tmux session, and in-process otherwise. The `"tmux"` setting enables split-pane mode and auto-detects whether to use tmux or iTerm2 based on your terminal. To override, set `teammateMode` in your [settings.json](/en/settings):104The default is `"auto"`, which uses split panes if you're already running inside a tmux session, and in-process otherwise. The `"tmux"` setting enables split-pane mode and auto-detects whether to use tmux or iTerm2 based on your terminal. To override, set `teammateMode` in your [global config](/en/settings#global-config-settings) at `~/.claude.json`:

105 105 

106```json theme={null}106```json theme={null}

107{107{

Details

20 20 

21Claude's context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.21Claude's context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.

22 22 

23This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start "forgetting" earlier instructions or making more mistakes. The context window is the most important resource to manage. Track context usage continuously with a [custom status line](/en/statusline), and see [Reduce token usage](/en/costs#reduce-token-usage) for strategies on reducing token usage.23This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start "forgetting" earlier instructions or making more mistakes. The context window is the most important resource to manage. To see how a session fills up in practice, [watch an interactive walkthrough](/en/context-window) of what loads at startup and what each file read costs. Track context usage continuously with a [custom status line](/en/statusline), and see [Reduce token usage](/en/costs#reduce-token-usage) for strategies on reducing token usage.

24 24 

25***25***

26 26 

claude-directory.md +1463 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Explore the .claude directory

6 

7> Where Claude Code reads CLAUDE.md, settings.json, hooks, skills, commands, subagents, rules, and auto memory. Explore the .claude directory in your project and ~/.claude in your home directory.

8 

9export const ClaudeExplorer = () => {

10 const A = useMemo(() => ({href, children}) => <a href={href} style={{

11 color: 'var(--ce-accent)',

12 textDecoration: 'none',

13 borderBottom: '1px dotted var(--ce-accent)'

14 }}>{children}</a>, []);

15 const C = useMemo(() => ({children}) => <code style={{

16 fontFamily: 'var(--ce-mono)',

17 fontSize: '0.92em',

18 padding: '1px 4px',

19 borderRadius: '3px',

20 background: 'var(--ce-surface)',

21 border: '0.5px solid var(--ce-border-subtle)'

22 }}>{children}</code>, []);

23 const commandsNote = useMemo(() => <>Commands and skills are now the same mechanism. For new workflows, use <A href="/en/skills">skills/</A> instead: same <C>/name</C> invocation, plus you can bundle supporting files.</>, []);

24 const FILE_TREE = useMemo(() => ({

25 project: {

26 label: 'your-project/',

27 children: [{

28 id: 'claude-md',

29 label: 'CLAUDE.md',

30 type: 'file',

31 icon: 'md',

32 color: '#6A9BCC',

33 badge: 'committed',

34 oneLiner: 'Project instructions Claude reads every session',

35 when: 'Loaded into context at the start of every session',

36 description: 'Project-specific instructions that shape how Claude works in this repository. Put your conventions, common commands, and architectural context here so Claude operates with the same assumptions your team does.',

37 tips: ['Target under 200 lines. Longer files still load in full but may reduce adherence', <>CLAUDE.md loads into every session. If something only matters for specific tasks, move it to a <A href="/en/skills">skill</A> or a path-scoped <A href="/en/memory#organize-rules-with-claude/rules/">rule</A> so it loads only when needed</>, 'List the commands you run most, like build, test, and format, so Claude knows them without you spelling them out each time', <>Run <C>/memory</C> to open and edit CLAUDE.md from within a session</>, <>Also works at <C>.claude/CLAUDE.md</C> if you prefer to keep the project root clean</>],

38 exampleIntro: 'This example is for a TypeScript and React project. It lists the build and test commands, the framework conventions Claude should follow, and project-specific rules like export style and file layout.',

39 example: `# Project conventions

40 

41## Commands

42- Build: \`npm run build\`

43- Test: \`npm test\`

44- Lint: \`npm run lint\`

45 

46## Stack

47- TypeScript with strict mode

48- React 19, functional components only

49 

50## Rules

51- Named exports, never default exports

52- Tests live next to source: \`foo.ts\` -> \`foo.test.ts\`

53- All API routes return \`{ data, error }\` shape`,

54 docsLink: '/en/memory'

55 }, {

56 id: 'mcp-json',

57 label: '.mcp.json',

58 type: 'file',

59 icon: 'json',

60 color: '#9B7BC4',

61 badge: 'committed',

62 oneLiner: 'Project-scoped MCP servers, shared with your team',

63 when: <>Servers connect when the session begins. Tool schemas are deferred by default and load on demand via <A href="/en/mcp#scale-with-mcp-tool-search">tool search</A></>,

64 description: <>Configures Model Context Protocol (MCP) servers that give Claude access to external tools: databases, APIs, browsers, and more. This file holds the project-scoped servers your whole team uses. Personal servers you want to keep to yourself go in <C>~/.claude.json</C> instead.</>,

65 tips: [<>Use environment variable references for secrets: <C>{'${GITHUB_TOKEN}'}</C></>, <>Lives at the project root, not inside <C>.claude/</C></>, <>For servers only you need, run <C>claude mcp add --scope user</C>. This writes to <C>~/.claude.json</C> instead of <C>.mcp.json</C></>],

66 exampleIntro: <>This example configures the GitHub MCP server so Claude can read issues and open pull requests. The <C>{'${GITHUB_TOKEN}'}</C> reference is read from your shell environment when Claude Code starts the server, so the token never lands in the file.</>,

67 example: `{

68 "mcpServers": {

69 "github": {

70 "command": "npx",

71 "args": ["-y", "@modelcontextprotocol/server-github"],

72 "env": {

73 "GITHUB_TOKEN": "\${GITHUB_TOKEN}"

74 }

75 }

76 }

77}`,

78 docsLink: '/en/mcp'

79 }, {

80 id: 'worktreeinclude',

81 label: '.worktreeinclude',

82 type: 'file',

83 icon: 'md',

84 color: '#8FA876',

85 badge: 'committed',

86 oneLiner: 'Gitignored files to copy into new worktrees',

87 when: <>Read when Claude creates a git worktree via <C>--worktree</C>, the <C>EnterWorktree</C> tool, or subagent <C>isolation: worktree</C></>,

88 description: <>Lists gitignored files to copy from your main repository into each new worktree. Worktrees are fresh checkouts, so untracked files like <C>.env</C> are missing by default. Patterns here use <C>.gitignore</C> syntax. Only files that match a pattern and are also gitignored get copied, so tracked files are never duplicated.</>,

89 tips: [<>Lives at the project root, not inside <C>.claude/</C></>, <>Git-only: if you configure a <A href="/en/hooks#worktreecreate">WorktreeCreate hook</A> for a different VCS, this file is not read. Copy files inside your hook script instead</>, <>Also applies to parallel sessions in the <A href="/en/desktop#work-in-parallel-with-sessions">desktop app</A></>],

90 exampleIntro: 'This example copies your local environment files and a secrets config into every worktree Claude creates. Comments start with # and blank lines are ignored, same as .gitignore.',

91 example: `# Local environment

92.env

93.env.local

94 

95# API credentials

96config/secrets.json`,

97 docsLink: '/en/common-workflows#copy-gitignored-files-to-worktrees'

98 }, {

99 id: 'dot-claude',

100 label: '.claude/',

101 type: 'folder',

102 icon: 'folder',

103 color: 'var(--ce-accent)',

104 oneLiner: 'Project-level configuration, rules, and extensions',

105 description: 'Everything Claude Code reads that is specific to this project. If you use git, commit most files here so your team shares them; a few, like settings.local.json, are automatically gitignored. Each file badge shows which.',

106 children: [{

107 id: 'settings-json',

108 label: 'settings.json',

109 type: 'file',

110 icon: 'json',

111 color: 'var(--ce-text-3)',

112 badge: 'committed',

113 oneLiner: 'Permissions, hooks, and configuration',

114 when: <>Overrides global <C>~/.claude/settings.json</C>. Local settings, CLI flags, and managed settings override this</>,

115 description: 'Settings that Claude Code applies directly. Permissions control which commands and tools Claude can use; hooks run your scripts at specific points in a session. Unlike CLAUDE.md, which Claude reads as guidance, these are enforced whether Claude follows them or not.',

116 contains: [<><A href="/en/permissions">permissions</A>: allow, deny, or prompt before Claude uses specific tools or commands</>, <><A href="/en/hooks">hooks</A>: run your own scripts on events like before a tool call or after a file edit</>, <><A href="/en/statusline">statusLine</A>: customize the line shown at the bottom while Claude works</>, <><A href="/en/settings#available-settings">model</A>: pick a default model for this project</>, <><A href="/en/settings#environment-variables">env</A>: environment variables set in every session</>, <><A href="/en/output-styles">outputStyle</A>: select a custom system-prompt style from output-styles/</>],

117 tips: [<>Bash permission patterns support wildcards: <C>Bash(npm test *)</C> matches any command starting with <C>npm test</C></>, <>Array settings like <C>permissions.allow</C> combine across all scopes; scalar settings like <C>model</C> use the most specific value</>],

118 exampleIntro: <>This example allows <C>npm test</C> and <C>npm run</C> commands without prompting, blocks <C>rm -rf</C>, and runs Prettier on files after Claude edits or writes them.</>,

119 example: `{

120 "permissions": {

121 "allow": [

122 "Bash(npm test *)",

123 "Bash(npm run *)"

124 ],

125 "deny": [

126 "Bash(rm -rf *)"

127 ]

128 },

129 "hooks": {

130 "PostToolUse": [{

131 "matcher": "Edit|Write",

132 "hooks": [{

133 "type": "command",

134 "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"

135 }]

136 }]

137 }

138}`,

139 docsLink: '/en/settings'

140 }, {

141 id: 'settings-local-json',

142 label: 'settings.local.json',

143 type: 'file',

144 icon: 'json',

145 color: 'var(--ce-text-3)',

146 badge: 'gitignored',

147 oneLiner: 'Your personal settings overrides for this project',

148 when: 'Highest of the user-editable settings files; CLI flags and managed settings still take precedence',

149 description: 'Personal settings that take precedence over the project defaults. Same JSON format as settings.json, but not committed. Use this when you need different permissions or defaults than the team config.',

150 tips: [<>Same schema as settings.json. Array settings like <C>permissions.allow</C> combine across scopes; scalar settings like <C>model</C> use the local value</>, <>Claude Code adds this file to <C>~/.config/git/ignore</C> the first time it writes one. If you use a custom <C>core.excludesFile</C>, add the pattern there too. To share the ignore rule with your team, also add it to the project <C>.gitignore</C></>],

151 exampleIntro: 'This example adds Docker permissions on top of whatever the team settings.json allows.',

152 example: `{

153 "permissions": {

154 "allow": [

155 "Bash(docker *)"

156 ]

157 }

158}`,

159 docsLink: '/en/settings'

160 }, {

161 id: 'rules',

162 label: 'rules/',

163 type: 'folder',

164 icon: 'folder',

165 color: '#9B7BC4',

166 oneLiner: 'Topic-scoped instructions, optionally gated by file paths',

167 when: <>Rules without <C>paths:</C> load at session start. Rules with <C>paths:</C> load when a matching file enters context</>,

168 description: [<>Project instructions split into topic files that can load conditionally based on file paths. A rule without <C>paths:</C> frontmatter loads at session start like CLAUDE.md; a rule with <C>paths:</C> loads only when Claude reads a matching file.</>, <>Like CLAUDE.md, rules are guidance Claude reads, not configuration Claude Code enforces. For guaranteed behavior use <A href="/en/hooks">hooks</A> or <A href="/en/permissions">permissions</A>.</>],

169 tips: [<>Use <C>paths:</C> frontmatter with globs to scope rules to directories or file types</>, <>Subdirectories work: <C>.claude/rules/frontend/react.md</C> is discovered automatically</>, 'When CLAUDE.md approaches 200 lines, start splitting into rules'],

170 docsLink: '/en/memory#organize-rules-with-claude/rules/',

171 children: [{

172 id: 'rule-testing',

173 label: 'testing.md',

174 type: 'file',

175 icon: 'md',

176 color: '#9B7BC4',

177 badge: 'committed',

178 oneLiner: 'Test conventions scoped to test files',

179 when: <>Loaded when Claude reads a file matching the <C>paths:</C> globs below</>,

180 description: <>An example rule that only loads when Claude is working on test files. The <C>paths:</C> globs in the frontmatter define which files trigger it; here, anything ending in .test.ts or .test.tsx. For other files, this rule is not loaded into context.</>,

181 example: `---

182paths:

183 - "**/*.test.ts"

184 - "**/*.test.tsx"

185---

186 

187# Testing Rules

188 

189- Use descriptive test names: "should [expected] when [condition]"

190- Mock external dependencies, not internal modules

191- Clean up side effects in afterEach`

192 }, {

193 id: 'rule-api',

194 label: 'api-design.md',

195 type: 'file',

196 icon: 'md',

197 color: '#9B7BC4',

198 badge: 'committed',

199 oneLiner: 'API conventions scoped to backend code',

200 when: <>Loaded when Claude reads a file matching the <C>paths:</C> glob below</>,

201 description: <>A second example showing a rule scoped to backend code. The <C>paths:</C> glob matches files under src/api/, so these conventions load only when Claude is editing API routes.</>,

202 example: `---

203paths:

204 - "src/api/**/*.ts"

205---

206 

207# API Design Rules

208 

209- All endpoints must validate input with Zod schemas

210- Return shape: { data: T } | { error: string }

211- Rate limit all public endpoints`

212 }]

213 }, {

214 id: 'skills',

215 label: 'skills/',

216 type: 'folder',

217 icon: 'folder',

218 color: '#D4A843',

219 oneLiner: 'Reusable prompts you or Claude invoke by name',

220 when: <>Invoked with <C>/skill-name</C> or when Claude matches the task to a skill</>,

221 description: <>Each skill is a folder with a SKILL.md file plus any supporting files it needs. By default, both you and Claude can invoke a skill. Use frontmatter to control that: <C>disable-model-invocation: true</C> for user-only workflows like <C>/deploy</C>, or <C>user-invocable: false</C> to hide from the <C>/</C> menu while Claude can still invoke it.</>,

222 tips: [<>Skills accept arguments: <C>/deploy staging</C> passes "staging" as <C>$ARGUMENTS</C>. Use <C>$0</C>, <C>$1</C>, and so on for positional access</>, <>The <C>description</C> frontmatter determines when Claude auto-invokes the skill</>, 'Bundle reference docs alongside SKILL.md. Claude knows the skill directory path and can read supporting files when you mention them'],

223 docsLink: '/en/skills',

224 children: [{

225 id: 'skill-review',

226 label: 'security-review/',

227 type: 'folder',

228 icon: 'folder',

229 color: '#D4A843',

230 oneLiner: 'A skill bundling SKILL.md with supporting files',

231 children: [{

232 id: 'skill-review-md',

233 label: 'SKILL.md',

234 type: 'file',

235 icon: 'md',

236 color: '#D4A843',

237 badge: 'committed',

238 oneLiner: 'Entrypoint: trigger, invocability, instructions',

239 when: <>User types <C>/security-review &lt;target&gt;</C>; Claude cannot auto-invoke this skill</>,

240 description: [<>This skill uses <C>disable-model-invocation: true</C> so only you can trigger it; Claude never invokes it on its own.</>, <>The <C>!`...`</C> line runs a shell command and injects its output into the prompt. <C>$ARGUMENTS</C> substitutes whatever you typed after the skill name. Claude sees the skill directory path, so mentioning a bundled file like checklist.md lets Claude read it.</>],

241 example: `---

242description: Reviews code changes for security vulnerabilities, authentication gaps, and injection risks

243disable-model-invocation: true

244argument-hint: <branch-or-path>

245---

246 

247## Diff to review

248 

249!\`git diff $ARGUMENTS\`

250 

251Audit the changes above for:

252 

2531. Injection vulnerabilities (SQL, XSS, command)

2542. Authentication and authorization gaps

2553. Hardcoded secrets or credentials

256 

257Use checklist.md in this skill directory for the full review checklist.

258 

259Report findings with severity ratings and remediation steps.`

260 }, {

261 id: 'skill-checklist',

262 label: 'checklist.md',

263 type: 'file',

264 icon: 'md',

265 color: '#D4A843',

266 badge: 'committed',

267 oneLiner: 'Supporting file bundled with the skill',

268 when: 'Claude reads it when SKILL.md mentions it',

269 description: <>Skills can bundle any supporting files: reference docs, templates, scripts. The skill directory path is prepended to SKILL.md, so Claude can read bundled files by name. For scripts in bash injection commands, use the <C>{'${CLAUDE_SKILL_DIR}'}</C> placeholder.</>,

270 example: `# Security Review Checklist

271 

272## Input Validation

273- [ ] All user input sanitized before DB queries

274- [ ] File upload MIME types validated

275- [ ] Path traversal prevented on file operations

276 

277## Authentication

278- [ ] JWT tokens expire after 24 hours

279- [ ] API keys stored in environment variables

280- [ ] Passwords hashed with bcrypt or argon2`

281 }]

282 }]

283 }, {

284 id: 'commands',

285 label: 'commands/',

286 type: 'folder',

287 icon: 'folder',

288 color: '#788C5D',

289 oneLiner: <>Single-file prompts invoked with <C>/name</C></>,

290 note: commandsNote,

291 when: <>User types <C>/command-name</C></>,

292 description: <>A file at <C>commands/deploy.md</C> creates <C>/deploy</C> the same way a skill at <C>skills/deploy/SKILL.md</C> does, and both can be auto-invoked by Claude. Skills use a directory with SKILL.md, letting you bundle reference docs, templates, or scripts alongside the prompt.</>,

293 tips: [<>Use <C>$ARGUMENTS</C> in the file to accept parameters: <C>/fix-issue 123</C></>, 'If a skill and command share a name, the skill takes precedence', 'New commands should usually be skills instead; commands remain supported'],

294 docsLink: '/en/skills',

295 children: [{

296 id: 'cmd-example',

297 label: 'fix-issue.md',

298 type: 'file',

299 icon: 'md',

300 color: '#788C5D',

301 badge: 'committed',

302 oneLiner: <>Invoked as <C>/fix-issue &lt;number&gt;</C></>,

303 note: commandsNote,

304 description: [<>An example command for fixing a GitHub issue. Type <C>/fix-issue 123</C> and the <C>!`...`</C> line runs <C>gh issue view 123</C> in your shell, injecting the output into the prompt before Claude sees it.</>, <><C>$ARGUMENTS</C> substitutes whatever you typed after the command name. For positional access, use <C>$0</C> <C>$1</C> and so on.</>],

305 example: `---

306argument-hint: <issue-number>

307---

308 

309!\`gh issue view $ARGUMENTS\`

310 

311Investigate and fix the issue above.

312 

3131. Trace the bug to its root cause

3142. Implement the fix

3153. Write or update tests

3164. Summarize what you changed and why`

317 }]

318 }, {

319 id: 'output-styles',

320 label: 'output-styles/',

321 type: 'folder',

322 icon: 'folder',

323 color: '#5AA7A7',

324 oneLiner: 'Project-scoped output styles, if your team shares any',

325 when: 'Applied at session start when selected via the outputStyle setting',

326 description: <>Output styles are usually personal, so most live in <C>~/.claude/output-styles/</C>. Put one here if your team shares a style, like a review mode everyone uses. See <A href="#ce-global-output-styles">the Global tab</A> for the full explanation and example.</>,

327 docsLink: '/en/output-styles',

328 children: []

329 }, {

330 id: 'agents',

331 label: 'agents/',

332 type: 'folder',

333 icon: 'folder',

334 color: '#C46686',

335 oneLiner: 'Specialized subagents with their own context window',

336 when: 'Runs in its own context window when you or Claude invoke it',

337 description: 'Each markdown file defines a subagent with its own system prompt, tool access, and optionally its own model. Subagents run in a fresh context window, keeping the main conversation clean. Useful for parallel work or isolated tasks.',

338 tips: ['Each agent gets a fresh context window, separate from your main session', <>Restrict tool access per agent with the <C>tools:</C> frontmatter field</>, 'Type @ and pick an agent from the autocomplete to delegate directly'],

339 docsLink: '/en/sub-agents',

340 children: [{

341 id: 'agent-reviewer',

342 label: 'code-reviewer.md',

343 type: 'file',

344 icon: 'md',

345 color: '#C46686',

346 badge: 'committed',

347 oneLiner: 'Subagent for isolated code review',

348 when: 'Claude spawns it for review tasks, or you @-mention it from the autocomplete',

349 description: <>An example subagent restricted to read-only tools. The <C>description</C> frontmatter tells Claude when to delegate to it automatically; <C>tools:</C> limits it to Read, Grep, and Glob so it can inspect code but never edit. The body becomes the subagent's system prompt.</>,

350 example: `---

351name: code-reviewer

352description: Reviews code for correctness, security, and maintainability

353tools: Read, Grep, Glob

354---

355 

356You are a senior code reviewer. Review for:

357 

3581. Correctness: logic errors, edge cases, null handling

3592. Security: injection, auth bypass, data exposure

3603. Maintainability: naming, complexity, duplication

361 

362Every finding must include a concrete fix.`

363 }]

364 }, {

365 id: 'agent-memory',

366 label: 'agent-memory/',

367 type: 'folder',

368 icon: 'folder',

369 color: '#C46686',

370 badge: 'committed',

371 autogen: true,

372 oneLiner: 'Subagent persistent memory, separate from your main session auto memory',

373 when: 'First 200 lines (capped at 25KB) of MEMORY.md loaded into the subagent system prompt when it runs',

374 description: <>Subagents with <C>memory: project</C> in their frontmatter get a dedicated memory directory here. This is distinct from your <A href="/en/memory#auto-memory">main session auto memory</A> at <C>~/.claude/projects/</C>: each subagent reads and writes its own MEMORY.md, not yours.</>,

375 tips: [<>Only created for subagents that set the <C>memory:</C> frontmatter field</>, <>This directory holds project-scoped subagent memory, meant to be shared with your team. To keep memory out of version control use <C>memory: local</C>, which writes to <C>.claude/agent-memory-local/</C> instead. For cross-project memory use <C>memory: user</C>, which writes to <C>~/.claude/agent-memory/</C></>, <>The main session auto memory is a different feature; see <C>~/.claude/projects/</C> in the Global tab</>],

376 docsLink: '/en/sub-agents#enable-persistent-memory',

377 children: [{

378 id: 'agent-memory-sub',

379 label: '<agent-name>/',

380 type: 'folder',

381 icon: 'folder',

382 color: '#C46686',

383 autogen: true,

384 children: [{

385 id: 'agent-memory-md',

386 label: 'MEMORY.md',

387 type: 'file',

388 icon: 'md',

389 color: '#C46686',

390 badge: 'committed',

391 autogen: true,

392 oneLiner: 'The subagent writes and maintains this file automatically',

393 when: 'Loaded into the subagent system prompt when the subagent starts',

394 description: <>Works the same as your <A href="/en/memory#auto-memory">main auto memory</A>: the subagent creates and updates this file itself. You do not write it. The subagent reads it at the start of each task and writes back what it learns.</>,

395 example: `# code-reviewer memory

396 

397## Patterns seen

398- Project uses custom Result<T, E> type, not exceptions

399- Auth middleware expects Bearer token in Authorization header

400- Tests use factory functions in test/factories/

401 

402## Recurring issues

403- Missing null checks on API responses (src/api/*)

404- Unhandled promise rejections in background jobs`

405 }]

406 }]

407 }]

408 }]

409 },

410 global: {

411 label: '~/',

412 children: [{

413 id: 'claude-json',

414 label: '.claude.json',

415 type: 'file',

416 icon: 'json',

417 color: 'var(--ce-text-3)',

418 badge: 'local',

419 oneLiner: 'App state and UI preferences',

420 when: <>Read at session start for your preferences and MCP servers. Claude Code writes back to it when you change settings in <C>/config</C> or approve trust prompts</>,

421 description: <>Holds state that does not belong in settings.json: theme, OAuth session, per-project trust decisions, your personal MCP servers, and UI toggles. Mostly managed through <C>/config</C> rather than editing directly.</>,

422 tips: [<>UI toggles like <C>showTurnDuration</C> and <C>terminalProgressBarEnabled</C> live here, not in settings.json</>, <>The <C>projects</C> key tracks per-project state like trust-dialog acceptance and last-session metrics. Permission rules you approve in-session go to <C>.claude/settings.local.json</C> instead</>, <>MCP servers here are yours only: user scope applies across all projects, local scope is per-project but not committed. Team-shared servers go in <C>.mcp.json</C> at the project root instead</>],

423 example: `{

424 "editorMode": "vim",

425 "showTurnDuration": false,

426 "mcpServers": {

427 "my-tools": {

428 "command": "npx",

429 "args": ["-y", "@example/mcp-server"]

430 }

431 }

432}`,

433 docsLink: '/en/settings#global-config-settings'

434 }, {

435 id: 'global-dot-claude',

436 label: '.claude/',

437 type: 'folder',

438 icon: 'folder',

439 color: 'var(--ce-accent)',

440 oneLiner: 'Your personal configuration across all projects',

441 description: 'The global counterpart to your project .claude/ directory. Files here apply to every project you work in and are never committed to any repository.',

442 children: [{

443 id: 'global-claude-md',

444 label: 'CLAUDE.md',

445 type: 'file',

446 icon: 'md',

447 color: '#6A9BCC',

448 badge: 'local',

449 oneLiner: 'Personal preferences across every project',

450 when: 'Loaded at the start of every session, in every project',

451 description: 'Your global instruction file. Loaded alongside the project CLAUDE.md at session start, so both are in context together. When instructions conflict, project-level instructions take priority. Keep this to preferences that apply everywhere: response style, commit format, personal conventions.',

452 tips: ['Keep it short since it loads into context for every project, alongside that project\'s own CLAUDE.md', 'Good for response style, commit format, and personal conventions'],

453 example: `# Global preferences

454 

455- Keep explanations concise

456- Use conventional commit format

457- Show the terminal command to verify changes

458- Prefer composition over inheritance`,

459 docsLink: '/en/memory'

460 }, {

461 id: 'global-settings',

462 label: 'settings.json',

463 type: 'file',

464 icon: 'json',

465 color: 'var(--ce-text-3)',

466 badge: 'local',

467 oneLiner: 'Default settings for all projects',

468 when: 'Your defaults. Project and local settings.json override any keys you also set there',

469 description: [<>Same keys as project <C>settings.json</C>: permissions, hooks, model, environment variables, and the rest. Put settings here that you want in every project, like permissions you always allow, a preferred model, or a notification hook that runs regardless of which project you're in.</>, <>Settings follow a precedence order: project <C>settings.json</C> overrides any matching keys you set here. This is different from CLAUDE.md, where global and project files are both loaded into context rather than merged key by key.</>],

470 example: `{

471 "permissions": {

472 "allow": [

473 "Bash(git log *)",

474 "Bash(git diff *)"

475 ]

476 }

477}`,

478 docsLink: '/en/settings'

479 }, {

480 id: 'keybindings',

481 label: 'keybindings.json',

482 type: 'file',

483 icon: 'json',

484 color: 'var(--ce-text-3)',

485 badge: 'local',

486 oneLiner: 'Custom keyboard shortcuts',

487 when: 'Read at session start and hot-reloaded when you edit the file',

488 description: <>Rebind keyboard shortcuts in the interactive CLI. Run <C>/keybindings</C> to create or open this file with a schema reference. Ctrl+C, Ctrl+D, and Ctrl+M are reserved and cannot be rebound.</>,

489 exampleIntro: <>This example binds <C>Ctrl+E</C> to open your external editor and unbinds <C>Ctrl+U</C> by setting it to <C>null</C>. The <C>context</C> field scopes bindings to a specific part of the CLI, here the main chat input.</>,

490 example: `{

491 "$schema": "https://www.schemastore.org/claude-code-keybindings.json",

492 "$docs": "https://code.claude.com/docs/en/keybindings",

493 "bindings": [

494 {

495 "context": "Chat",

496 "bindings": {

497 "ctrl+e": "chat:externalEditor",

498 "ctrl+u": null

499 }

500 }

501 ]

502}`,

503 docsLink: '/en/keybindings'

504 }, {

505 id: 'global-projects',

506 label: 'projects/',

507 type: 'folder',

508 icon: 'folder',

509 color: '#E8A45C',

510 autogen: true,

511 oneLiner: "Auto memory: Claude's notes to itself, per project",

512 when: 'MEMORY.md loaded at session start; topic files read on demand',

513 description: 'Auto memory lets Claude accumulate knowledge across sessions without you writing anything. Claude saves notes as it works: build commands, debugging insights, architecture notes. Each project gets its own memory directory keyed by the repository path.',

514 tips: [<>On by default. Toggle with <C>/memory</C> or <C>autoMemoryEnabled</C> in settings</>, 'MEMORY.md is the index loaded each session. The first 200 lines, or 25KB, whichever comes first, are read', 'Topic files like debugging.md are read on demand, not at startup', 'These are plain markdown. Edit or delete them anytime'],

515 docsLink: '/en/memory#auto-memory',

516 children: [{

517 id: 'memory-dir',

518 label: '<project>/memory/',

519 type: 'folder',

520 icon: 'folder',

521 color: '#E8A45C',

522 autogen: true,

523 oneLiner: "Claude's accumulated knowledge for one project",

524 children: [{

525 id: 'memory-md',

526 label: 'MEMORY.md',

527 type: 'file',

528 icon: 'md',

529 color: '#E8A45C',

530 badge: 'local',

531 autogen: true,

532 oneLiner: 'Claude writes and maintains this file automatically',

533 when: 'First 200 lines (capped at 25KB) loaded at session start',

534 description: 'Claude creates and updates this file as it works; you do not write it yourself. It acts as an index that Claude reads at the start of every session, pointing to topic files for detail. You can edit or delete it, but Claude will keep updating it.',

535 example: `# Memory Index

536 

537## Project

538- [build-and-test.md](build-and-test.md): npm run build (~45s), Vitest, dev server on 3001

539- [architecture.md](architecture.md): API client singleton, refresh-token auth

540 

541## Reference

542- [debugging.md](debugging.md): auth token rotation and DB connection troubleshooting`,

543 docsLink: '/en/memory'

544 }, {

545 id: 'memory-topic',

546 label: 'debugging.md',

547 type: 'file',

548 icon: 'md',

549 color: '#E8A45C',

550 badge: 'local',

551 autogen: true,

552 oneLiner: 'Topic notes Claude writes when MEMORY.md gets long',

553 when: 'Claude reads this when a related task comes up',

554 description: 'An example of a topic file Claude creates when MEMORY.md grows too long. Claude picks the filename based on what it splits out: debugging.md, architecture.md, build-commands.md, or similar. You never create these yourself. Claude reads a topic file back only when the current task relates to it.',

555 example: `---

556name: Debugging patterns

557description: Auth token rotation and database connection troubleshooting for this project

558type: reference

559---

560 

561## Auth Token Issues

562- Refresh token rotation: old token invalidated immediately

563- If 401 after refresh: check clock skew between client and server

564 

565## Database Connection Drops

566- Connection pool: max 10 in dev, 50 in prod

567- Always check \`docker compose ps\` first`

568 }]

569 }]

570 }, {

571 id: 'global-rules',

572 label: 'rules/',

573 type: 'folder',

574 icon: 'folder',

575 color: '#9B7BC4',

576 oneLiner: 'User-level rules that apply to every project',

577 when: <>Rules without <C>paths:</C> load at session start. Rules with <C>paths:</C> load when a matching file enters context</>,

578 description: 'Same as project .claude/rules/ but applies everywhere. Use this for conventions you want across all your work, like personal code style or commit message format.',

579 docsLink: '/en/memory#organize-rules-with-claude/rules/',

580 children: []

581 }, {

582 id: 'global-skills',

583 label: 'skills/',

584 type: 'folder',

585 icon: 'folder',

586 color: '#D4A843',

587 oneLiner: 'Personal skills available in every project',

588 when: <>Invoked with <C>/skill-name</C> in any project</>,

589 description: 'Skills you built for yourself that work everywhere. Same structure as project skills: each is a folder with SKILL.md, scoped to your user account instead of a single project.',

590 docsLink: '/en/skills',

591 children: []

592 }, {

593 id: 'global-commands',

594 label: 'commands/',

595 type: 'folder',

596 icon: 'folder',

597 color: '#788C5D',

598 oneLiner: 'Personal single-file commands available in every project',

599 note: commandsNote,

600 when: <>User types <C>/command-name</C> in any project</>,

601 description: 'Same as project commands/ but scoped to your user account. Each markdown file becomes a command available everywhere.',

602 docsLink: '/en/skills',

603 children: []

604 }, {

605 id: 'global-output-styles',

606 label: 'output-styles/',

607 type: 'folder',

608 icon: 'folder',

609 color: '#5AA7A7',

610 oneLiner: 'Custom system-prompt sections that adjust how Claude works',

611 when: 'Applied at session start when selected via the outputStyle setting',

612 description: [<>Each markdown file defines an output style: a section appended to the system prompt that, by default, also drops the built-in software-engineering task instructions. Use this to adapt Claude Code for uses beyond coding, or to add teaching or review modes.</>, <>Select a built-in or custom style with <C>/config</C> or the <C>outputStyle</C> key in settings. Styles here are available in every project; project-level styles with the same name take precedence.</>],

613 tips: ['Built-in styles Explanatory and Learning are included with Claude Code; custom styles go here', <>Set <C>keep-coding-instructions: true</C> in frontmatter to keep the default task instructions alongside your additions</>, 'Changes take effect on the next session since the system prompt is fixed at startup for caching'],

614 docsLink: '/en/output-styles',

615 children: [{

616 id: 'output-style-example',

617 label: 'teaching.md',

618 type: 'file',

619 icon: 'md',

620 color: '#5AA7A7',

621 badge: 'local',

622 oneLiner: 'Example style that adds explanations and leaves small changes for you',

623 when: <>Active when <C>outputStyle</C> in settings is set to <C>teaching</C></>,

624 description: <>This style appends instructions to the system prompt: Claude adds a "Why this approach" note after each task and leaves TODO(human) markers for changes under 10 lines instead of writing them itself. Select it by setting <C>outputStyle</C> to the filename without .md, or to the <C>name</C> field if you set one in frontmatter.</>,

625 example: `---

626description: Explains reasoning and asks you to implement small pieces

627keep-coding-instructions: true

628---

629 

630After completing each task, add a brief "Why this approach" note

631explaining the key design decision.

632 

633When a change is under 10 lines, ask the user to implement it

634themselves by leaving a TODO(human) marker instead of writing it.`

635 }]

636 }, {

637 id: 'global-agents',

638 label: 'agents/',

639 type: 'folder',

640 icon: 'folder',

641 color: '#C46686',

642 oneLiner: 'Personal subagents available in every project',

643 when: 'Claude delegates or you @-mention in any project',

644 description: 'Subagents defined here are available across all your projects. Same format as project agents.',

645 docsLink: '/en/sub-agents',

646 children: []

647 }, {

648 id: 'global-agent-memory',

649 label: 'agent-memory/',

650 type: 'folder',

651 icon: 'folder',

652 color: '#C46686',

653 autogen: true,

654 oneLiner: <>Persistent memory for subagents with <C>memory: user</C></>,

655 when: 'Loaded into the subagent system prompt when the subagent starts',

656 description: <>Subagents with <C>memory: user</C> in their frontmatter store knowledge here that persists across all projects. For project-scoped subagent memory, see <C>.claude/agent-memory/</C> instead.</>,

657 docsLink: '/en/sub-agents#enable-persistent-memory',

658 children: []

659 }]

660 }]

661 }

662 }), []);

663 const BADGE_STYLES = useMemo(() => ({

664 committed: {

665 bg: 'rgba(85,138,66,0.08)',

666 color: 'var(--ce-badge-committed)',

667 border: 'rgba(85,138,66,0.15)',

668 label: 'committed'

669 },

670 gitignored: {

671 bg: 'rgba(217,119,87,0.06)',

672 color: 'var(--ce-badge-gitignored)',

673 border: 'rgba(217,119,87,0.15)',

674 label: 'gitignored'

675 },

676 local: {

677 bg: 'rgba(115,114,108,0.06)',

678 color: 'var(--ce-badge-local)',

679 border: 'rgba(115,114,108,0.12)',

680 label: 'local only'

681 },

682 autogen: {

683 bg: 'rgba(232,164,92,0.1)',

684 color: 'var(--ce-badge-autogen)',

685 border: 'rgba(232,164,92,0.2)',

686 label: 'Claude writes'

687 }

688 }), []);

689 const allNodes = useMemo(() => {

690 const flatten = (nodes, acc, path, parentId) => {

691 for (const node of nodes) {

692 const nextPath = [...path, node.label];

693 acc[node.id] = {

694 ...node,

695 path: nextPath,

696 parentId

697 };

698 if (node.children) flatten(node.children, acc, nextPath, node.id);

699 }

700 return acc;

701 };

702 const project = flatten(FILE_TREE.project.children, {}, [FILE_TREE.project.label]);

703 const global = flatten(FILE_TREE.global.children, {}, [FILE_TREE.global.label]);

704 for (const id in project) project[id].root = 'project';

705 for (const id in global) global[id].root = 'global';

706 return {

707 ...project,

708 ...global

709 };

710 }, [FILE_TREE]);

711 const allFolderIds = useMemo(() => Object.keys(allNodes).filter(id => allNodes[id].type === 'folder'), [allNodes]);

712 const DEFAULT_EXPANDED = ['dot-claude', 'rules', 'skills', 'skill-review', 'commands', 'agents', 'agent-memory', 'agent-memory-sub', 'global-dot-claude', 'global-output-styles', 'global-projects', 'memory-dir'];

713 const [mounted, setMounted] = useState(false);

714 const [activeRoot, setActiveRoot] = useState('project');

715 const [selectedId, setSelectedId] = useState('claude-md');

716 const [expandedFolders, setExpandedFolders] = useState(() => new Set(DEFAULT_EXPANDED));

717 const [forceMobile, setForceMobile] = useState(false);

718 const [copiedId, setCopiedId] = useState(null);

719 const [isFullscreen, setIsFullscreen] = useState(false);

720 const copyTimeoutRef = useRef(null);

721 const rootRef = useRef(null);

722 useEffect(() => {

723 setMounted(true);

724 const applyHash = scroll => {

725 const hash = window.location.hash.slice(1);

726 if (!hash.startsWith('ce-')) return;

727 const id = hash.slice(3);

728 const node = allNodes[id];

729 if (!node) return;

730 setActiveRoot(node.root);

731 setSelectedId(id);

732 setExpandedFolders(new Set(allFolderIds));

733 if (scroll && rootRef.current) rootRef.current.scrollIntoView({

734 behavior: 'smooth',

735 block: 'start'

736 });

737 };

738 applyHash(false);

739 const onHashChange = () => applyHash(true);

740 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);

741 window.addEventListener('hashchange', onHashChange);

742 document.addEventListener('fullscreenchange', onFsChange);

743 return () => {

744 if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);

745 window.removeEventListener('hashchange', onHashChange);

746 document.removeEventListener('fullscreenchange', onFsChange);

747 };

748 }, []);

749 useEffect(() => {

750 if (!mounted || !rootRef.current) return;

751 const hash = window.location.hash.slice(1);

752 if (hash.startsWith('ce-') && allNodes[hash.slice(3)]) {

753 rootRef.current.scrollIntoView({

754 behavior: 'smooth',

755 block: 'start'

756 });

757 }

758 }, [mounted]);

759 if (!mounted) return null;

760 const selected = allNodes[selectedId];

761 const tree = FILE_TREE[activeRoot];

762 const isCopied = copiedId === selected.id;

763 const toggleFolder = id => {

764 const next = new Set(expandedFolders);

765 next.has(id) ? next.delete(id) : next.add(id);

766 setExpandedFolders(next);

767 };

768 const switchRoot = root => {

769 if (root === activeRoot) return;

770 setActiveRoot(root);

771 const firstId = FILE_TREE[root].children[0].id;

772 setSelectedId(firstId);

773 try {

774 history.replaceState(null, '', '#ce-' + firstId);

775 } catch (e) {}

776 };

777 const toggleFullscreen = () => {

778 if (!rootRef.current) return;

779 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});

780 };

781 const selectNode = n => {

782 setSelectedId(n.id);

783 if (n.type === 'folder' && !expandedFolders.has(n.id)) toggleFolder(n.id);

784 try {

785 history.replaceState(null, '', '#ce-' + n.id);

786 } catch (e) {}

787 };

788 const iconBtn = {

789 width: 28,

790 flexShrink: 0,

791 borderRadius: '6px',

792 border: 'none',

793 cursor: 'pointer',

794 background: 'transparent',

795 color: 'var(--ce-text-4)',

796 display: 'flex',

797 alignItems: 'center',

798 justifyContent: 'center'

799 };

800 const visibleFolderIds = allFolderIds.filter(id => allNodes[id].root === activeRoot);

801 const allExpanded = visibleFolderIds.every(id => expandedFolders.has(id));

802 const toggleAllFolders = () => {

803 const next = new Set(expandedFolders);

804 visibleFolderIds.forEach(id => allExpanded ? next.delete(id) : next.add(id));

805 setExpandedFolders(next);

806 };

807 const onTreeKeyDown = e => {

808 if (!['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft'].includes(e.key)) return;

809 const visible = [];

810 const walk = nodes => {

811 for (const n of nodes) {

812 visible.push(n.id);

813 if (n.children && expandedFolders.has(n.id)) walk(n.children);

814 }

815 };

816 walk(tree.children);

817 const i = visible.indexOf(selectedId);

818 if (i === -1) return;

819 e.preventDefault();

820 if (e.key === 'ArrowDown' && i < visible.length - 1) selectNode(allNodes[visible[i + 1]]); else if (e.key === 'ArrowUp' && i > 0) selectNode(allNodes[visible[i - 1]]); else if (e.key === 'ArrowRight' && selected.type === 'folder') {

821 if (!expandedFolders.has(selectedId)) toggleFolder(selectedId); else if (selected.children && selected.children.length) selectNode(allNodes[selected.children[0].id]);

822 } else if (e.key === 'ArrowLeft') {

823 if (selected.type === 'folder' && expandedFolders.has(selectedId)) toggleFolder(selectedId); else if (selected.parentId) selectNode(allNodes[selected.parentId]);

824 }

825 };

826 const copyExample = (id, text) => {

827 const done = () => {

828 setCopiedId(id);

829 if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);

830 copyTimeoutRef.current = setTimeout(() => setCopiedId(null), 2000);

831 };

832 const fallback = () => {

833 const ta = document.createElement('textarea');

834 ta.value = text;

835 ta.style.position = 'fixed';

836 ta.style.opacity = '0';

837 document.body.appendChild(ta);

838 ta.select();

839 try {

840 if (document.execCommand('copy')) done();

841 } catch (e) {}

842 document.body.removeChild(ta);

843 };

844 if (navigator.clipboard) {

845 navigator.clipboard.writeText(text).then(done, fallback);

846 } else {

847 fallback();

848 }

849 };

850 const renderIcon = (icon, color, size) => {

851 const sz = size || 14;

852 if (icon === 'folder') {

853 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">

854 <path d="M1.5 3.5a1 1 0 0 1 1-1h2.6l1 1.2h5.4a1 1 0 0 1 1 1v5.8a1 1 0 0 1-1 1h-9a1 1 0 0 1-1-1V3.5z" fill={color} fillOpacity="0.15" stroke={color} strokeWidth="1" />

855 </svg>;

856 }

857 if (icon === 'json') {

858 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">

859 <rect x="2" y="1.5" width="10" height="11" rx="1.5" fill={color} fillOpacity="0.15" stroke={color} strokeWidth="1" />

860 <text x="7" y="9" fontSize="6" fontFamily="monospace" fill={color} textAnchor="middle" fontWeight="700">{'{}'}</text>

861 </svg>;

862 }

863 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">

864 <rect x="2" y="1.5" width="10" height="11" rx="1.5" fill={color} fillOpacity="0.15" stroke={color} strokeWidth="1" />

865 <line x1="4.5" y1="5" x2="9.5" y2="5" stroke={color} strokeWidth="1" />

866 <line x1="4.5" y1="7" x2="9.5" y2="7" stroke={color} strokeWidth="1" />

867 <line x1="4.5" y1="9" x2="8" y2="9" stroke={color} strokeWidth="1" />

868 </svg>;

869 };

870 const renderNode = (node, depth) => {

871 const isFolder = node.type === 'folder';

872 const isExpanded = expandedFolders.has(node.id);

873 const isSelected = selectedId === node.id;

874 return <div key={node.id}>

875 <button role="treeitem" tabIndex={-1} onClick={() => selectNode(node)} aria-selected={isSelected} aria-expanded={isFolder ? isExpanded : undefined} style={{

876 display: 'flex',

877 alignItems: 'center',

878 gap: '5px',

879 width: '100%',

880 padding: `4px 8px 4px ${8 + depth * 16}px`,

881 background: isSelected ? 'var(--ce-accent-bg)' : 'transparent',

882 borderTop: 'none',

883 borderRight: 'none',

884 borderBottom: 'none',

885 borderLeft: isSelected ? '2px solid var(--ce-accent)' : '2px solid transparent',

886 outline: 'none',

887 cursor: 'pointer',

888 textAlign: 'left',

889 fontFamily: 'var(--ce-mono)',

890 fontSize: '13.5px',

891 color: isSelected ? 'var(--ce-accent)' : 'var(--ce-text-2)',

892 fontWeight: isSelected ? 550 : 400,

893 transition: 'all 0.1s'

894 }}>

895 {isFolder ? <span onClick={e => {

896 e.stopPropagation();

897 toggleFolder(node.id);

898 }} style={{

899 fontSize: '14px',

900 color: 'var(--ce-text-4)',

901 width: '20px',

902 height: '20px',

903 display: 'inline-flex',

904 alignItems: 'center',

905 justifyContent: 'center',

906 cursor: 'pointer',

907 borderRadius: '4px',

908 marginLeft: '-6px',

909 flexShrink: 0

910 }} onMouseEnter={e => {

911 e.currentTarget.style.background = 'var(--ce-arrow-hover)';

912 e.currentTarget.style.color = 'var(--ce-text-2)';

913 }} onMouseLeave={e => {

914 e.currentTarget.style.background = 'transparent';

915 e.currentTarget.style.color = 'var(--ce-text-4)';

916 }}>{isExpanded ? '▾' : '▸'}</span> : <span style={{

917 width: '14px',

918 flexShrink: 0

919 }} />}

920 {renderIcon(node.icon, node.color)}

921 <span style={{

922 flex: 1,

923 overflow: 'hidden',

924 textOverflow: 'ellipsis',

925 whiteSpace: 'nowrap'

926 }}>{node.label}</span>

927 {node.badge && BADGE_STYLES[node.badge] && <span title={BADGE_STYLES[node.badge].label} style={{

928 width: 6,

929 height: 6,

930 borderRadius: '50%',

931 background: BADGE_STYLES[node.badge].color,

932 flexShrink: 0,

933 opacity: 0.7

934 }} />}

935 </button>

936 {isFolder && isExpanded && node.children && <div role="group">{node.children.map(child => renderNode(child, depth + 1))}</div>}

937 </div>;

938 };

939 return <>

940 <style>{`

941 .ce-root {

942 --ce-mono: var(--font-mono, ui-monospace, monospace);

943 --ce-accent: #D97757;

944 --ce-accent-bg: rgba(217,119,87,0.06);

945 --ce-accent-border: rgba(217,119,87,0.12);

946 --ce-bg: #fff;

947 --ce-surface: #FAFAF7;

948 --ce-surface-hover: #F0EEE6;

949 --ce-border: #E8E6DC;

950 --ce-border-subtle: #F0EEE6;

951 --ce-text: #141413;

952 --ce-text-2: #5E5D59;

953 --ce-text-3: #73726C;

954 --ce-text-4: #9C9A92;

955 --ce-text-5: #B8B6AE;

956 --ce-sep: #D1CFC5;

957 --ce-code-header: #F5F4ED;

958 --ce-code-bg: #1A1918;

959 --ce-arrow-hover: rgba(0,0,0,0.08);

960 --ce-badge-committed: #3d6b2e;

961 --ce-badge-gitignored: #b85c3a;

962 --ce-badge-local: #5e5d59;

963 --ce-badge-autogen: #b07520;

964 --ce-when-text: #4a7fb5;

965 }

966 .dark .ce-root {

967 --ce-bg: #1a1918;

968 --ce-surface: #232221;

969 --ce-surface-hover: #2e2d2b;

970 --ce-border: #3a3936;

971 --ce-border-subtle: #2e2d2b;

972 --ce-text: #e8e6dc;

973 --ce-text-2: #c4c2b8;

974 --ce-text-3: #9c9a92;

975 --ce-text-4: #73726c;

976 --ce-text-5: #5e5d59;

977 --ce-sep: #4a4946;

978 --ce-code-header: #2e2d2b;

979 --ce-code-bg: #0d0d0c;

980 --ce-arrow-hover: rgba(255,255,255,0.08);

981 --ce-badge-committed: #6fa85c;

982 --ce-badge-gitignored: #e08a60;

983 --ce-badge-local: #9c9a92;

984 --ce-badge-autogen: #e8a45c;

985 --ce-when-text: #8bb4e0;

986 }

987 .ce-mobile-fallback { display: none; border: 1px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.03); }

988 .dark .ce-mobile-fallback { border-color: rgba(255,255,255,0.15); background: rgba(255,255,255,0.04); }

989 @media (max-width: 700px) {

990 .ce-root:not(.ce-force) { display: none !important; }

991 .ce-mobile-fallback { display: block; }

992 }

993 `}</style>

994 {!forceMobile && <div className="ce-mobile-fallback" style={{

995 padding: '14px 16px',

996 borderRadius: '8px',

997 fontSize: '14px'

998 }}>

999 The interactive explorer works best on a larger screen. See the <a href="#file-reference" style={{

1000 color: '#D97757'

1001 }}>file reference table</a> below, or <button onClick={() => setForceMobile(true)} style={{

1002 border: 'none',

1003 background: 'none',

1004 padding: 0,

1005 color: '#D97757',

1006 textDecoration: 'underline',

1007 cursor: 'pointer',

1008 font: 'inherit'

1009 }}>show the explorer anyway</button>.

1010 </div>}

1011 <div ref={rootRef} className={forceMobile ? 'ce-root ce-force' : 'ce-root'} style={{

1012 borderRadius: isFullscreen ? 0 : '12px',

1013 border: '1px solid var(--ce-border)',

1014 background: 'var(--ce-bg)',

1015 display: 'flex',

1016 alignItems: 'stretch',

1017 overflow: 'hidden',

1018 fontFamily: 'var(--font-sans, -apple-system, sans-serif)',

1019 ...isFullscreen && ({

1020 height: '100vh'

1021 })

1022 }}>

1023 {}

1024 <div style={{

1025 width: 'min(240px, 35%)',

1026 minWidth: '180px',

1027 flexShrink: 0,

1028 borderRight: '1px solid var(--ce-border-subtle)',

1029 background: 'var(--ce-surface)',

1030 display: 'flex',

1031 flexDirection: 'column'

1032 }}>

1033 <div style={{

1034 padding: '8px 8px 4px',

1035 borderBottom: '1px solid var(--ce-border-subtle)',

1036 display: 'flex',

1037 gap: '4px'

1038 }}>

1039 {['project', 'global'].map(root => <button key={root} onClick={() => switchRoot(root)} style={{

1040 flex: 1,

1041 padding: '6px 0',

1042 borderRadius: '6px',

1043 border: 'none',

1044 cursor: 'pointer',

1045 fontFamily: 'var(--ce-mono)',

1046 fontSize: '11.5px',

1047 background: activeRoot === root ? 'var(--ce-accent-bg)' : 'transparent',

1048 color: activeRoot === root ? 'var(--ce-accent)' : 'var(--ce-text-4)',

1049 fontWeight: activeRoot === root ? 600 : 430

1050 }}>

1051 {root === 'project' ? 'Project' : 'Global (~/)'}

1052 </button>)}

1053 <button onClick={toggleAllFolders} title={allExpanded ? 'Collapse all' : 'Expand all'} style={{

1054 ...iconBtn,

1055 fontSize: 11

1056 }}>

1057 {allExpanded ? '⊟' : '⊞'}

1058 </button>

1059 <button onClick={toggleFullscreen} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} style={{

1060 ...iconBtn,

1061 fontSize: 13

1062 }}>

1063 {isFullscreen ? '⤡' : '⛶'}

1064 </button>

1065 </div>

1066 <div role="tree" aria-label="Configuration files" tabIndex={0} onKeyDown={onTreeKeyDown} style={{

1067 padding: '6px 0',

1068 overflowY: 'auto',

1069 flex: 1,

1070 outline: 'none'

1071 }}>

1072 {tree.children.map(node => renderNode(node, 0))}

1073 </div>

1074 </div>

1075 

1076 {}

1077 <div style={{

1078 flex: 1,

1079 minWidth: 0,

1080 padding: '20px 24px',

1081 minHeight: '400px',

1082 overflowY: 'auto'

1083 }}>

1084 <span aria-live="polite" style={{

1085 position: 'absolute',

1086 width: 1,

1087 height: 1,

1088 overflow: 'hidden',

1089 clip: 'rect(0 0 0 0)'

1090 }}>{selected.label} selected</span>

1091 {}

1092 <div style={{

1093 fontFamily: 'var(--ce-mono)',

1094 fontSize: '11px',

1095 color: 'var(--ce-text-4)',

1096 marginBottom: '10px',

1097 cursor: 'default'

1098 }}>

1099 {selected.path.map((seg, i) => <span key={i}>

1100 <span style={{

1101 color: i === selected.path.length - 1 ? 'var(--ce-accent)' : 'var(--ce-text-4)'

1102 }}>{seg.replace(/\/$/, '')}</span>

1103 {i < selected.path.length - 1 && <span style={{

1104 color: 'var(--ce-sep)'

1105 }}> / </span>}

1106 </span>)}

1107 </div>

1108 

1109 {}

1110 <div style={{

1111 display: 'flex',

1112 alignItems: 'flex-start',

1113 gap: '10px',

1114 marginBottom: '10px'

1115 }}>

1116 <span style={{

1117 flexShrink: 0,

1118 display: 'flex'

1119 }}>{renderIcon(selected.icon, selected.color, 24)}</span>

1120 <div style={{

1121 flex: 1,

1122 minWidth: 0

1123 }}>

1124 <div style={{

1125 fontSize: '22px',

1126 fontWeight: 600,

1127 color: 'var(--ce-text)',

1128 letterSpacing: '-0.3px',

1129 lineHeight: '26px'

1130 }}>{selected.label}</div>

1131 {selected.oneLiner && <div style={{

1132 fontSize: '15px',

1133 color: 'var(--ce-text-3)',

1134 marginTop: '3px'

1135 }}>{selected.oneLiner}</div>}

1136 </div>

1137 <div style={{

1138 display: 'flex',

1139 gap: '4px',

1140 flexShrink: 0

1141 }}>

1142 {[selected.autogen && 'autogen', selected.badge].filter(Boolean).map(k => {

1143 const s = BADGE_STYLES[k];

1144 if (!s) return null;

1145 return <span key={k} style={{

1146 fontFamily: 'var(--ce-mono)',

1147 fontSize: '10px',

1148 fontWeight: 600,

1149 textTransform: 'uppercase',

1150 letterSpacing: '0.3px',

1151 padding: '2px 6px',

1152 borderRadius: '4px',

1153 background: s.bg,

1154 color: s.color,

1155 border: `0.5px solid ${s.border}`

1156 }}>{s.label}</span>;

1157 })}

1158 </div>

1159 </div>

1160 

1161 {}

1162 {selected.note && <div style={{

1163 padding: '10px 12px',

1164 borderRadius: '8px',

1165 marginBottom: '14px',

1166 background: 'rgba(217,119,87,0.06)',

1167 border: '1px solid rgba(217,119,87,0.2)',

1168 borderLeft: '3px solid var(--ce-accent)',

1169 fontSize: '15px',

1170 color: 'var(--ce-text-2)',

1171 lineHeight: 1.6

1172 }}>

1173 {selected.note}

1174 </div>}

1175 

1176 {}

1177 {selected.when && <div style={{

1178 padding: '8px 12px',

1179 borderRadius: '6px',

1180 background: 'rgba(106,155,204,0.06)',

1181 border: '0.5px solid rgba(106,155,204,0.12)',

1182 fontSize: '15px',

1183 color: 'var(--ce-when-text)',

1184 marginBottom: '16px'

1185 }}>

1186 <div style={{

1187 fontSize: '10px',

1188 fontWeight: 700,

1189 textTransform: 'uppercase',

1190 letterSpacing: '0.4px',

1191 opacity: 0.65,

1192 marginBottom: '3px'

1193 }}>When it loads</div>

1194 <div style={{

1195 fontWeight: 500

1196 }}>{selected.when}</div>

1197 </div>}

1198 

1199 {}

1200 {selected.description && <div style={{

1201 fontSize: '16px',

1202 color: 'var(--ce-text-2)',

1203 lineHeight: 1.65,

1204 marginBottom: '16px'

1205 }}>

1206 {Array.isArray(selected.description) ? selected.description.map((para, i) => <div key={i} style={{

1207 marginBottom: i < selected.description.length - 1 ? '12px' : 0

1208 }}>{para}</div>) : selected.description}

1209 </div>}

1210 

1211 {}

1212 {selected.contains && selected.contains.length > 0 && <div style={{

1213 marginBottom: '16px'

1214 }}>

1215 <div style={{

1216 fontSize: '11px',

1217 fontWeight: 700,

1218 color: 'var(--ce-text-4)',

1219 textTransform: 'uppercase',

1220 letterSpacing: '0.4px',

1221 marginBottom: '8px'

1222 }}>Common keys</div>

1223 {selected.contains.map((item, i) => <div key={i} style={{

1224 display: 'flex',

1225 gap: '7px',

1226 fontSize: '15px',

1227 color: 'var(--ce-text-2)',

1228 lineHeight: 1.5,

1229 marginBottom: '5px'

1230 }}>

1231 <span style={{

1232 fontSize: '7px',

1233 color: 'var(--ce-text-4)',

1234 marginTop: '6px'

1235 }}>●</span>

1236 <span>{item}</span>

1237 </div>)}

1238 </div>}

1239 

1240 {}

1241 {selected.tips && selected.tips.length > 0 && <div style={{

1242 padding: '12px 14px',

1243 borderRadius: '8px',

1244 background: 'var(--ce-surface)',

1245 border: '1px solid var(--ce-border-subtle)',

1246 marginBottom: '16px'

1247 }}>

1248 <div style={{

1249 fontSize: '11px',

1250 fontWeight: 700,

1251 color: 'var(--ce-accent)',

1252 textTransform: 'uppercase',

1253 letterSpacing: '0.4px',

1254 marginBottom: '6px'

1255 }}>Tips</div>

1256 {selected.tips.map((tip, i) => <div key={i} style={{

1257 display: 'flex',

1258 gap: '7px',

1259 fontSize: '14.5px',

1260 color: 'var(--ce-text-2)',

1261 marginBottom: i < selected.tips.length - 1 ? '5px' : 0

1262 }}>

1263 <span style={{

1264 fontSize: '7px',

1265 color: 'var(--ce-accent)',

1266 marginTop: '6px'

1267 }}>●</span>

1268 <span>{tip}</span>

1269 </div>)}

1270 </div>}

1271 

1272 {}

1273 {selected.example && <div style={{

1274 marginBottom: '16px'

1275 }}>

1276 {selected.exampleIntro && <div style={{

1277 fontSize: '15px',

1278 color: 'var(--ce-text-2)',

1279 lineHeight: 1.6,

1280 marginBottom: '10px'

1281 }}>

1282 {selected.exampleIntro}

1283 </div>}

1284 <div style={{

1285 display: 'flex',

1286 justifyContent: 'space-between',

1287 alignItems: 'center',

1288 padding: '6px 10px',

1289 background: 'var(--ce-code-header)',

1290 border: '1px solid var(--ce-border)',

1291 borderRadius: '8px 8px 0 0'

1292 }}>

1293 <span style={{

1294 fontFamily: 'var(--ce-mono)',

1295 fontSize: '11px',

1296 fontWeight: 600,

1297 color: 'var(--ce-text-3)'

1298 }}>{selected.label}</span>

1299 <button onClick={() => copyExample(selected.id, selected.example)} style={{

1300 padding: '3px 8px',

1301 borderRadius: '4px',

1302 fontSize: '11px',

1303 fontWeight: 600,

1304 cursor: 'pointer',

1305 transition: 'all 0.15s',

1306 background: isCopied ? 'rgba(85,138,66,0.08)' : 'var(--ce-code-header)',

1307 border: isCopied ? '0.5px solid rgba(85,138,66,0.2)' : '0.5px solid var(--ce-border)',

1308 color: isCopied ? '#558A42' : 'var(--ce-text-3)'

1309 }}>

1310 {isCopied ? '✓ Copied' : 'Copy'}

1311 </button>

1312 </div>

1313 <pre style={{

1314 margin: 0,

1315 padding: '12px 14px',

1316 background: 'var(--ce-code-bg)',

1317 color: '#E8E6DC',

1318 fontFamily: 'var(--ce-mono)',

1319 fontSize: '13px',

1320 lineHeight: 1.65,

1321 borderRadius: '0 0 8px 8px',

1322 overflowX: 'auto',

1323 whiteSpace: 'pre'

1324 }}>{selected.example}</pre>

1325 </div>}

1326 

1327 {}

1328 {selected.docsLink && <a href={selected.docsLink} style={{

1329 display: 'inline-flex',

1330 padding: '5px 12px',

1331 borderRadius: '6px',

1332 background: 'var(--ce-accent-bg)',

1333 border: '1px solid var(--ce-accent-border)',

1334 color: 'var(--ce-accent)',

1335 fontSize: '12px',

1336 fontWeight: 600,

1337 textDecoration: 'none'

1338 }}>Full docs →</a>}

1339 

1340 {}

1341 {selected.children && selected.children.length > 0 && <div style={{

1342 marginTop: '20px'

1343 }}>

1344 <div style={{

1345 fontSize: '11px',

1346 fontWeight: 700,

1347 color: 'var(--ce-text-4)',

1348 textTransform: 'uppercase',

1349 letterSpacing: '0.4px',

1350 marginBottom: '8px'

1351 }}>Contents</div>

1352 <div style={{

1353 display: 'flex',

1354 flexDirection: 'column',

1355 gap: '4px'

1356 }}>

1357 {selected.children.map(child => <button key={child.id} onClick={() => selectNode(child)} style={{

1358 display: 'flex',

1359 alignItems: 'center',

1360 gap: '8px',

1361 padding: '6px 8px',

1362 width: '100%',

1363 background: 'var(--ce-surface)',

1364 borderRadius: '6px',

1365 border: 'none',

1366 cursor: 'pointer',

1367 textAlign: 'left',

1368 transition: 'background 0.1s'

1369 }} onMouseEnter={e => e.currentTarget.style.background = 'var(--ce-surface-hover)'} onMouseLeave={e => e.currentTarget.style.background = 'var(--ce-surface)'}>

1370 {renderIcon(child.icon, child.color, 13)}

1371 <span style={{

1372 fontFamily: 'var(--ce-mono)',

1373 fontSize: '12px',

1374 color: 'var(--ce-text-2)'

1375 }}>{child.label}</span>

1376 {child.oneLiner && <span style={{

1377 fontSize: '11px',

1378 color: 'var(--ce-text-4)',

1379 overflow: 'hidden',

1380 textOverflow: 'ellipsis',

1381 whiteSpace: 'nowrap'

1382 }}>{child.oneLiner}</span>}

1383 </button>)}

1384 </div>

1385 </div>}

1386 </div>

1387 </div>

1388 </>;

1389};

1390 

1391Claude Code reads instructions, settings, skills, subagents, and memory from your project directory and from `~/.claude` in your home directory. Commit project files to git to share them with your team; files in `~/.claude` are personal configuration that applies across all your projects.

1392 

1393Most users only edit `CLAUDE.md` and `settings.json`. The rest of the directory is optional: add skills, rules, or subagents as you need them.

1394 

1395This page is an interactive explorer: click files in the tree to see what each one does, when it loads, and an example. For a quick reference, see the [file reference table](#file-reference) below.

1396 

1397<ClaudeExplorer />

1398 

1399## What's not shown

1400 

1401The explorer covers the files you'll interact with most. A few things live elsewhere:

1402 

1403| File | Location | Purpose |

1404| ----------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------- |

1405| `managed-settings.json` | System-level, varies by OS | Enterprise-enforced settings that you can't override. See [server-managed settings](/en/server-managed-settings). |

1406| `CLAUDE.local.md` | Project root | Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to `.gitignore`. |

1407 

1408## File reference

1409 

1410This table lists every file the explorer covers. Project-scope files live in your repo under `.claude/` (or at the root for `CLAUDE.md`, `.mcp.json`, and `.worktreeinclude`). Global-scope files live in `~/.claude/` and apply across all projects.

1411 

1412<Note>

1413 Several things can override what you put in these files:

1414 

1415 * [Managed settings](/en/server-managed-settings) deployed by your organization take precedence over everything

1416 * CLI flags like `--permission-mode` or `--settings` override `settings.json` for that session

1417 * Some environment variables take precedence over their equivalent setting, but this varies: check the [environment variables reference](/en/env-vars) for each one

1418 

1419 See [settings precedence](/en/settings#settings-precedence) for the full order.

1420</Note>

1421 

1422Click a filename to open that node in the explorer above.

1423 

1424| File | Scope | Commit | What it does | Reference |

1425| --------------------------------------------------- | ------------------ | ------ | ----------------------------------------------------- | -------------------------------------------------------------------- |

1426| [`CLAUDE.md`](#ce-claude-md) | Project and global | ✓ | Instructions loaded every session | [Memory](/en/memory) |

1427| [`rules/*.md`](#ce-rules) | Project and global | ✓ | Topic-scoped instructions, optionally path-gated | [Rules](/en/memory#organize-rules-with-claude/rules/) |

1428| [`settings.json`](#ce-settings-json) | Project and global | ✓ | Permissions, hooks, env vars, model defaults | [Settings](/en/settings) |

1429| [`settings.local.json`](#ce-settings-local-json) | Project only | | Your personal overrides, auto-gitignored | [Settings scopes](/en/settings#settings-files) |

1430| [`.mcp.json`](#ce-mcp-json) | Project only | ✓ | Team-shared MCP servers | [MCP scopes](/en/mcp#mcp-installation-scopes) |

1431| [`.worktreeinclude`](#ce-worktreeinclude) | Project only | ✓ | Gitignored files to copy into new worktrees | [Worktrees](/en/common-workflows#copy-gitignored-files-to-worktrees) |

1432| [`skills/<name>/SKILL.md`](#ce-skills) | Project and global | ✓ | Reusable prompts invoked with `/name` or auto-invoked | [Skills](/en/skills) |

1433| [`commands/*.md`](#ce-commands) | Project and global | ✓ | Single-file prompts; same mechanism as skills | [Skills](/en/skills) |

1434| [`output-styles/*.md`](#ce-output-styles) | Project and global | ✓ | Custom system-prompt sections | [Output styles](/en/output-styles) |

1435| [`agents/*.md`](#ce-agents) | Project and global | ✓ | Subagent definitions with their own prompt and tools | [Subagents](/en/sub-agents) |

1436| [`agent-memory/<name>/`](#ce-agent-memory) | Project and global | ✓ | Persistent memory for subagents | [Persistent memory](/en/sub-agents#enable-persistent-memory) |

1437| [`~/.claude.json`](#ce-claude-json) | Global only | | App state, OAuth, UI toggles, personal MCP servers | [Global config](/en/settings#global-config-settings) |

1438| [`projects/<project>/memory/`](#ce-global-projects) | Global only | | Auto memory: Claude's notes to itself across sessions | [Auto memory](/en/memory#auto-memory) |

1439| [`keybindings.json`](#ce-keybindings) | Global only | | Custom keyboard shortcuts | [Keybindings](/en/keybindings) |

1440 

1441## Check what loaded

1442 

1443The explorer shows what files can exist. To see what actually loaded in your current session, use these commands:

1444 

1445| Command | Shows |

1446| -------------- | ------------------------------------------------------------------------------------- |

1447| `/context` | Token usage by category: system prompt, memory files, skills, MCP tools, and messages |

1448| `/memory` | Which CLAUDE.md and rules files loaded, plus auto-memory entries |

1449| `/agents` | Configured subagents and their settings |

1450| `/hooks` | Active hook configurations |

1451| `/mcp` | Connected MCP servers and their status |

1452| `/skills` | Available skills from project, user, and plugin sources |

1453| `/permissions` | Current allow and deny rules |

1454| `/doctor` | Installation and configuration diagnostics |

1455 

1456Run `/context` first for the overview, then the specific command for the area you want to investigate.

1457 

1458## Related resources

1459 

1460* [Manage Claude's memory](/en/memory): write and organize CLAUDE.md, rules, and auto memory

1461* [Configure settings](/en/settings): set permissions, hooks, environment variables, and model defaults

1462* [Create skills](/en/skills): build reusable prompts and workflows

1463* [Configure subagents](/en/sub-agents): define specialized agents with their own context

Details

91| `--verbose` | Enable verbose logging, shows full turn-by-turn output | `claude --verbose` |91| `--verbose` | Enable verbose logging, shows full turn-by-turn output | `claude --verbose` |

92| `--version`, `-v` | Output the version number | `claude -v` |92| `--version`, `-v` | Output the version number | `claude -v` |

93| `--worktree`, `-w` | Start Claude in an isolated [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees) at `<repo>/.claude/worktrees/<name>`. If no name is given, one is auto-generated | `claude -w feature-auth` |93| `--worktree`, `-w` | Start Claude in an isolated [git worktree](/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees) at `<repo>/.claude/worktrees/<name>`. If no name is given, one is auto-generated | `claude -w feature-auth` |

94| `--tmux` | Create a tmux session for the worktree. Requires `--worktree`. Uses iTerm2 native panes when available; pass `--tmux=classic` for traditional tmux | `claude -w feature-auth --tmux` |

94 95 

95### System prompt flags96### System prompt flags

96 97 

code-review.md +37 −7

Details

20 20 

21* [How reviews work](#how-reviews-work)21* [How reviews work](#how-reviews-work)

22* [Setup](#set-up-code-review)22* [Setup](#set-up-code-review)

23* [Triggering reviews manually](#manually-trigger-reviews) with `@claude review` and `@claude review once`

23* [Customizing reviews](#customize-reviews) with `CLAUDE.md` and `REVIEW.md`24* [Customizing reviews](#customize-reviews) with `CLAUDE.md` and `REVIEW.md`

24* [Pricing](#pricing)25* [Pricing](#pricing)

25 26 


37 38 

38| Marker | Severity | Meaning |39| Marker | Severity | Meaning |

39| :----- | :----------- | :------------------------------------------------------------------ |40| :----- | :----------- | :------------------------------------------------------------------ |

40| 🔴 | Normal | A bug that should be fixed before merging |41| 🔴 | Important | A bug that should be fixed before merging |

41| 🟡 | Nit | A minor issue, worth fixing but not blocking |42| 🟡 | Nit | A minor issue, worth fixing but not blocking |

42| 🟣 | Pre-existing | A bug that exists in the codebase but was not introduced by this PR |43| 🟣 | Pre-existing | A bug that exists in the codebase but was not introduced by this PR |

43 44 

44Findings include a collapsible extended reasoning section you can expand to understand why Claude flagged the issue and how it verified the problem.45Findings include a collapsible extended reasoning section you can expand to understand why Claude flagged the issue and how it verified the problem.

45 46 

47### Check run output

48 

49Beyond the inline review comments, each review populates the **Claude Code Review** check run that appears alongside your CI checks. Expand its **Details** link to see a summary of every finding in one place, sorted by severity:

50 

51| Severity | File:Line | Issue |

52| ------------ | ------------------------- | -------------------------------------------------------------- |

53| 🔴 Important | `src/auth/session.ts:142` | Token refresh races with logout, leaving stale sessions active |

54| 🟡 Nit | `src/auth/session.ts:88` | `parseExpiry` silently returns 0 on malformed input |

55 

56Each finding also appears as an annotation in the **Files changed** tab, marked directly on the relevant diff lines. Important findings render with a red marker, nits with a yellow warning, and pre-existing bugs with a gray notice.

57 

58The check run always completes with a neutral conclusion so it never blocks merging through branch protection rules. If you want to gate merges on Code Review findings, read the severity breakdown from the check run output in your own CI. The last line of the Details text is a machine-readable comment your workflow can parse with `gh` and jq:

59 

60```bash theme={null}

61gh api repos/OWNER/REPO/check-runs/CHECK_RUN_ID \

62 --jq '.output.text | split("bughunter-severity: ")[1] | split(" -->")[0] | fromjson'

63```

64 

65This returns a JSON object with counts per severity, for example `{"normal": 2, "nit": 1, "pre_existing": 0}`. The `normal` key holds the count of Important findings; a non-zero value means Claude found at least one bug worth fixing before merge.

66 

46### What Code Review checks67### What Code Review checks

47 68 

48By default, Code Review focuses on correctness: bugs that would break production, not formatting preferences or missing test coverage. You can expand what it checks by [adding guidance files](#customize-reviews) to your repository.69By default, Code Review focuses on correctness: bugs that would break production, not formatting preferences or missing test coverage. You can expand what it checks by [adding guidance files](#customize-reviews) to your repository.


79 100 

80 * **Once after PR creation**: review runs once when a PR is opened or marked ready for review101 * **Once after PR creation**: review runs once when a PR is opened or marked ready for review

81 * **After every push**: review runs on every push to the PR branch, catching new issues as the PR evolves and auto-resolving threads when you fix flagged issues102 * **After every push**: review runs on every push to the PR branch, catching new issues as the PR evolves and auto-resolving threads when you fix flagged issues

82 * **Manual**: reviews start only when someone [comments `@claude review` on a PR](#manually-trigger-reviews); subsequent pushes to that PR are then reviewed automatically103 * **Manual**: reviews start only when someone [comments `@claude review` or `@claude review once` on a PR](#manually-trigger-reviews); `@claude review` also subscribes the PR to reviews on subsequent pushes

83 104 

84 Reviewing on every push runs the most reviews and costs the most. Manual mode is useful for high-traffic repos where you want to opt specific PRs into review, or to only start reviewing your PRs once they're ready.105 Reviewing on every push runs the most reviews and costs the most. Manual mode is useful for high-traffic repos where you want to opt specific PRs into review, or to only start reviewing your PRs once they're ready.

85 </Step>106 </Step>


91 112 

92## Manually trigger reviews113## Manually trigger reviews

93 114 

94Comment `@claude review` on a pull request to start a review and opt that PR into push-triggered reviews going forward. This works regardless of the repository's configured trigger: use it to opt specific PRs into review in Manual mode, or to get an immediate re-review in other modes. Either way, pushes to that PR trigger reviews from then on.115Two comment commands start a review on demand. Both work regardless of the repository's configured trigger, so you can use them to opt specific PRs into review in Manual mode or to get an immediate re-review in other modes.

116 

117| Command | What it does |

118| :-------------------- | :---------------------------------------------------------------------------- |

119| `@claude review` | Starts a review and subscribes the PR to push-triggered reviews going forward |

120| `@claude review once` | Starts a single review without subscribing the PR to future pushes |

95 121 

96For the comment to trigger a review:122Use `@claude review once` when you want feedback on the current state of a PR but don't want every subsequent push to incur a review. This is useful for long-running PRs with frequent pushes, or when you want a one-off second opinion without changing the PR's review behavior.

123 

124For either command to trigger a review:

97 125 

98* Post it as a top-level PR comment, not an inline comment on a diff line126* Post it as a top-level PR comment, not an inline comment on a diff line

99* Put `@claude review` at the start of the comment127* Put the command at the start of the comment, with `once` on the same line if you're using the one-shot form

100* You must have owner, member, or collaborator access to the repository128* You must have owner, member, or collaborator access to the repository

101* The PR must be open and not a draft129* The PR must be open

130 

131Unlike automatic triggers, manual triggers run on draft PRs, since an explicit request signals you want the review now regardless of draft status.

102 132 

103If a review is already running on that PR, the request is queued until the in-progress review completes. You can monitor progress via the check run on the PR.133If a review is already running on that PR, the request is queued until the in-progress review completes. You can monitor progress via the check run on the PR.

104 134 


170* **After every push**: runs on each push, multiplying cost by the number of pushes200* **After every push**: runs on each push, multiplying cost by the number of pushes

171* **Manual**: no reviews until someone comments `@claude review` on a PR201* **Manual**: no reviews until someone comments `@claude review` on a PR

172 202 

173In any mode, commenting `@claude review` [opts the PR into push-triggered reviews](#manually-trigger-reviews), so additional cost accrues per push after that comment.203In any mode, commenting `@claude review` [opts the PR into push-triggered reviews](#manually-trigger-reviews), so additional cost accrues per push after that comment. To run a single review without subscribing to future pushes, comment `@claude review once` instead.

174 204 

175Costs appear on your Anthropic bill regardless of whether your organization uses AWS Bedrock or Google Vertex AI for other Claude Code features. To set a monthly spend cap for Code Review, go to [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage) and configure the limit for the Claude Code Review service.205Costs appear on your Anthropic bill regardless of whether your organization uses AWS Bedrock or Google Vertex AI for other Claude Code features. To set a monthly spend cap for Code Review, go to [claude.ai/admin-settings/usage](https://claude.ai/admin-settings/usage) and configure the limit for the Claude Code Review service.

176 206 

Details

666claude --worktree666claude --worktree

667```667```

668 668 

669Worktrees are created at `<repo>/.claude/worktrees/<name>` and branch from the default remote branch. The worktree branch is named `worktree-<name>`.669Worktrees are created at `<repo>/.claude/worktrees/<name>` and branch from the default remote branch, which is where `origin/HEAD` points. The worktree branch is named `worktree-<name>`.

670 

671The base branch is not configurable through a Claude Code flag or setting. `origin/HEAD` is a reference stored in your local `.git` directory that Git set once when you cloned. If the repository's default branch later changes on GitHub or GitLab, your local `origin/HEAD` keeps pointing at the old one, and worktrees will branch from there. To re-sync your local reference with whatever the remote currently considers its default:

672 

673```bash theme={null}

674git remote set-head origin -a

675```

676 

677This is a standard Git command that only updates your local `.git` directory. Nothing on the remote server changes. If you want worktrees to base off a specific branch rather than the remote's default, set it explicitly with `git remote set-head origin your-branch-name`.

678 

679For full control over how worktrees are created, including choosing a different base per invocation, configure a [WorktreeCreate hook](/en/hooks#worktreecreate). The hook replaces Claude Code's default `git worktree` logic entirely, so you can fetch and branch from whatever ref you need.

670 680 

671You can also ask Claude to "work in a worktree" or "start a worktree" during a session, and it will create one automatically.681You can also ask Claude to "work in a worktree" or "start a worktree" during a session, and it will create one automatically.

672 682 


728 738 

729### Non-git version control739### Non-git version control

730 740 

731Worktree isolation works with git by default. For other version control systems like SVN, Perforce, or Mercurial, configure [WorktreeCreate and WorktreeRemove hooks](/en/hooks#worktreecreate) to provide custom worktree creation and cleanup logic. When configured, these hooks replace the default git behavior when you use `--worktree`.741Worktree isolation works with git by default. For other version control systems like SVN, Perforce, or Mercurial, configure [WorktreeCreate and WorktreeRemove hooks](/en/hooks#worktreecreate) to provide custom worktree creation and cleanup logic. When configured, these hooks replace the default git behavior when you use `--worktree`, so [`.worktreeinclude`](#copy-gitignored-files-to-worktrees) is not processed. Copy any local configuration files inside your hook script instead.

732 742 

733For automated coordination of parallel sessions with shared tasks and messaging, see [agent teams](/en/agent-teams).743For automated coordination of parallel sessions with shared tasks and messaging, see [agent teams](/en/agent-teams).

734 744 

context-window.md +1596 −0 created

Details

1> ## Documentation Index

2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt

3> Use this file to discover all available pages before exploring further.

4 

5# Explore the context window

6 

7> An interactive simulation of how Claude Code's context window fills during a session. See what loads automatically, what each file read costs, and when rules and hooks fire.

8 

9export const ContextWindow = () => {

10 const MAX = 200000;

11 const STARTUP_END = 0.2;

12 {}

13 const EVENTS = useMemo(() => [{}, {

14 t: 0.015,

15 kind: 'auto',

16 label: 'System prompt',

17 tokens: 4200,

18 color: '#6B6964',

19 vis: 'hidden',

20 desc: 'Core instructions for behavior, tool use, and response formatting. Always loaded first. You never see it.',

21 link: null

22 }, {

23 t: 0.035,

24 kind: 'auto',

25 label: 'Auto memory (MEMORY.md)',

26 tokens: 680,

27 color: '#E8A45C',

28 vis: 'hidden',

29 desc: "Claude's notes to itself from previous sessions: build commands it learned, patterns it noticed, mistakes to avoid. The first 200 lines or 25KB, whichever comes first, are loaded into the conversation context.",

30 link: '/en/memory#auto-memory'

31 }, {

32 t: 0.06,

33 kind: 'auto',

34 label: 'Environment info',

35 tokens: 280,

36 color: '#6B6964',

37 vis: 'hidden',

38 desc: 'Working directory, platform, shell, OS version, and whether this is a git repo. Git branch, status, and recent commits load as a separate block at the very end of the system prompt.',

39 link: null

40 }, {

41 t: 0.08,

42 kind: 'auto',

43 label: 'MCP tools (deferred)',

44 tokens: 120,

45 color: '#9B7BC4',

46 vis: 'hidden',

47 desc: 'MCP tool names listed so Claude knows what is available. By default, full schemas stay deferred and Claude loads specific ones on demand via tool search when a task needs them. Set `ENABLE_TOOL_SEARCH=auto` to load schemas upfront when they fit within 10% of the context window, or `ENABLE_TOOL_SEARCH=false` to load everything.',

48 link: '/en/mcp#scale-with-mcp-tool-search'

49 }, {

50 t: 0.1,

51 kind: 'auto',

52 label: 'Skill descriptions',

53 tokens: 450,

54 color: '#D4A843',

55 vis: 'hidden',

56 noSurviveCompact: true,

57 desc: 'One-line descriptions of available skills so Claude knows what it can invoke. Full skill content loads only when Claude actually uses one. Skills with `disable-model-invocation: true` are not in this list. They stay completely out of context until you invoke them with `/name`. Unlike the rest of the startup content, this listing is not re-injected after `/compact`. Only skills you actually invoked get preserved.',

58 link: '/en/skills'

59 }, {

60 t: 0.12,

61 kind: 'auto',

62 label: '~/.claude/CLAUDE.md',

63 tokens: 320,

64 color: '#6A9BCC',

65 vis: 'hidden',

66 desc: 'Your global preferences. Applies to every project. Loaded alongside project instructions at the start of every conversation.',

67 link: '/en/memory#choose-where-to-put-claude-md-files'

68 }, {

69 t: 0.14,

70 kind: 'auto',

71 label: 'Project CLAUDE.md',

72 tokens: 1800,

73 color: '#6A9BCC',

74 vis: 'hidden',

75 desc: 'Project conventions, build commands, architecture notes. The most important file you can create. Lives in your project root, so your whole team gets the same instructions.',

76 tip: 'Keep it under 200 lines. Move reference content to skills or path-scoped rules so it only loads when needed.',

77 link: '/en/memory'

78 }, {}, {

79 t: 0.22,

80 kind: 'user',

81 label: 'Your prompt',

82 tokens: 45,

83 color: '#558A42',

84 vis: 'full',

85 desc: '"Fix the auth bug where users get 401 after token refresh"',

86 link: null

87 }, {}, {

88 t: 0.28,

89 kind: 'claude',

90 label: 'Read src/api/auth.ts',

91 tokens: 2400,

92 color: '#8A8880',

93 vis: 'brief',

94 desc: 'Main auth file. You see "Read auth.ts" in your terminal, but the 2,400 tokens of file content only Claude sees.',

95 tip: 'File reads dominate context usage. Be specific in prompts ("fix the bug in auth.ts") so Claude reads fewer files. For research-heavy tasks, use a subagent.',

96 link: null

97 }, {

98 t: 0.32,

99 kind: 'claude',

100 label: 'Read src/lib/tokens.ts',

101 tokens: 1100,

102 color: '#8A8880',

103 vis: 'brief',

104 desc: 'Following imports to the token module. Shown as a one-liner in your terminal.',

105 link: null

106 }, {

107 t: 0.35,

108 kind: 'auto',

109 label: 'Rule: api-conventions.md',

110 tokens: 380,

111 color: '#4A9B8E',

112 vis: 'brief',

113 desc: 'This rule in `.claude/rules/` has a `paths:` pattern matching `src/api/**`. It loaded automatically when Claude read a file in that directory. You see "Loaded .claude/rules/api-conventions.md" in your terminal, but not the rule content.',

114 link: '/en/memory#path-specific-rules'

115 }, {

116 t: 0.38,

117 kind: 'claude',

118 label: 'Read middleware.ts',

119 tokens: 1800,

120 color: '#8A8880',

121 vis: 'brief',

122 desc: 'Tracing the auth flow deeper.',

123 link: null

124 }, {

125 t: 0.41,

126 kind: 'claude',

127 label: 'Read auth.test.ts',

128 tokens: 1600,

129 color: '#8A8880',

130 vis: 'brief',

131 desc: 'Checking existing tests for expected behavior.',

132 link: null

133 }, {

134 t: 0.44,

135 kind: 'auto',

136 label: 'Rule: testing.md',

137 tokens: 290,

138 color: '#4A9B8E',

139 vis: 'brief',

140 desc: 'Another path-scoped rule, this one matching `*.test.ts` files. Triggered when Claude read auth.test.ts. Shown as a one-line "Loaded" notice.',

141 link: '/en/memory#path-specific-rules'

142 }, {

143 t: 0.47,

144 kind: 'claude',

145 label: 'grep "refreshToken"',

146 tokens: 600,

147 color: '#A09E96',

148 vis: 'brief',

149 desc: 'Search results across the codebase. You see the command ran, not the full output.',

150 link: null

151 }, {}, {

152 t: 0.53,

153 kind: 'claude',

154 label: "Claude's analysis",

155 tokens: 800,

156 color: '#D97757',

157 vis: 'full',

158 desc: 'Explains the bug: token invalidated too early in the rotation. This text appears in your terminal.',

159 link: null

160 }, {

161 t: 0.57,

162 kind: 'claude',

163 label: 'Edit auth.ts',

164 tokens: 400,

165 color: '#D97757',

166 vis: 'full',

167 desc: 'Fixes the token rotation order. The diff appears in your terminal.',

168 link: null

169 }, {

170 t: 0.59,

171 kind: 'hook',

172 label: 'Hook: prettier',

173 tokens: 120,

174 color: '#B8860B',

175 vis: 'hidden',

176 desc: 'A PostToolUse hook in `settings.json` runs prettier after every file edit and reports back via `hookSpecificOutput.additionalContext`. That field enters Claude\'s context. Plain stdout on exit 0 does not. It only appears in verbose mode via Ctrl+O.',

177 tip: 'Output JSON with `additionalContext` to send info to Claude. For PostToolUse hooks, exit code 2 surfaces stderr as an error but cannot block since the tool already ran. Keep output concise since it enters context without truncation.',

178 link: '/en/hooks-guide'

179 }, {

180 t: 0.62,

181 kind: 'claude',

182 label: 'Edit auth.test.ts',

183 tokens: 600,

184 color: '#D97757',

185 vis: 'full',

186 desc: 'Adds a regression test for the fix. The diff appears in your terminal.',

187 link: null

188 }, {

189 t: 0.64,

190 kind: 'hook',

191 label: 'Hook: prettier',

192 tokens: 100,

193 color: '#B8860B',

194 vis: 'hidden',

195 desc: 'The same hook fires again for the test file. Every matching tool event triggers it.',

196 link: '/en/hooks-guide'

197 }, {

198 t: 0.67,

199 kind: 'claude',

200 label: 'npm test output',

201 tokens: 1200,

202 color: '#A09E96',

203 vis: 'brief',

204 desc: 'Runs the test suite. You see "Running npm test..." and the pass count, not the full 1,200 tokens of output.',

205 link: null

206 }, {

207 t: 0.70,

208 kind: 'claude',

209 label: 'Summary',

210 tokens: 400,

211 color: '#D97757',

212 vis: 'full',

213 desc: '"Fixed token rotation. Added regression test. All tests pass."',

214 link: null

215 }, {}, {

216 t: 0.72,

217 kind: 'user',

218 label: 'Your follow-up',

219 tokens: 40,

220 color: '#558A42',

221 vis: 'full',

222 desc: '"Use a subagent to research session timeout handling, then fix it"',

223 tip: 'Follow-ups add to the same context. Delegating research to a subagent keeps large file reads out of your main window.',

224 link: null

225 }, {

226 t: 0.79,

227 kind: 'claude',

228 label: 'Spawn research subagent',

229 tokens: 80,

230 color: '#D97757',

231 vis: 'brief',

232 desc: "Claude delegates the research to a subagent with a fresh, separate context window. It loads CLAUDE.md and the same MCP and skill setup, but starts without your conversation history or the main session's auto memory.",

233 link: '/en/sub-agents'

234 }, {

235 t: 0.795,

236 kind: 'sub',

237 label: 'System prompt',

238 tokens: 0,

239 subTokens: 900,

240 color: '#6B6964',

241 vis: 'hidden',

242 desc: "The subagent gets its own system prompt, shorter than the main session's. For the general-purpose agent, it's a brief prompt plus environment details. The main session's auto memory is not included. If a custom agent has memory: in its frontmatter, it loads its own separate MEMORY.md here instead.",

243 link: '/en/sub-agents#enable-persistent-memory'

244 }, {

245 t: 0.80,

246 kind: 'sub',

247 label: 'Project CLAUDE.md (own copy)',

248 tokens: 0,

249 subTokens: 1800,

250 color: '#6A9BCC',

251 vis: 'hidden',

252 desc: "The subagent loads CLAUDE.md too. Same file, same content, but it counts against the subagent's context, not yours. The built-in Explore and Plan agents skip this for a smaller context.",

253 link: '/en/sub-agents'

254 }, {

255 t: 0.805,

256 kind: 'sub',

257 label: 'MCP tools + skills',

258 tokens: 0,

259 subTokens: 970,

260 color: '#9B7BC4',

261 vis: 'hidden',

262 desc: "The subagent has access to the same MCP servers and skills. It gets most of the parent's tools, minus several that don't apply in a nested context, including plan-mode controls, background-task tools, and by default the Agent tool itself to prevent recursion.",

263 link: '/en/sub-agents'

264 }, {

265 t: 0.81,

266 kind: 'sub',

267 label: 'Task prompt from main',

268 tokens: 0,

269 subTokens: 120,

270 color: '#558A42',

271 vis: 'hidden',

272 desc: "Instead of a user prompt, the subagent receives the task Claude wrote for it: 'Research session timeout handling in this codebase.'",

273 link: '/en/sub-agents'

274 }, {

275 t: 0.82,

276 kind: 'sub',

277 label: 'Read session.ts',

278 tokens: 0,

279 subTokens: 2200,

280 color: '#8A8880',

281 vis: 'hidden',

282 desc: "Now the subagent does its work. This file read fills the subagent's context, not yours.",

283 link: '/en/sub-agents'

284 }, {

285 t: 0.825,

286 kind: 'sub',

287 label: 'Read timeouts.ts',

288 tokens: 0,

289 subTokens: 800,

290 color: '#8A8880',

291 vis: 'hidden',

292 desc: "Another file read in the subagent's separate context.",

293 link: '/en/sub-agents'

294 }, {

295 t: 0.83,

296 kind: 'sub',

297 label: 'Read config/*.ts',

298 tokens: 0,

299 subTokens: 3100,

300 color: '#8A8880',

301 vis: 'hidden',

302 desc: "The subagent can read as many files as it needs. None of this touches your main context.",

303 link: '/en/sub-agents'

304 }, {

305 t: 0.85,

306 kind: 'claude',

307 label: 'Subagent returns summary',

308 tokens: 420,

309 color: '#D97757',

310 vis: 'brief',

311 desc: "Only the subagent's final text response comes back to your context, plus a small metadata trailer with token counts and duration. The subagent read 6,100 tokens of files. You got a 420-token result. That's the context savings.",

312 link: '/en/sub-agents'

313 }, {

314 t: 0.86,

315 kind: 'claude',

316 label: "Claude's response",

317 tokens: 1200,

318 color: '#D97757',

319 vis: 'full',

320 desc: 'Analysis and fix for session timeouts. This text appears in your terminal.',

321 link: null

322 }, {}, {

323 t: 0.875,

324 kind: 'user',

325 label: '!git status',

326 tokens: 180,

327 color: '#558A42',

328 vis: 'full',

329 desc: "You ran a shell command with the ! prefix to see which files Claude modified. The command and its output both enter context as part of your message. Useful for grounding Claude in command output without Claude running it.",

330 link: '/en/interactive-mode#bash-mode-with-prefix'

331 }, {

332 t: 0.89,

333 kind: 'user',

334 label: '/commit-push',

335 tokens: 620,

336 color: '#558A42',

337 vis: 'brief',

338 desc: 'You invoked a skill that has `disable-model-invocation: true`. Its description was not in the skill index at startup, so it cost zero context until this moment. Now the full skill content loads and Claude follows its instructions to stage, commit, and push your changes.',

339 tip: 'Set `disable-model-invocation: true` on skills with side effects like committing, deploying, or sending messages. They stay out of context entirely until you need them.',

340 link: '/en/skills#control-who-invokes-a-skill'

341 }, {}, {

342 t: 0.93,

343 kind: 'compact',

344 label: '/compact',

345 tokens: 0,

346 color: '#D97757',

347 vis: 'brief',

348 desc: 'Replaces the conversation with a structured summary. You see a "Conversation compacted" message. The summarization happens without appearing in your terminal.',

349 link: '/en/how-claude-code-works#the-context-window'

350 }].filter(e => e.t !== undefined), []);

351 const VIS_META = {

352 hidden: {

353 label: 'Invisible in your terminal',

354 sub: 'This content does not appear in your terminal.'

355 },

356 brief: {

357 label: 'One-liner in your terminal',

358 sub: 'You see a brief mention, not the full content.'

359 },

360 full: {

361 label: 'Shown in your terminal',

362 sub: 'The actual content appears in your terminal.'

363 }

364 };

365 {}

366 const GATES = [{

367 at: 0.18,

368 kind: 'prompt',

369 text: 'Fix the auth bug where users get 401 after token refresh',

370 resumeTo: 0.22

371 }, {

372 at: 0.705,

373 kind: 'prompt',

374 text: 'Use a subagent to research session timeout handling, then fix it',

375 resumeTo: 0.72

376 }, {

377 at: 0.865,

378 kind: 'bang',

379 text: '!git status',

380 resumeTo: 0.875

381 }, {

382 at: 0.88,

383 kind: 'slash',

384 text: '/commit-push',

385 resumeTo: 0.89

386 }, {

387 at: 0.90,

388 kind: 'compact',

389 text: '/compact',

390 resumeTo: 1

391 }];

392 const KIND_META = {

393 auto: {

394 badge: 'auto',

395 detail: 'Auto-loaded',

396 badgeBg: 'rgba(94,93,89,0.15)',

397 badgeColor: '#8A8880'

398 },

399 user: {

400 badge: 'you',

401 detail: 'You typed this',

402 badgeBg: 'rgba(85,138,66,0.15)',

403 badgeColor: '#6BA656'

404 },

405 claude: {

406 badge: 'claude',

407 detail: "Claude's work",

408 badgeBg: 'rgba(217,119,87,0.12)',

409 badgeColor: '#D97757'

410 },

411 hook: {

412 badge: 'hook',

413 detail: 'Hook (automatic)',

414 badgeBg: 'rgba(184,134,11,0.15)',

415 badgeColor: '#CCA020'

416 },

417 compact: {

418 badge: 'compact',

419 detail: 'Compaction',

420 badgeBg: 'rgba(217,119,87,0.12)',

421 badgeColor: '#D97757'

422 },

423 sub: {

424 badge: 'subagent',

425 detail: "In subagent's context",

426 badgeBg: 'rgba(155,123,196,0.12)',

427 badgeColor: '#9B7BC4'

428 }

429 };

430 const LEGEND = [{

431 c: '#6B6964',

432 l: 'System'

433 }, {

434 c: '#6A9BCC',

435 l: 'CLAUDE.md'

436 }, {

437 c: '#E8A45C',

438 l: 'Memory'

439 }, {

440 c: '#D4A843',

441 l: 'Skills'

442 }, {

443 c: '#9B7BC4',

444 l: 'MCP'

445 }, {

446 c: '#4A9B8E',

447 l: 'Rules'

448 }, {

449 c: '#558A42',

450 l: 'You'

451 }, {

452 c: '#8A8880',

453 l: 'Files'

454 }, {

455 c: '#A09E96',

456 l: 'Output'

457 }, {

458 c: '#D97757',

459 l: 'Claude'

460 }, {

461 c: '#B8860B',

462 l: 'Hooks'

463 }];

464 const fmt = n => n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'K' : n + '';

465 const [time, setTime] = useState(0);

466 const [playing, setPlaying] = useState(false);

467 const [hovIdx, setHovIdx] = useState(null);

468 const [selIdx, setSelIdx] = useState(null);

469 const [hovCat, setHovCat] = useState(null);

470 const [gatesPassed, setGatesPassed] = useState(0);

471 const [mounted, setMounted] = useState(false);

472 const [hasInteracted, setHasInteracted] = useState(false);

473 const lastRef = useRef(null);

474 const scrollRef = useRef(null);

475 const detailRef = useRef(null);

476 useEffect(() => setMounted(true), []);

477 const activeGate = GATES.find((g, i) => i >= gatesPassed && time >= g.at && time < g.resumeTo);

478 useEffect(() => {

479 if (!playing) return;

480 let raf;

481 let stopped = false;

482 const tick = ts => {

483 if (stopped) return;

484 if (!lastRef.current) lastRef.current = ts;

485 const dt = (ts - lastRef.current) / 1000;

486 lastRef.current = ts;

487 setTime(prev => {

488 const next = prev + dt * 0.032;

489 const gate = GATES.find((g, i) => i >= gatesPassed && next >= g.at && prev < g.resumeTo);

490 if (gate) {

491 stopped = true;

492 setPlaying(false);

493 return gate.at;

494 }

495 if (next >= 1) {

496 stopped = true;

497 setPlaying(false);

498 return 1;

499 }

500 return next;

501 });

502 if (!stopped) raf = requestAnimationFrame(tick);

503 };

504 raf = requestAnimationFrame(tick);

505 return () => {

506 stopped = true;

507 cancelAnimationFrame(raf);

508 lastRef.current = null;

509 };

510 }, [playing, gatesPassed]);

511 const sendPrompt = () => {

512 if (!activeGate) return;

513 const isCompact = activeGate.kind === 'compact';

514 setGatesPassed(n => n + 1);

515 setTime(activeGate.resumeTo);

516 setSelIdx(null);

517 setHovIdx(null);

518 if (!isCompact) setPlaying(true);

519 };

520 const visibleCount = EVENTS.filter(e => e.t <= time).length;

521 const preCompactVisible = useMemo(() => EVENTS.slice(0, visibleCount), [EVENTS, visibleCount]);

522 const compactGateIdx = GATES.length - 1;

523 const isCompacted = gatesPassed > compactGateIdx && preCompactVisible.some(e => e.kind === 'compact');

524 const {visible, preCompactTotal} = useMemo(() => {

525 const nonCompact = preCompactVisible.filter(e => e.kind !== 'compact');

526 if (!isCompacted) {

527 return {

528 visible: preCompactVisible,

529 preCompactTotal: 0

530 };

531 }

532 {}

533 const autoLoads = nonCompact.filter(e => e.kind === 'auto' && e.t < STARTUP_END && !e.noSurviveCompact);

534 const summarized = nonCompact.filter(e => e.t >= STARTUP_END && e.kind !== 'sub');

535 const sumTokens = summarized.reduce((s, e) => s + e.tokens, 0);

536 const summaryBlock = {

537 t: STARTUP_END,

538 kind: 'compact',

539 label: 'Conversation summary',

540 tokens: Math.round(sumTokens * 0.12),

541 color: '#A09E96',

542 vis: 'hidden',

543 desc: `All ${summarized.length} conversation events condensed into one structured summary. The summary keeps: your requests and intent, key technical concepts, files examined or modified with important code snippets, errors and how they were fixed, pending tasks, and current work. It replaces the verbatim conversation: full tool outputs and intermediate reasoning are gone. Claude can still reference the work but won't have the exact code it read earlier.`,

544 link: '/en/how-claude-code-works#the-context-window'

545 };

546 return {

547 visible: [...autoLoads, summaryBlock],

548 preCompactTotal: nonCompact.reduce((s, e) => s + e.tokens, 0)

549 };

550 }, [preCompactVisible, isCompacted]);

551 const {blocks, totalTokens} = useMemo(() => {

552 const bl = visible.map((e, visIdx) => ({

553 ...e,

554 id: e.label + e.t,

555 visIdx

556 })).filter(e => e.tokens > 0 || e.label === 'Conversation summary');

557 return {

558 blocks: bl,

559 totalTokens: bl.reduce((s, b) => s + b.tokens, 0)

560 };

561 }, [visible]);

562 const subTotal = useMemo(() => visible.filter(e => e.kind === 'sub').reduce((s, e) => s + (e.subTokens || 0), 0), [visible]);

563 useEffect(() => {

564 if (!scrollRef.current) return;

565 if (isCompacted) scrollRef.current.scrollTo({

566 top: 0,

567 behavior: 'smooth'

568 }); else if (playing || activeGate) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;

569 }, [visible.length, !!activeGate, isCompacted]);

570 const rootRef = useRef(null);

571 const keyStateRef = useRef({});

572 const [isFullscreen, setIsFullscreen] = useState(false);

573 keyStateRef.current = {

574 time,

575 activeGate,

576 sendPrompt,

577 hasInteracted

578 };

579 useEffect(() => {

580 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);

581 document.addEventListener('fullscreenchange', onFsChange);

582 return () => document.removeEventListener('fullscreenchange', onFsChange);

583 }, []);

584 const toggleFullscreen = () => {

585 if (!rootRef.current) return;

586 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});

587 };

588 useEffect(() => {

589 const onKey = e => {

590 const tag = e.target.tagName;

591 if (tag === 'INPUT' || tag === 'BUTTON' || tag === 'TEXTAREA' || tag === 'SELECT' || e.target.isContentEditable) return;

592 if (!rootRef.current) return;

593 const rect = rootRef.current.getBoundingClientRect();

594 if (rect.width === 0 && rect.height === 0) return;

595 if (rect.bottom < 0 || rect.top > window.innerHeight) return;

596 if (e.code === 'Space') {

597 const {time: t, activeGate: g, sendPrompt: send, hasInteracted: hi} = keyStateRef.current;

598 if (!hi) return;

599 e.preventDefault();

600 if (t === 0) setPlaying(true); else if (g) send(); else if (t >= 1) {

601 setTime(0);

602 setGatesPassed(0);

603 setSelIdx(null);

604 setHovIdx(null);

605 setPlaying(true);

606 } else setPlaying(p => !p);

607 }

608 };

609 window.addEventListener('keydown', onKey);

610 return () => window.removeEventListener('keydown', onKey);

611 }, []);

612 const pct = totalTokens / MAX * 100;

613 const barColor = pct > 75 ? '#D97757' : pct > 50 ? '#B8860B' : '#558A42';

614 const activeIdx = selIdx !== null ? selIdx : hovIdx;

615 const hovEvent = activeIdx !== null ? visible[activeIdx] : null;

616 useEffect(() => {

617 if (detailRef.current) detailRef.current.scrollTop = 0;

618 }, [hovEvent]);

619 const focusT = hovEvent ? hovEvent.t : time;

620 const takeaway = isCompacted ? 'Compaction replaces the conversation with a structured summary. System prompt, CLAUDE.md, memory, and MCP tools reload automatically. The skill listing is the one exception. Only skills you actually invoked are preserved.' : focusT < STARTUP_END ? 'A lot loads before you type anything. CLAUDE.md, memory, skills, and MCP tools are all in context before your first prompt.' : focusT < 0.28 ? "Your prompt is tiny compared to what's already loaded. Most of Claude's context is project knowledge, not your words." : focusT < 0.50 ? 'Each file Claude reads grows the context. Path-scoped rules load automatically alongside matching files.' : focusT < 0.71 ? 'Hooks fire automatically on tool events. Output reaches Claude via additionalContext JSON. Exit code 2 surfaces stderr to Claude. Plain stdout stays in verbose mode only.' : focusT < 0.79 ? 'Follow-up questions keep building on the same context. Everything from earlier is still there.' : focusT < 0.87 ? "The subagent works in its own separate context window. None of its file reads touch yours. Only the final summary comes back." : focusT < 0.88 ? 'Bang commands run in your shell and prefix the output to your next message. Useful for grounding Claude in command results without it running them.' : focusT < 0.90 ? 'User-only skills stay out of context entirely until you invoke them. The skill index at startup only lists skills Claude can call on its own.' : '/compact summarizes the conversation to free space while keeping key information. In a real session, run it when context starts affecting performance or before a long new task.';

621 const terminalView = isCompacted ? 'A "Conversation compacted" message. The summarization happens silently.' : focusT < STARTUP_END ? 'The input box, waiting for your first message. Everything above loads silently before you type anything.' : focusT < 0.28 ? 'Your prompt. Claude hasn\'t started working yet.' : focusT < 0.52 ? 'Your prompt and "Reading files...". Rules show as one-line "Loaded" notices, not their content.' : focusT < 0.72 ? "Claude's response and file diffs. Hooks fire silently. Tool output like npm test shows as a brief summary, not the full content." : focusT < 0.79 ? 'Your follow-up prompt.' : focusT < 0.86 ? "A brief notice that a subagent is working, then its result. You don't see the subagent's individual file reads." : focusT < 0.90 ? "Claude's response, your git status output, and the commit-push skill running." : 'Your full conversation. /compact is available to run.';

622 const mono = 'var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace)';

623 const renderWithCode = s => s.split('`').map((part, i) => i % 2 === 1 ? <code key={i} style={{

624 fontFamily: mono,

625 fontSize: '0.92em',

626 background: 'var(--cw-track)',

627 padding: '1px 4px',

628 borderRadius: 3

629 }}>{part}</code> : part);

630 if (!mounted) return null;

631 return <>

632 <div className="cw-mobile-fallback">

633 This interactive timeline works best on a larger screen. See <a href="#what-the-timeline-shows" style={{

634 color: '#D97757'

635 }}>the written breakdown below</a> for the same concepts.

636 </div>

637 <div className="cw-root" ref={rootRef} onClickCapture={() => setHasInteracted(true)} style={isFullscreen ? {

638 height: '100vh',

639 borderRadius: 0,

640 display: 'flex',

641 flexDirection: 'column'

642 } : {}}>

643 <style>{`

644 .cw-root {

645 --cw-bg: #FAFAF8;

646 --cw-text: #1A1918;

647 --cw-text-2: #3D3C38;

648 --cw-text-3: #5E5D59;

649 --cw-text-dim: #6E6C64;

650 --cw-text-faint: #8A8880;

651 --cw-surface: rgba(0,0,0,0.025);

652 --cw-surface-2: rgba(0,0,0,0.04);

653 --cw-border: rgba(0,0,0,0.08);

654 --cw-track: rgba(0,0,0,0.04);

655 --cw-hover: rgba(0,0,0,0.04);

656 --cw-rail: rgba(0,0,0,0.08);

657 --cw-scrollbar: rgba(0,0,0,0.22);

658 background: var(--cw-bg);

659 border-radius: 12px;

660 overflow: hidden;

661 font-family: var(--font-sans, -apple-system, BlinkMacSystemFont, sans-serif);

662 color: var(--cw-text);

663 border: 1px solid var(--cw-border);

664 }

665 .dark .cw-root {

666 --cw-bg: #111110;

667 --cw-text: #E8E6DC;

668 --cw-text-2: #B8B6AE;

669 --cw-text-3: #9C9A92;

670 --cw-text-dim: #8A8880;

671 --cw-text-faint: #6E6C64;

672 --cw-surface: rgba(255,255,255,0.02);

673 --cw-surface-2: rgba(255,255,255,0.015);

674 --cw-border: rgba(255,255,255,0.06);

675 --cw-track: rgba(255,255,255,0.03);

676 --cw-hover: rgba(255,255,255,0.04);

677 --cw-rail: rgba(255,255,255,0.04);

678 --cw-scrollbar: rgba(255,255,255,0.18);

679 }

680 .cw-scroll::-webkit-scrollbar { width: 6px; }

681 .cw-scroll::-webkit-scrollbar-track { background: transparent; }

682 .cw-scroll::-webkit-scrollbar-thumb { background: var(--cw-scrollbar); border-radius: 3px; }

683 @keyframes cw-blink { 50% { opacity: 0; } }

684 @keyframes cw-fadein { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

685 .cw-compacted-row { animation: cw-fadein 0.3s ease-out backwards; }

686 .cw-mobile-fallback { display: none; padding: 14px 16px; border-radius: 8px; font-size: 14px; border: 1px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.03); }

687 .dark .cw-mobile-fallback { border-color: rgba(255,255,255,0.15); background: rgba(255,255,255,0.04); }

688 @media (max-width: 700px) {

689 .cw-root { display: none !important; }

690 .cw-mobile-fallback { display: block; }

691 }

692 `}</style>

693 

694 {}

695 <div style={{

696 padding: '16px 20px 12px',

697 display: 'flex',

698 alignItems: 'flex-end',

699 gap: 24

700 }}>

701 <div style={{

702 flex: 1,

703 minWidth: 0

704 }}>

705 <div style={{

706 fontSize: 18,

707 fontWeight: 600,

708 letterSpacing: -0.3,

709 lineHeight: 1

710 }}>

711 Explore the context window

712 </div>

713 <div style={{

714 fontSize: 14,

715 color: 'var(--cw-text-dim)',

716 marginTop: 4

717 }}>

718 A simulated session showing what enters context and what it costs

719 </div>

720 </div>

721 <div style={{

722 textAlign: 'right',

723 flexShrink: 0

724 }}>

725 <div style={{

726 fontFamily: mono,

727 fontSize: 20,

728 fontWeight: 600,

729 color: barColor,

730 letterSpacing: -0.5,

731 lineHeight: 1

732 }}>

733 ~{fmt(totalTokens)}<span style={{

734 fontSize: 15,

735 fontWeight: 500,

736 marginLeft: 4

737 }}>tokens</span>

738 </div>

739 <div style={{

740 fontFamily: mono,

741 fontSize: 13,

742 color: 'var(--cw-text-dim)',

743 marginTop: 2

744 }} title="Token counts are illustrative. Actual values vary with your CLAUDE.md size, MCP servers, and file lengths.">

745 / {fmt(MAX)} · illustrative

746 </div>

747 </div>

748 </div>

749 

750 {}

751 <div style={{

752 padding: '0 20px'

753 }}>

754 <div style={{

755 height: 4,

756 borderRadius: 2,

757 background: 'var(--cw-track)',

758 overflow: 'hidden',

759 marginBottom: 6

760 }}>

761 <div style={{

762 width: pct + '%',

763 height: '100%',

764 background: barColor,

765 transition: 'width 0.6s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s'

766 }} />

767 </div>

768 <div style={{

769 height: 28,

770 borderRadius: 5,

771 background: 'var(--cw-track)',

772 border: '1px solid var(--cw-border)',

773 overflow: 'hidden',

774 display: 'flex'

775 }}>

776 {blocks.map((b, i) => {

777 const w = Math.max(b.tokens / MAX * 100, 0.15);

778 const isHov = b.visIdx === activeIdx;

779 const catMatch = hovCat && b.color === hovCat;

780 const dimmed = hovCat ? !catMatch : activeIdx !== null && !isHov;

781 return <div key={b.id} onMouseEnter={() => setHovIdx(b.visIdx)} onMouseLeave={() => setHovIdx(null)} onClick={() => setSelIdx(selIdx === b.visIdx ? null : b.visIdx)} style={{

782 width: w + '%',

783 height: '100%',

784 background: b.color,

785 opacity: isHov || catMatch ? 1 : dimmed ? 0.25 : 0.65,

786 borderRight: i < blocks.length - 1 ? '0.5px solid var(--cw-border)' : 'none',

787 transition: 'opacity 0.15s',

788 cursor: 'pointer'

789 }} />;

790 })}

791 </div>

792 <div style={{

793 display: 'flex',

794 gap: 12,

795 marginTop: 6,

796 flexWrap: 'wrap',

797 justifyContent: 'space-between'

798 }}>

799 <div style={{

800 display: 'flex',

801 gap: 12,

802 flexWrap: 'wrap'

803 }}>

804 {LEGEND.map(x => {

805 const active = hovCat === x.c;

806 return <div key={x.l} onMouseEnter={() => setHovCat(x.c)} onMouseLeave={() => setHovCat(null)} style={{

807 display: 'flex',

808 alignItems: 'center',

809 gap: 4,

810 padding: '2px 6px',

811 borderRadius: 4,

812 cursor: 'pointer',

813 background: active ? 'var(--cw-hover)' : 'transparent',

814 transition: 'background 0.1s'

815 }}>

816 <div style={{

817 width: 6,

818 height: 6,

819 borderRadius: 1.5,

820 background: x.c,

821 opacity: active ? 1 : 0.7

822 }} />

823 <span style={{

824 fontSize: 12,

825 color: active ? 'var(--cw-text)' : 'var(--cw-text-dim)'

826 }}>{x.l}</span>

827 </div>;

828 })}

829 </div>

830 <div style={{

831 display: 'flex',

832 gap: 6,

833 alignItems: 'center',

834 fontSize: 12,

835 color: 'var(--cw-text-dim)'

836 }}>

837 <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#558A42" strokeWidth="2.5">

838 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" />

839 </svg>

840 <span>= appears in your terminal</span>

841 </div>

842 </div>

843 </div>

844 

845 {}

846 <div style={{

847 display: 'flex',

848 padding: '14px 20px 0',

849 gap: 16,

850 height: isFullscreen ? 'calc(100vh - 240px)' : 420

851 }}>

852 

853 {}

854 <div ref={scrollRef} className="cw-scroll" style={{

855 flex: 1,

856 minWidth: 0,

857 overflowY: 'auto',

858 paddingRight: 8,

859 scrollBehavior: 'smooth'

860 }}>

861 {visible.length === 0 && !playing && <div style={{

862 height: '100%',

863 display: 'flex',

864 flexDirection: 'column',

865 alignItems: 'center',

866 justifyContent: 'center',

867 gap: 16

868 }}>

869 <div style={{

870 fontFamily: mono,

871 fontSize: 16,

872 color: 'var(--cw-text-dim)',

873 display: 'flex',

874 alignItems: 'center',

875 gap: 8

876 }}>

877 <span style={{

878 color: 'var(--cw-text-faint)'

879 }}>$</span>

880 <span>claude</span>

881 <span style={{

882 display: 'inline-block',

883 width: 8,

884 height: 16,

885 background: 'var(--cw-text-dim)',

886 opacity: 0.5,

887 animation: 'cw-blink 1s step-end infinite'

888 }} />

889 </div>

890 <button onClick={() => setPlaying(true)} style={{

891 padding: '10px 20px',

892 borderRadius: 8,

893 border: '1px solid rgba(217,119,87,0.3)',

894 background: 'rgba(217,119,87,0.08)',

895 color: '#D97757',

896 fontSize: 15,

897 fontWeight: 600,

898 cursor: 'pointer',

899 display: 'flex',

900 alignItems: 'center',

901 gap: 8

902 }}>

903 <span>▶</span>

904 <span>Start session</span>

905 </button>

906 <div style={{

907 fontSize: 13,

908 color: 'var(--cw-text-faint)',

909 maxWidth: 280,

910 textAlign: 'center',

911 lineHeight: 1.5

912 }}>

913 Watch what loads into context, from the moment you run <code style={{

914 fontFamily: mono

915 }}>claude</code> through a full conversation.

916 </div>

917 </div>}

918 {isCompacted && <div style={{

919 marginBottom: 10,

920 padding: '10px 12px',

921 borderRadius: 6,

922 background: 'rgba(217,119,87,0.05)',

923 border: '1px solid rgba(217,119,87,0.15)'

924 }}>

925 <div style={{

926 fontSize: 13,

927 fontWeight: 600,

928 color: '#D97757',

929 marginBottom: 3

930 }}>

931 After /compact

932 </div>

933 <div style={{

934 fontSize: 13,

935 color: 'var(--cw-text-3)',

936 lineHeight: 1.5,

937 fontFamily: mono

938 }}>

939 {fmt(preCompactTotal)} → {fmt(totalTokens)} tokens · freed {fmt(preCompactTotal - totalTokens)}

940 </div>

941 <div style={{

942 fontSize: 13,

943 color: 'var(--cw-text-dim)',

944 lineHeight: 1.5,

945 marginTop: 4

946 }}>

947 This is what's left in context: startup content, which lives outside the message history and reloads after compaction, plus a structured summary of the entire conversation. Skill descriptions don't reload.

948 </div>

949 </div>}

950 {time > 0 && visible.length > 0 && <div style={{

951 fontSize: 12,

952 fontWeight: 700,

953 color: 'var(--cw-text-faint)',

954 textTransform: 'uppercase',

955 letterSpacing: 0.6,

956 marginBottom: 6,

957 paddingLeft: 28

958 }}>

959 {isCompacted ? 'Reloaded after compact' : 'Before you type anything'}

960 </div>}

961 

962 {time > 0 && visible.map((evt, i) => {

963 const meta = KIND_META[evt.kind];

964 const isHov = hovIdx === i;

965 const prevKind = i > 0 ? visible[i - 1].kind : null;

966 const isSub = evt.kind === 'sub';

967 const enteringSubagent = isSub && prevKind !== 'sub';

968 const leavingSubagent = prevKind === 'sub' && !isSub;

969 let showPhase = null;

970 if (evt.kind === 'user' && prevKind !== 'user') showPhase = 'You'; else if (evt.kind === 'claude' && prevKind === 'user') showPhase = 'Claude works'; else if (evt.label === 'Conversation summary') showPhase = 'Summarized by /compact';

971 const isNewRow = isCompacted && !(evt.kind === 'auto' && evt.t < STARTUP_END);

972 return <div key={evt.label + evt.t} className={isNewRow ? 'cw-compacted-row' : ''} style={isNewRow ? {

973 animationDelay: `${i * 60}ms`

974 } : {}}>

975 {showPhase && <div style={{

976 fontSize: 12,

977 fontWeight: 700,

978 color: 'var(--cw-text-faint)',

979 textTransform: 'uppercase',

980 letterSpacing: 0.6,

981 marginTop: 14,

982 marginBottom: 6,

983 paddingLeft: 28

984 }}>

985 {showPhase}

986 </div>}

987 {enteringSubagent && <div style={{

988 marginLeft: 28,

989 marginTop: 6,

990 marginBottom: 2,

991 paddingLeft: 10,

992 borderLeft: '2px solid rgba(155,123,196,0.4)',

993 fontSize: 12,

994 fontWeight: 600,

995 color: '#9B7BC4',

996 textTransform: 'uppercase',

997 letterSpacing: 0.5

998 }}>

999 Subagent's separate context window

1000 </div>}

1001 {leavingSubagent && <div style={{

1002 marginLeft: 28,

1003 marginBottom: 6,

1004 paddingLeft: 10,

1005 paddingBottom: 6,

1006 borderLeft: '2px solid rgba(155,123,196,0.4)',

1007 fontSize: 12,

1008 color: 'var(--cw-text-dim)',

1009 fontFamily: mono

1010 }}>

1011 ↓ {fmt(subTotal)} tokens stayed in subagent's context · only the summary returns

1012 </div>}

1013 <div onMouseEnter={() => setHovIdx(i)} onMouseLeave={() => setHovIdx(null)} onClick={() => setSelIdx(selIdx === i ? null : i)} style={{

1014 display: 'flex',

1015 alignItems: 'flex-start',

1016 borderRadius: 6,

1017 cursor: 'pointer',

1018 background: selIdx === i || isHov ? 'var(--cw-hover)' : 'transparent',

1019 outline: selIdx === i ? '1px solid rgba(217,119,87,0.4)' : 'none',

1020 opacity: hovCat && evt.color !== hovCat ? 0.35 : 1,

1021 transition: 'background 0.1s, opacity 0.15s',

1022 marginLeft: isSub ? 28 : 0,

1023 paddingLeft: isSub ? 10 : 0,

1024 borderLeft: isSub ? '2px solid rgba(155,123,196,0.4)' : 'none'

1025 }}>

1026 <div style={{

1027 width: 28,

1028 display: 'flex',

1029 flexDirection: 'column',

1030 alignItems: 'center',

1031 paddingTop: 8,

1032 flexShrink: 0

1033 }}>

1034 <div style={{

1035 width: evt.kind === 'user' || evt.kind === 'compact' ? 10 : 7,

1036 height: evt.kind === 'user' || evt.kind === 'compact' ? 10 : 7,

1037 borderRadius: '50%',

1038 background: evt.color,

1039 opacity: isHov ? 1 : 0.6,

1040 transition: 'opacity 0.15s',

1041 boxShadow: isHov ? `0 0 8px ${evt.color}40` : 'none'

1042 }} />

1043 {i < visible.length - 1 && <div style={{

1044 width: 1.5,

1045 flex: 1,

1046 background: 'var(--cw-rail)',

1047 marginTop: 2,

1048 minHeight: 6

1049 }} />}

1050 </div>

1051 <div style={{

1052 flex: 1,

1053 minWidth: 0,

1054 padding: '5px 10px 5px 4px',

1055 display: 'flex',

1056 alignItems: 'center',

1057 gap: 8

1058 }}>

1059 <span style={{

1060 fontSize: 12,

1061 fontWeight: 600,

1062 padding: '1px 5px',

1063 borderRadius: 3,

1064 background: meta.badgeBg,

1065 color: meta.badgeColor,

1066 flexShrink: 0,

1067 fontFamily: mono

1068 }}>

1069 {meta.badge}

1070 </span>

1071 <span style={{

1072 fontSize: 15,

1073 fontFamily: mono,

1074 color: isHov ? 'var(--cw-text)' : evt.kind === 'user' ? '#558A42' : evt.kind === 'auto' ? 'var(--cw-text-dim)' : 'var(--cw-text-2)',

1075 flex: 1,

1076 minWidth: 0,

1077 overflow: 'hidden',

1078 textOverflow: 'ellipsis',

1079 whiteSpace: 'nowrap',

1080 fontWeight: evt.kind === 'user' ? 550 : 400

1081 }}>

1082 {evt.label}

1083 </span>

1084 {evt.tokens > 0 && <span style={{

1085 fontSize: 12,

1086 fontFamily: mono,

1087 color: 'var(--cw-text-faint)',

1088 flexShrink: 0

1089 }}>

1090 +{fmt(evt.tokens)}

1091 </span>}

1092 {evt.subTokens > 0 && <span style={{

1093 fontSize: 12,

1094 fontFamily: mono,

1095 color: '#9B7BC4',

1096 flexShrink: 0,

1097 opacity: 0.6

1098 }}>

1099 +{fmt(evt.subTokens)}

1100 </span>}

1101 {evt.tokens > 0 && <div style={{

1102 width: 50,

1103 height: 5,

1104 borderRadius: 2,

1105 background: 'var(--cw-track)',

1106 flexShrink: 0,

1107 overflow: 'hidden'

1108 }}>

1109 <div style={{

1110 width: Math.min(evt.tokens / 5000 * 100, 100) + '%',

1111 height: '100%',

1112 background: evt.color,

1113 opacity: isHov ? 0.8 : 0.4,

1114 transition: 'opacity 0.15s'

1115 }} />

1116 </div>}

1117 <span style={{

1118 width: 14,

1119 flexShrink: 0,

1120 display: 'flex',

1121 justifyContent: 'center'

1122 }} title={VIS_META[evt.vis].label}>

1123 {evt.vis !== 'hidden' && <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke={evt.vis === 'full' ? '#558A42' : 'currentColor'} style={{

1124 color: 'var(--cw-text-faint)',

1125 opacity: evt.vis === 'full' ? 1 : 0.5

1126 }} strokeWidth="2">

1127 <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" />

1128 </svg>}

1129 </span>

1130 </div>

1131 </div>

1132 </div>;

1133 })}

1134 

1135 {activeGate && (activeGate.kind === 'prompt' || activeGate.kind === 'bang' || activeGate.kind === 'slash') && <div style={{

1136 paddingLeft: 28,

1137 marginTop: 12,

1138 paddingRight: 8

1139 }}>

1140 <div style={{

1141 fontSize: 11,

1142 fontWeight: 600,

1143 color: '#6BA656',

1144 fontFamily: mono,

1145 textTransform: 'uppercase',

1146 letterSpacing: 0.5,

1147 marginBottom: 4,

1148 paddingLeft: 2

1149 }}>

1150 You type in your terminal

1151 </div>

1152 <div style={{

1153 display: 'flex',

1154 alignItems: 'flex-start',

1155 gap: 8,

1156 padding: '10px 12px',

1157 borderRadius: 6,

1158 background: 'rgba(85,138,66,0.06)',

1159 border: '1px solid rgba(85,138,66,0.2)'

1160 }}>

1161 <span style={{

1162 color: '#558A42',

1163 fontSize: 15,

1164 fontFamily: mono,

1165 flexShrink: 0

1166 }}>❯</span>

1167 <span style={{

1168 fontSize: 15,

1169 fontFamily: mono,

1170 color: 'var(--cw-text-2)',

1171 flex: 1,

1172 lineHeight: 1.5

1173 }}>

1174 {activeGate.text}

1175 <span style={{

1176 display: 'inline-block',

1177 width: 7,

1178 height: 13,

1179 marginLeft: 2,

1180 background: '#558A42',

1181 opacity: 0.5,

1182 verticalAlign: 'middle',

1183 animation: 'cw-blink 1s step-end infinite'

1184 }} />

1185 </span>

1186 <button onClick={sendPrompt} style={{

1187 padding: '5px 12px',

1188 borderRadius: 5,

1189 border: 'none',

1190 background: '#558A42',

1191 color: '#fff',

1192 fontSize: 13,

1193 fontWeight: 600,

1194 cursor: 'pointer',

1195 flexShrink: 0

1196 }}>

1197 {activeGate.kind === 'prompt' ? 'Send ↵' : 'Run ↵'}

1198 </button>

1199 </div>

1200 </div>}

1201 {activeGate && activeGate.kind === 'compact' && <div style={{

1202 paddingLeft: 28,

1203 marginTop: 12,

1204 paddingRight: 8

1205 }}>

1206 <div style={{

1207 padding: '12px 14px',

1208 borderRadius: 6,

1209 background: 'rgba(217,119,87,0.06)',

1210 border: '1px solid rgba(217,119,87,0.25)'

1211 }}>

1212 <div style={{

1213 fontSize: 13,

1214 color: 'var(--cw-text-3)',

1215 marginBottom: 8,

1216 lineHeight: 1.5

1217 }}>

1218 Context is at <span style={{

1219 fontFamily: mono,

1220 fontWeight: 600,

1221 color: barColor

1222 }}>{fmt(totalTokens)} tokens</span>.

1223 Run <code style={{

1224 fontFamily: mono,

1225 background: 'var(--cw-track)',

1226 padding: '1px 4px',

1227 borderRadius: 3

1228 }}>/compact</code> to

1229 summarize older exchanges and free space for more work.

1230 </div>

1231 <div style={{

1232 display: 'flex',

1233 alignItems: 'center',

1234 gap: 8

1235 }}>

1236 <span style={{

1237 color: '#D97757',

1238 fontSize: 15,

1239 fontFamily: mono

1240 }}>❯</span>

1241 <span style={{

1242 fontSize: 15,

1243 fontFamily: mono,

1244 color: 'var(--cw-text-2)',

1245 flex: 1

1246 }}>

1247 {activeGate.text}

1248 </span>

1249 <button onClick={sendPrompt} style={{

1250 padding: '5px 12px',

1251 borderRadius: 5,

1252 border: 'none',

1253 background: '#D97757',

1254 color: '#fff',

1255 fontSize: 13,

1256 fontWeight: 600,

1257 cursor: 'pointer',

1258 flexShrink: 0

1259 }}>

1260 Run ↵

1261 </button>

1262 </div>

1263 </div>

1264 </div>}

1265 </div>

1266 

1267 {}

1268 <div style={{

1269 width: 300,

1270 flexShrink: 0,

1271 display: 'flex',

1272 flexDirection: 'column'

1273 }}>

1274 <div ref={detailRef} className="cw-scroll" style={{

1275 padding: '14px 16px',

1276 borderRadius: 10,

1277 background: 'var(--cw-surface)',

1278 border: '1px solid var(--cw-border)',

1279 flex: 1,

1280 minHeight: 0,

1281 overflowY: 'auto',

1282 display: 'flex',

1283 flexDirection: 'column',

1284 gap: 10

1285 }}>

1286 {hovEvent ? <div>

1287 <div style={{

1288 display: 'flex',

1289 alignItems: 'center',

1290 gap: 8,

1291 marginBottom: 8

1292 }}>

1293 <div style={{

1294 width: 10,

1295 height: 10,

1296 borderRadius: 3,

1297 background: hovEvent.color,

1298 opacity: 0.8

1299 }} />

1300 <span style={{

1301 fontSize: 16,

1302 fontWeight: 600

1303 }}>{hovEvent.label}</span>

1304 </div>

1305 <div style={{

1306 display: 'flex',

1307 width: 'fit-content',

1308 padding: '3px 8px',

1309 borderRadius: 4,

1310 marginBottom: 8,

1311 background: KIND_META[hovEvent.kind].badgeBg

1312 }}>

1313 <span style={{

1314 fontSize: 12,

1315 fontWeight: 600,

1316 color: KIND_META[hovEvent.kind].badgeColor

1317 }}>

1318 {KIND_META[hovEvent.kind].detail}

1319 </span>

1320 </div>

1321 {hovEvent.tokens > 0 && <div style={{

1322 fontSize: 14,

1323 fontFamily: mono,

1324 color: 'var(--cw-text-dim)',

1325 marginBottom: 6

1326 }}>

1327 {fmt(hovEvent.tokens)} tokens

1328 </div>}

1329 {hovEvent.subTokens > 0 && <div style={{

1330 fontSize: 14,

1331 fontFamily: mono,

1332 color: '#9B7BC4',

1333 marginBottom: 6

1334 }}>

1335 {fmt(hovEvent.subTokens)} tokens in the subagent's context

1336 </div>}

1337 <p style={{

1338 fontSize: 15,

1339 color: 'var(--cw-text-3)',

1340 lineHeight: 1.55,

1341 margin: 0

1342 }}>

1343 {renderWithCode(hovEvent.desc)}

1344 </p>

1345 <div style={{

1346 marginTop: 10,

1347 padding: '8px 10px',

1348 borderRadius: 6,

1349 background: hovEvent.vis === 'full' ? 'rgba(85,138,66,0.08)' : 'var(--cw-surface-2)',

1350 border: '1px solid ' + (hovEvent.vis === 'full' ? 'rgba(85,138,66,0.2)' : 'var(--cw-border)')

1351 }}>

1352 <div style={{

1353 display: 'flex',

1354 alignItems: 'center',

1355 gap: 6,

1356 marginBottom: 3

1357 }}>

1358 <span style={{

1359 fontSize: 13,

1360 color: hovEvent.vis === 'full' ? '#558A42' : 'var(--cw-text-dim)'

1361 }}>

1362 {hovEvent.vis === 'full' ? '●' : hovEvent.vis === 'brief' ? '◐' : '○'}

1363 </span>

1364 <span style={{

1365 fontSize: 12,

1366 fontWeight: 600,

1367 color: 'var(--cw-text-2)'

1368 }}>

1369 {VIS_META[hovEvent.vis].label}

1370 </span>

1371 </div>

1372 <div style={{

1373 fontSize: 13,

1374 color: 'var(--cw-text-dim)',

1375 lineHeight: 1.4

1376 }}>

1377 {VIS_META[hovEvent.vis].sub}

1378 </div>

1379 </div>

1380 {hovEvent.tip && <div style={{

1381 marginTop: 10,

1382 padding: '8px 10px',

1383 borderRadius: 6,

1384 background: 'rgba(85,138,66,0.06)',

1385 border: '1px solid rgba(85,138,66,0.15)'

1386 }}>

1387 <div style={{

1388 fontSize: 12,

1389 fontWeight: 600,

1390 color: '#558A42',

1391 marginBottom: 3,

1392 display: 'flex',

1393 alignItems: 'center',

1394 gap: 4

1395 }}>

1396 <span>💡</span> Save context

1397 </div>

1398 <div style={{

1399 fontSize: 13,

1400 color: 'var(--cw-text-3)',

1401 lineHeight: 1.5

1402 }}>

1403 {renderWithCode(hovEvent.tip)}

1404 </div>

1405 </div>}

1406 {hovEvent.link && <a href={hovEvent.link} style={{

1407 display: 'inline-block',

1408 marginTop: 10,

1409 fontSize: 13,

1410 color: '#D97757',

1411 textDecoration: 'none',

1412 borderBottom: '1px solid rgba(217,119,87,0.3)'

1413 }}>

1414 Learn more →

1415 </a>}

1416 </div> : <div style={{

1417 display: 'flex',

1418 flexDirection: 'column',

1419 alignItems: 'center',

1420 textAlign: 'center',

1421 gap: 4,

1422 padding: '12px 0 4px'

1423 }}>

1424 <div style={{

1425 fontSize: 22,

1426 opacity: 0.2

1427 }}>👁</div>

1428 <div style={{

1429 fontSize: 14,

1430 fontWeight: 500,

1431 color: 'var(--cw-text-dim)'

1432 }}>Hover or click any event</div>

1433 <div style={{

1434 fontSize: 12,

1435 color: 'var(--cw-text-faint)',

1436 lineHeight: 1.4,

1437 maxWidth: 200

1438 }}>

1439 Hover to preview. Click to pin so you can scroll.

1440 </div>

1441 </div>}

1442 

1443 <div style={{

1444 padding: '10px 12px',

1445 borderRadius: 8,

1446 background: 'rgba(217,119,87,0.05)',

1447 border: '1px solid rgba(217,119,87,0.12)'

1448 }}>

1449 <div style={{

1450 fontSize: 11,

1451 fontWeight: 700,

1452 color: '#D97757',

1453 textTransform: 'uppercase',

1454 letterSpacing: 0.5,

1455 marginBottom: 3

1456 }}>

1457 Key takeaway

1458 </div>

1459 <div style={{

1460 fontSize: 13,

1461 color: 'var(--cw-text-3)',

1462 lineHeight: 1.5

1463 }}>

1464 {takeaway}

1465 </div>

1466 </div>

1467 

1468 <div style={{

1469 padding: '10px 12px',

1470 borderRadius: 8,

1471 background: 'var(--cw-surface-2)',

1472 border: '1px solid var(--cw-border)'

1473 }}>

1474 <div style={{

1475 fontSize: 11,

1476 fontWeight: 700,

1477 color: 'var(--cw-text-dim)',

1478 textTransform: 'uppercase',

1479 letterSpacing: 0.5,

1480 marginBottom: 3

1481 }}>

1482 In your terminal you see

1483 </div>

1484 <div style={{

1485 fontSize: 13,

1486 color: 'var(--cw-text-3)',

1487 lineHeight: 1.5

1488 }}>

1489 {terminalView}

1490 </div>

1491 </div>

1492 </div>

1493 </div>

1494 </div>

1495 

1496 {}

1497 <div style={{

1498 padding: '10px 20px 14px',

1499 display: 'flex',

1500 alignItems: 'center',

1501 gap: 10

1502 }}>

1503 <button aria-label={time >= 1 ? 'Restart' : activeGate ? 'Continue' : playing ? 'Pause' : 'Play'} onClick={() => {

1504 if (time >= 1) {

1505 setTime(0);

1506 setGatesPassed(0);

1507 setSelIdx(null);

1508 setHovIdx(null);

1509 setPlaying(true);

1510 } else if (activeGate) sendPrompt(); else setPlaying(!playing);

1511 }} style={{

1512 width: 30,

1513 height: 30,

1514 borderRadius: 6,

1515 border: 'none',

1516 background: 'rgba(217,119,87,0.1)',

1517 color: '#D97757',

1518 cursor: 'pointer',

1519 fontSize: 15,

1520 fontWeight: 700,

1521 display: 'flex',

1522 alignItems: 'center',

1523 justifyContent: 'center'

1524 }}>

1525 {time >= 1 ? '↺' : playing ? '⏸' : '▶'}

1526 </button>

1527 <div style={{

1528 flex: 1,

1529 height: 3,

1530 borderRadius: 2,

1531 background: 'var(--cw-track)',

1532 overflow: 'hidden'

1533 }}>

1534 <div style={{

1535 width: time * 100 + '%',

1536 height: '100%',

1537 background: '#D97757',

1538 transition: 'width 0.1s linear'

1539 }} />

1540 </div>

1541 <span style={{

1542 fontSize: 12,

1543 fontFamily: mono,

1544 color: 'var(--cw-text-faint)',

1545 minWidth: 30

1546 }}>

1547 {Math.round(time * 100)}%

1548 </span>

1549 <button onClick={toggleFullscreen} aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} style={{

1550 width: 28,

1551 height: 28,

1552 borderRadius: 6,

1553 border: '1px solid var(--cw-border)',

1554 background: 'var(--cw-surface)',

1555 color: 'var(--cw-text-dim)',

1556 cursor: 'pointer',

1557 fontSize: 15,

1558 flexShrink: 0,

1559 marginLeft: 4,

1560 display: 'flex',

1561 alignItems: 'center',

1562 justifyContent: 'center'

1563 }}>

1564 {isFullscreen ? '⤡' : '⛶'}

1565 </button>

1566 </div>

1567 </div>

1568 </>;

1569};

1570 

1571Claude Code's context window holds everything Claude knows about your session: your instructions, the files it reads, its own responses, and content that never appears in your terminal. The timeline below walks through what loads and when. See [the written breakdown](#what-the-timeline-shows) for the same content as a list.

1572 

1573<ContextWindow />

1574 

1575## What the timeline shows

1576 

1577The session walks through a realistic flow with representative token counts:

1578 

1579* **Before you type anything**: CLAUDE.md, auto memory, MCP tool names, and skill descriptions all load into context. Your own setup may add more here, like an [output style](/en/output-styles) or text from [`--append-system-prompt`](/en/cli-reference), which both go into the system prompt the same way.

1580* **As Claude works**: each file read adds to context, [path-scoped rules](/en/memory#path-specific-rules) load automatically alongside matching files, and a [PostToolUse hook](/en/hooks-guide) fires after each edit.

1581* **The follow-up prompt**: a [subagent](/en/sub-agents) handles the research in its own separate context window, so the large file reads stay out of yours. Only the summary and a small metadata trailer come back.

1582* **At the end**: `/compact` replaces the conversation with a structured summary. Most startup content reloads automatically. The [skill](/en/skills) listing is the one exception.

1583 

1584## Check your own session

1585 

1586The visualization uses representative numbers. To see your actual context usage at any point, run `/context` for a live breakdown by category with optimization suggestions. Run `/memory` to check which CLAUDE.md and auto memory files loaded at startup.

1587 

1588## Related resources

1589 

1590For deeper coverage of the features shown in the timeline, see these pages:

1591 

1592* [Extend Claude Code](/en/features-overview): when to use CLAUDE.md vs skills vs rules vs hooks vs MCP

1593* [Store instructions and memories](/en/memory): CLAUDE.md hierarchy and auto memory

1594* [Subagents](/en/sub-agents): delegate research to a separate context window

1595* [Best practices](/en/best-practices): managing context as your primary constraint

1596* [Reduce token usage](/en/costs#reduce-token-usage): strategies for keeping context usage low

costs.md +2 −3

Details

99 99 

100### Reduce MCP server overhead100### Reduce MCP server overhead

101 101 

102Each MCP server adds tool definitions to your context, even when idle. Run `/context` to see what's consuming space.102MCP tool definitions are [deferred by default](/en/mcp#scale-with-mcp-tool-search), so only tool names enter context until Claude uses a specific tool. Run `/context` to see what's consuming space.

103 103 

104* **Prefer CLI tools when available**: Tools like `gh`, `aws`, `gcloud`, and `sentry-cli` are more context-efficient than MCP servers because they don't add persistent tool definitions. Claude can run CLI commands directly without the overhead.104* **Prefer CLI tools when available**: Tools like `gh`, `aws`, `gcloud`, and `sentry-cli` are still more context-efficient than MCP servers because they don't add any per-tool listing. Claude can run CLI commands directly.

105* **Disable unused servers**: Run `/mcp` to see configured servers and disable any you're not actively using.105* **Disable unused servers**: Run `/mcp` to see configured servers and disable any you're not actively using.

106* **Tool search is automatic**: When MCP tool descriptions exceed 10% of your context window, Claude Code automatically defers them and loads tools on-demand via [tool search](/en/mcp#scale-with-mcp-tool-search). Since deferred tools only enter context when actually used, a lower threshold means fewer idle tool definitions consuming space. Set a lower threshold with `ENABLE_TOOL_SEARCH=auto:<N>` (for example, `auto:5` triggers when tools exceed 5% of your context window).

107 106 

108### Install code intelligence plugins for typed languages107### Install code intelligence plugins for typed languages

109 108 

env-vars.md +1 −1

Details

109| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models |109| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models |

110| `DISABLE_TELEMETRY` | Set to `1` to opt out of Statsig telemetry (note that Statsig events do not include user data like code, file paths, or bash commands) |110| `DISABLE_TELEMETRY` | Set to `1` to opt out of Statsig telemetry (note that Statsig events do not include user data like code, file paths, or bash commands) |

111| `ENABLE_CLAUDEAI_MCP_SERVERS` | Set to `false` to disable [claude.ai MCP servers](/en/mcp#use-mcp-servers-from-claude-ai) in Claude Code. Enabled by default for logged-in users |111| `ENABLE_CLAUDEAI_MCP_SERVERS` | Set to `false` to disable [claude.ai MCP servers](/en/mcp#use-mcp-servers-from-claude-ai) in Claude Code. Enabled by default for logged-in users |

112| `ENABLE_TOOL_SEARCH` | Controls [MCP tool search](/en/mcp#scale-with-mcp-tool-search). Unset: enabled by default, but disabled when `ANTHROPIC_BASE_URL` points to a non-first-party host. Values: `true` (always on including proxies), `auto` (enables at 10% context), `auto:N` (custom threshold, e.g., `auto:5` for 5%), `false` (disabled) |112| `ENABLE_TOOL_SEARCH` | Controls [MCP tool search](/en/mcp#scale-with-mcp-tool-search). Unset: all MCP tools deferred by default, but loaded upfront when `ANTHROPIC_BASE_URL` points to a non-first-party host. Values: `true` (always defer including proxies), `auto` (threshold mode: load upfront if tools fit within 10% of context), `auto:N` (custom threshold, e.g., `auto:5` for 5%), `false` (load all upfront) |

113| `FORCE_AUTOUPDATE_PLUGINS` | Set to `true` to force plugin auto-updates even when the main auto-updater is disabled via `DISABLE_AUTOUPDATER` |113| `FORCE_AUTOUPDATE_PLUGINS` | Set to `true` to force plugin auto-updates even when the main auto-updater is disabled via `DISABLE_AUTOUPDATER` |

114| `HTTP_PROXY` | Specify HTTP proxy server for network connections |114| `HTTP_PROXY` | Specify HTTP proxy server for network connections |

115| `HTTPS_PROXY` | Specify HTTPS proxy server for network connections |115| `HTTPS_PROXY` | Specify HTTPS proxy server for network connections |

Details

168 168 

169## Understand context costs169## Understand context costs

170 170 

171Every feature you add consumes some of Claude's context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup.171Every feature you add consumes some of Claude's context. Too much can fill up your context window, but it can also add noise that makes Claude less effective; skills may not trigger correctly, or Claude may lose track of your conventions. Understanding these trade-offs helps you build an effective setup. For an interactive view of how these features combine in a running session, see [Explore the context window](/en/context-window).

172 172 

173### Context cost by feature173### Context cost by feature

174 174 


178| --------------- | ------------------------- | --------------------------------------------- | -------------------------------------------- |178| --------------- | ------------------------- | --------------------------------------------- | -------------------------------------------- |

179| **CLAUDE.md** | Session start | Full content | Every request |179| **CLAUDE.md** | Session start | Full content | Every request |

180| **Skills** | Session start + when used | Descriptions at start, full content when used | Low (descriptions every request)\* |180| **Skills** | Session start + when used | Descriptions at start, full content when used | Low (descriptions every request)\* |

181| **MCP servers** | Session start | All tool definitions and schemas | Every request |181| **MCP servers** | Session start | Tool names; full schemas on demand | Low until a tool is used |

182| **Subagents** | When spawned | Fresh context with specified skills | Isolated from main session |182| **Subagents** | When spawned | Fresh context with specified skills | Isolated from main session |

183| **Hooks** | On trigger | Nothing (runs externally) | Zero, unless hook returns additional context |183| **Hooks** | On trigger | Nothing (runs externally) | Zero, unless hook returns additional context |

184 184 


188 188 

189Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.189Each feature loads at different points in your session. The tabs below explain when each one loads and what goes into context.

190 190 

191<img src="https://mintcdn.com/claude-code/c5r9_6tjPMzFdDDT/images/context-loading.svg?fit=max&auto=format&n=c5r9_6tjPMzFdDDT&q=85&s=729b5b634ba831d1d64772c6c9485b30" alt="Context loading: CLAUDE.md and MCP load at session start and stay in every request. Skills load descriptions at start, full content on invocation. Subagents get isolated context. Hooks run externally." width="720" height="410" data-path="images/context-loading.svg" />191<img src="https://mintcdn.com/claude-code/6yTCYq1p37ZB8-CQ/images/context-loading.svg?fit=max&auto=format&n=6yTCYq1p37ZB8-CQ&q=85&s=5a58ce953a35a2412892015e2ad6cb67" alt="Context loading: CLAUDE.md loads at session start and stays in every request. MCP tool names load at start with full schemas deferred until use. Skills load descriptions at start, full content on invocation. Subagents get isolated context. Hooks run externally." width="720" height="410" data-path="images/context-loading.svg" />

192 192 

193<Tabs>193<Tabs>

194 <Tab title="CLAUDE.md">194 <Tab title="CLAUDE.md">


220 <Tab title="MCP servers">220 <Tab title="MCP servers">

221 **When:** Session start.221 **When:** Session start.

222 222 

223 **What loads:** All tool definitions and JSON schemas from connected servers.223 **What loads:** Tool names from connected servers. Full JSON schemas stay deferred until Claude needs a specific tool.

224 224 

225 **Context cost:** [Tool search](/en/mcp#scale-with-mcp-tool-search) (enabled by default) loads MCP tools up to 10% of context and defers the rest until needed.225 **Context cost:** [Tool search](/en/mcp#scale-with-mcp-tool-search) is on by default, so idle MCP tools consume minimal context.

226 226 

227 **Reliability note:** MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with `/mcp`.227 **Reliability note:** MCP connections can fail silently mid-session. If a server disconnects, its tools disappear without warning. Claude may try to use a tool that no longer exists. If you notice Claude failing to use an MCP tool it previously could access, check the connection with `/mcp`.

228 228 

hooks.md +32 −11

Details

54 54 

55### How a hook resolves55### How a hook resolves

56 56 

57To see how these pieces fit together, consider this `PreToolUse` hook that blocks destructive shell commands. The hook runs `block-rm.sh` before every Bash tool call:57To see how these pieces fit together, consider this `PreToolUse` hook that blocks destructive shell commands. The `matcher` narrows to Bash tool calls and the `if` condition narrows further to commands starting with `rm`, so `block-rm.sh` only spawns when both filters match:

58 58 

59```json theme={null}59```json theme={null}

60{60{


65 "hooks": [65 "hooks": [

66 {66 {

67 "type": "command",67 "type": "command",

68 "command": ".claude/hooks/block-rm.sh"68 "if": "Bash(rm *)",

69 "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"

69 }70 }

70 ]71 ]

71 }72 }


97Now suppose Claude Code decides to run `Bash "rm -rf /tmp/build"`. Here's what happens:98Now suppose Claude Code decides to run `Bash "rm -rf /tmp/build"`. Here's what happens:

98 99 

99<Frame>100<Frame>

100 <img src="https://mintcdn.com/claude-code/c5r9_6tjPMzFdDDT/images/hook-resolution.svg?fit=max&auto=format&n=c5r9_6tjPMzFdDDT&q=85&s=ad667ee6d86ab2276aa48a4e73e220df" alt="Hook resolution flow: PreToolUse event fires, matcher checks for Bash match, hook handler runs, result returns to Claude Code" width="780" height="290" data-path="images/hook-resolution.svg" />101 <img src="https://mintcdn.com/claude-code/-tYw1BD_DEqfyyOZ/images/hook-resolution.svg?fit=max&auto=format&n=-tYw1BD_DEqfyyOZ&q=85&s=c73ebc1eeda2037570427d7af1e0a891" alt="Hook resolution flow: PreToolUse event fires, matcher checks for Bash match, if condition checks for Bash(rm *) match, hook handler runs, result returns to Claude Code" width="930" height="290" data-path="images/hook-resolution.svg" />

101</Frame>102</Frame>

102 103 

103<Steps>104<Steps>


110 </Step>111 </Step>

111 112 

112 <Step title="Matcher checks">113 <Step title="Matcher checks">

113 The matcher `"Bash"` matches the tool name, so `block-rm.sh` runs. If you omit the matcher or use `"*"`, the hook runs on every occurrence of the event. Hooks only skip when a matcher is defined and doesn't match.114 The matcher `"Bash"` matches the tool name, so this hook group activates. If you omit the matcher or use `"*"`, the group activates on every occurrence of the event.

115 </Step>

116 

117 <Step title="If condition checks">

118 The `if` condition `"Bash(rm *)"` matches because the command starts with `rm`, so this handler spawns. If the command had been `npm test`, the `if` check would fail and `block-rm.sh` would never run, avoiding the process spawn overhead. The `if` field is optional; without it, every handler in the matched group runs.

114 </Step>119 </Step>

115 120 

116 <Step title="Hook handler runs">121 <Step title="Hook handler runs">

117 The script extracts `"rm -rf /tmp/build"` from the input and finds `rm -rf`, so it prints a decision to stdout:122 The script inspects the full command and finds `rm -rf`, so it prints a decision to stdout:

118 123 

119 ```json theme={null}124 ```json theme={null}

120 {125 {


126 }131 }

127 ```132 ```

128 133 

129 If the command had been safe (like `npm test`), the script would hit `exit 0` instead, which tells Claude Code to allow the tool call with no further action.134 If the command had been a safer `rm` variant like `rm file.txt`, the script would hit `exit 0` instead, which tells Claude Code to allow the tool call with no further action.

130 </Step>135 </Step>

131 136 

132 <Step title="Claude Code acts on the result">137 <Step title="Claude Code acts on the result">


211 216 

212`UserPromptSubmit`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, and `CwdChanged` don't support matchers and always fire on every occurrence. If you add a `matcher` field to these events, it is silently ignored.217`UserPromptSubmit`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, and `CwdChanged` don't support matchers and always fire on every occurrence. If you add a `matcher` field to these events, it is silently ignored.

213 218 

219For tool events, you can filter more narrowly by setting the [`if` field](#common-fields) on individual hook handlers. `if` uses [permission rule syntax](/en/permissions) to match against the tool name and arguments together, so `"Bash(git *)"` runs only for `git` commands and `"Edit(*.ts)"` runs only for TypeScript files.

220 

214#### Match MCP tools221#### Match MCP tools

215 222 

216[MCP](/en/mcp) server tools appear as regular tools in tool events (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`), so you can match them the same way you match any other tool name.223[MCP](/en/mcp) server tools appear as regular tools in tool events (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`), so you can match them the same way you match any other tool name.


269These fields apply to all hook types:276These fields apply to all hook types:

270 277 

271| Field | Required | Description |278| Field | Required | Description |

272| :-------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |279| :-------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

273| `type` | yes | `"command"`, `"http"`, `"prompt"`, or `"agent"` |280| `type` | yes | `"command"`, `"http"`, `"prompt"`, or `"agent"` |

281| `if` | no | Permission rule syntax to filter when this hook runs, such as `"Bash(git *)"` or `"Edit(*.ts)"`. The hook only spawns if the tool call matches the pattern. Only evaluated on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, and `PermissionRequest`. On other events, a hook with `if` set never runs. Uses the same syntax as [permission rules](/en/permissions) |

274| `timeout` | no | Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent |282| `timeout` | no | Seconds before canceling. Defaults: 600 for command, 30 for prompt, 60 for agent |

275| `statusMessage` | no | Custom spinner message displayed while the hook runs |283| `statusMessage` | no | Custom spinner message displayed while the hook runs |

276| `once` | no | If `true`, runs only once per session then is removed. Skills only, not agents. See [Hooks in skills and agents](#hooks-in-skills-and-agents) |284| `once` | no | If `true`, runs only once per session then is removed. Skills only, not agents. See [Hooks in skills and agents](#hooks-in-skills-and-agents) |


835 843 

836### PreToolUse844### PreToolUse

837 845 

838Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `WebFetch`, `WebSearch`, and any [MCP tool names](#match-mcp-tools).846Runs after Claude creates tool parameters and before processing the tool call. Matches on tool name: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `WebFetch`, `WebSearch`, `AskUserQuestion`, `ExitPlanMode`, and any [MCP tool names](#match-mcp-tools).

839 847 

840Use [PreToolUse decision control](#pretooluse-decision-control) to allow, deny, or ask for permission to use the tool.848Use [PreToolUse decision control](#pretooluse-decision-control) to allow, deny, or ask for permission to use the tool.

841 849 


936| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |944| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |

937| `model` | string | `"sonnet"` | Optional model alias to override the default |945| `model` | string | `"sonnet"` | Optional model alias to override the default |

938 946 

947##### AskUserQuestion

948 

949Asks the user one to four multiple-choice questions.

950 

951| Field | Type | Example | Description |

952| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

953| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Questions to present, each with a `question` string, short `header`, `options` array, and optional `multiSelect` flag |

954| `answers` | object | `{"Which framework?": "React"}` | Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude does not set this field; supply it via `updatedInput` to answer programmatically |

955 

939#### PreToolUse decision control956#### PreToolUse decision control

940 957 

941`PreToolUse` hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level `decision` field, PreToolUse returns its decision inside a `hookSpecificOutput` object. This gives it richer control: three outcomes (allow, deny, or ask) plus the ability to modify tool input before execution.958`PreToolUse` hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level `decision` field, PreToolUse returns its decision inside a `hookSpecificOutput` object. This gives it richer control: three outcomes (allow, deny, or ask) plus the ability to modify tool input before execution.

942 959 

943| Field | Description |960| Field | Description |

944| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |961| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

945| `permissionDecision` | `"allow"` skips the permission prompt. `"deny"` prevents the tool call. `"ask"` prompts the user to confirm. [Deny and ask rules](/en/permissions#manage-permissions) still apply when a hook returns `"allow"` |962| `permissionDecision` | `"allow"` skips the permission prompt. `"deny"` prevents the tool call. `"ask"` prompts the user to confirm. [Deny and ask rules](/en/permissions#manage-permissions) still apply when a hook returns `"allow"` |

946| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude |963| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude |

947| `updatedInput` | Modifies the tool's input parameters before execution. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user |964| `updatedInput` | Modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user |

948| `additionalContext` | String added to Claude's context before the tool executes |965| `additionalContext` | String added to Claude's context before the tool executes |

949 966 

950When a hook returns `"ask"`, the permission prompt displayed to the user includes a label identifying where the hook came from: for example, `[User]`, `[Project]`, `[Plugin]`, or `[Local]`. This helps users understand which configuration source is requesting confirmation.967When a hook returns `"ask"`, the permission prompt displayed to the user includes a label identifying where the hook came from: for example, `[User]`, `[Project]`, `[Plugin]`, or `[Local]`. This helps users understand which configuration source is requesting confirmation.


963}980}

964```981```

965 982 

983`AskUserQuestion` and `ExitPlanMode` require user interaction and normally block in [non-interactive mode](/en/headless) with the `-p` flag. Returning `permissionDecision: "allow"` together with `updatedInput` satisfies that requirement: the hook reads the tool's input from stdin, collects the answer through your own UI, and returns it in `updatedInput` so the tool runs without prompting. Returning `"allow"` alone is not sufficient for these tools. For `AskUserQuestion`, echo back the original `questions` array and add an [`answers`](#askuserquestion) object mapping each question's text to the chosen answer.

984 

966<Note>985<Note>

967 PreToolUse previously used top-level `decision` and `reason` fields, but these are deprecated for this event. Use `hookSpecificOutput.permissionDecision` and `hookSpecificOutput.permissionDecisionReason` instead. The deprecated values `"approve"` and `"block"` map to `"allow"` and `"deny"` respectively. Other events like PostToolUse and Stop continue to use top-level `decision` and `reason` as their current format.986 PreToolUse previously used top-level `decision` and `reason` fields, but these are deprecated for this event. Use `hookSpecificOutput.permissionDecision` and `hookSpecificOutput.permissionDecisionReason` instead. The deprecated values `"approve"` and `"block"` map to `"allow"` and `"deny"` respectively. Other events like PostToolUse and Stop continue to use top-level `decision` and `reason` as their current format.

968</Note>987</Note>


1008| Field | Description |1027| Field | Description |

1009| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |1028| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

1010| `behavior` | `"allow"` grants the permission, `"deny"` denies it |1029| `behavior` | `"allow"` grants the permission, `"deny"` denies it |

1011| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution |1030| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones |

1012| `updatedPermissions` | For `"allow"` only: array of [permission update entries](#permission-update-entries) to apply, such as adding an allow rule or changing the session permission mode |1031| `updatedPermissions` | For `"allow"` only: array of [permission update entries](#permission-update-entries) to apply, such as adding an allow rule or changing the session permission mode |

1013| `message` | For `"deny"` only: tells Claude why the permission was denied |1032| `message` | For `"deny"` only: tells Claude why the permission was denied |

1014| `interrupt` | For `"deny"` only: if `true`, stops Claude |1033| `interrupt` | For `"deny"` only: if `true`, stops Claude |


1632 1651 

1633When you run `claude --worktree` or a [subagent uses `isolation: "worktree"`](/en/sub-agents#choose-the-subagent-scope), Claude Code creates an isolated working copy using `git worktree`. If you configure a WorktreeCreate hook, it replaces the default git behavior, letting you use a different version control system like SVN, Perforce, or Mercurial.1652When you run `claude --worktree` or a [subagent uses `isolation: "worktree"`](/en/sub-agents#choose-the-subagent-scope), Claude Code creates an isolated working copy using `git worktree`. If you configure a WorktreeCreate hook, it replaces the default git behavior, letting you use a different version control system like SVN, Perforce, or Mercurial.

1634 1653 

1654Because the hook replaces the default behavior entirely, [`.worktreeinclude`](/en/common-workflows#copy-gitignored-files-to-worktrees) is not processed. If you need to copy local configuration files like `.env` into the new worktree, do it inside your hook script.

1655 

1635The hook must return the absolute path to the created worktree directory. Claude Code uses this path as the working directory for the isolated session. Command hooks print it on stdout; HTTP hooks return it via `hookSpecificOutput.worktreePath`.1656The hook must return the absolute path to the created worktree directory. Claude Code uses this path as the working directory for the isolated session. Command hooks print it on stdout; HTTP hooks return it via `hookSpecificOutput.worktreePath`.

1636 1657 

1637This example creates an SVN working copy and prints the path for Claude Code to use. Replace the repository URL with your own:1658This example creates an SVN working copy and prints the path for Claude Code to use. Replace the repository URL with your own:

hooks-guide.md +33 −0

Details

603 603 

604For full matcher syntax, see the [Hooks reference](/en/hooks#configuration).604For full matcher syntax, see the [Hooks reference](/en/hooks#configuration).

605 605 

606#### Filter by tool name and arguments with the `if` field

607 

608<Note>

609 The `if` field requires Claude Code v2.1.85 or later. Earlier versions ignore it and run the hook on every matched call.

610</Note>

611 

612The `if` field uses [permission rule syntax](/en/permissions) to filter hooks by tool name and arguments together, so the hook process only spawns when the tool call matches. This goes beyond `matcher`, which filters at the group level by tool name only.

613 

614For example, to run a hook only when Claude uses `git` commands rather than all Bash commands:

615 

616```json theme={null}

617{

618 "hooks": {

619 "PreToolUse": [

620 {

621 "matcher": "Bash",

622 "hooks": [

623 {

624 "type": "command",

625 "if": "Bash(git *)",

626 "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-git-policy.sh"

627 }

628 ]

629 }

630 ]

631 }

632}

633```

634 

635The hook process only spawns when the Bash command starts with `git`. Other Bash commands skip this handler entirely. The `if` field accepts the same patterns as permission rules: `"Bash(git *)"`, `"Edit(*.ts)"`, and so on. To match multiple tool names, use separate handlers each with its own `if` value, or match at the `matcher` level where pipe alternation is supported.

636 

637`if` only works on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, and `PermissionRequest`. Adding it to any other event prevents the hook from running.

638 

606### Configure hook location639### Configure hook location

607 640 

608Where you add a hook determines its scope:641Where you add a hook determines its scope:

Details

126 126 

127Claude's context window holds your conversation history, file contents, command outputs, [CLAUDE.md](/en/memory), [auto memory](/en/memory#auto-memory), loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run `/context` to see what's using space.127Claude's context window holds your conversation history, file contents, command outputs, [CLAUDE.md](/en/memory), [auto memory](/en/memory#auto-memory), loaded skills, and system instructions. As you work, context fills up. Claude compacts automatically, but instructions from early in the conversation can get lost. Put persistent rules in CLAUDE.md, and run `/context` to see what's using space.

128 128 

129For an interactive walkthrough of what loads and when, see [Explore the context window](/en/context-window).

130 

129#### When context fills up131#### When context fills up

130 132 

131Claude Code manages context automatically as you approach the limit. It clears older tool outputs first, then summarizes the conversation if needed. Your requests and key code snippets are preserved; detailed instructions from early in the conversation may be lost. Put persistent rules in CLAUDE.md rather than relying on conversation history.133Claude Code manages context automatically as you approach the limit. It clears older tool outputs first, then summarizes the conversation if needed. Your requests and key code snippets are preserved; detailed instructions from early in the conversation may be lost. Put persistent rules in CLAUDE.md rather than relying on conversation history.

132 134 

133To control what's preserved during compaction, add a "Compact Instructions" section to CLAUDE.md or run `/compact` with a focus (like `/compact focus on the API changes`).135To control what's preserved during compaction, add a "Compact Instructions" section to CLAUDE.md or run `/compact` with a focus (like `/compact focus on the API changes`).

134 136 

135Run `/context` to see what's using space. MCP servers add tool definitions to every request, so a few servers can consume significant context before you start working. Run `/mcp` to check per-server costs.137Run `/context` to see what's using space. MCP tool definitions are deferred by default and loaded on demand via [tool search](/en/mcp#scale-with-mcp-tool-search), so only tool names consume context until Claude uses a specific tool. Run `/mcp` to check per-server costs.

136 138 

137#### Manage context with skills and subagents139#### Manage context with skills and subagents

138 140 

Details

59| :------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------- |59| :------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------- |

60| `Ctrl+T` | Toggle syntax highlighting for code blocks | Only works inside the `/theme` picker menu. Controls whether code in Claude's responses uses syntax coloring |60| `Ctrl+T` | Toggle syntax highlighting for code blocks | Only works inside the `/theme` picker menu. Controls whether code in Claude's responses uses syntax coloring |

61 61 

62<Note>

63 Syntax highlighting is only available in the native build of Claude Code.

64</Note>

65 

66### Multiline input62### Multiline input

67 63 

68| Method | Shortcut | Context |64| Method | Shortcut | Context |

mcp.md +19 −13

Details

749 749 

750### Override OAuth metadata discovery750### Override OAuth metadata discovery

751 751 

752If your MCP server returns errors on the standard OAuth metadata endpoint (`/.well-known/oauth-authorization-server`) but exposes a working OIDC endpoint, you can tell Claude Code to fetch OAuth metadata directly from a URL you specify, bypassing the standard discovery chain.752If your MCP server's standard OAuth metadata endpoints return errors but the server exposes a working OIDC endpoint, you can point Claude Code at a specific metadata URL to bypass the default discovery chain. By default, Claude Code first checks RFC 9728 Protected Resource Metadata at `/.well-known/oauth-protected-resource`, then falls back to RFC 8414 authorization server metadata at `/.well-known/oauth-authorization-server`.

753 753 

754Set `authServerMetadataUrl` in the `oauth` object of your server's config in `.mcp.json`:754Set `authServerMetadataUrl` in the `oauth` object of your server's config in `.mcp.json`:

755 755 


807 807 

808The helper runs fresh on each connection (at session start and on reconnect). There is no caching, so your script is responsible for any token reuse.808The helper runs fresh on each connection (at session start and on reconnect). There is no caching, so your script is responsible for any token reuse.

809 809 

810Claude Code sets these environment variables when executing the helper:

811 

812| Variable | Value |

813| :---------------------------- | :------------------------- |

814| `CLAUDE_CODE_MCP_SERVER_NAME` | the name of the MCP server |

815| `CLAUDE_CODE_MCP_SERVER_URL` | the URL of the MCP server |

816 

817Use these to write a single helper script that serves multiple MCP servers.

818 

810<Note>819<Note>

811 `headersHelper` executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.820 `headersHelper` executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.

812</Note>821</Note>


1051 1060 

1052## Scale with MCP Tool Search1061## Scale with MCP Tool Search

1053 1062 

1054When you have many MCP servers configured, tool definitions can consume a significant portion of your context window. MCP Tool Search solves this by dynamically loading tools on-demand instead of preloading all of them.1063Tool search keeps MCP context usage low by deferring tool definitions until Claude needs them. Only tool names load at session start, so adding more MCP servers has minimal impact on your context window.

1055 1064 

1056### How it works1065### How it works

1057 1066 

1058Claude Code automatically enables Tool Search when your MCP tool descriptions would consume more than 10% of the context window. You can [adjust this threshold](#configure-tool-search) or disable tool search entirely. When triggered:1067Tool search is enabled by default. MCP tools are deferred rather than loaded into context upfront, and Claude uses a search tool to discover relevant ones when a task needs them. Only the tools Claude actually uses enter context. From your perspective, MCP tools work exactly as before.

1059 1068 

10601. MCP tools are deferred rather than loaded into context upfront1069If you prefer threshold-based loading, set `ENABLE_TOOL_SEARCH=auto` to load schemas upfront when they fit within 10% of the context window and defer only the overflow. See [Configure tool search](#configure-tool-search) for all options.

10612. Claude uses a search tool to discover relevant MCP tools when needed

10623. Only the tools Claude actually needs are loaded into context

10634. MCP tools continue to work exactly as before from your perspective

1064 1070 

1065### For MCP server authors1071### For MCP server authors

1066 1072 


1081Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:1087Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:

1082 1088 

1083| Value | Behavior |1089| Value | Behavior |

1084| :--------- | :--------------------------------------------------------------------------------- |1090| :--------- | :----------------------------------------------------------------------------------------------------------------------------- |

1085| (unset) | Enabled by default. Disabled when `ANTHROPIC_BASE_URL` is a non-first-party host |1091| (unset) | All MCP tools deferred and loaded on demand. Falls back to loading upfront when `ANTHROPIC_BASE_URL` is a non-first-party host |

1086| `true` | Always enabled, including for non-first-party `ANTHROPIC_BASE_URL` |1092| `true` | All MCP tools deferred, including for non-first-party `ANTHROPIC_BASE_URL` |

1087| `auto` | Activates when MCP tools exceed 10% of context |1093| `auto` | Threshold mode: tools load upfront if they fit within 10% of the context window, deferred otherwise |

1088| `auto:<N>` | Activates at custom threshold, where `<N>` is a percentage (e.g., `auto:5` for 5%) |1094| `auto:<N>` | Threshold mode with a custom percentage, where `<N>` is 0-100 (e.g., `auto:5` for 5%) |

1089| `false` | Disabled, all MCP tools loaded upfront |1095| `false` | All MCP tools loaded upfront, no deferral |

1090 1096 

1091```bash theme={null}1097```bash theme={null}

1092# Use a custom 5% threshold1098# Use a custom 5% threshold

memory.md +1 −1

Details

64 64 

65### Write effective instructions65### Write effective instructions

66 66 

67CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation. Because they're context rather than enforced configuration, how you write instructions affects how reliably Claude follows them. Specific, concise, well-structured instructions work best.67CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation. The [context window visualization](/en/context-window) shows where CLAUDE.md loads relative to the rest of the startup context. Because they're context rather than enforced configuration, how you write instructions affects how reliably Claude follows them. Specific, concise, well-structured instructions work best.

68 68 

69**Size**: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence. If your instructions are growing large, split them using [imports](#import-additional-files) or [`.claude/rules/`](#organize-rules-with-claude/rules/) files.69**Size**: target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence. If your instructions are growing large, split them using [imports](#import-additional-files) or [`.claude/rules/`](#organize-rules-with-claude/rules/) files.

70 70 

Details

17export CLAUDE_CODE_ENABLE_TELEMETRY=117export CLAUDE_CODE_ENABLE_TELEMETRY=1

18 18 

19# 2. Choose exporters (both are optional - configure only what you need)19# 2. Choose exporters (both are optional - configure only what you need)

20export OTEL_METRICS_EXPORTER=otlp # Options: otlp, prometheus, console20export OTEL_METRICS_EXPORTER=otlp # Options: otlp, prometheus, console, none

21export OTEL_LOGS_EXPORTER=otlp # Options: otlp, console21export OTEL_LOGS_EXPORTER=otlp # Options: otlp, console, none

22 22 

23# 3. Configure OTLP endpoint (for OTLP exporter)23# 3. Configure OTLP endpoint (for OTLP exporter)

24export OTEL_EXPORTER_OTLP_PROTOCOL=grpc24export OTEL_EXPORTER_OTLP_PROTOCOL=grpc


69### Common configuration variables69### Common configuration variables

70 70 

71| Environment Variable | Description | Example Values |71| Environment Variable | Description | Example Values |

72| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |72| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |

73| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |73| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |

74| `OTEL_METRICS_EXPORTER` | Metrics exporter types, comma-separated | `console`, `otlp`, `prometheus` |74| `OTEL_METRICS_EXPORTER` | Metrics exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `prometheus`, `none` |

75| `OTEL_LOGS_EXPORTER` | Logs/events exporter types, comma-separated | `console`, `otlp` |75| `OTEL_LOGS_EXPORTER` | Logs/events exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |

76| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter, applies to all signals | `grpc`, `http/json`, `http/protobuf` |76| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter, applies to all signals | `grpc`, `http/json`, `http/protobuf` |

77| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint for all signals | `http://localhost:4317` |77| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint for all signals | `http://localhost:4317` |

78| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics, overrides general setting | `grpc`, `http/json`, `http/protobuf` |78| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics, overrides general setting | `grpc`, `http/json`, `http/protobuf` |


85| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |85| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |

86| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |86| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |

87| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |87| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |

88| `OTEL_LOG_TOOL_DETAILS` | Enable logging of tool input arguments, MCP server/tool names, and skill names in tool events (default: disabled) | `1` to enable |88| `OTEL_LOG_TOOL_DETAILS` | Enable logging of tool parameters and input arguments in tool events: Bash commands, MCP server and tool names, skill names, and tool input (default: disabled) | `1` to enable |

89| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metrics temporality preference (default: `delta`). Set to `cumulative` if your backend expects cumulative temporality | `delta`, `cumulative` |89| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metrics temporality preference (default: `delta`). Set to `cumulative` if your backend expects cumulative temporality | `delta`, `cumulative` |

90| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |90| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |

91 91 


386* `decision_source`: Decision source - `"config"`, `"hook"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`386* `decision_source`: Decision source - `"config"`, `"hook"`, `"user_permanent"`, `"user_temporary"`, `"user_abort"`, or `"user_reject"`

387* `tool_result_size_bytes`: Size of the tool result in bytes387* `tool_result_size_bytes`: Size of the tool result in bytes

388* `mcp_server_scope`: MCP server scope identifier (for MCP tools)388* `mcp_server_scope`: MCP server scope identifier (for MCP tools)

389* `tool_parameters`: JSON string containing tool-specific parameters (when available)389* `tool_parameters` (when `OTEL_LOG_TOOL_DETAILS=1`): JSON string containing tool-specific parameters:

390 * For Bash tool: includes `bash_command`, `full_command`, `timeout`, `description`, `dangerouslyDisableSandbox`, and `git_commit_id` (the commit SHA, when a `git commit` command succeeds)390 * For Bash tool: includes `bash_command`, `full_command`, `timeout`, `description`, `dangerouslyDisableSandbox`, and `git_commit_id` (the commit SHA, when a `git commit` command succeeds)

391 * For MCP tools (when `OTEL_LOG_TOOL_DETAILS=1`): includes `mcp_server_name`, `mcp_tool_name`391 * For MCP tools: includes `mcp_server_name`, `mcp_tool_name`

392 * For Skill tool (when `OTEL_LOG_TOOL_DETAILS=1`): includes `skill_name`392 * For Skill tool: includes `skill_name`

393* `tool_input` (when `OTEL_LOG_TOOL_DETAILS=1`): JSON-serialized tool arguments. Individual values over 512 characters are truncated, and the full payload is bounded to \~4 K characters. Applies to all tools including MCP tools.393* `tool_input` (when `OTEL_LOG_TOOL_DETAILS=1`): JSON-serialized tool arguments. Individual values over 512 characters are truncated, and the full payload is bounded to \~4 K characters. Applies to all tools including MCP tools.

394 394 

395#### API request event395#### API request event


532## Security and privacy532## Security and privacy

533 533 

534* Telemetry is opt-in and requires explicit configuration534* Telemetry is opt-in and requires explicit configuration

535* Raw file contents and code snippets are not included in metrics or events. Tool execution events include bash commands and file paths in the `tool_parameters` field, which may contain sensitive values. If your commands may include secrets, configure your telemetry backend to filter or redact `tool_parameters`535* Raw file contents and code snippets are not included in metrics or events

536* When authenticated via OAuth, `user.email` is included in telemetry attributes. If this is a concern for your organization, work with your telemetry backend to filter or redact this field536* When authenticated via OAuth, `user.email` is included in telemetry attributes. If this is a concern for your organization, work with your telemetry backend to filter or redact this field

537* User prompt content is not collected by default. Only prompt length is recorded. To include prompt content, set `OTEL_LOG_USER_PROMPTS=1`537* User prompt content is not collected by default. Only prompt length is recorded. To include prompt content, set `OTEL_LOG_USER_PROMPTS=1`

538* Tool input arguments are not logged by default. To include them, set `OTEL_LOG_TOOL_DETAILS=1`. When enabled, `tool_result` events include MCP server/tool names and skill names plus a `tool_input` attribute with file paths, URLs, search patterns, and other arguments. Individual values over 512 characters are truncated and the total is bounded to \~4 K characters, but the arguments may still contain sensitive values. Configure your telemetry backend to filter or redact `tool_input` as needed538* Tool input arguments and parameters are not logged by default. To include them, set `OTEL_LOG_TOOL_DETAILS=1`. When enabled, `tool_result` events include a `tool_parameters` attribute with Bash commands, MCP server and tool names, and skill names, plus a `tool_input` attribute with file paths, URLs, search patterns, and other arguments. Individual values over 512 characters are truncated and the total is bounded to \~4 K characters, but the arguments may still contain sensitive values. Configure your telemetry backend to filter or redact these attributes as needed

539 539 

540## Monitor Claude Code on Amazon Bedrock540## Monitor Claude Code on Amazon Bedrock

541 541 

settings.md +7 −3

Details

153`settings.json` supports a number of options:153`settings.json` supports a number of options:

154 154 

155| Key | Description | Example |155| Key | Description | Example |

156| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |156| :-------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |

157| `apiKeyHelper` | Custom script, to be executed in `/bin/sh`, to generate an auth value. This value will be sent as `X-Api-Key` and `Authorization: Bearer` headers for model requests | `/bin/generate_temp_api_key.sh` |157| `apiKeyHelper` | Custom script, to be executed in `/bin/sh`, to generate an auth value. This value will be sent as `X-Api-Key` and `Authorization: Bearer` headers for model requests | `/bin/generate_temp_api_key.sh` |

158| `autoMemoryDirectory` | Custom directory for [auto memory](/en/memory#storage-location) storage. Accepts `~/`-expanded paths. Not accepted in project settings (`.claude/settings.json`) to prevent shared repos from redirecting memory writes to sensitive locations. Accepted from policy, local, and user settings | `"~/my-memory-dir"` |158| `autoMemoryDirectory` | Custom directory for [auto memory](/en/memory#storage-location) storage. Accepts `~/`-expanded paths. Not accepted in project settings (`.claude/settings.json`) to prevent shared repos from redirecting memory writes to sensitive locations. Accepted from policy, local, and user settings | `"~/my-memory-dir"` |

159| `cleanupPeriodDays` | Sessions inactive for longer than this period are deleted at startup (default: 30 days).<br /><br />Setting to `0` deletes all existing transcripts at startup and disables session persistence entirely. No new `.jsonl` files are written, `/resume` shows no conversations, and hooks receive an empty `transcript_path`. | `20` |159| `cleanupPeriodDays` | Sessions inactive for longer than this period are deleted at startup (default: 30 days).<br /><br />Setting to `0` deletes all existing transcripts at startup and disables session persistence entirely. No new `.jsonl` files are written, `/resume` shows no conversations, and hooks receive an empty `transcript_path`. | `20` |


166| `autoMode` | Customize what the [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier blocks and allows. Contains `environment`, `allow`, and `soft_deny` arrays of prose rules. See [Configure the auto mode classifier](/en/permissions#configure-the-auto-mode-classifier). Not read from shared project settings | `{"environment": ["Trusted repo: github.example.com/acme"]}` |166| `autoMode` | Customize what the [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) classifier blocks and allows. Contains `environment`, `allow`, and `soft_deny` arrays of prose rules. See [Configure the auto mode classifier](/en/permissions#configure-the-auto-mode-classifier). Not read from shared project settings | `{"environment": ["Trusted repo: github.example.com/acme"]}` |

167| `disableAutoMode` | Set to `"disable"` to prevent [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) from being activated. Removes `auto` from the `Shift+Tab` cycle and rejects `--permission-mode auto` at startup. Most useful in [managed settings](/en/permissions#managed-settings) where users cannot override it | `"disable"` |167| `disableAutoMode` | Set to `"disable"` to prevent [auto mode](/en/permission-modes#eliminate-prompts-with-auto-mode) from being activated. Removes `auto` from the `Shift+Tab` cycle and rejects `--permission-mode auto` at startup. Most useful in [managed settings](/en/permissions#managed-settings) where users cannot override it | `"disable"` |

168| `useAutoModeDuringPlan` | Whether plan mode uses auto mode semantics when auto mode is available. Default: `true`. Not read from shared project settings. Appears in `/config` as "Use auto mode during plan" | `false` |168| `useAutoModeDuringPlan` | Whether plan mode uses auto mode semantics when auto mode is available. Default: `true`. Not read from shared project settings. Appears in `/config` as "Use auto mode during plan" | `false` |

169| `disableDeepLinkRegistration` | Set to `"disable"` to prevent Claude Code from registering the `claude-cli://` protocol handler with the operating system on startup. Deep links let external tools open a Claude Code session with a pre-filled prompt via `claude-cli://open?q=...`. Useful in environments where protocol handler registration is restricted or managed separately | `"disable"` |

169| `hooks` | Configure custom commands to run at lifecycle events. See [hooks documentation](/en/hooks) for format | See [hooks](/en/hooks) |170| `hooks` | Configure custom commands to run at lifecycle events. See [hooks documentation](/en/hooks) for format | See [hooks](/en/hooks) |

170| `defaultShell` | Default shell for input-box `!` commands. Accepts `"bash"` (default) or `"powershell"`. Setting `"powershell"` routes interactive `!` commands through PowerShell on Windows. Requires `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. See [PowerShell tool](/en/tools-reference#powershell-tool) | `"powershell"` |171| `defaultShell` | Default shell for input-box `!` commands. Accepts `"bash"` (default) or `"powershell"`. Setting `"powershell"` routes interactive `!` commands through PowerShell on Windows. Requires `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. See [PowerShell tool](/en/tools-reference#powershell-tool) | `"powershell"` |

171| `disableAllHooks` | Disable all [hooks](/en/hooks) and any custom [status line](/en/statusline) | `true` |172| `disableAllHooks` | Disable all [hooks](/en/hooks) and any custom [status line](/en/statusline) | `true` |


209| `spinnerTipsOverride` | Override spinner tips with custom strings. `tips`: array of tip strings. `excludeDefault`: if `true`, only show custom tips; if `false` or absent, custom tips are merged with built-in tips | `{ "excludeDefault": true, "tips": ["Use our internal tool X"] }` |210| `spinnerTipsOverride` | Override spinner tips with custom strings. `tips`: array of tip strings. `excludeDefault`: if `true`, only show custom tips; if `false` or absent, custom tips are merged with built-in tips | `{ "excludeDefault": true, "tips": ["Use our internal tool X"] }` |

210| `prefersReducedMotion` | Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility | `true` |211| `prefersReducedMotion` | Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility | `true` |

211| `fastModePerSessionOptIn` | When `true`, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with `/fast`. The user's fast mode preference is still saved. See [Require per-session opt-in](/en/fast-mode#require-per-session-opt-in) | `true` |212| `fastModePerSessionOptIn` | When `true`, fast mode does not persist across sessions. Each session starts with fast mode off, requiring users to enable it with `/fast`. The user's fast mode preference is still saved. See [Require per-session opt-in](/en/fast-mode#require-per-session-opt-in) | `true` |

212| `teammateMode` | How [agent team](/en/agent-teams) teammates display: `auto` (picks split panes in tmux or iTerm2, in-process otherwise), `in-process`, or `tmux`. See [set up agent teams](/en/agent-teams#set-up-agent-teams) | `"in-process"` |

213| `feedbackSurveyRate` | Probability (0–1) that the [session quality survey](/en/data-usage#session-quality-surveys) appears when eligible. Set to `0` to suppress entirely. Useful when using Bedrock, Vertex, or Foundry where the default sample rate does not apply | `0.05` |213| `feedbackSurveyRate` | Probability (0–1) that the [session quality survey](/en/data-usage#session-quality-surveys) appears when eligible. Set to `0` to suppress entirely. Useful when using Bedrock, Vertex, or Foundry where the default sample rate does not apply | `0.05` |

214 214 

215### Global config settings215### Global config settings


217These settings are stored in `~/.claude.json` rather than `settings.json`. Adding them to `settings.json` will trigger a schema validation error.217These settings are stored in `~/.claude.json` rather than `settings.json`. Adding them to `settings.json` will trigger a schema validation error.

218 218 

219| Key | Description | Example |219| Key | Description | Example |

220| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ |220| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------- |

221| `autoConnectIde` | Automatically connect to a running IDE when Claude Code starts from an external terminal. Default: `false`. Appears in `/config` as **Auto-connect to IDE (external terminal)** when running outside a VS Code or JetBrains terminal | `true` |221| `autoConnectIde` | Automatically connect to a running IDE when Claude Code starts from an external terminal. Default: `false`. Appears in `/config` as **Auto-connect to IDE (external terminal)** when running outside a VS Code or JetBrains terminal | `true` |

222| `autoInstallIdeExtension` | Automatically install the Claude Code IDE extension when running from a VS Code terminal. Default: `true`. Appears in `/config` as **Auto-install IDE extension** when running inside a VS Code or JetBrains terminal. You can also set the [`CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL`](/en/env-vars) environment variable | `false` |222| `autoInstallIdeExtension` | Automatically install the Claude Code IDE extension when running from a VS Code terminal. Default: `true`. Appears in `/config` as **Auto-install IDE extension** when running inside a VS Code or JetBrains terminal. You can also set the [`CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL`](/en/env-vars) environment variable | `false` |

223| `editorMode` | Key binding mode for the input prompt: `"normal"` or `"vim"`. Default: `"normal"`. Written automatically when you run `/vim`. Appears in `/config` as **Key binding mode** | `"vim"` |223| `editorMode` | Key binding mode for the input prompt: `"normal"` or `"vim"`. Default: `"normal"`. Written automatically when you run `/vim`. Appears in `/config` as **Key binding mode** | `"vim"` |

224| `showTurnDuration` | Show turn duration messages after responses, e.g. "Cooked for 1m 6s". Default: `true`. Appears in `/config` as **Show turn duration** | `false` |224| `showTurnDuration` | Show turn duration messages after responses, e.g. "Cooked for 1m 6s". Default: `true`. Appears in `/config` as **Show turn duration** | `false` |

225| `terminalProgressBarEnabled` | Show the terminal progress bar in supported terminals: ConEmu, Ghostty 1.2.0+, and iTerm2 3.6.6+. Default: `true`. Appears in `/config` as **Terminal progress bar** | `false` |225| `terminalProgressBarEnabled` | Show the terminal progress bar in supported terminals: ConEmu, Ghostty 1.2.0+, and iTerm2 3.6.6+. Default: `true`. Appears in `/config` as **Terminal progress bar** | `false` |

226| `teammateMode` | How [agent team](/en/agent-teams) teammates display: `auto` (picks split panes in tmux or iTerm2, in-process otherwise), `in-process`, or `tmux`. See [choose a display mode](/en/agent-teams#choose-a-display-mode) | `"in-process"` |

226 227 

227### Worktree settings228### Worktree settings

228 229 


233| `worktree.symlinkDirectories` | Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. No directories are symlinked by default | `["node_modules", ".cache"]` |234| `worktree.symlinkDirectories` | Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. No directories are symlinked by default | `["node_modules", ".cache"]` |

234| `worktree.sparsePaths` | Directories to check out in each worktree via git sparse-checkout (cone mode). Only the listed paths are written to disk, which is faster in large monorepos | `["packages/my-app", "shared/utils"]` |235| `worktree.sparsePaths` | Directories to check out in each worktree via git sparse-checkout (cone mode). Only the listed paths are written to disk, which is faster in large monorepos | `["packages/my-app", "shared/utils"]` |

235 236 

237To copy gitignored files like `.env` into new worktrees, use a [`.worktreeinclude` file](/en/common-workflows#copy-gitignored-files-to-worktrees) in your project root instead of a setting.

238 

236### Permission settings239### Permission settings

237 240 

238| Keys | Description | Example |241| Keys | Description | Example |


538* **User settings** (`~/.claude/settings.json`): Personal plugin preferences541* **User settings** (`~/.claude/settings.json`): Personal plugin preferences

539* **Project settings** (`.claude/settings.json`): Project-specific plugins shared with team542* **Project settings** (`.claude/settings.json`): Project-specific plugins shared with team

540* **Local settings** (`.claude/settings.local.json`): Per-machine overrides (not committed)543* **Local settings** (`.claude/settings.local.json`): Per-machine overrides (not committed)

544* **Managed settings** (`managed-settings.json`): Organization-wide policy overrides that block installation at all scopes and hide the plugin from the marketplace

541 545 

542**Example**:546**Example**:

543 547 

sub-agents.md +2 −2

Details

6 6 

7> Create and use specialized AI subagents in Claude Code for task-specific workflows and improved context management.7> Create and use specialized AI subagents in Claude Code for task-specific workflows and improved context management.

8 8 

9Subagents are specialized AI assistants that handle specific types of tasks. Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent's description, it delegates to that subagent, which works independently and returns results.9Subagents are specialized AI assistants that handle specific types of tasks. Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When Claude encounters a task that matches a subagent's description, it delegates to that subagent, which works independently and returns results. To see the context savings in practice, the [context window visualization](/en/context-window) walks through a session where a subagent handles research in its own separate window.

10 10 

11<Note>11<Note>

12 If you need multiple agents working in parallel and communicating with each other, see [agent teams](/en/agent-teams) instead. Subagents work within a single session; agent teams coordinate across separate sessions.12 If you need multiple agents working in parallel and communicating with each other, see [agent teams](/en/agent-teams) instead. Subagents work within a single session; agent teams coordinate across separate sessions.


399When memory is enabled:399When memory is enabled:

400 400 

401* The subagent's system prompt includes instructions for reading and writing to the memory directory.401* The subagent's system prompt includes instructions for reading and writing to the memory directory.

402* The subagent's system prompt also includes the first 200 lines of `MEMORY.md` in the memory directory, with instructions to curate `MEMORY.md` if it exceeds 200 lines.402* The subagent's system prompt also includes the first 200 lines or 25KB of `MEMORY.md` in the memory directory, whichever comes first, with instructions to curate `MEMORY.md` if it exceeds that limit.

403* Read, Write, and Edit tools are automatically enabled so the subagent can manage its memory files.403* Read, Write, and Edit tools are automatically enabled so the subagent can manage its memory files.

404 404 

405##### Persistent memory tips405##### Persistent memory tips