> ## 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.

# 02-1 The Configuration Layer Model

> Build a two-axis coordinate system of scope and setting type so you can instantly judge any AI coding tool's configuration file: its precedence, merge semantics, and version-control strategy.

export const ScopeFilePicker = ({lang = "zh"}) => {
  const t = {
    zh: {
      kindLabel: "設定種類",
      scopeLabel: "作用範圍",
      kinds: ["個人化", "記憶", "規則 / 指令", "隱私", "權限", "自動化"],
      scopes: ["使用者", "專案", "本地"],
      resultTitle: "放哪裡？",
      vcsLabel: "版控",
      commit: "提交（團隊共享）",
      gitignore: "gitignore（個人）",
      hint: "選擇種類與範圍，查看應寫入的檔案",
      examples: {
        "個人化-使用者": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "跨所有專案的語言偏好、語氣、輸出格式。只影響你自己，不污染團隊。"
        },
        "個人化-專案": {
          file: "./CLAUDE.md",
          vcs: "commit",
          note: "通常不建議把純個人偏好放進專案層，除非是全隊共識的格式規範。"
        },
        "個人化-本地": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "個人沙箱 URL、本地路徑、測試資料偏好，只有你看得到。"
        },
        "記憶-使用者": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "跨 session 持久化的個人事實與偏好。"
        },
        "記憶-專案": {
          file: "./CLAUDE.md 或 .claude/rules/",
          vcs: "commit",
          note: "專案共用的背景知識（架構說明、領域詞彙）。"
        },
        "記憶-本地": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "個人本地記憶覆寫，不進版控。"
        },
        "規則 / 指令-使用者": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "跨所有專案生效的個人慣例，例如：永遠用台灣繁中回覆。"
        },
        "規則 / 指令-專案": {
          file: "./CLAUDE.md 或 .claude/rules/*.md",
          vcs: "commit",
          note: "團隊共用的程式碼風格規約、專案約束。全隊共享，放這裡。"
        },
        "規則 / 指令-本地": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "個人覆寫規則，例如本地測試用的特殊約束。"
        },
        "隱私-使用者": {
          file: "~/.claude/settings.json",
          vcs: "gitignore",
          note: "訓練退出、資料保留期限等隱私設定。個人層，不進版控。"
        },
        "隱私-專案": {
          file: ".claude/settings.json",
          vcs: "commit",
          note: "少見：若整個專案有統一的資料處理政策，可放這裡，但通常是個人設定。"
        },
        "隱私-本地": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "本地個人隱私設定覆寫。"
        },
        "權限-使用者": {
          file: "~/.claude/settings.json",
          vcs: "gitignore",
          note: "你個人跨所有專案的 allow / ask / deny 規則基線。"
        },
        "權限-專案": {
          file: ".claude/settings.json",
          vcs: "commit",
          note: "這個專案全隊共用的權限規則，例如：deny 讀取 .env、ask git push。"
        },
        "權限-本地": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "個人本地權限覆寫，高於專案層、低於 CLI 參數。密鑰相關設定放這裡。"
        },
        "自動化-使用者": {
          file: "~/.claude/settings.json (hooks/skills)",
          vcs: "gitignore",
          note: "跨所有專案生效的個人 hook 或 skill，例如全域 PostToolUse 日誌 hook。"
        },
        "自動化-專案": {
          file: ".claude/settings.json + .claude/skills/",
          vcs: "commit",
          note: "這個專案專屬的 hook 與 skill，全隊共享，版本化管理。"
        },
        "自動化-本地": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "個人本地的 hook 覆寫，例如本機除錯用的額外日誌。"
        }
      }
    },
    en: {
      kindLabel: "Setting type",
      scopeLabel: "Scope",
      kinds: ["Personalization", "Memory", "Rules / Instructions", "Privacy", "Permissions", "Automation"],
      scopes: ["User", "Project", "Local"],
      resultTitle: "Where does it go?",
      vcsLabel: "Version control",
      commit: "Commit (shared with team)",
      gitignore: "gitignore (personal only)",
      hint: "Pick a type and scope to see the target file",
      examples: {
        "Personalization-User": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "Language preference, tone, output format for all your projects. Affects only you, does not pollute the team."
        },
        "Personalization-Project": {
          file: "./CLAUDE.md",
          vcs: "commit",
          note: "Generally avoid putting purely personal preferences in the project layer, unless it is a formatting convention the whole team agrees on."
        },
        "Personalization-Local": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "Personal sandbox URLs, local paths, test data preferences visible only to you."
        },
        "Memory-User": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "Personal facts and preferences persisted across sessions."
        },
        "Memory-Project": {
          file: "./CLAUDE.md or .claude/rules/",
          vcs: "commit",
          note: "Shared project background knowledge: architecture notes, domain vocabulary."
        },
        "Memory-Local": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "Personal local memory overrides, not committed."
        },
        "Rules / Instructions-User": {
          file: "~/.claude/CLAUDE.md",
          vcs: "gitignore",
          note: "Personal conventions active across all projects, e.g. always reply in Traditional Chinese."
        },
        "Rules / Instructions-Project": {
          file: "./CLAUDE.md or .claude/rules/*.md",
          vcs: "commit",
          note: "Team-shared coding style conventions and project constraints. This is the right place."
        },
        "Rules / Instructions-Local": {
          file: "./CLAUDE.local.md",
          vcs: "gitignore",
          note: "Personal rule overrides, e.g. special constraints for local testing."
        },
        "Privacy-User": {
          file: "~/.claude/settings.json",
          vcs: "gitignore",
          note: "Training opt-out, data retention period, and other privacy settings. Personal, not committed."
        },
        "Privacy-Project": {
          file: ".claude/settings.json",
          vcs: "commit",
          note: "Rare: use when the whole project has a unified data handling policy; usually a personal setting."
        },
        "Privacy-Local": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "Local personal privacy setting overrides."
        },
        "Permissions-User": {
          file: "~/.claude/settings.json",
          vcs: "gitignore",
          note: "Your personal allow / ask / deny baseline across all projects."
        },
        "Permissions-Project": {
          file: ".claude/settings.json",
          vcs: "commit",
          note: "Team-shared permission rules for this project, e.g. deny reading .env, ask before git push."
        },
        "Permissions-Local": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "Personal local permission overrides; higher priority than project layer, lower than CLI args. Put secret-related settings here."
        },
        "Automation-User": {
          file: "~/.claude/settings.json (hooks/skills)",
          vcs: "gitignore",
          note: "Personal hooks or skills active across all projects, e.g. a global PostToolUse logging hook."
        },
        "Automation-Project": {
          file: ".claude/settings.json + .claude/skills/",
          vcs: "commit",
          note: "Project-specific hooks and skills shared with the team, version-controlled."
        },
        "Automation-Local": {
          file: ".claude/settings.local.json",
          vcs: "gitignore",
          note: "Personal local hook overrides, e.g. extra debug logging on your machine."
        }
      }
    }
  };
  const ui = t[lang] || t["zh"];
  const [selectedKind, setSelectedKind] = useState(null);
  const [selectedScope, setSelectedScope] = useState(null);
  const resultKey = selectedKind && selectedScope ? `${selectedKind}-${selectedScope}` : null;
  const result = resultKey ? ui.examples[resultKey] : null;
  const isCommit = result && result.vcs === "commit";
  const css = `
    .sfp-root {
      --sfp-accent: #bf7551;
      --sfp-accent-light: #cf8a68;
      --sfp-bg: #faf8f4;
      --sfp-card: #f3efe8;
      --sfp-border: #d9c9b4;
      --sfp-text: #2d2418;
      --sfp-muted: #7a6a57;
      --sfp-commit: #3b6b3b;
      --sfp-commit-bg: #eaf3ea;
      --sfp-gitignore: #5a3f6b;
      --sfp-gitignore-bg: #f0eaf5;
      font-family: inherit;
      border: 1px solid var(--sfp-border);
      border-radius: 10px;
      background: var(--sfp-bg);
      padding: 1.25rem 1.5rem 1.5rem;
      max-width: 640px;
    }
    .dark .sfp-root {
      --sfp-bg: #1e1a16;
      --sfp-card: #2a2420;
      --sfp-border: #4a3e30;
      --sfp-text: #e8ddd0;
      --sfp-muted: #a08870;
      --sfp-commit: #7ec87e;
      --sfp-commit-bg: #1a2e1a;
      --sfp-gitignore: #c8a8e8;
      --sfp-gitignore-bg: #1e1428;
    }
    .sfp-hint {
      font-size: 0.82rem;
      color: var(--sfp-muted);
      margin-bottom: 1rem;
    }
    .sfp-row {
      display: flex;
      gap: 1.25rem;
      flex-wrap: wrap;
      margin-bottom: 1rem;
    }
    .sfp-col {
      flex: 1;
      min-width: 160px;
    }
    .sfp-col-label {
      font-size: 0.75rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.06em;
      color: var(--sfp-muted);
      margin-bottom: 0.45rem;
    }
    .sfp-chips {
      display: flex;
      flex-direction: column;
      gap: 0.35rem;
    }
    .sfp-chip {
      padding: 0.38rem 0.8rem;
      border-radius: 6px;
      border: 1.5px solid var(--sfp-border);
      background: var(--sfp-card);
      color: var(--sfp-text);
      font-size: 0.83rem;
      cursor: pointer;
      text-align: left;
      transition: border-color 0.15s, background 0.15s;
    }
    .sfp-chip:hover {
      border-color: var(--sfp-accent-light);
    }
    .sfp-chip.active {
      border-color: var(--sfp-accent);
      background: var(--sfp-accent);
      color: #fff;
    }
    .sfp-result {
      margin-top: 0.75rem;
      border: 1.5px solid var(--sfp-border);
      border-radius: 8px;
      background: var(--sfp-card);
      padding: 0.9rem 1.1rem;
      animation: sfp-fadein 0.18s ease;
    }
    @keyframes sfp-fadein { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
    .sfp-result-title {
      font-size: 0.72rem;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.07em;
      color: var(--sfp-muted);
      margin-bottom: 0.35rem;
    }
    .sfp-file {
      font-family: monospace;
      font-size: 0.88rem;
      font-weight: 600;
      color: var(--sfp-accent);
      margin-bottom: 0.55rem;
      word-break: break-all;
    }
    .sfp-vcs {
      display: inline-block;
      padding: 0.2rem 0.65rem;
      border-radius: 4px;
      font-size: 0.76rem;
      font-weight: 600;
      margin-bottom: 0.55rem;
    }
    .sfp-vcs.commit {
      background: var(--sfp-commit-bg);
      color: var(--sfp-commit);
    }
    .sfp-vcs.gitignore {
      background: var(--sfp-gitignore-bg);
      color: var(--sfp-gitignore);
    }
    .sfp-note {
      font-size: 0.82rem;
      color: var(--sfp-muted);
      line-height: 1.55;
    }
    .sfp-placeholder {
      color: var(--sfp-muted);
      font-size: 0.84rem;
      padding: 0.5rem 0;
      text-align: center;
    }
    @media (max-width: 480px) {
      .sfp-row { flex-direction: column; gap: 0.85rem; }
    }
  `;
  return <div className="sfp-root">
      <style>{css}</style>
      <div className="sfp-hint">{ui.hint}</div>
      <div className="sfp-row">
        <div className="sfp-col">
          <div className="sfp-col-label">{ui.kindLabel}</div>
          <div className="sfp-chips">
            {ui.kinds.map(k => <button key={k} className={"sfp-chip" + (selectedKind === k ? " active" : "")} onClick={() => setSelectedKind(selectedKind === k ? null : k)}>
                {k}
              </button>)}
          </div>
        </div>
        <div className="sfp-col">
          <div className="sfp-col-label">{ui.scopeLabel}</div>
          <div className="sfp-chips">
            {ui.scopes.map(s => <button key={s} className={"sfp-chip" + (selectedScope === s ? " active" : "")} onClick={() => setSelectedScope(selectedScope === s ? null : s)}>
                {s}
              </button>)}
          </div>
        </div>
      </div>
      <div className="sfp-result">
        {result ? <>
            <div className="sfp-result-title">{ui.resultTitle}</div>
            <div className="sfp-file">{result.file}</div>
            <div className={"sfp-vcs " + result.vcs}>
              {result.vcs === "commit" ? ui.commit : ui.gitignore}
            </div>
            <div className="sfp-note">{result.note}</div>
          </> : <div className="sfp-placeholder">{ui.hint}</div>}
      </div>
    </div>;
};

