> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 04-0 The .claude Directory: A Complete Map

> The map for Part IV: understand the full structure of .claude/ first, then dive into each unit. Covers every file in the project and user layers -- purpose, load timing, and version-control guidance -- plus five supplementary topics: output-styles, keybindings, themes, workflows, and agent-memory.

export const DirExplorer = ({lang = "zh", scopes = []}) => {
  const UI = lang === "en" ? {
    expandAll: "Expand all",
    collapseAll: "Collapse all",
    whenLoads: "WHEN IT LOADS",
    tips: "TIPS",
    copy: "Copy",
    copied: "Copied",
    mapsToLabel: "Maps to Claude",
    badgeLabels: {
      committed: "Committed to version control",
      gitignored: "Git-ignored (local only)",
      local: "Local override",
      autogen: "Auto-generated"
    },
    badgeTexts: {
      committed: "COMMITTED",
      gitignored: "GITIGNORED",
      local: "LOCAL",
      autogen: "AUTOGEN"
    }
  } : {
    expandAll: "全部展開",
    collapseAll: "全部收合",
    whenLoads: "載入時機",
    tips: "提示",
    copy: "複製",
    copied: "已複製",
    mapsToLabel: "對照 Claude",
    badgeLabels: {
      committed: "已提交至版本控制",
      gitignored: "Git 忽略（僅本機）",
      local: "本機覆寫",
      autogen: "自動產生"
    },
    badgeTexts: {
      committed: "COMMITTED",
      gitignored: "GITIGNORED",
      local: "LOCAL",
      autogen: "AUTOGEN"
    }
  };
  const ACCENT_LIGHT = "#bf7551";
  const ACCENT_DARK = "#cf8a68";
  const DIR_COLORS = {
    blue: "#5b6c8f",
    purple: "#8a6f8e",
    yellow: "#c9a35b",
    green: "#8a9a7b",
    teal: "#6f9290",
    rose: "#ab7269",
    amber: "#b9835c",
    gray: "#8a8378",
    default: "#8a8378"
  };
  const BADGE_COLORS = {
    committed: {
      dot: "#6dab7d",
      title: "committed"
    },
    gitignored: {
      dot: "#d4844a",
      title: "gitignored"
    },
    local: {
      dot: "#8a8378",
      title: "local"
    },
    autogen: {
      dot: "#c8a240",
      title: "autogen"
    }
  };
  const safeScopes = Array.isArray(scopes) && scopes.length > 0 ? scopes : [];
  if (safeScopes.length === 0) return null;
  const [activeScopeId, setActiveScopeId] = useState(safeScopes[0].id);
  const [expandedIds, setExpandedIds] = useState({});
  const [selectedNode, setSelectedNode] = useState(null);
  const [copiedFlag, setCopiedFlag] = useState(false);
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const detectDark = () => setIsDark(document.documentElement.classList.contains("dark"));
    detectDark();
    const obs = new MutationObserver(detectDark);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    const firstScope = safeScopes[0];
    if (firstScope && Array.isArray(firstScope.tree)) {
      const initExpanded = {};
      firstScope.tree.forEach((node, i) => {
        if (node.kind === "dir") initExpanded[firstScope.id + ":" + i] = true;
      });
      setExpandedIds(initExpanded);
    }
    return () => obs.disconnect();
  }, []);
  const switchScope = id => {
    setActiveScopeId(id);
    setSelectedNode(null);
    const scope = safeScopes.find(s => s.id === id);
    if (!scope) return;
    const initExpanded = {};
    (scope.tree || []).forEach((node, i) => {
      if (node.kind === "dir") initExpanded[id + ":" + i] = true;
    });
    setExpandedIds(initExpanded);
  };
  const activeScope = safeScopes.find(s => s.id === activeScopeId) || safeScopes[0];
  const tree = Array.isArray(activeScope.tree) ? activeScope.tree : [];
  const collectAllDirKeys = (nodes, scopeId, prefix) => {
    const keys = [];
    (nodes || []).forEach((node, i) => {
      const key = prefix + i;
      if (node.kind === "dir") {
        keys.push(scopeId + ":" + key);
        const childKeys = collectAllDirKeys(node.children, scopeId, key + "-");
        childKeys.forEach(k => keys.push(k));
      }
    });
    return keys;
  };
  const handleExpandAll = () => {
    const keys = collectAllDirKeys(tree, activeScopeId, "");
    const next = {};
    keys.forEach(k => {
      next[k] = true;
    });
    setExpandedIds(next);
  };
  const handleCollapseAll = () => {
    setExpandedIds({});
  };
  const isAllExpanded = () => {
    const keys = collectAllDirKeys(tree, activeScopeId, "");
    return keys.length > 0 && keys.every(k => expandedIds[k]);
  };
  const handleCopy = code => {
    if (!code) return;
    try {
      navigator.clipboard.writeText(code).then(() => {
        setCopiedFlag(true);
        setTimeout(() => setCopiedFlag(false), 1600);
      });
    } catch (_) {
      setCopiedFlag(false);
    }
  };
  const FolderIcon = ({color}) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={color || DIR_COLORS.default} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{
    flexShrink: 0
  }}>
      <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
    </svg>;
  const FileDocIcon = ({color}) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={color || DIR_COLORS.default} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{
    flexShrink: 0
  }}>
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
      <polyline points="14 2 14 8 20 8" />
      <line x1="16" y1="13" x2="8" y2="13" />
      <line x1="16" y1="17" x2="8" y2="17" />
      <polyline points="10 9 9 9 8 9" />
    </svg>;
  const FileJsonIcon = ({color}) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke={color || DIR_COLORS.default} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{
    flexShrink: 0
  }}>
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
      <polyline points="14 2 14 8 20 8" />
      <text x="7" y="19" fontSize="7" fontWeight="700" fill={color || DIR_COLORS.default} stroke="none" fontFamily="monospace">{"{}"}</text>
    </svg>;
  const ChevronRight = () => <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{
    flexShrink: 0,
    transition: "transform 0.15s"
  }}>
      <polyline points="9 18 15 12 9 6" />
    </svg>;
  const getFileIcon = node => {
    const c = DIR_COLORS[node.color] || DIR_COLORS.default;
    if (node.kind === "dir") return <FolderIcon color={c} />;
    if (node.name && (node.name.endsWith(".json") || node.name.endsWith(".jsonc"))) return <FileJsonIcon color={c} />;
    return <FileDocIcon color={c} />;
  };
  const renderNodes = (nodes, scopeId, depth, keyPrefix) => {
    return (nodes || []).map((node, i) => {
      const nodeKey = keyPrefix + i;
      const stateKey = scopeId + ":" + nodeKey;
      const isExpanded = !!expandedIds[stateKey];
      const isSelected = selectedNode && selectedNode._key === stateKey;
      const badge = node.badge ? BADGE_COLORS[node.badge] : null;
      const hasDetail = node.detail && typeof node.detail === "object";
      const isDir = node.kind === "dir";
      const handleClick = () => {
        if (isDir) {
          setExpandedIds(prev => ({
            ...prev,
            [stateKey]: !prev[stateKey]
          }));
        }
        if (hasDetail) {
          setSelectedNode(isSelected ? null : {
            ...node,
            _key: stateKey
          });
        } else if (isDir && !hasDetail) {}
      };
      return <div key={stateKey} className="dx-node-wrap">
          <button type="button" className={"dx-node" + (isSelected ? " dx-node-selected" : "")} style={{
        paddingLeft: depth * 14 + 8 + "px"
      }} onClick={handleClick} aria-pressed={isSelected ? "true" : "false"}>
            {isDir ? <span className="dx-chevron" style={{
        transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
      }}>
                <ChevronRight />
              </span> : <span className="dx-chevron-spacer" />}
            {getFileIcon(node)}
            <span className="dx-node-name">{node.name}</span>
            {badge && <span className="dx-badge-dot" style={{
        background: badge.dot
      }} title={UI.badgeLabels[node.badge] || node.badge} />}
          </button>
          {isDir && isExpanded && node.children && node.children.length > 0 && <div className="dx-children">
              {renderNodes(node.children, scopeId, depth + 1, nodeKey + "-")}
            </div>}
        </div>;
    });
  };
  const renderDetail = () => {
    if (!selectedNode || !selectedNode.detail) {
      return <div className="dx-detail-empty">
          <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{
        opacity: 0.25,
        marginBottom: "10px"
      }}>
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
            <polyline points="14 2 14 8 20 8" />
            <line x1="16" y1="13" x2="8" y2="13" />
            <line x1="16" y1="17" x2="8" y2="17" />
          </svg>
          <span>{lang === "en" ? "Select a file or folder" : "點選左側項目查看說明"}</span>
        </div>;
    }
    const d = selectedNode.detail;
    const c = DIR_COLORS[selectedNode.color] || DIR_COLORS.default;
    const badge = selectedNode.badge ? BADGE_COLORS[selectedNode.badge] : null;
    return <div className="dx-detail-inner">
        {d.breadcrumb && <div className="dx-breadcrumb">{d.breadcrumb}</div>}

        <div className="dx-detail-title-row">
          {getFileIcon(selectedNode)}
          <span className="dx-detail-title">{d.title || selectedNode.name}</span>
          {badge && <span className="dx-pill" style={{
      color: badge.dot,
      borderColor: badge.dot + "55",
      background: badge.dot + "18"
    }}>
              {UI.badgeTexts[selectedNode.badge]}
            </span>}
        </div>

        {d.tagline && <div className="dx-tagline">{d.tagline}</div>}

        {d.whenItLoads && <div className="dx-when-card">
            <div className="dx-when-label">{UI.whenLoads}</div>
            <div className="dx-when-body">{d.whenItLoads}</div>
          </div>}

        {d.description && <div className="dx-description">{d.description}</div>}

        {d.tips && d.tips.length > 0 && <div className="dx-tips-card">
            <div className="dx-tips-label">{UI.tips}</div>
            <ul className="dx-tips-list">
              {d.tips.map((tip, i) => <li key={i} className="dx-tips-item">{tip}</li>)}
            </ul>
          </div>}

        {d.example && d.example.code && <div className="dx-code-block">
            <div className="dx-code-header">
              <span className="dx-code-filename">{d.example.filename || ""}</span>
              <button type="button" className="dx-copy-btn" onClick={() => handleCopy(d.example.code)}>
                {copiedFlag ? UI.copied : UI.copy}
              </button>
            </div>
            <pre className="dx-code-pre"><code>{d.example.code}</code></pre>
          </div>}

        {d.mapsTo && <div className="dx-maps-card">
            <div className="dx-maps-label">{UI.mapsToLabel}</div>
            <div className="dx-maps-body">{d.mapsTo}</div>
          </div>}
      </div>;
  };
  const accentColor = isDark ? ACCENT_DARK : ACCENT_LIGHT;
  const css = `
  .dx-root {
    --dx-bg: #FAF8F3;
    --dx-surface: rgba(0,0,0,0.025);
    --dx-border: rgba(0,0,0,0.09);
    --dx-text: #2b2722;
    --dx-dim: #6f6a62;
    --dx-faint: #8a8378;
    --dx-accent: #bf7551;
    --dx-accent-bg: rgba(191,117,81,0.08);
    --dx-accent-border: rgba(191,117,81,0.30);
    --dx-when-bg: rgba(91,108,143,0.07);
    --dx-when-border: rgba(91,108,143,0.35);
    --dx-when-label: #46587a;
    --dx-tips-bg: rgba(191,117,81,0.06);
    --dx-code-bg: #1A1918;
    --dx-code-text: #e2ddd7;
    --dx-code-header: #2a2826;
    --dx-maps-bg: rgba(138,111,142,0.09);
    --dx-maps-border: rgba(138,111,142,0.35);
    --dx-maps-label: #6f5673;
    border: 1px solid var(--dx-border);
    border-radius: 12px;
    background: var(--dx-bg);
    color: var(--dx-text);
    overflow: hidden;
    display: flex;
    min-height: 560px;
  }
  .dark .dx-root {
    --dx-bg: #1b1a18;
    --dx-surface: rgba(255,255,255,0.03);
    --dx-border: rgba(255,255,255,0.08);
    --dx-text: #e7e3da;
    --dx-dim: #a8a299;
    --dx-faint: #8a8378;
    --dx-accent: #cf8a68;
    --dx-accent-bg: rgba(207,138,104,0.09);
    --dx-accent-border: rgba(207,138,104,0.30);
    --dx-when-bg: rgba(91,108,143,0.14);
    --dx-when-border: rgba(91,108,143,0.42);
    --dx-when-label: #9fb0d4;
    --dx-tips-bg: rgba(207,138,104,0.07);
    --dx-code-bg: #121110;
    --dx-code-text: #d8d4ce;
    --dx-code-header: #1e1c1a;
    --dx-maps-bg: rgba(138,111,142,0.14);
    --dx-maps-border: rgba(138,111,142,0.42);
    --dx-maps-label: #c4a8c8;
  }

  /* ── 左面板 ── */
  .dx-left {
    width: min(264px, 38%);
    min-width: 196px;
    flex-shrink: 0;
    border-right: 1px solid var(--dx-border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  /* scope bar 強制單列：scope 按鈕收縮溢出省略，展開鈕固定不擠掉 */
  .dx-scope-bar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 7px 8px 6px;
    border-bottom: 1px solid var(--dx-border);
    flex-wrap: nowrap;
  }
  .dx-scope-btn {
    flex: 1 1 0;
    min-width: 0;
    font-size: 11px;
    font-weight: 600;
    padding: 4px 7px;
    border-radius: 6px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--dx-dim);
    cursor: pointer;
    transition: background 0.13s, color 0.13s, border-color 0.13s;
    font: inherit;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .dx-scope-btn:hover {
    background: var(--dx-surface);
    color: var(--dx-text);
  }
  .dx-scope-btn.dx-scope-active {
    background: var(--dx-accent-bg);
    border-color: var(--dx-accent-border);
    color: var(--dx-accent);
  }
  .dx-expand-btn {
    flex-shrink: 0;
    font-size: 10.5px;
    padding: 4px 7px;
    border-radius: 6px;
    border: 1px solid var(--dx-border);
    background: transparent;
    color: var(--dx-faint);
    cursor: pointer;
    transition: color 0.13s, background 0.13s;
    font: inherit;
    white-space: nowrap;
    letter-spacing: 0.01em;
  }
  .dx-expand-btn:hover {
    background: var(--dx-surface);
    color: var(--dx-text);
  }
  .dx-tree {
    flex: 1 1 0;
    overflow-y: auto;
    padding: 6px 0 10px;
  }
  .dx-tree::-webkit-scrollbar { width: 5px; }
  .dx-tree::-webkit-scrollbar-thumb { background: var(--dx-border); border-radius: 4px; }
  .dx-node-wrap { display: flex; flex-direction: column; }
  .dx-node {
    display: flex;
    align-items: center;
    gap: 5px;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    border-left: 2px solid transparent;
    cursor: pointer;
    padding-top: 4px;
    padding-bottom: 4px;
    padding-right: 10px;
    color: var(--dx-text);
    font: inherit;
    font-size: 13px;
    line-height: 1.4;
    transition: background 0.12s, border-color 0.12s;
    -webkit-tap-highlight-color: transparent;
  }
  .dx-node:hover {
    background: var(--dx-surface);
  }
  .dx-node-selected {
    border-left-color: var(--dx-accent);
    background: var(--dx-accent-bg);
    color: var(--dx-text);
  }
  .dx-chevron {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--dx-faint);
    width: 13px;
  }
  .dx-chevron-spacer { width: 13px; flex-shrink: 0; }
  .dx-node-name {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* 狀態 badge 改小圓角方塊（非外部文件站的圓點），保持自家識別 */
  .dx-badge-dot {
    width: 5.5px;
    height: 5.5px;
    border-radius: 1.5px;
    transform: rotate(45deg);
    flex-shrink: 0;
    margin-left: 2px;
    opacity: 0.85;
  }

  /* ── 右詳情面板 ── */
  .dx-right {
    flex: 1 1 0;
    min-width: 0;
    overflow-y: auto;
    padding: 20px 24px;
    display: flex;
    flex-direction: column;
  }
  .dx-right::-webkit-scrollbar { width: 5px; }
  .dx-right::-webkit-scrollbar-thumb { background: var(--dx-border); border-radius: 4px; }
  .dx-detail-empty {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--dx-faint);
    font-size: 13px;
    gap: 4px;
    text-align: center;
  }
  .dx-detail-inner {
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  .dx-breadcrumb {
    font-size: 11.5px;
    color: var(--dx-faint);
    font-family: monospace;
    letter-spacing: 0.01em;
  }
  .dx-detail-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
  }
  .dx-detail-title {
    font-size: 22px;
    font-weight: 700;
    line-height: 1.25;
    color: var(--dx-text);
  }
  .dx-pill {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 20px;
    border: 1px solid;
    flex-shrink: 0;
  }
  .dx-tagline {
    font-size: 13.5px;
    color: var(--dx-dim);
    line-height: 1.5;
    margin-top: -4px;
  }
  /* 載入時機卡走自家樣式：左緣色條 + 暖中性底（非外部文件站的藍框卡） */
  .dx-when-card {
    background: var(--dx-when-bg);
    border: none;
    border-left: 3px solid var(--dx-when-border);
    border-radius: 4px 10px 10px 4px;
    padding: 11px 14px;
  }
  .dx-when-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--dx-when-label);
    margin-bottom: 5px;
  }
  .dx-when-body {
    font-size: 13.5px;
    color: var(--dx-text);
    line-height: 1.55;
  }
  .dx-description {
    font-size: 15px;
    line-height: 1.65;
    color: var(--dx-dim);
  }
  .dx-tips-card {
    background: var(--dx-tips-bg);
    border-radius: 8px;
    padding: 11px 14px 12px;
  }
  .dx-tips-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--dx-accent);
    margin-bottom: 7px;
  }
  .dx-tips-list {
    margin: 0;
    padding-left: 18px;
    display: flex;
    flex-direction: column;
    gap: 5px;
  }
  .dx-tips-item {
    font-size: 13.5px;
    color: var(--dx-dim);
    line-height: 1.55;
  }
  .dx-code-block {
    border-radius: 9px;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,0.06);
  }
  .dx-code-header {
    background: var(--dx-code-header);
    padding: 7px 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
  }
  .dx-code-filename {
    font-size: 11.5px;
    font-family: monospace;
    color: var(--dx-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .dx-copy-btn {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 5px;
    border: 1px solid rgba(255,255,255,0.12);
    background: rgba(255,255,255,0.06);
    color: #c0bbb4;
    cursor: pointer;
    transition: background 0.13s, color 0.13s;
    font: inherit;
    font-size: 11px;
    font-weight: 600;
  }
  .dx-copy-btn:hover {
    background: rgba(255,255,255,0.12);
    color: #e2ddd7;
  }
  .dx-code-pre {
    margin: 0;
    background: var(--dx-code-bg);
    padding: 14px 16px;
    overflow-x: auto;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--dx-code-text);
    font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace;
    tab-size: 2;
  }
  .dx-code-pre::-webkit-scrollbar { height: 5px; }
  .dx-code-pre::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 3px; }
  .dx-maps-card {
    background: var(--dx-maps-bg);
    border: 1px solid var(--dx-maps-border);
    border-radius: 8px;
    padding: 11px 14px;
  }
  .dx-maps-label {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--dx-maps-label);
    margin-bottom: 5px;
  }
  .dx-maps-body {
    font-size: 13.5px;
    color: var(--dx-dim);
    line-height: 1.55;
  }

  /* ── 手機堆疊 ── */
  @media (max-width: 700px) {
    .dx-root { flex-direction: column; min-height: unset; }
    .dx-left {
      width: 100%;
      min-width: unset;
      border-right: none;
      border-bottom: 1px solid var(--dx-border);
      max-height: 260px;
    }
    .dx-right { padding: 16px; }
    .dx-detail-title { font-size: 18px; }
  }
  `;
  return <div className="dx-root">
      <style>{css}</style>

      {}
      <div className="dx-left">
        <div className="dx-scope-bar">
          {safeScopes.map(scope => <button key={scope.id} type="button" className={"dx-scope-btn" + (scope.id === activeScopeId ? " dx-scope-active" : "")} onClick={() => switchScope(scope.id)}>
              {scope.label}
            </button>)}
          <button type="button" className="dx-expand-btn" onClick={isAllExpanded() ? handleCollapseAll : handleExpandAll} title={isAllExpanded() ? UI.collapseAll : UI.expandAll}>
            {isAllExpanded() ? "⊟" : "⊞"}
          </button>
        </div>

        <div className="dx-tree" role="tree">
          {renderNodes(tree, activeScopeId, 0, "")}
        </div>
      </div>

      {}
      <div className="dx-right">
        {renderDetail()}
      </div>
    </div>;
};

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="en"
  items={[
"CLAUDE.md and .mcp.json live in the repo root, not inside .claude/ -- wrong location means Claude never reads them.",
"settings.local.json missing from .gitignore means your personal overrides get pushed to the whole team.",
"rules/ markdown files don't auto-load by path alone -- they need to be registered in settings.json rules paths.",
"Changing output style without /clear leaves the current session on the old style: the system prompt locks at session start.",
"A subagent without a memory: frontmatter entry has no agent-memory directory at all.",
"The three memory: scopes write to different directories -- confusing project / local / user means writing to the wrong place.",
"Copy-pasting .claude/ paths to other tools will burn you: Codex skills live in .agents/, not .codex/.",
]}
/>

