6 6
7> Claude Code가 CLAUDE.md, settings.json, hooks, skills, commands, subagents, workflows, rules, auto memory를 읽는 위치입니다. 프로젝트의 .claude 디렉토리와 홈 디렉토리의 ~/.claude를 탐색합니다.7> Claude Code가 CLAUDE.md, settings.json, hooks, skills, commands, subagents, workflows, rules, auto memory를 읽는 위치입니다. 프로젝트의 .claude 디렉토리와 홈 디렉토리의 ~/.claude를 탐색합니다.
8 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/worktrees#copy-gitignored-files-into-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 <target></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 on demand while running the skill',
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 <number></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: 'workflows',
366 label: 'workflows/',
367 type: 'folder',
368 icon: 'folder',
369 color: '#C46686',
370 oneLiner: 'Dynamic workflow scripts that orchestrate many subagents',
371 when: 'Loaded at startup; each file becomes a /<name> command',
372 description: <>Each <C>.js</C> file is a <A href="/en/workflows">dynamic workflow</A>: a script the runtime executes to spawn and coordinate many subagents. Workflows are written by Claude and saved here from <C>/workflows</C> rather than authored from scratch.</>,
373 tips: [<>Save a run from <C>/workflows</C> with <C>s</C> to create one of these</>, <>A project workflow takes precedence over a personal one in <C>~/.claude/workflows/</C> with the same name</>],
374 docsLink: '/en/workflows'
375 }, {
376 id: 'agent-memory',
377 label: 'agent-memory/',
378 type: 'folder',
379 icon: 'folder',
380 color: '#C46686',
381 badge: 'committed',
382 autogen: true,
383 oneLiner: 'Subagent persistent memory, separate from your main session auto memory',
384 when: 'First 200 lines (capped at 25KB) of MEMORY.md loaded into the subagent system prompt when it runs',
385 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.</>,
386 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</>],
387 docsLink: '/en/sub-agents#enable-persistent-memory',
388 children: [{
389 id: 'agent-memory-sub',
390 label: '<agent-name>/',
391 type: 'folder',
392 icon: 'folder',
393 color: '#C46686',
394 autogen: true,
395 children: [{
396 id: 'agent-memory-md',
397 label: 'MEMORY.md',
398 type: 'file',
399 icon: 'md',
400 color: '#C46686',
401 badge: 'committed',
402 autogen: true,
403 oneLiner: 'The subagent writes and maintains this file automatically',
404 when: 'Loaded into the subagent system prompt when the subagent starts',
405 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.</>,
406 example: `# code-reviewer memory
407
408## Patterns seen
409- Project uses custom Result<T, E> type, not exceptions
410- Auth middleware expects Bearer token in Authorization header
411- Tests use factory functions in test/factories/
412
413## Recurring issues
414- Missing null checks on API responses (src/api/*)
415- Unhandled promise rejections in background jobs`
416 }]
417 }]
418 }]
419 }]
420 },
421 global: {
422 label: '~/',
423 children: [{
424 id: 'claude-json',
425 label: '.claude.json',
426 type: 'file',
427 icon: 'json',
428 color: 'var(--ce-text-3)',
429 badge: 'local',
430 oneLiner: 'App state and UI preferences',
431 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</>,
432 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.</>,
433 tips: [<>IDE toggles like <C>autoConnectIde</C> and <C>externalEditorContext</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</>],
434 example: `{
435 "autoConnectIde": true,
436 "externalEditorContext": true,
437 "mcpServers": {
438 "my-tools": {
439 "command": "npx",
440 "args": ["-y", "@example/mcp-server"]
441 }
442 }
443}`,
444 docsLink: '/en/settings#global-config-settings'
445 }, {
446 id: 'global-dot-claude',
447 label: '.claude/',
448 type: 'folder',
449 icon: 'folder',
450 color: 'var(--ce-accent)',
451 oneLiner: 'Your personal configuration across all projects',
452 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.',
453 children: [{
454 id: 'global-claude-md',
455 label: 'CLAUDE.md',
456 type: 'file',
457 icon: 'md',
458 color: '#6A9BCC',
459 badge: 'local',
460 oneLiner: 'Personal preferences across every project',
461 when: 'Loaded at the start of every session, in every project',
462 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.',
463 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'],
464 example: `# Global preferences
465
466- Keep explanations concise
467- Use conventional commit format
468- Show the terminal command to verify changes
469- Prefer composition over inheritance`,
470 docsLink: '/en/memory'
471 }, {
472 id: 'global-settings',
473 label: 'settings.json',
474 type: 'file',
475 icon: 'json',
476 color: 'var(--ce-text-3)',
477 badge: 'local',
478 oneLiner: 'Default settings for all projects',
479 when: 'Your defaults. Project and local settings.json override any keys you also set there',
480 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.</>],
481 example: `{
482 "permissions": {
483 "allow": [
484 "Bash(git log *)",
485 "Bash(git diff *)"
486 ]
487 }
488}`,
489 docsLink: '/en/settings'
490 }, {
491 id: 'keybindings',
492 label: 'keybindings.json',
493 type: 'file',
494 icon: 'json',
495 color: 'var(--ce-text-3)',
496 badge: 'local',
497 oneLiner: 'Custom keyboard shortcuts',
498 when: 'Read at session start and hot-reloaded when you edit the file',
499 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, Ctrl+M, and Caps Lock are reserved and cannot be rebound.</>,
500 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.</>,
501 example: `{
502 "$schema": "https://www.schemastore.org/claude-code-keybindings.json",
503 "$docs": "https://code.claude.com/docs/en/keybindings",
504 "bindings": [
505 {
506 "context": "Chat",
507 "bindings": {
508 "ctrl+e": "chat:externalEditor",
509 "ctrl+u": null
510 }
511 }
512 ]
513}`,
514 docsLink: '/en/keybindings'
515 }, {
516 id: 'themes',
517 label: 'themes/',
518 type: 'folder',
519 icon: 'folder',
520 color: '#5AA7A7',
521 oneLiner: 'Custom color themes',
522 when: <>Read at session start and hot-reloaded when files change. Listed in <C>/theme</C></>,
523 description: <>Each <C>.json</C> file defines a custom color theme: a built-in <C>base</C> preset plus an <C>overrides</C> map of color tokens. Create one interactively with <C>/theme</C> or write the JSON by hand. Selecting a custom theme stores <C>custom:<slug></C> as your theme preference.</>,
524 example: `{
525 "name": "Dracula",
526 "base": "dark",
527 "overrides": {
528 "claude": "#bd93f9",
529 "error": "#ff5555",
530 "success": "#50fa7b"
531 }
532}`,
533 docsLink: '/en/terminal-config#create-a-custom-theme',
534 children: []
535 }, {
536 id: 'global-projects',
537 label: 'projects/',
538 type: 'folder',
539 icon: 'folder',
540 color: '#E8A45C',
541 autogen: true,
542 oneLiner: "Auto memory: Claude's notes to itself, per project",
543 when: 'MEMORY.md loaded at session start; topic files read on demand',
544 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.',
545 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'],
546 docsLink: '/en/memory#auto-memory',
547 children: [{
548 id: 'memory-dir',
549 label: '<project>/memory/',
550 type: 'folder',
551 icon: 'folder',
552 color: '#E8A45C',
553 autogen: true,
554 oneLiner: "Claude's accumulated knowledge for one project",
555 children: [{
556 id: 'memory-md',
557 label: 'MEMORY.md',
558 type: 'file',
559 icon: 'md',
560 color: '#E8A45C',
561 badge: 'local',
562 autogen: true,
563 oneLiner: 'Claude writes and maintains this file automatically',
564 when: 'First 200 lines (capped at 25KB) loaded at session start',
565 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.',
566 example: `# Memory Index
567
568## Project
569- [build-and-test.md](build-and-test.md): npm run build (~45s), Vitest, dev server on 3001
570- [architecture.md](architecture.md): API client singleton, refresh-token auth
571
572## Reference
573- [debugging.md](debugging.md): auth token rotation and DB connection troubleshooting`,
574 docsLink: '/en/memory'
575 }, {
576 id: 'memory-topic',
577 label: 'debugging.md',
578 type: 'file',
579 icon: 'md',
580 color: '#E8A45C',
581 badge: 'local',
582 autogen: true,
583 oneLiner: 'Topic notes Claude writes when MEMORY.md gets long',
584 when: 'Claude reads this when a related task comes up',
585 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.',
586 example: `---
587name: Debugging patterns
588description: Auth token rotation and database connection troubleshooting for this project
589type: reference
590---
591
592## Auth Token Issues
593- Refresh token rotation: old token invalidated immediately
594- If 401 after refresh: check clock skew between client and server
595
596## Database Connection Drops
597- Connection pool: max 10 in dev, 50 in prod
598- Always check \`docker compose ps\` first`
599 }]
600 }]
601 }, {
602 id: 'global-rules',
603 label: 'rules/',
604 type: 'folder',
605 icon: 'folder',
606 color: '#9B7BC4',
607 oneLiner: 'User-level rules that apply to every project',
608 when: <>Rules without <C>paths:</C> load at session start. Rules with <C>paths:</C> load when a matching file enters context</>,
609 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.',
610 docsLink: '/en/memory#organize-rules-with-claude/rules/',
611 children: []
612 }, {
613 id: 'global-skills',
614 label: 'skills/',
615 type: 'folder',
616 icon: 'folder',
617 color: '#D4A843',
618 oneLiner: 'Personal skills available in every project',
619 when: <>Invoked with <C>/skill-name</C> in any project</>,
620 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.',
621 docsLink: '/en/skills',
622 children: []
623 }, {
624 id: 'global-commands',
625 label: 'commands/',
626 type: 'folder',
627 icon: 'folder',
628 color: '#788C5D',
629 oneLiner: 'Personal single-file commands available in every project',
630 note: commandsNote,
631 when: <>User types <C>/command-name</C> in any project</>,
632 description: 'Same as project commands/ but scoped to your user account. Each markdown file becomes a command available everywhere.',
633 docsLink: '/en/skills',
634 children: []
635 }, {
636 id: 'global-output-styles',
637 label: 'output-styles/',
638 type: 'folder',
639 icon: 'folder',
640 color: '#5AA7A7',
641 oneLiner: 'Custom system-prompt sections that adjust how Claude works',
642 when: 'Applied at session start when selected via the outputStyle setting',
643 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.</>],
644 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'],
645 docsLink: '/en/output-styles',
646 children: [{
647 id: 'output-style-example',
648 label: 'teaching.md',
649 type: 'file',
650 icon: 'md',
651 color: '#5AA7A7',
652 badge: 'local',
653 oneLiner: 'Example style that adds explanations and leaves small changes for you',
654 when: <>Active when <C>outputStyle</C> in settings is set to <C>teaching</C></>,
655 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.</>,
656 example: `---
657description: Explains reasoning and asks you to implement small pieces
658keep-coding-instructions: true
659---
660
661After completing each task, add a brief "Why this approach" note
662explaining the key design decision.
663
664When a change is under 10 lines, ask the user to implement it
665themselves by leaving a TODO(human) marker instead of writing it.`
666 }]
667 }, {
668 id: 'global-agents',
669 label: 'agents/',
670 type: 'folder',
671 icon: 'folder',
672 color: '#C46686',
673 oneLiner: 'Personal subagents available in every project',
674 when: 'Claude delegates or you @-mention in any project',
675 description: 'Subagents defined here are available across all your projects. Same format as project agents.',
676 docsLink: '/en/sub-agents',
677 children: []
678 }, {
679 id: 'global-workflows',
680 label: 'workflows/',
681 type: 'folder',
682 icon: 'folder',
683 color: '#C46686',
684 oneLiner: 'Personal dynamic workflows available in every project',
685 when: 'Loaded at startup; each file becomes a /<name> command',
686 description: <>Workflow scripts saved here are available across all your projects. A project workflow with the same name in <C>.claude/workflows/</C> takes precedence.</>,
687 docsLink: '/en/workflows',
688 children: []
689 }, {
690 id: 'global-agent-memory',
691 label: 'agent-memory/',
692 type: 'folder',
693 icon: 'folder',
694 color: '#C46686',
695 autogen: true,
696 oneLiner: <>Persistent memory for subagents with <C>memory: user</C></>,
697 when: 'Loaded into the subagent system prompt when the subagent starts',
698 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.</>,
699 docsLink: '/en/sub-agents#enable-persistent-memory',
700 children: []
701 }]
702 }]
703 }
704 }), []);
705 const BADGE_STYLES = useMemo(() => ({
706 committed: {
707 bg: 'rgba(85,138,66,0.08)',
708 color: 'var(--ce-badge-committed)',
709 border: 'rgba(85,138,66,0.15)',
710 label: 'committed'
711 },
712 gitignored: {
713 bg: 'rgba(217,119,87,0.06)',
714 color: 'var(--ce-badge-gitignored)',
715 border: 'rgba(217,119,87,0.15)',
716 label: 'gitignored'
717 },
718 local: {
719 bg: 'rgba(115,114,108,0.06)',
720 color: 'var(--ce-badge-local)',
721 border: 'rgba(115,114,108,0.12)',
722 label: 'local only'
723 },
724 autogen: {
725 bg: 'rgba(232,164,92,0.1)',
726 color: 'var(--ce-badge-autogen)',
727 border: 'rgba(232,164,92,0.2)',
728 label: 'Claude writes'
729 }
730 }), []);
731 const allNodes = useMemo(() => {
732 const flatten = (nodes, acc, path, parentId) => {
733 for (const node of nodes) {
734 const nextPath = [...path, node.label];
735 acc[node.id] = {
736 ...node,
737 path: nextPath,
738 parentId
739 };
740 if (node.children) flatten(node.children, acc, nextPath, node.id);
741 }
742 return acc;
743 };
744 const project = flatten(FILE_TREE.project.children, {}, [FILE_TREE.project.label]);
745 const global = flatten(FILE_TREE.global.children, {}, [FILE_TREE.global.label]);
746 for (const id in project) project[id].root = 'project';
747 for (const id in global) global[id].root = 'global';
748 return {
749 ...project,
750 ...global
751 };
752 }, [FILE_TREE]);
753 const allFolderIds = useMemo(() => Object.keys(allNodes).filter(id => allNodes[id].type === 'folder'), [allNodes]);
754 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'];
755 const [mounted, setMounted] = useState(false);
756 const [activeRoot, setActiveRoot] = useState('project');
757 const [selectedId, setSelectedId] = useState('claude-md');
758 const [expandedFolders, setExpandedFolders] = useState(() => new Set(DEFAULT_EXPANDED));
759 const [forceMobile, setForceMobile] = useState(false);
760 const [copiedId, setCopiedId] = useState(null);
761 const [isFullscreen, setIsFullscreen] = useState(false);
762 const copyTimeoutRef = useRef(null);
763 const rootRef = useRef(null);
764 useEffect(() => {
765 setMounted(true);
766 const applyHash = scroll => {
767 const hash = window.location.hash.slice(1);
768 if (!hash.startsWith('ce-')) return;
769 const id = hash.slice(3);
770 const node = allNodes[id];
771 if (!node) return;
772 setActiveRoot(node.root);
773 setSelectedId(id);
774 setExpandedFolders(new Set(allFolderIds));
775 if (scroll && rootRef.current) rootRef.current.scrollIntoView({
776 behavior: 'smooth',
777 block: 'start'
778 });
779 };
780 applyHash(false);
781 const onHashChange = () => applyHash(true);
782 const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
783 window.addEventListener('hashchange', onHashChange);
784 document.addEventListener('fullscreenchange', onFsChange);
785 return () => {
786 if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);
787 window.removeEventListener('hashchange', onHashChange);
788 document.removeEventListener('fullscreenchange', onFsChange);
789 };
790 }, []);
791 useEffect(() => {
792 if (!mounted || !rootRef.current) return;
793 const hash = window.location.hash.slice(1);
794 if (hash.startsWith('ce-') && allNodes[hash.slice(3)]) {
795 rootRef.current.scrollIntoView({
796 behavior: 'smooth',
797 block: 'start'
798 });
799 }
800 }, [mounted]);
801 if (!mounted) return null;
802 const selected = allNodes[selectedId];
803 const tree = FILE_TREE[activeRoot];
804 const isCopied = copiedId === selected.id;
805 const toggleFolder = id => {
806 const next = new Set(expandedFolders);
807 next.has(id) ? next.delete(id) : next.add(id);
808 setExpandedFolders(next);
809 };
810 const switchRoot = root => {
811 if (root === activeRoot) return;
812 setActiveRoot(root);
813 const firstId = FILE_TREE[root].children[0].id;
814 setSelectedId(firstId);
815 try {
816 history.replaceState(null, '', '#ce-' + firstId);
817 } catch (e) {}
818 };
819 const toggleFullscreen = () => {
820 if (!rootRef.current) return;
821 if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});
822 };
823 const selectNode = n => {
824 setSelectedId(n.id);
825 if (n.type === 'folder' && !expandedFolders.has(n.id)) toggleFolder(n.id);
826 try {
827 history.replaceState(null, '', '#ce-' + n.id);
828 } catch (e) {}
829 };
830 const iconBtn = {
831 width: 28,
832 flexShrink: 0,
833 borderRadius: '6px',
834 border: 'none',
835 cursor: 'pointer',
836 background: 'transparent',
837 color: 'var(--ce-text-4)',
838 display: 'flex',
839 alignItems: 'center',
840 justifyContent: 'center'
841 };
842 const visibleFolderIds = allFolderIds.filter(id => allNodes[id].root === activeRoot);
843 const allExpanded = visibleFolderIds.every(id => expandedFolders.has(id));
844 const toggleAllFolders = () => {
845 const next = new Set(expandedFolders);
846 visibleFolderIds.forEach(id => allExpanded ? next.delete(id) : next.add(id));
847 setExpandedFolders(next);
848 };
849 const onTreeKeyDown = e => {
850 if (!['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft'].includes(e.key)) return;
851 const visible = [];
852 const walk = nodes => {
853 for (const n of nodes) {
854 visible.push(n.id);
855 if (n.children && expandedFolders.has(n.id)) walk(n.children);
856 }
857 };
858 walk(tree.children);
859 const i = visible.indexOf(selectedId);
860 if (i === -1) return;
861 e.preventDefault();
862 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') {
863 if (!expandedFolders.has(selectedId)) toggleFolder(selectedId); else if (selected.children && selected.children.length) selectNode(allNodes[selected.children[0].id]);
864 } else if (e.key === 'ArrowLeft') {
865 if (selected.type === 'folder' && expandedFolders.has(selectedId)) toggleFolder(selectedId); else if (selected.parentId) selectNode(allNodes[selected.parentId]);
866 }
867 };
868 const copyExample = (id, text) => {
869 const done = () => {
870 setCopiedId(id);
871 if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);
872 copyTimeoutRef.current = setTimeout(() => setCopiedId(null), 2000);
873 };
874 const fallback = () => {
875 const ta = document.createElement('textarea');
876 ta.value = text;
877 ta.style.position = 'fixed';
878 ta.style.opacity = '0';
879 document.body.appendChild(ta);
880 ta.select();
881 try {
882 if (document.execCommand('copy')) done();
883 } catch (e) {}
884 document.body.removeChild(ta);
885 };
886 if (navigator.clipboard) {
887 navigator.clipboard.writeText(text).then(done, fallback);
888 } else {
889 fallback();
890 }
891 };
892 const renderIcon = (icon, color, size) => {
893 const sz = size || 14;
894 if (icon === 'folder') {
895 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">
896 <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" />
897 </svg>;
898 }
899 if (icon === 'json') {
900 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">
901 <rect x="2" y="1.5" width="10" height="11" rx="1.5" fill={color} fillOpacity="0.15" stroke={color} strokeWidth="1" />
902 <text x="7" y="9" fontSize="6" fontFamily="monospace" fill={color} textAnchor="middle" fontWeight="700">{'{}'}</text>
903 </svg>;
904 }
905 return <svg width={sz} height={sz} viewBox="0 0 14 14" fill="none">
906 <rect x="2" y="1.5" width="10" height="11" rx="1.5" fill={color} fillOpacity="0.15" stroke={color} strokeWidth="1" />
907 <line x1="4.5" y1="5" x2="9.5" y2="5" stroke={color} strokeWidth="1" />
908 <line x1="4.5" y1="7" x2="9.5" y2="7" stroke={color} strokeWidth="1" />
909 <line x1="4.5" y1="9" x2="8" y2="9" stroke={color} strokeWidth="1" />
910 </svg>;
911 };
912 const renderNode = (node, depth) => {
913 const isFolder = node.type === 'folder';
914 const isExpanded = expandedFolders.has(node.id);
915 const isSelected = selectedId === node.id;
916 return <div key={node.id}>
917 <button role="treeitem" tabIndex={-1} onClick={() => selectNode(node)} aria-selected={isSelected} aria-expanded={isFolder ? isExpanded : undefined} style={{
918 display: 'flex',
919 alignItems: 'center',
920 gap: '5px',
921 width: '100%',
922 padding: `4px 8px 4px ${8 + depth * 16}px`,
923 background: isSelected ? 'var(--ce-accent-bg)' : 'transparent',
924 borderTop: 'none',
925 borderRight: 'none',
926 borderBottom: 'none',
927 borderLeft: isSelected ? '2px solid var(--ce-accent)' : '2px solid transparent',
928 outline: 'none',
929 cursor: 'pointer',
930 textAlign: 'left',
931 fontFamily: 'var(--ce-mono)',
932 fontSize: '13.5px',
933 color: isSelected ? 'var(--ce-accent)' : 'var(--ce-text-2)',
934 fontWeight: isSelected ? 550 : 400,
935 transition: 'all 0.1s'
936 }}>
937 {isFolder ? <span onClick={e => {
938 e.stopPropagation();
939 toggleFolder(node.id);
940 }} style={{
941 fontSize: '14px',
942 color: 'var(--ce-text-4)',
943 width: '20px',
944 height: '20px',
945 display: 'inline-flex',
946 alignItems: 'center',
947 justifyContent: 'center',
948 cursor: 'pointer',
949 borderRadius: '4px',
950 marginLeft: '-6px',
951 flexShrink: 0
952 }} onMouseEnter={e => {
953 e.currentTarget.style.background = 'var(--ce-arrow-hover)';
954 e.currentTarget.style.color = 'var(--ce-text-2)';
955 }} onMouseLeave={e => {
956 e.currentTarget.style.background = 'transparent';
957 e.currentTarget.style.color = 'var(--ce-text-4)';
958 }}>{isExpanded ? '▾' : '▸'}</span> : <span style={{
959 width: '14px',
960 flexShrink: 0
961 }} />}
962 {renderIcon(node.icon, node.color)}
963 <span style={{
964 flex: 1,
965 overflow: 'hidden',
966 textOverflow: 'ellipsis',
967 whiteSpace: 'nowrap'
968 }}>{node.label}</span>
969 {node.badge && BADGE_STYLES[node.badge] && <span title={BADGE_STYLES[node.badge].label} style={{
970 width: 6,
971 height: 6,
972 borderRadius: '50%',
973 background: BADGE_STYLES[node.badge].color,
974 flexShrink: 0,
975 opacity: 0.7
976 }} />}
977 </button>
978 {isFolder && isExpanded && node.children && <div role="group">{node.children.map(child => renderNode(child, depth + 1))}</div>}
979 </div>;
980 };
981 return <>
982 <style>{`
983 .ce-root {
984 --ce-mono: var(--font-mono, ui-monospace, monospace);
985 --ce-accent: #D97757;
986 --ce-accent-bg: rgba(217,119,87,0.06);
987 --ce-accent-border: rgba(217,119,87,0.12);
988 --ce-bg: #fff;
989 --ce-surface: #FAFAF7;
990 --ce-surface-hover: #F0EEE6;
991 --ce-border: #E8E6DC;
992 --ce-border-subtle: #F0EEE6;
993 --ce-text: #141413;
994 --ce-text-2: #5E5D59;
995 --ce-text-3: #73726C;
996 --ce-text-4: #9C9A92;
997 --ce-text-5: #B8B6AE;
998 --ce-sep: #D1CFC5;
999 --ce-code-header: #F5F4ED;
1000 --ce-code-bg: #1A1918;
1001 --ce-arrow-hover: rgba(0,0,0,0.08);
1002 --ce-badge-committed: #3d6b2e;
1003 --ce-badge-gitignored: #b85c3a;
1004 --ce-badge-local: #5e5d59;
1005 --ce-badge-autogen: #b07520;
1006 --ce-when-text: #4a7fb5;
1007 }
1008 .dark .ce-root {
1009 --ce-bg: #1a1918;
1010 --ce-surface: #232221;
1011 --ce-surface-hover: #2e2d2b;
1012 --ce-border: #3a3936;
1013 --ce-border-subtle: #2e2d2b;
1014 --ce-text: #e8e6dc;
1015 --ce-text-2: #c4c2b8;
1016 --ce-text-3: #9c9a92;
1017 --ce-text-4: #73726c;
1018 --ce-text-5: #5e5d59;
1019 --ce-sep: #4a4946;
1020 --ce-code-header: #2e2d2b;
1021 --ce-code-bg: #0d0d0c;
1022 --ce-arrow-hover: rgba(255,255,255,0.08);
1023 --ce-badge-committed: #6fa85c;
1024 --ce-badge-gitignored: #e08a60;
1025 --ce-badge-local: #9c9a92;
1026 --ce-badge-autogen: #e8a45c;
1027 --ce-when-text: #8bb4e0;
1028 }
1029 .ce-mobile-fallback { display: none; border: 1px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.03); }
1030 .dark .ce-mobile-fallback { border-color: rgba(255,255,255,0.15); background: rgba(255,255,255,0.04); }
1031 @media (max-width: 700px) {
1032 .ce-root:not(.ce-force) { display: none !important; }
1033 .ce-mobile-fallback { display: block; }
1034 }
1035 `}</style>
1036 {!forceMobile && <div className="ce-mobile-fallback" style={{
1037 padding: '14px 16px',
1038 borderRadius: '8px',
1039 fontSize: '14px'
1040 }}>
1041 The interactive explorer works best on a larger screen. See the <a href="#file-reference" style={{
1042 color: '#D97757'
1043 }}>file reference table</a> below, or <button onClick={() => setForceMobile(true)} style={{
1044 border: 'none',
1045 background: 'none',
1046 padding: 0,
1047 color: '#D97757',
1048 textDecoration: 'underline',
1049 cursor: 'pointer',
1050 font: 'inherit'
1051 }}>show the explorer anyway</button>.
1052 </div>}
1053 <div ref={rootRef} className={forceMobile ? 'ce-root ce-force' : 'ce-root'} style={{
1054 borderRadius: isFullscreen ? 0 : '12px',
1055 border: '1px solid var(--ce-border)',
1056 background: 'var(--ce-bg)',
1057 display: 'flex',
1058 alignItems: 'stretch',
1059 overflow: 'hidden',
1060 fontFamily: 'var(--font-sans, -apple-system, sans-serif)',
1061 ...isFullscreen && ({
1062 height: '100vh'
1063 })
1064 }}>
1065 {}
1066 <div style={{
1067 width: 'min(240px, 35%)',
1068 minWidth: '180px',
1069 flexShrink: 0,
1070 borderRight: '1px solid var(--ce-border-subtle)',
1071 background: 'var(--ce-surface)',
1072 display: 'flex',
1073 flexDirection: 'column'
1074 }}>
1075 <div style={{
1076 padding: '8px 8px 4px',
1077 borderBottom: '1px solid var(--ce-border-subtle)',
1078 display: 'flex',
1079 gap: '4px'
1080 }}>
1081 {['project', 'global'].map(root => <button key={root} onClick={() => switchRoot(root)} style={{
1082 flex: 1,
1083 padding: '6px 0',
1084 borderRadius: '6px',
1085 border: 'none',
1086 cursor: 'pointer',
1087 fontFamily: 'var(--ce-mono)',
1088 fontSize: '11.5px',
1089 background: activeRoot === root ? 'var(--ce-accent-bg)' : 'transparent',
1090 color: activeRoot === root ? 'var(--ce-accent)' : 'var(--ce-text-4)',
1091 fontWeight: activeRoot === root ? 600 : 430
1092 }}>
1093 {root === 'project' ? 'Project' : 'Global (~/)'}
1094 </button>)}
1095 <button onClick={toggleAllFolders} title={allExpanded ? 'Collapse all' : 'Expand all'} style={{
1096 ...iconBtn,
1097 fontSize: 11
1098 }}>
1099 {allExpanded ? '⊟' : '⊞'}
1100 </button>
1101 <button onClick={toggleFullscreen} title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'} style={{
1102 ...iconBtn,
1103 fontSize: 13
1104 }}>
1105 {isFullscreen ? '⤡' : '⛶'}
1106 </button>
1107 </div>
1108 <div role="tree" aria-label="Configuration files" tabIndex={0} onKeyDown={onTreeKeyDown} style={{
1109 padding: '6px 0',
1110 overflowY: 'auto',
1111 flex: 1,
1112 outline: 'none'
1113 }}>
1114 {tree.children.map(node => renderNode(node, 0))}
1115 </div>
1116 </div>
1117
1118 {}
1119 <div style={{
1120 flex: 1,
1121 minWidth: 0,
1122 padding: '20px 24px',
1123 minHeight: '400px',
1124 overflowY: 'auto'
1125 }}>
1126 <span aria-live="polite" style={{
1127 position: 'absolute',
1128 width: 1,
1129 height: 1,
1130 overflow: 'hidden',
1131 clip: 'rect(0 0 0 0)'
1132 }}>{selected.label} selected</span>
1133 {}
1134 <div style={{
1135 fontFamily: 'var(--ce-mono)',
1136 fontSize: '11px',
1137 color: 'var(--ce-text-4)',
1138 marginBottom: '10px',
1139 cursor: 'default'
1140 }}>
1141 {selected.path.map((seg, i) => <span key={i}>
1142 <span style={{
1143 color: i === selected.path.length - 1 ? 'var(--ce-accent)' : 'var(--ce-text-4)'
1144 }}>{seg.replace(/\/$/, '')}</span>
1145 {i < selected.path.length - 1 && <span style={{
1146 color: 'var(--ce-sep)'
1147 }}> / </span>}
1148 </span>)}
1149 </div>
1150
1151 {}
1152 <div style={{
1153 display: 'flex',
1154 alignItems: 'flex-start',
1155 gap: '10px',
1156 marginBottom: '10px'
1157 }}>
1158 <span style={{
1159 flexShrink: 0,
1160 display: 'flex'
1161 }}>{renderIcon(selected.icon, selected.color, 24)}</span>
1162 <div style={{
1163 flex: 1,
1164 minWidth: 0
1165 }}>
1166 <div style={{
1167 fontSize: '22px',
1168 fontWeight: 600,
1169 color: 'var(--ce-text)',
1170 letterSpacing: '-0.3px',
1171 lineHeight: '26px'
1172 }}>{selected.label}</div>
1173 {selected.oneLiner && <div style={{
1174 fontSize: '15px',
1175 color: 'var(--ce-text-3)',
1176 marginTop: '3px'
1177 }}>{selected.oneLiner}</div>}
1178 </div>
1179 <div style={{
1180 display: 'flex',
1181 gap: '4px',
1182 flexShrink: 0
1183 }}>
1184 {[selected.autogen && 'autogen', selected.badge].filter(Boolean).map(k => {
1185 const s = BADGE_STYLES[k];
1186 if (!s) return null;
1187 return <span key={k} style={{
1188 fontFamily: 'var(--ce-mono)',
1189 fontSize: '10px',
1190 fontWeight: 600,
1191 textTransform: 'uppercase',
1192 letterSpacing: '0.3px',
1193 padding: '2px 6px',
1194 borderRadius: '4px',
1195 background: s.bg,
1196 color: s.color,
1197 border: `0.5px solid ${s.border}`
1198 }}>{s.label}</span>;
1199 })}
1200 </div>
1201 </div>
1202
1203 {}
1204 {selected.note && <div style={{
1205 padding: '10px 12px',
1206 borderRadius: '8px',
1207 marginBottom: '14px',
1208 background: 'rgba(217,119,87,0.06)',
1209 border: '1px solid rgba(217,119,87,0.2)',
1210 borderLeft: '3px solid var(--ce-accent)',
1211 fontSize: '15px',
1212 color: 'var(--ce-text-2)',
1213 lineHeight: 1.6
1214 }}>
1215 {selected.note}
1216 </div>}
1217
1218 {}
1219 {selected.when && <div style={{
1220 padding: '8px 12px',
1221 borderRadius: '6px',
1222 background: 'rgba(106,155,204,0.06)',
1223 border: '0.5px solid rgba(106,155,204,0.12)',
1224 fontSize: '15px',
1225 color: 'var(--ce-when-text)',
1226 marginBottom: '16px'
1227 }}>
1228 <div style={{
1229 fontSize: '10px',
1230 fontWeight: 700,
1231 textTransform: 'uppercase',
1232 letterSpacing: '0.4px',
1233 opacity: 0.65,
1234 marginBottom: '3px'
1235 }}>When it loads</div>
1236 <div style={{
1237 fontWeight: 500
1238 }}>{selected.when}</div>
1239 </div>}
1240
1241 {}
1242 {selected.description && <div style={{
1243 fontSize: '16px',
1244 color: 'var(--ce-text-2)',
1245 lineHeight: 1.65,
1246 marginBottom: '16px'
1247 }}>
1248 {Array.isArray(selected.description) ? selected.description.map((para, i) => <div key={i} style={{
1249 marginBottom: i < selected.description.length - 1 ? '12px' : 0
1250 }}>{para}</div>) : selected.description}
1251 </div>}
1252
1253 {}
1254 {selected.contains && selected.contains.length > 0 && <div style={{
1255 marginBottom: '16px'
1256 }}>
1257 <div style={{
1258 fontSize: '11px',
1259 fontWeight: 700,
1260 color: 'var(--ce-text-4)',
1261 textTransform: 'uppercase',
1262 letterSpacing: '0.4px',
1263 marginBottom: '8px'
1264 }}>Common keys</div>
1265 {selected.contains.map((item, i) => <div key={i} style={{
1266 display: 'flex',
1267 gap: '7px',
1268 fontSize: '15px',
1269 color: 'var(--ce-text-2)',
1270 lineHeight: 1.5,
1271 marginBottom: '5px'
1272 }}>
1273 <span style={{
1274 fontSize: '7px',
1275 color: 'var(--ce-text-4)',
1276 marginTop: '6px'
1277 }}>●</span>
1278 <span>{item}</span>
1279 </div>)}
1280 </div>}
1281
1282 {}
1283 {selected.tips && selected.tips.length > 0 && <div style={{
1284 padding: '12px 14px',
1285 borderRadius: '8px',
1286 background: 'var(--ce-surface)',
1287 border: '1px solid var(--ce-border-subtle)',
1288 marginBottom: '16px'
1289 }}>
1290 <div style={{
1291 fontSize: '11px',
1292 fontWeight: 700,
1293 color: 'var(--ce-accent)',
1294 textTransform: 'uppercase',
1295 letterSpacing: '0.4px',
1296 marginBottom: '6px'
1297 }}>Tips</div>
1298 {selected.tips.map((tip, i) => <div key={i} style={{
1299 display: 'flex',
1300 gap: '7px',
1301 fontSize: '14.5px',
1302 color: 'var(--ce-text-2)',
1303 marginBottom: i < selected.tips.length - 1 ? '5px' : 0
1304 }}>
1305 <span style={{
1306 fontSize: '7px',
1307 color: 'var(--ce-accent)',
1308 marginTop: '6px'
1309 }}>●</span>
1310 <span>{tip}</span>
1311 </div>)}
1312 </div>}
1313
1314 {}
1315 {selected.example && <div style={{
1316 marginBottom: '16px'
1317 }}>
1318 {selected.exampleIntro && <div style={{
1319 fontSize: '15px',
1320 color: 'var(--ce-text-2)',
1321 lineHeight: 1.6,
1322 marginBottom: '10px'
1323 }}>
1324 {selected.exampleIntro}
1325 </div>}
1326 <div style={{
1327 display: 'flex',
1328 justifyContent: 'space-between',
1329 alignItems: 'center',
1330 padding: '6px 10px',
1331 background: 'var(--ce-code-header)',
1332 border: '1px solid var(--ce-border)',
1333 borderRadius: '8px 8px 0 0'
1334 }}>
1335 <span style={{
1336 fontFamily: 'var(--ce-mono)',
1337 fontSize: '11px',
1338 fontWeight: 600,
1339 color: 'var(--ce-text-3)'
1340 }}>{selected.label}</span>
1341 <button onClick={() => copyExample(selected.id, selected.example)} style={{
1342 padding: '3px 8px',
1343 borderRadius: '4px',
1344 fontSize: '11px',
1345 fontWeight: 600,
1346 cursor: 'pointer',
1347 transition: 'all 0.15s',
1348 background: isCopied ? 'rgba(85,138,66,0.08)' : 'var(--ce-code-header)',
1349 border: isCopied ? '0.5px solid rgba(85,138,66,0.2)' : '0.5px solid var(--ce-border)',
1350 color: isCopied ? '#558A42' : 'var(--ce-text-3)'
1351 }}>
1352 {isCopied ? '✓ Copied' : 'Copy'}
1353 </button>
1354 </div>
1355 <pre style={{
1356 margin: 0,
1357 padding: '12px 14px',
1358 background: 'var(--ce-code-bg)',
1359 color: '#E8E6DC',
1360 fontFamily: 'var(--ce-mono)',
1361 fontSize: '13px',
1362 lineHeight: 1.65,
1363 borderRadius: '0 0 8px 8px',
1364 overflowX: 'auto',
1365 whiteSpace: 'pre'
1366 }}>{selected.example}</pre>
1367 </div>}
1368
1369 {}
1370 {selected.docsLink && <a href={selected.docsLink} style={{
1371 display: 'inline-flex',
1372 padding: '5px 12px',
1373 borderRadius: '6px',
1374 background: 'var(--ce-accent-bg)',
1375 border: '1px solid var(--ce-accent-border)',
1376 color: 'var(--ce-accent)',
1377 fontSize: '12px',
1378 fontWeight: 600,
1379 textDecoration: 'none'
1380 }}>Full docs →</a>}
1381
1382 {}
1383 {selected.children && selected.children.length > 0 && <div style={{
1384 marginTop: '20px'
1385 }}>
1386 <div style={{
1387 fontSize: '11px',
1388 fontWeight: 700,
1389 color: 'var(--ce-text-4)',
1390 textTransform: 'uppercase',
1391 letterSpacing: '0.4px',
1392 marginBottom: '8px'
1393 }}>Contents</div>
1394 <div style={{
1395 display: 'flex',
1396 flexDirection: 'column',
1397 gap: '4px'
1398 }}>
1399 {selected.children.map(child => <button key={child.id} onClick={() => selectNode(child)} style={{
1400 display: 'flex',
1401 alignItems: 'center',
1402 gap: '8px',
1403 padding: '6px 8px',
1404 width: '100%',
1405 background: 'var(--ce-surface)',
1406 borderRadius: '6px',
1407 border: 'none',
1408 cursor: 'pointer',
1409 textAlign: 'left',
1410 transition: 'background 0.1s'
1411 }} onMouseEnter={e => e.currentTarget.style.background = 'var(--ce-surface-hover)'} onMouseLeave={e => e.currentTarget.style.background = 'var(--ce-surface)'}>
1412 {renderIcon(child.icon, child.color, 13)}
1413 <span style={{
1414 fontFamily: 'var(--ce-mono)',
1415 fontSize: '12px',
1416 color: 'var(--ce-text-2)'
1417 }}>{child.label}</span>
1418 {child.oneLiner && <span style={{
1419 fontSize: '11px',
1420 color: 'var(--ce-text-4)',
1421 overflow: 'hidden',
1422 textOverflow: 'ellipsis',
1423 whiteSpace: 'nowrap'
1424 }}>{child.oneLiner}</span>}
1425 </button>)}
1426 </div>
1427 </div>}
1428 </div>
1429 </div>
1430 </>;
1431};
1432
9Claude Code는 프로젝트 디렉토리와 홈 디렉토리의 `~/.claude`에서 지침, 설정, skills, subagents, 메모리를 읽습니다. 프로젝트 파일을 git에 커밋하여 팀과 공유합니다. `~/.claude`의 파일은 모든 프로젝트에 적용되는 개인 설정입니다.1433Claude Code는 프로젝트 디렉토리와 홈 디렉토리의 `~/.claude`에서 지침, 설정, skills, subagents, 메모리를 읽습니다. 프로젝트 파일을 git에 커밋하여 팀과 공유합니다. `~/.claude`의 파일은 모든 프로젝트에 적용되는 개인 설정입니다.
10 1434
11Windows에서 `~/.claude`는 `%USERPROFILE%\.claude`로 확인됩니다. [`CLAUDE_CONFIG_DIR`](/ko/env-vars)을 설정하면, 이 페이지의 모든 `~/.claude` 경로가 대신 해당 디렉토리 아래에 있습니다.1435Windows에서 `~/.claude`는 `%USERPROFILE%\.claude`로 확인됩니다. [`CLAUDE_CONFIG_DIR`](/ko/env-vars)을 설정하면, 이 페이지의 모든 `~/.claude` 경로가 대신 해당 디렉토리 아래에 있습니다.
18 1442
19트리의 파일을 클릭하여 각 파일이 무엇을 하는지, 언제 로드되는지, 예제를 확인합니다.1443트리의 파일을 클릭하여 각 파일이 무엇을 하는지, 언제 로드되는지, 예제를 확인합니다.
20 1444
21<h2 id="what-s-not-shown">1445<ClaudeExplorer />
1446
1447<h2 id="what’s-not-shown">
22 표시되지 않는 항목1448 표시되지 않는 항목
23</h2>1449</h2>
24 1450