跳转到内容

配置系统

Claude Code 的配置系统是一个多层架构,settings 从 5+ 个来源流入,拥有明确定义的优先级。理解这一系统至关重要,因为配置影响一切:可用 tool、权限规则、模型选择和行为。

Settings 从多个来源加载,后面的来源覆盖前面的

graph TB
    subgraph "Lowest Priority"
        A["1. User Settings<br/>~/.claude/settings.json"]
    end

    subgraph "Medium Priority"
        B["2. Project Settings<br/>.claude/settings.json"]
        C["3. Local Settings<br/>.claude/settings.local.json"]
    end

    subgraph "High Priority"
        D["4. Flag Settings<br/>--settings CLI flag"]
    end

    subgraph "Highest Priority"
        E["5. Policy Settings<br/>managed-settings.json / remote API"]
    end

    A --> B --> C --> D --> E

    style E fill:#f96,stroke:#333,stroke-width:2px

来自 src/utils/settings/constants.ts

src/utils/settings/constants.ts
export const SETTING_SOURCES = [
'userSettings', // Global: ~/.claude/settings.json
'projectSettings', // Shared: .claude/settings.json (checked into VCS)
'localSettings', // Private: .claude/settings.local.json (gitignored)
'flagSettings', // CLI: --settings flag
'policySettings', // Enterprise: managed-settings.json or remote API
] as const
来源位置VCS使用场景
userSettings~/.claude/settings.jsonN/A(主目录)个人全局偏好
projectSettings.claude/settings.json提交入库团队共享项目规则
localSettings.claude/settings.local.jsonGitignored私有项目覆盖
flagSettings--settings CLI 参数N/ACI/CD、脚本
policySettings/etc/claude-code/managed-settings.jsonN/A企业 IT 管理

覆盖逻辑使用 lodash 的 mergeWith 配合自定义合并策略:

src/utils/settings/settings.ts
function settingsMergeCustomizer(objValue: unknown, srcValue: unknown): unknown {
// Arrays are replaced, not concatenated
if (Array.isArray(srcValue)) {
return srcValue
}
// Objects are deep-merged
return undefined // fall through to default deep merge
}

关键行为:数组会被高优先级来源替换(而非合并)。这意味着项目可以完全覆盖用户级别的权限规则。

Policy settings 具有最高优先级,支持两种机制:

src/utils/settings/settings.ts
export function loadManagedFileSettings(): {
settings: SettingsJson | null
errors: ValidationError[]
} {
// Base: /etc/claude-code/managed-settings.json (or platform equivalent)
const { settings } = parseSettingsFile(getManagedSettingsFilePath())
// Drop-ins: /etc/claude-code/managed-settings.d/*.json
// Sorted alphabetically, higher precedence
const entries = readdirSync(dropInDir)
.filter(d => d.name.endsWith('.json') && !d.name.startsWith('.'))
.sort()
// Merge each on top
}

drop-in 模式借鉴了 systemd 的约定——团队可以独立发布策略片段(如 10-otel.json20-security.json),无需编辑单一文件。

对于使用 Anthropic 管理 API 的组织,settings 会被远程获取并缓存:

src/services/remoteManagedSettings/index.ts
export function initializeRemoteManagedSettingsLoadingPromise(): void
export function waitForRemoteManagedSettingsToLoad(): Promise<void>

在 macOS 和 Windows 上,Claude Code 还会从平台原生 MDM 读取:

src/utils/settings/mdm/rawRead.ts
export function startMdmRawRead(): void {
// macOS: plutil to read com.anthropic.claude-code preferences
// Windows: registry query for HKCU\Software\Anthropic\Claude Code
}

MDM 读取在导入时触发(init 之前),与模块加载并行运行。

所有 settings 都会经过 zod schema 验证:

src/utils/settings/types.ts
import { z } from 'zod/v4'
export const SettingsSchema = z.object({
// Permission rules
permissions: z.object({
allow: z.array(PermissionRuleSchema).optional(),
deny: z.array(PermissionRuleSchema).optional(),
ask: z.array(PermissionRuleSchema).optional(),
}).optional(),
// Environment variables
env: z.record(z.string()).optional(),
// MCP server configuration
mcpServers: z.record(McpServerConfigSchema).optional(),
// Hooks
hooks: z.record(HookConfigSchema).optional(),
// Model preferences
model: z.string().optional(),
// ... many more fields
}).passthrough()
export type SettingsJson = z.infer<typeof SettingsSchema>

无效 settings 会被报告,但不会导致应用崩溃:

src/utils/settings/validation.ts
export type ValidationError = {
source: SettingSource
field: string
message: string
}
// Settings loading always returns both valid settings and errors
export type SettingsWithErrors = {
settings: SettingsJson
errors: ValidationError[]
}