<Info>
  **This page is the map for Part IV**

  Part IV (04-0 through 04-11) covers the entire customization layer of Claude Code. This page's job is to give you the full picture first: every file and folder under `.claude/`, what it does, when it loads, and whether to commit it. With this map in hand, the deep-dive units (04-1 through 04-11) become much easier to navigate.

  **Boundary with 02-6**: this page is the complete reference for Claude's own `.claude/` directory. [02-6](/en/code-agent/configuration/other-tools-comparison) is the cross-tool comparison (Claude vs Codex vs Antigravity vs Copilot). To find where a Codex equivalent lives, see 02-6. To understand what a file inside `.claude/` does, see this page.

  **Five topics without dedicated units**: output-styles, keybindings, themes, workflows, and agent-memory have no standalone unit in Part IV. Section 2 of this page covers them to an actionable level.
</Info>

## Learning objectives

* [ ] State the purpose, load timing, and commit status of every file and folder under `.claude/`.
* [ ] Distinguish the files that live in the project root (`CLAUDE.md`, `.mcp.json`, `.worktreeinclude`) from those inside `.claude/`.
* [ ] Configure output-styles, keybindings, and themes, and identify where workflows and agent-memory are stored.
* [ ] Map any file to its deep-dive unit and know where to look for details.

<Warning>
  **Timeliness notice**

  Directory structure and filenames verified as of 2026-06, sourced from the official interactive directory page at `code.claude.com/docs/zh-TW/claude-directory` \[1] and the corresponding topic pages. Claude Code changes frequently; treat the current official page as the authoritative reference before acting.