export const ArchFlow = ({nodes = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    flow: "Data flow",
    hint: "Click any stage to see what it does",
    stage: "Stage"
  } : {
    flow: "資料流",
    hint: "點任一階段看它做什麼",
    stage: "階段"
  };
  const safe = Array.isArray(nodes) ? nodes : [];
  const [active, setActive] = useState(0);
  if (safe.length === 0) return null;
  const idx = Math.min(active, safe.length - 1);
  const current = safe[idx];
  const css = `
  .af-root{--af-bg:#FAF8F3;--af-surface:rgba(191,117,81,0.06);--af-surface2:rgba(0,0,0,0.025);--af-border:rgba(0,0,0,0.09);--af-text:#2b2722;--af-dim:#6f6a62;--af-faint:#8a8378;--af-rail:rgba(0,0,0,0.12);--af-accent:#bf7551;border:1px solid var(--af-border);border-radius:14px;background:var(--af-bg);color:var(--af-text);overflow:hidden;}
  .dark .af-root{--af-bg:#1b1a18;--af-surface:rgba(207,138,104,0.09);--af-surface2:rgba(255,255,255,0.03);--af-border:rgba(255,255,255,0.08);--af-text:#e7e3da;--af-dim:#a8a299;--af-faint:#8a8378;--af-rail:rgba(255,255,255,0.13);--af-accent:#cf8a68;}
  .af-head{padding:13px 18px 11px;display:flex;align-items:center;gap:9px;flex-wrap:wrap;border-bottom:1px solid var(--af-border);}
  .af-head-ic{color:var(--af-accent);flex-shrink:0;}
  .af-head-t{font-size:12px;font-weight:700;letter-spacing:.6px;color:var(--af-dim);text-transform:uppercase;}
  .af-head-h{font-size:12px;color:var(--af-faint);}
  .af-grid{display:flex;gap:0;align-items:stretch;}
  .af-list{flex:1 1 0;min-width:0;padding:12px 12px 16px;}
  .af-node{display:flex;align-items:stretch;gap:10px;width:100%;text-align:left;background:transparent;border:none;cursor:pointer;padding:0;color:inherit;font:inherit;-webkit-tap-highlight-color:transparent;}
  .af-railcol{width:22px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;}
  .af-dot{width:9px;height:9px;border-radius:50%;margin-top:14px;background:var(--af-faint);opacity:.5;flex-shrink:0;transition:background .15s,box-shadow .15s,opacity .15s;}
  .af-line{width:2px;flex:1 1 0;background:var(--af-rail);min-height:10px;}
  .af-body{flex:1 1 0;min-width:0;padding:9px 12px;margin:2px 0;border-radius:9px;border:1px solid transparent;transition:background .15s,border-color .15s;}
  .af-node:hover .af-body{background:var(--af-surface2);}
  .af-node-on .af-body{background:var(--af-surface);border-color:rgba(191,117,81,.30);}
  .af-node-on .af-dot{background:var(--af-accent);opacity:1;box-shadow:0 0 0 4px rgba(191,117,81,.15);}
  .af-label{font-size:14.5px;font-weight:550;line-height:1.45;}
  .af-node-on .af-label{color:var(--af-accent);}
  .af-detail{width:300px;flex-shrink:0;border-left:1px solid var(--af-border);padding:16px 18px;background:var(--af-surface2);}
  .af-detail-k{font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--af-accent);margin-bottom:7px;}
  .af-detail-l{font-size:16px;font-weight:600;margin-bottom:9px;line-height:1.35;}
  .af-detail-d{font-size:13.5px;line-height:1.65;color:var(--af-dim);}
  @media (max-width:640px){.af-grid{flex-direction:column;}.af-detail{width:auto;border-left:none;border-top:1px solid var(--af-border);}}
  `;
  return <div className="af-root">
      <style>{css}</style>
      <div className="af-head">
        <svg className="af-head-ic" xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect width="8" height="8" x="3" y="3" rx="2" /><path d="M7 11v4a2 2 0 0 0 2 2h4" /><rect width="8" height="8" x="13" y="13" rx="2" /></svg>
        <span className="af-head-t">{t.flow}</span>
        <span className="af-head-h">{t.hint}</span>
      </div>
      <div className="af-grid">
        <div className="af-list">
          {safe.map((n, i) => <button key={i} type="button" className={"af-node" + (i === idx ? " af-node-on" : "")} onClick={() => setActive(i)} onMouseEnter={() => setActive(i)}>
              <div className="af-railcol">
                <div className="af-dot" />
                {i < safe.length - 1 && <div className="af-line" />}
              </div>
              <div className="af-body">
                <div className="af-label">{n.label}</div>
              </div>
            </button>)}
        </div>
        <div className="af-detail">
          <div className="af-detail-k">{t.stage} {idx + 1} / {safe.length}</div>
          <div className="af-detail-l">{current.label}</div>
          <div className="af-detail-d">{current.detail}</div>
        </div>
      </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={[
"Settings have three semantics: override, concatenate, merge. Don't treat them as the same.",
"You think the user-layer CLAUDE.md gets overridden by the project layer? Both are read.",
"Write your personal language preference into ./CLAUDE.md and you pollute the whole team.",
"An API key in settings.json is the same as pasting it on GitHub.",
"A deny rule overridden by a lower-layer allow? That can't happen.",
"'I clearly set this, why isn't it working?' -- nine times out of ten a closer layer covered it.",
"Pick the wrong scope axis and your next commit is a secret leak.",
]}
/>

<Info>
  **What this unit solves**

  Before learning any tool's configuration details, build a universal coordinate system first. Grasp the two axes -- scope and setting type -- and you can immediately judge where any configuration file belongs, whether it will be overridden by something else, and whether it should be committed to version control.
</Info>

## Learning objectives

* [ ] Use the scope axis (managed, user, project, local) to describe the effective range of any setting.
* [ ] Use the setting-type axis (personalization, memory, rules, privacy, permissions, automation) to classify any configuration item.
* [ ] Explain the override precedence order and distinguish the three distinct layer semantics: override, concatenate, and merge.
* [ ] Correctly identify which configuration files should be committed (team-shared) and which should be gitignored (personal).

***

## 1. First axis: scope

The same setting can appear at different scopes; which one takes effect depends on precedence. Using Claude Code as the primary reference, five layers from highest to lowest (as of 2026-05 official documentation \[1]):

<ArchFlow
  lang="en"
  nodes={[
{
  label: "Managed policy",
  detail: "Deployed by an enterprise via MDM or Group Policy. Cannot be overridden by any lower layer. macOS: /Library/Application Support/ClaudeCode/managed-settings.json; Linux/WSL: /etc/claude-code/managed-settings.json; Windows: C:\\Program Files\\ClaudeCode\\managed-settings.json.",
},
{
  label: "CLI arguments / session",
  detail: "Temporary overrides for the current run, higher priority than all persisted settings. Effective only for the duration of the session.",
},
{
  label: "Local (personal)",
  detail: ".claude/settings.local.json, ./CLAUDE.local.md. Already gitignored; only you can see it. Not shared with anyone.",
},
{
  label: "Project",
  detail: ".claude/settings.json, ./CLAUDE.md (or ./.claude/CLAUDE.md). Committed to version control; shared with the whole team. The right place for team conventions and constraints.",
},
{
  label: "User",
  detail: "~/.claude/settings.json, ~/.claude/CLAUDE.md. Your personal preference baseline, applied to all projects on your machine.",
},
]}
/>

<Tip>
  **One rule to remember**

  "The closer a setting is to the current task, the higher its precedence." Managed policy is the only exception that flows top-down and cannot be overridden -- that is for IT administration. The remaining four layers all obey "closer wins."
</Tip>

### Three layer semantics: override vs concatenate vs merge

This is the biggest misconception people have about "layers": **not all settings use "higher layer overrides lower layer."** Claude Code has at least three distinct merge behaviors. Mixing up these mental models costs a great deal of debug time (\[1]\[2]):

| Semantic        | Applies to                             | Behavior                                                                                                                                                                                                |
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Override**    | The same key in `settings.json`        | The higher-priority layer's value replaces the lower layer's; only one value takes effect                                                                                                               |
| **Concatenate** | `CLAUDE.md` / memory rule files        | All layers are **loaded in full** without overriding each other; spliced into context in root-to-current-directory order                                                                                |
| **Merge**       | `permissions` allow / ask / deny rules | Rule arrays are **concatenated and deduplicated** across layers into one set; evaluated in `deny, ask, allow` order; the first matching rule wins; **`deny` cannot be unlocked by any layer's `allow`** |

In other words: your `~/.claude/CLAUDE.md` and the project's `./CLAUDE.md` **do not override each other** -- both are read (user layer first, project layer second). But for the same key in `~/.claude/settings.json` and `.claude/settings.json`, the higher-priority layer wins. Treating these two situations as identical is the root cause of confusion like "I clearly set this at the user layer, why does the project behave differently?"

## 2. Second axis: setting type

Scope determines "where it takes effect"; type determines "what it controls." Six types:

* **Personalization**: role, language, tone, output format.
* **Memory**: facts and preferences persisted across sessions (short-term vs long-term covered in [01-4](/en/code-agent/foundations/context-engineering)).
* **Rules / instructions**: project conventions and constraints (`CLAUDE.md`, `AGENTS.md`, `.claude/rules/`).
* **Privacy**: training opt-out, retention period, temporary conversations.
* **Permissions**: which tools can execute, which paths can be read or written (allow / ask / deny).
* **Automation**: skills, hooks, workflows.

Cross the two axes and any configuration item maps to exactly one cell: a rule is "rules type x some scope," a permission is "permissions type x some scope."

## 3. Two axes combined: decision tool

Treat "type x scope" as a matrix. Every time you need to place a setting, pick these two axes first -- the result determines which file it goes in and whether to commit it.

<ScopeFilePicker lang="en" />

<Note>
  **Three settings, three locations**

  1. **Team-shared coding style conventions**: rules type x project scope -- write into `./CLAUDE.md`, **commit to version control**, shared with the team.
  2. **Your personal sandbox URL and preferred test data**: personalization / rules type x local scope -- write into `./CLAUDE.local.md`, **add to `.gitignore`**, only you can see it, does not pollute the team.
  3. **Your cross-project language preference (always reply in Traditional Chinese)**: personalization type x user scope -- write into `~/.claude/CLAUDE.md`, applied to every project on your machine.

  All three are "rules / personalization" type; the only difference is scope, and scope directly determines "commit or gitignore, who can see it." That is the two-axis coordinate system in practice: fix the type, fix the scope, and the file location and version-control strategy fall out automatically.
</Note>

<Warning>
  **When the same key appears at multiple layers, decide first: override or concatenate**

  If you set `model` in `~/.claude/settings.json` and also set a different `model` in `.claude/settings.json`, the **project layer wins** (override; closer wins). But if you write style rules in both `~/.claude/CLAUDE.md` and `./CLAUDE.md`, **both take effect** (concatenate). When they conflict, Claude may follow either one, so do not let rules at two layers contradict each other.
</Warning>

## 4. Commit vs gitignore (critical practice)

The most direct version-control consequence of the scope axis is this binary:

* **Commit (version control, team-shared)**: rules and settings the whole team should follow consistently. `./CLAUDE.md`, `.claude/settings.json`, `.claude/rules/`, `AGENTS.md`.
* **gitignore (personal, not shared)**: personal overrides, secrets, local paths. `./CLAUDE.local.md`, `.claude/settings.local.json`, anything containing tokens.

This is the same mental model as `.env` vs `.env.example`: the shareable template goes into version control; the instance that contains secrets stays local. The test is simple: **if a teammate applied this setting, would it help them or leak something about you?** If it helps them, commit it; if it leaks you, gitignore it.

<Warning>
  **Secrets never go in a file that will be committed**

  The most common and most expensive mistake: writing an API key or token into `.claude/settings.json` (which is committed) instead of `settings.local.json` (gitignored). Once pushed to a remote, it is effectively public. Secrets, local absolute paths, and personal sandbox addresses always go in the local layer.
</Warning>

## 5. Mapping any new tool to this model

The value of this coordinate system is that it works across tools. When you encounter an unfamiliar tool, answer these five questions in order and you understand its configuration surface without reading the entire documentation:

<Steps>
  <Step title="Where is the user-level configuration?">
    Which file or directory holds personal preferences that apply to all your projects?
  </Step>

  <Step title="Which file is the project-level rules file?">
    Which file is committed to version control and takes effect for the whole team?
  </Step>

  <Step title="Is there a local override layer?">
    Is there a gitignored personal configuration entry point?
  </Step>

  <Step title="Where is the privacy / training opt-out toggle?">
    How do you opt out of data training or set a data retention period?
  </Step>

  <Step title="How are permissions controlled?">
    Can you restrict what the tool reads, writes, and executes? Where are deny / ask / allow configured?
  </Step>
</Steps>

Answer all five and you can start using it safely, rather than discovering "I set this and it did nothing" or "I accidentally committed a secret" after the fact.

## Tool comparison

Configuration layer mapping across vendors (as of 2026-05; exact filenames and mechanisms are subject to each vendor's current documentation; per-item details in [02-2](/en/code-agent/configuration/anthropic-claude-setup) and [02-6](/en/code-agent/configuration/other-tools-comparison)):

| Scope          | Anthropic Claude (primary)                  | OpenAI Codex                                                 | Google Antigravity                                                   | GitHub Copilot CLI                                                                            | Cursor                                          |
| -------------- | ------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| User level     | `~/.claude/` (`settings.json`, `CLAUDE.md`) | `~/.codex/config.toml`                                       | `~/.gemini/` (`GEMINI.md`, `AGENTS.md`)                              | `~/.copilot/copilot-instructions.md` (single file)                                            | User Rules (GUI)                                |
| Project level  | `.claude/`, `./CLAUDE.md`                   | `AGENTS.md`, `.codex/config.toml` (loaded only when trusted) | `.agent/rules/` (singular), `GEMINI.md`                              | `.github/copilot-instructions.md`, `.github/instructions/*.instructions.md`                   | `.cursor/rules/*.mdc`                           |
| Local override | `settings.local.json`, `CLAUDE.local.md`    | CLI flags                                                    | (No explicit dedicated local layer; workspace is the effective unit) | `~/.copilot/copilot-instructions.md` (CLI supports a local layer, used alongside `AGENTS.md`) | (No equivalent dedicated local layer; see 02-6) |

<Note>
  **The comparison table gives coordinates, not details**

  This table tells you "what the same layer is called in your tool." The exact semantics of each cell (what overrides what, which files are committed) are fast-moving facts; verify them in 02-2 (Claude) and 02-6 (others) with dated notes. The key takeaway: almost every vendor has the user / project / local scope axis; the differences are only in filenames and how complete the local layer is.
</Note>

## Common pitfalls

<Warning>
  **Anti-pattern list**

  * **Assuming all layers use "higher overrides lower"**: `settings.json` uses override, but `CLAUDE.md` uses concatenation and `permissions` uses merge. Using the wrong mental model has a real debug cost (Section 1).
  * **Writing personal preferences into team-shared project rule files**: your language preference and sandbox URL in `./CLAUDE.md` pollute every teammate's context. That belongs in `CLAUDE.local.md` or the user layer.
  * **Writing secrets into committed configuration files**: `settings.json` goes into version control; secrets belong in `settings.local.json` (Section 4).
  * **Not knowing a setting is being overridden by a higher-priority layer**: "I clearly set this, why isn't it working?" is almost always a closer layer covering it, or a managed policy locking it out. First confirm which layer is actually in effect.
</Warning>

## Self-check

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

  1. Can you name where your primary tool's "user-level" and "project-level" configuration files live, and which ones are already committed to version control?
  2. Given an API key, a team style rule, and a personal language preference, can you say for each: "which cell, commit or gitignore?"
  3. Can you explain why `~/.claude/CLAUDE.md` and `./CLAUDE.md` do not override each other, while the same key in two `settings.json` files does?
</Check>

## Sources and further reading

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

<div className="references">
  * \[1] Anthropic, "Claude Code settings" (setting precedence: managed, CLI, local, project, user; file locations; permissions as cross-layer merge), Claude Code Docs. [https://code.claude.com/docs/en/settings](https://code.claude.com/docs/en/settings) (as of 2026-05)

  * \[2] Anthropic, "How Claude remembers your project" (`CLAUDE.md` hierarchy and concatenation loading, `CLAUDE.local.md`, `@path` import syntax, `.claude/rules/`, Claude Code reads `CLAUDE.md` not `AGENTS.md`), Claude Code Docs. [https://code.claude.com/docs/en/memory](https://code.claude.com/docs/en/memory) (as of 2026-05)
</div>

* Related: [02-2](/en/code-agent/configuration/anthropic-claude-setup) Claude configuration item by item; [02-6](/en/code-agent/configuration/other-tools-comparison) configuration comparison across tools; [04-1](/en/code-agent/customization/claude-md-memory) CLAUDE.md and memory files; [04-2](/en/code-agent/customization/rules) rules files.