除 JSON settings 之外,Claude Code 还会加载 markdown 指令文件——CLAUDE.md 记忆系统

// src/utils/claudemd.ts — File loading hierarchy (from comments)
// 1. Managed memory → /etc/claude-code/CLAUDE.md
// 2. User memory → ~/.claude/CLAUDE.md
// 3. Project memory → CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md
// 4. Local memory → CLAUDE.local.md

文件按逆优先级顺序加载——最后加载的文件优先级最高:

graph TB
    A["1. Managed Memory<br/>/etc/claude-code/CLAUDE.md<br/>(Lowest priority)"]
    B["2. User Memory<br/>~/.claude/CLAUDE.md"]
    C["3. Project Memory - Git Root<br/>CLAUDE.md in repo root"]
    D["4. Project Memory - Current Dir<br/>CLAUDE.md in cwd"]
    E["5. Local Memory<br/>CLAUDE.local.md<br/>(Highest priority)"]

    A --> B --> C --> D --> E

    style E fill:#9f6,stroke:#333,stroke-width:2px

项目记忆文件通过从当前目录向上遍历到仓库根目录来发现:

// src/utils/claudemd.ts (conceptual)
// For each directory from cwd up to git root:
// 1. Check CLAUDE.md
// 2. Check .claude/CLAUDE.md
// 3. Check .claude/rules/*.md (all .md files)
// Files closer to cwd have higher priority

记忆文件支持包含其他文件:

<!-- In CLAUDE.md -->
@./coding-standards.md
@./api-conventions.md
@~/personal-preferences.md
src/utils/claudemd.ts
const MEMORY_INSTRUCTION_PROMPT =
'Codebase and user instructions are shown below. Be sure to adhere to these instructions. ' +
'IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.'
// Recommended max character count for a memory file
export const MAX_MEMORY_CHARACTER_COUNT = 40000

@include 规则:

  • @path@./path — 相对于引用文件
  • @~/path — 相对于主目录
  • @/path — 绝对路径
  • 仅在叶文本节点中有效(不在代码块内)
  • 防止循环引用
  • 不存在的文件被静默忽略
  • 仅允许文本文件扩展名(.md.txt.ts.py 等)

Settings 会被积极缓存,以避免重复的文件系统读取:

src/utils/settings/settingsCache.ts
export function getCachedSettingsForSource(source: SettingSource): SettingsJson | null
export function setCachedSettingsForSource(source: SettingSource, settings: SettingsJson): void
export function resetSettingsCache(): void

缓存失效发生在:

  • 调用 resetSettingsCache()(worktree 创建后、plugin 重新加载后)
  • settings 变更检测器检测到 settings 文件变化时
  • 远程 settings 刷新时
src/utils/settings/changeDetector.ts
export function settingsChangeDetector(): void {
// Watches settings files for changes
// Triggers cache invalidation and hook re-capture
}

Settings 可以设置环境变量:

{
"env": {
"ANTHROPIC_MODEL": "claude-sonnet-4-20250514",
"NODE_OPTIONS": "--max-old-space-size=4096"
}
}

环境变量分两个阶段应用:

  1. 安全阶段(信任对话框之前)——仅限非敏感变量:
src/utils/managedEnv.ts
export function applySafeConfigEnvironmentVariables(): void
// Applied during init(), before any trust dialog
  1. 完整阶段(信任建立后)——包含敏感变量的所有变量:
export function applyConfigEnvironmentVariables(): void
// Applied after trust is established

--setting-sources CLI flag 允许限制加载哪些来源:

src/utils/settings/constants.ts
export function parseSettingSourcesFlag(flag: string): SettingSource[] {
// "user,project" → ['userSettings', 'projectSettings']
// Valid names: user, project, local
}
export function getEnabledSettingSources(): SettingSource[] {
const allowed = getAllowedSettingSources()
// Always include policy and flag settings (cannot be disabled)
const result = new Set<SettingSource>(allowed)
result.add('policySettings')
result.add('flagSettings')
return Array.from(result)
}

关键规则policySettingsflagSettings 始终包含——任何 flag 都无法禁用它们。这确保企业策略和显式 CLI flag 始终生效。

graph LR
    S["settings.ts"] --> P["permissionSetup.ts"]
    P --> TPC["ToolPermissionContext"]
    TPC --> T["tools.ts → getTools()"]
    T --> POOL["Tool pool for session"]

    S --> E["managedEnv.ts"]
    E --> ENV["process.env"]
    ENV --> TOOLS["Tool implementations"]
graph LR
    CM["claudemd.ts"] --> QC["queryContext.ts"]
    QC --> SP["System prompt assembly"]
    SP --> C["claude.ts"]
    C --> API["Anthropic API"]