</Warning>

***

## Interactive directory explorer

Click any item on the left to see its purpose, load timing, and usage tips on the right. Switch between **Project** and **Global** tabs to view the project layer and user layer respectively.

<DirExplorer
  lang="en"
  scopes={[
{
  id: "project",
  label: "Project",
  tree: [
    {
      name: "CLAUDE.md",
      kind: "file",
      color: "blue",
      badge: "committed",
      detail: {
        breadcrumb: "(repo root) / CLAUDE.md",
        title: "CLAUDE.md",
        tagline: "Primary project instructions file, loaded in full at every session start",
        whenItLoads: "Loaded in full at every session start, alongside ~/.claude/CLAUDE.md. Project layer wins on conflict.",
        description: "Place project conventions, common commands, architecture context, and maintenance rules here. Can also be placed at .claude/CLAUDE.md (both locations are equivalent; official docs recommend the repo root). This is context, not enforced settings -- for enforced behavior use settings.json.",
        tips: [
          "Place in the repo root (not inside .claude/). Wrong location means Claude never reads it.",
          "Content beyond the context window gets truncated: put critical rules first, move details into rules/ files with paths: frontmatter for on-demand loading.",
          "Use @filename syntax to import other .md files, splitting a large CLAUDE.md into multiple managed files."
        ],
        example: {
          filename: "CLAUDE.md",
          code: `# My Project

## Common commands
- Install: \`npm install\`
- Test: \`npm test\`
- Build: \`npm run build\`

## Architecture context
src/api/ contains REST endpoints. src/domain/ contains pure business logic.
These two directories must not import from each other.

@.claude/rules/security.md`
        },
        mapsTo: "~/.claude/CLAUDE.md (personal cross-project instructions)"
      }
    },
    {
      name: "CLAUDE.local.md",
      kind: "file",
      color: "default",
      badge: "gitignored",
      detail: {
        breadcrumb: "(repo root) / CLAUDE.local.md",
        title: "CLAUDE.local.md",
        tagline: "Machine-private settings for this project, gitignored",
        whenItLoads: "Loaded at session start alongside CLAUDE.md, not committed to version control.",
        description: "Place machine-specific settings here: sandbox URLs, local test accounts, local paths. These should not be shared with the team, which is why the file is gitignored.",
        tips: [
          "Verify .gitignore contains CLAUDE.local.md, otherwise your personal settings get pushed to the whole team.",
          "Loaded alongside CLAUDE.md, not as a replacement -- both take effect simultaneously."
        ]
      }
    },
    {
      name: ".mcp.json",
      kind: "file",
      color: "purple",
      badge: "committed",
      detail: {
        breadcrumb: "(repo root) / .mcp.json",
        title: ".mcp.json",
        tagline: "Project-level MCP server configuration, shared with the team",
        whenItLoads: "Connection established at session start; tool schemas lazy-loaded by default.",
        description: "Defines the MCP servers used by this project. Once committed, the entire team shares the same configuration. Personal MCP servers (only you need them) go in ~/.claude.json, not here.",
        tips: [
          "Place in the repo root, not inside .claude/.",
          "Personal MCP servers go in the mcpServers field of ~/.claude.json -- do not push them into the project."
        ],
        example: {
          filename: ".mcp.json",
          code: `{
"mcpServers": {
"filesystem": {
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
}
}
}`
        },
        mapsTo: "~/.claude.json mcpServers field (personal MCP)"
      }
    },
    {
      name: ".worktreeinclude",
      kind: "file",
      color: "default",
      badge: "committed",
      detail: {
        breadcrumb: "(repo root) / .worktreeinclude",
        title: ".worktreeinclude",
        tagline: "List of gitignored files to copy when creating a git worktree",
        whenItLoads: "Read at git worktree creation time only.",
        description: "Uses .gitignore syntax to list gitignored files (e.g. .env) that should be copied from the main repo into each new worktree. This lets every worktree have its own copy of environment variables without manual copying.",
        tips: [
          "Only affects the git worktree creation workflow -- not read during normal sessions.",
          "Common use: .env is in .gitignore but worktrees need it; listing it here copies it automatically."
        ]
      }
    },
    {
      name: ".claude",
      kind: "dir",
      color: "blue",
      children: [
        {
          name: "settings.json",
          kind: "file",
          color: "gray",
          badge: "committed",
          detail: {
            breadcrumb: ".claude/ settings.json",
            title: "settings.json",
            tagline: "Project-shared enforced settings (not context -- actual execution rules)",
            whenItLoads: "Read at session start, merged with ~/.claude/settings.json. Arrays merge across layers; scalars take the nearest layer.",
            description: "Controls permissions (allow/deny list), hooks (PreToolUse / PostToolUse / Stop), default model, environment variables, statusLine, outputStyle, and more. Key difference from CLAUDE.md: settings here are enforced -- Claude cannot ignore them. CLAUDE.md is context; Claude usually follows it but could choose not to.",
            tips: [
              "Hooks go here: PostToolUse for auto-formatting, PreToolUse for safety checks, Stop for session-end verification.",
              "Deny list format: { \"permissions\": { \"deny\": [\"Bash(rm -rf *)\", \"Read(**/.env*)\"] } }",
              "settings.local.json can override this file personally and stays out of version control."
            ],
            example: {
              filename: ".claude/settings.json",
              code: `{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(git *)"],
"deny": ["Bash(rm -rf *)", "Read(**/.env*)"]
},
"hooks": {
"PostToolUse": [{
  "matcher": "Write|Edit",
  "hooks": [{ "type": "command", "command": "npx prettier --write $CLAUDE_TOOL_INPUT_FILE_PATH" }]
}]
},
"model": "claude-sonnet-4-5"
}`
            },
            mapsTo: "~/.claude/settings.json (global default, overridden by project layer)"
          }
        },
        {
          name: "settings.local.json",
          kind: "file",
          color: "default",
          badge: "gitignored",
          detail: {
            breadcrumb: ".claude/ settings.local.json",
            title: "settings.local.json",
            tagline: "Personal override for settings.json, gitignored",
            whenItLoads: "Read alongside settings.json; scalars take this layer (nearest wins), arrays merge across layers.",
            description: "Identical schema to settings.json, but gitignored. Use it for your personal overrides in this project. Permissions you approve during a session are automatically stored here -- not in settings.json.",
            tips: [
              "Must be in .gitignore: without that, approved personal permissions get pushed to the whole team.",
              "Tool permissions you approve during a session are automatically written here -- no need to edit it manually."
            ]
          }
        },
        {
          name: "rules",
          kind: "dir",
          color: "purple",
          children: [
            {
              name: "security.md",
              kind: "file",
              color: "purple",
              badge: "committed",
              detail: {
                breadcrumb: ".claude/rules/ security.md (example)",
                title: "rules/<name>.md",
                tagline: "Topic-scoped rule file, loaded on-demand or at session start",
                whenItLoads: "Without paths: frontmatter: loaded at session start like CLAUDE.md. With paths: frontmatter: loaded only when Claude reads a file matching the glob.",
                description: "Topic rules extracted from CLAUDE.md: security boundaries, coding style, testing requirements, commit format, and more. With paths: frontmatter, a rule only loads in the relevant context, reducing context consumption.",
                tips: [
                  "paths: frontmatter example: paths: ['src/api/**'] -- loads only when Claude reads something under src/api/.",
                  "Rules without paths: are loaded at session start like CLAUDE.md -- avoid putting long explanatory text here.",
                  "Rules are context, not enforced settings. To enforce behavior (deny lists, hooks) use settings.json."
                ],
                example: {
                  filename: ".claude/rules/security.md",
                  code: `---
description: Security rules: no reading .env, no writing credentials
paths: ["src/auth/**", "src/api/**"]
---

# Security rules

- Never read .env or any file that may contain secrets.
- Never write API keys or tokens as string literals in source code.
- Every new API endpoint must include an authentication middleware.`
                }
              }
            },
            {
              name: "<name>.md",
              kind: "file",
              color: "purple",
              detail: {
                breadcrumb: ".claude/rules/ <name>.md",
                title: "rules/*.md (naming convention)",
                tagline: "One file per topic, use semantic filenames",
                description: "Suggested names: house-style.md (typography), coding-standards.md (code), testing.md (tests), security.md (security), git-workflow.md (version control). No hard restrictions, but semantic names let maintainers identify scope at a glance.",
                tips: [
                  "Subdirectories are allowed: rules/frontend/react.md is fine.",
                  "Global layer (~/.claude/rules/) and project layer (.claude/rules/) both take effect simultaneously -- they are not mutually exclusive."
                ]
              }
            }
          ]
        },
        {
          name: "skills",
          kind: "dir",
          color: "yellow",
          children: [
            {
              name: "security-review",
              kind: "dir",
              color: "yellow",
              children: [
                {
                  name: "SKILL.md",
                  kind: "file",
                  color: "yellow",
                  badge: "committed",
                  detail: {
                    breadcrumb: ".claude/skills/security-review/ SKILL.md",
                    title: "SKILL.md (full example: security-review)",
                    tagline: "Skill invokable via /security-review or auto-triggered by Claude",
                    whenItLoads: "When you type /security-review, or when Claude determines from the description that it should be called.",
                    description: "Each skill is a subdirectory; SKILL.md is the entry point. The description frontmatter field determines when Claude auto-triggers the skill. The directory can include references/ (reference material) and scripts/ (helper scripts).",
                    tips: [
                      "Make description explicit: Claude uses this text to decide when to auto-trigger. Vague descriptions do not trigger.",
                      "references/ holds supporting documents Claude should consult when running the skill (checklists, templates).",
                      "scripts/ holds helper scripts (shell, Python) that SKILL.md can instruct Claude to run via the Bash tool."
                    ],
                    example: {
                      filename: ".claude/skills/security-review/SKILL.md",
                      code: `---
name: security-review
description: >
Triggered automatically when modifying authentication, authorization,
user input handling, database queries, or cryptographic operations.
Run /security-review explicitly for a full audit of the current diff.
---

# Security Review Skill

## Steps

1. Scan the diff for all changes touching auth / input / DB / crypto.
2. Check each change against the references/owasp-top10.md checklist.
3. Report findings at CRITICAL (must fix) / HIGH (should fix) / INFO (note) levels.
4. On a CRITICAL finding, stop and ask the user to confirm before continuing.`
                    }
                  }
                },
                {
                  name: "references",
                  kind: "dir",
                  color: "default",
                  detail: {
                    breadcrumb: ".claude/skills/security-review/ references/",
                    title: "references/ (optional)",
                    tagline: "Supporting material Claude consults when running the skill",
                    description: "Place checklists, templates, and standard documents here. Claude can Read these files during skill execution. Both references/ and scripts/ are optional -- only create them if the skill needs them."
                  }
                },
                {
                  name: "scripts",
                  kind: "dir",
                  color: "default",
                  detail: {
                    breadcrumb: ".claude/skills/security-review/ scripts/",
                    title: "scripts/ (optional)",
                    tagline: "Helper scripts the skill can invoke",
                    description: "Place shell scripts, Python scripts, and similar here. SKILL.md can instruct Claude to run them via the Bash tool, enabling automated operations (running linters, generating reports, etc.)."
                  }
                }
              ]
            },
            {
              name: "<skill-name>",
              kind: "dir",
              color: "yellow",
              detail: {
                breadcrumb: ".claude/skills/ <skill-name>/",
                title: "skills/<name>/ (naming convention)",
                tagline: "One subdirectory per skill; directory name becomes the command name",
                description: "The directory name determines the slash command: skills/add-content/ becomes /add-content. On name conflict, skills/ takes priority over single-file commands in commands/. Cross-project personal skills go in ~/.claude/skills/."
              }
            }
          ]
        },
        {
          name: "commands",
          kind: "dir",
          color: "green",
          children: [
            {
              name: "<name>.md",
              kind: "file",
              color: "green",
              badge: "committed",
              detail: {
                breadcrumb: ".claude/commands/ <name>.md",
                title: "commands/<name>.md",
                tagline: "Legacy single-file slash command; new workflows should prefer skills/",
                whenItLoads: "When you type /<name>.",
                description: "commands/ and skills/ share the same mechanism now; the only difference is structure: commands/ is a single .md file, skills/ is a subdirectory (can include references/ and scripts/). On name conflict, skills/ wins. New workflows should use skills/ directly; commands/ is for existing legacy commands.",
                tips: [
                  "If a command needs no supporting material or scripts, the single-file form in commands/ is sufficient.",
                  "skills/ wins on name conflict: if skills/foo/ exists, commands/foo.md will not be executed."
                ]
              }
            }
          ]
        },
        {
          name: "output-styles",
          kind: "dir",
          color: "teal",
          children: [
            {
              name: "<name>.md",
              kind: "file",
              color: "teal",
              badge: "committed",
              detail: {
                breadcrumb: ".claude/output-styles/ <name>.md",
                title: "output-styles/<name>.md",
                tagline: "Replaces or appends to the system prompt, adjusting Claude's work mode",
                whenItLoads: "Injected into the system prompt at session start (not reloaded mid-session; requires /clear to update).",
                description: "An output style is a block of text appended to the system prompt. By default it replaces Claude Code's built-in software-engineering task instructions, making it possible to repurpose Claude Code for non-coding tasks (teaching, review mode). Personal styles go in ~/.claude/output-styles/; project-shared styles go here.",
                tips: [
                  "keep-coding-instructions: true in frontmatter retains the built-in task instructions while adding your own rules.",
                  "After changing an output style, use /clear or open a new session: the system prompt locks at session start.",
                  "Activate via /config or by setting the outputStyle key in settings.json."
                ],
                example: {
                  filename: ".claude/output-styles/review-mode.md",
                  code: `---
name: Review mode
description: Explain design decisions after each task; leave small changes for the user to implement
keep-coding-instructions: true
---

After each task, add a paragraph explaining the key trade-offs in the design.
When a change is fewer than 10 lines, mark it TODO(human) and leave it for
the user to implement rather than writing it yourself.`
                }
              }
            }
          ]
        },
        {
          name: "agents",
          kind: "dir",
          color: "rose",
          children: [
            {
              name: "*.md",
              kind: "file",
              color: "rose",
              badge: "committed",
              detail: {
                breadcrumb: ".claude/agents/ *.md",
                title: "agents/*.md",
                tagline: "Subagent definition: isolated context, tool set, optional model override",
                whenItLoads: "When the Task tool is called, or when you explicitly invoke the subagent by name in conversation.",
                description: "Each .md file defines one subagent. Subagents run in an isolated context window with their own tool set and can specify a different model (e.g. haiku for lightweight tasks). The main session can launch multiple subagents in parallel.",
                tips: [
                  "Set model: claude-haiku-4-5 in frontmatter to reduce token cost for lightweight subagents.",
                  "The tools: field restricts which tools this subagent can use -- an important security boundary.",
                  "memory: project / local / user determines the subagent's memory scope (see Section 2.5)."
                ],
                example: {
                  filename: ".claude/agents/code-reviewer.md",
                  code: `---
name: code-reviewer
description: >
Run after writing or modifying any code. Reviews for correctness,
security issues, and code quality. Invoked automatically after edits.
model: claude-sonnet-4-5
tools: [Read, Grep, Glob]
---

# Code Reviewer

Review the most recent code changes and report issues at
CRITICAL / HIGH / MEDIUM severity levels.
Do not modify code directly -- provide specific, actionable suggestions.`
                }
              }
            }
          ]
        },
        {
          name: "workflows",
          kind: "dir",
          color: "rose",
          children: [
            {
              name: "*.js",
              kind: "file",
              color: "rose",
              badge: "committed",
              detail: {
                breadcrumb: ".claude/workflows/ *.js",
                title: "workflows/*.js",
                tagline: "Dynamic multi-agent coordination scripts; requires v2.1.154+",
                whenItLoads: "When you type /<name> (filename becomes command name); executes in the background.",
                description: "JavaScript scripts that run in the background at runtime to dynamically generate and coordinate tens to hundreds of subagents. Not hand-written: generated by running /workflows and pressing s to save. Each .js becomes a /<name> command. Project layer overrides personal layer (~/.claude/workflows/) on name conflict.",
                tips: [
                  "Requires Claude Code v2.1.154+; older versions do not have this feature.",
                  "To disable: use /config to toggle Dynamic workflows, set disableWorkflows: true in settings.json, or set CLAUDE_CODE_DISABLE_WORKFLOWS=1.",
                  "The built-in /deep-research is a workflow -- use it as a reference for the expected structure."
                ]
              }
            }
          ]
        },
        {
          name: "agent-memory",
          kind: "dir",
          color: "rose",
          children: [
            {
              name: "<agent-name>",
              kind: "dir",
              color: "rose",
              children: [
                {
                  name: "MEMORY.md",
                  kind: "file",
                  color: "rose",
                  badge: "committed",
                  detail: {
                    breadcrumb: ".claude/agent-memory/<agent>/ MEMORY.md",
                    title: "agent-memory/<agent>/MEMORY.md",
                    tagline: "Project-scoped persistent memory for a subagent (memory: project)",
                    whenItLoads: "Loaded at subagent start: first 200 lines, up to 25 KB.",
                    description: "Created and maintained automatically when a subagent has memory: project in its frontmatter. Stores information the subagent needs to remember across sessions. Completely separate from the main session's auto-memory (~/.claude/projects/<repo>/memory/MEMORY.md) -- do not confuse the two.",
                    tips: [
                      "You do not write this file manually -- the subagent maintains it.",
                      "memory: local writes to agent-memory-local/ (gitignored); memory: user writes to ~/.claude/agent-memory/ (cross-project).",
                      "Without memory: in the subagent's frontmatter, no memory directory is created at all."
                    ]
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
},
{
  id: "global",
  label: "Global ~/.claude",
  tree: [
    {
      name: ".claude.json",
      kind: "file",
      color: "gray",
      detail: {
        breadcrumb: "~/ .claude.json",
        title: ".claude.json",
        tagline: "App state, UI preferences, OAuth, personal MCP (managed by /config, not hand-edited)",
        whenItLoads: "Read at Claude Code startup; managed by the tool, not hand-edited.",
        description: "Stores app state, UI preferences (theme, language), OAuth session, per-project trust decisions, and personal MCP servers. Most fields are managed automatically by /config and Claude Code. IDE-switching flags (autoConnectIde etc.) live here; permissions approved during a session are stored in .claude/settings.local.json.",
        tips: [
          "Personal MCP servers (only you need them) go in the mcpServers field here -- do not push them into the project's .mcp.json.",
          "Use /config to manage this file. Manual edits can introduce format errors that prevent Claude Code from starting."
        ],
        mapsTo: "(no project-layer equivalent; this is global app state)"
      }
    },
    {
      name: ".claude",
      kind: "dir",
      color: "default",
      children: [
        {
          name: "CLAUDE.md",
          kind: "file",
          color: "blue",
          detail: {
            breadcrumb: "~/.claude/ CLAUDE.md",
            title: "~/.claude/CLAUDE.md",
            tagline: "Personal cross-project instructions, loaded alongside project CLAUDE.md",
            whenItLoads: "At every session start, alongside the project CLAUDE.md. Project layer wins on conflict.",
            description: "Place personal preferences and rules that apply to all your projects: preferred language, output format requirements, thinking principles, and similar. Project-layer CLAUDE.md is more specific and takes priority.",
            tips: [
              "Avoid secrets or machine-local paths here: the file is in your home directory and could be exposed if you back up dotfiles.",
              "Both this file and the project CLAUDE.md are loaded simultaneously; project layer wins on conflict."
            ]
          }
        },
        {
          name: "settings.json",
          kind: "file",
          color: "gray",
          detail: {
            breadcrumb: "~/.claude/ settings.json",
            title: "~/.claude/settings.json",
            tagline: "Global default settings applied to all projects",
            whenItLoads: "At session start; overridden by project-layer .claude/settings.json for matching keys.",
            description: "Global defaults: deny list, hooks, default model, and so on. Project-layer settings are more specific and take priority. Good for security boundaries that apply to every project (e.g. globally denying .env reads/writes).",
            tips: [
              "Array-type settings (such as hooks) merge across layers: both global hooks and project hooks take effect.",
              "Scalar values (such as model) use the nearest layer: project setting wins if set; otherwise falls back to this global value."
            ],
            mapsTo: ".claude/settings.json (project layer, higher priority)"
          }
        },
        {
          name: "keybindings.json",
          kind: "file",
          color: "gray",
          detail: {
            breadcrumb: "~/.claude/ keybindings.json",
            title: "keybindings.json",
            tagline: "Custom interactive CLI keybindings; requires v2.1.18+",
            whenItLoads: "Read at CLI startup; supports hot-reload (changes take effect immediately without restart).",
            description: "Rebinds keyboard shortcuts in the interactive CLI. Multiple context types (Chat, Autocomplete, Settings, etc.) can be configured independently. Set a binding to null to remove it. Chords (sequential keypresses separated by a space) are supported.",
            tips: [
              "Use /keybindings to create or open this file (with JSON schema attached) -- safer than writing it by hand.",
              "/doctor reports binding conflict warnings.",
              "Reserved keys that cannot be rebound: Ctrl+C, Ctrl+D, Ctrl+M, Caps Lock."
            ],
            example: {
              filename: "~/.claude/keybindings.json",
              code: `{
"bindings": [
{
  "context": "Chat",
  "bindings": {
    "ctrl+e": "chat:externalEditor",
    "ctrl+u": null
  }
}
]
}`
            }
          }
        },
        {
          name: "themes",
          kind: "dir",
          color: "teal",
          children: [
            {
              name: "<name>.json",
              kind: "file",
              color: "teal",
              detail: {
                breadcrumb: "~/.claude/themes/ <name>.json",
                title: "themes/<name>.json",
                tagline: "Custom CLI color theme: built-in base preset plus overrides",
                whenItLoads: "Read at session start; supports hot-reload.",
                description: "Define a custom theme by choosing a built-in base (light or dark) and providing color overrides. Create one interactively with /theme or write the JSON directly. After selecting a custom theme the preference is stored as custom:<slug>.",
                tips: [
                  "Use /theme to create interactively -- less error-prone than hand-writing JSON.",
                  "Hot-reload is supported: changes take effect without restarting the CLI."
                ],
                example: {
                  filename: "~/.claude/themes/dracula.json",
                  code: `{
"name": "Dracula",
"base": "dark",
"overrides": {
"claude": "#bd93f9",
"error": "#ff5555",
"success": "#50fa7b"
}
}`
                }
              }
            }
          ]
        },
        {
          name: "rules",
          kind: "dir",
          color: "purple",
          children: [
            {
              name: "*.md",
              kind: "file",
              color: "purple",
              detail: {
                breadcrumb: "~/.claude/rules/ *.md",
                title: "~/.claude/rules/*.md",
                tagline: "Cross-project personal rules, active alongside project rules",
                description: "Identical mechanism to .claude/rules/, but applies to all your projects. Good for cross-project personal standards: writing style, security boundaries, output preferences, and similar."
              }
            }
          ]
        },
        {
          name: "skills",
          kind: "dir",
          color: "yellow",
          children: [
            {
              name: "<name>/SKILL.md",
              kind: "file",
              color: "yellow",
              detail: {
                breadcrumb: "~/.claude/skills/ <name>/SKILL.md",
                title: "~/.claude/skills/<name>/SKILL.md",
                tagline: "Cross-project personal skill",
                description: "Identical mechanism to .claude/skills/, but active across all projects. Good for personal workflows used in many projects (code-review, research, debug, and similar)."
              }
            }
          ]
        },
        {
          name: "agents",
          kind: "dir",
          color: "rose",
          children: [
            {
              name: "*.md",
              kind: "file",
              color: "rose",
              detail: {
                breadcrumb: "~/.claude/agents/ *.md",
                title: "~/.claude/agents/*.md",
                tagline: "Cross-project personal subagent",
                description: "Identical mechanism to .claude/agents/, but active across all projects. Good for personal subagent definitions used in many projects (reviewers, researchers, and similar)."
              }
            }
          ]
        },
        {
          name: "projects",
          kind: "dir",
          color: "amber",
          children: [
            {
              name: "<repo-path>",
              kind: "dir",
              color: "amber",
              children: [
                {
                  name: "memory",
                  kind: "dir",
                  color: "amber",
                  children: [
                    {
                      name: "MEMORY.md",
                      kind: "file",
                      color: "amber",
                      badge: "autogen",
                      detail: {
                        breadcrumb: "~/.claude/projects/<repo>/memory/ MEMORY.md",
                        title: "~/.claude/projects/<repo>/memory/MEMORY.md",
                        tagline: "Main session auto-memory (v2.1.59+; first 200 lines or 25 KB at start)",
                        whenItLoads: "Loaded at every session start: first 200 lines, up to 25 KB. Requires v2.1.59+.",
                        description: "This is the main session's cross-session auto-memory, not a subagent memory file. Claude Code maintains this file itself, recording information worth remembering across sessions. You can read it, but avoid large manual rewrites (Claude's incremental update logic may break).",
                        tips: [
                          "The actual path is ~/.claude/projects/<hash-of-repo-path>/memory/MEMORY.md -- not a file inside your repo.",
                          "Completely separate from .claude/agent-memory/: this is main session memory, not subagent memory.",
                          "Reading is fine; avoid large manual rewrites, as Claude uses incremental updates and hand-edits may corrupt the format."
                        ]
                      }
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
]}
/>

***

## 1. Three location families

`.claude`-related files are spread across three places. Pinning this boundary first keeps everything below from sliding out of position:

| Family             | Location                                                              | Commit to VCS                            | Visible to                         |
| ------------------ | --------------------------------------------------------------------- | ---------------------------------------- | ---------------------------------- |
| Project root       | repo root directory (`CLAUDE.md`, `.mcp.json`, `.worktreeinclude`)    | mostly committed                         | team                               |
| Project `.claude/` | `.claude/` inside the repo                                            | mostly committed; `*.local.*` gitignored | team (personal overrides excepted) |
| User layer         | `~/.claude/` (Windows: `%USERPROFILE%\.claude\`) and `~/.claude.json` | not committed (machine-local)            | only you                           |

The most common mistake is treating `CLAUDE.md` and `.mcp.json` as files inside `.claude/`. They live in the **project root**, not in `.claude/` \[1].

## 2. Five topics without dedicated units

Units 04-1 through 04-11 each have a deep-dive page. The five items below are exceptions; this section covers them to an actionable level.

### 2.1 output-styles: rewriting the system prompt for a different mode

An output style is a block of text appended to the system prompt. By default it **replaces the built-in software-engineering task instructions**, making it possible to repurpose Claude Code for non-coding work (teaching, review mode) \[2].

* Four built-in styles: `Default`, `Proactive`, `Explanatory`, `Learning`.
* Custom styles: place at `~/.claude/output-styles/<name>.md` (personal) or `.claude/output-styles/` (project-shared). Frontmatter fields: `name`, `description`, `keep-coding-instructions` (defaults to `false`; set to `true` to keep the built-in task instructions), `force-for-plugin` (plugin-specific).
* To activate: use `/config` to select an output style, or set the `outputStyle` key in `settings.json`. The system prompt is locked at session start for caching purposes -- **a change requires `/clear` or a new session before it takes effect**.

### 2.2 keybindings: custom shortcuts

`~/.claude/keybindings.json` rebinds keys in the interactive CLI (requires v2.1.18+) \[3].

* Format: `{ "bindings": [{ "context": "Chat", "bindings": { "ctrl+e": "chat:externalEditor", "ctrl+u": null } }] }`. Setting a value to `null` removes the binding. Chords (sequential keypresses separated by a space) are supported.
* Context types include `Global`, `Chat`, `Autocomplete`, `Settings`, and others; a binding is scoped to its declared interface area.
* Reserved keys that cannot be rebound: `Ctrl+C`, `Ctrl+D`, `Ctrl+M`, `Caps Lock`.
* Use `/keybindings` to create or open the file (with schema attached); `/doctor` reports binding conflicts. Changes are auto-detected and hot-reloaded.

### 2.3 themes: custom colors

`~/.claude/themes/<name>.json` defines a theme as a built-in `base` preset plus a set of `overrides` color values \[1]. Create one interactively with `/theme` or write the JSON directly. After selecting a custom theme the preference is stored as `custom:<slug>`. Themes are read at session start and hot-reloaded.

```json theme={null}
{
  "name": "Dracula",
  "base": "dark",
  "overrides": { "claude": "#bd93f9", "error": "#ff5555", "success": "#50fa7b" }
}
```

### 2.4 workflows: dynamic multi-agent scripts

`.claude/workflows/<name>.js` (project) or `~/.claude/workflows/` (personal) are JavaScript scripts that run in the background at runtime to generate and coordinate tens to hundreds of subagents. Requires Claude Code v2.1.154+ \[1, 4]. These files are not hand-written; they are generated by running `/workflows` and pressing `s` to save (the built-in `/deep-research` is a ready-made example). Each `.js` becomes a `/<name>` command; project-layer files override personal-layer files of the same name. To disable: use `/config` to toggle Dynamic workflows, set `disableWorkflows: true` in `settings.json`, or set the environment variable `CLAUDE_CODE_DISABLE_WORKFLOWS=1` \[4].

### 2.5 agent-memory: persistent memory for subagents

A subagent only gets a dedicated memory directory when `memory:` is set in its frontmatter. The write destination depends on the scope \[1]:

| frontmatter       | Write location                           | Committed     | Scope                      |
| ----------------- | ---------------------------------------- | ------------- | -------------------------- |
| `memory: project` | `.claude/agent-memory/<agent>/MEMORY.md` | committed     | team-shared                |
| `memory: local`   | `.claude/agent-memory-local/`            | gitignored    | this machine, this project |
| `memory: user`    | `~/.claude/agent-memory/`                | machine-local | cross-project              |

The mechanism mirrors main session auto-memory: the subagent reads and writes its own file; the first 200 lines (up to 25 KB) are loaded at start. You do not write to this file manually.

## 3. Hands-on: audit your `.claude/`

<Steps>
  <Step title="List what you have">
    Run `ls -la .claude/` and `ls -la ~/.claude/` in a project you use regularly. Compare against the interactive explorer above and note which items you already have and which you have not yet used.
  </Step>

  <Step title="Check your .gitignore">
    For each file present, ask: should this be committed? `settings.local.json`, `CLAUDE.local.md`, and `agent-memory-local/` must be in `.gitignore`. Missing entries push personal settings to your team.
  </Step>

  <Step title="Try one personalization feature">
    Pick one personalization area you have not used: run `/theme` to create a theme, or `/keybindings` to bind a frequently used key, then confirm hot-reload works.
  </Step>

  <Step title="Check your output style">
    Run `/config` to see the current output style. If you regularly do non-coding work (review, teaching), try switching to a built-in style.
  </Step>
</Steps>

## 4. Common pitfalls

<Warning>
  **Anti-pattern list**

  * **Treating `CLAUDE.md` / `.mcp.json` as files inside `.claude/`**: they belong in the project root. Wrong location means Claude never reads them.
  * **Missing gitignore for personal-layer files**: once `settings.local.json`, `CLAUDE.local.md`, or `.claude/agent-memory-local/` are committed, your personal overrides and local memory go to the whole team.
  * **Assuming output style or theme changes take effect immediately**: the system prompt is locked at session start; a change requires `/clear` or a new session.
  * **Conflating subagent memory with main session memory**: they use different directories and different scopes. Without a `memory:` frontmatter entry, a subagent has no memory directory at all.
  * **Copy-pasting `.claude/` paths to other tools**: the structure does not transfer verbatim to Codex or Antigravity. Look up each entry in [02-6](/en/code-agent/configuration/other-tools-comparison).
</Warning>

## Self-check

<Check>
  **The bar for passing this unit**

  1. Given any filename under `.claude/`, can you state its purpose, when it loads, whether to commit it, and which unit covers it in depth?
  2. Can you name the three files that live in the project root rather than inside `.claude/`?
  3. Do you know the config file location and the moment a change takes effect for output styles, keybindings, and themes?
  4. Where do the three `memory:` scopes for a subagent each write to, and which one gets committed?
</Check>

## Sources and further reading

Factual claims are grounded in official documentation; fast-changing items are annotated as of 2026-06.

<div className="references">
  * \[1] Anthropic, "Explore the .claude directory" (interactive file reference listing location, load timing, commit status, and examples for each entry), Claude Code Docs. Accessed: 2026-06. \[Online]. Available: [https://code.claude.com/docs/zh-TW/claude-directory](https://code.claude.com/docs/zh-TW/claude-directory) (as of 2026-06)

  * \[2] Anthropic, "Output styles" (four built-in styles, custom frontmatter fields, `outputStyle` setting, and when changes take effect), Claude Code Docs. Accessed: 2026-06. \[Online]. Available: [https://code.claude.com/docs/en/output-styles](https://code.claude.com/docs/en/output-styles) (as of 2026-06)

  * \[3] Anthropic, "Keybindings" (`~/.claude/keybindings.json`, context and action fields, chords, reserved keys), Claude Code Docs. Accessed: 2026-06. \[Online]. Available: [https://code.claude.com/docs/en/keybindings](https://code.claude.com/docs/en/keybindings) (as of 2026-06)

  * \[4] Anthropic, "Orchestrate subagents at scale with dynamic workflows" (`.claude/workflows/*.js` runtime background execution, generating and coordinating tens to hundreds of subagents, saved from `/workflows` with `s`, each file becomes `/<name>`, project overrides personal, requires v2.1.154+, disabled via `disableWorkflows` or `CLAUDE_CODE_DISABLE_WORKFLOWS=1`), Claude Code Docs. Accessed: 2026-06. \[Online]. Available: [https://code.claude.com/docs/en/workflows](https://code.claude.com/docs/en/workflows) (as of 2026-06)
</div>

* Deep-dive units: [02-3 settings.json](/en/code-agent/configuration/settings-json), [02-4 claude.json](/en/code-agent/configuration/claude-json), [04-1 CLAUDE.md and memory](/en/code-agent/customization/claude-md-memory), [04-2 rules](/en/code-agent/customization/rules), [04-3 commands](/en/code-agent/customization/commands), [04-4 skills](/en/code-agent/customization/skills), [04-5 subagents](/en/code-agent/customization/subagents), [04-6 hooks](/en/code-agent/customization/hooks), [04-9 MCP integration](/en/code-agent/customization/mcp-integration).
* Tool directory equivalents: [02-6 other tools comparison](/en/code-agent/configuration/other-tools-comparison).
