9.2 KiB
配置与迁移系统
Claude Code 使用 Zod 进行配置模式验证,并通过迁移系统处理配置版本升级。
目录结构
src/
├── schemas/ # Zod 配置模式定义
├── migrations/ # 配置迁移脚本
└── utils/settings/ # 设置管理系统
├── settings.ts # 设置管理核心
├── validation.ts # 验证逻辑
├── changeDetector.ts # 变更检测
├── applySettingsChange.ts # 变更应用
├── permissionValidation.ts # 权限规则验证
├── toolValidationConfig.ts # 工具验证配置
├── types.ts # 类型定义
├── constants.ts # 常量
├── mdm/ # 移动设备管理
└── settingsCache.ts # 设置缓存
1. 配置模式 (schemas/)
1.1 主模式文件
文件: src/schemas/hooks.ts (7884行)
使用 Zod 定义所有配置项的验证模式。
1.2 核心模式示例
// 基础设置模式
const baseSettingsSchema = z.object({
// 模型配置
model: z.string(),
maxTokens: z.number().optional(),
// UI 设置
theme: z.enum(['dark', 'light', 'system']),
fontSize: z.number().min(8).max(24),
// 权限设置
allowPermissions: z.boolean(),
permissionRules: z.array(permissionRuleSchema).optional(),
})
// MCP 服务器配置
const mcpServerSchema = z.object({
name: z.string(),
command: z.string(),
args: z.array(z.string()).optional(),
env: z.record(z.string()).optional(),
})
2. 设置管理 (utils/settings/)
2.1 设置核心 (settings.ts)
文件: src/utils/settings/settings.ts (~32KB)
主要函数:
| 函数 | 用途 |
|---|---|
getSettings() |
获取当前设置 |
updateSettings(partial) |
更新设置 |
resetSettings() |
重置为默认值 |
loadManagedFileSettings() |
加载托管配置文件 |
parseSettingsFile(path) |
解析设置文件 |
设置加载优先级 (从低到高):
- 默认值
- 托管设置文件 (
managed-settings.json) - 托管设置 Drop-in 目录 (
managed-settings.d/*.json) - 用户设置文件 (
~/.claude/settings.json)
托管设置系统:
// 加载托管文件设置
export function loadManagedFileSettings(): {
settings: SettingsJson | null
errors: ValidationError[]
} {
// 1. 加载 managed-settings.json (基础)
// 2. 按字母顺序加载 managed-settings.d/*.json (覆盖)
}
2.2 变更检测 (changeDetector.ts)
文件: src/utils/settings/changeDetector.ts (~16KB)
检测设置变更并触发相应的处理逻辑。
主要功能:
- 检测设置项的变化
- 生成变更事件
- 防止循环依赖
2.3 变更应用 (applySettingsChange.ts)
文件: src/utils/settings/applySettingsChange.ts
应用设置变更到运行时系统。
// 示例:应用主题变更
async function applyThemeChange(theme: Theme): Promise<void> {
// 1. 更新渲染器主题
// 2. 通知所有订阅者
// 3. 持久化到磁盘
}
2.4 验证 (validation.ts)
文件: src/utils/settings/validation.ts (~8KB)
主要函数:
| 函数 | 用途 |
|---|---|
validateSettings(settings) |
验证完整设置 |
validateSetting(key, value) |
验证单个设置 |
formatZodError(error) |
格式化 Zod 错误 |
filterInvalidPermissionRules(rules) |
过滤无效权限规则 |
验证流程:
export function validateSettings(
settings: unknown
): SettingsWithErrors {
const result = SettingsSchema.safeParse(settings)
if (result.success) {
return { settings: result.data, errors: [] }
}
// 转换 Zod 错误为友好格式
return {
settings: null,
errors: formatZodError(result.error)
}
}
2.5 权限验证 (permissionValidation.ts)
文件: src/utils/settings/permissionValidation.ts (~8.5KB)
验证权限规则的有效性。
权限规则结构:
interface PermissionRule {
tool: string // 工具名称
path?: string // 路径模式
deny?: boolean // 拒绝还是允许
reason?: string // 原因说明
}
验证规则:
- 工具名称必须有效
- 路径模式必须是有效的 glob 或正则
- 冲突规则被拒绝
2.6 工具验证配置 (toolValidationConfig.ts)
文件: src/utils/settings/toolValidationConfig.ts
配置哪些工具需要验证或可以直接执行。
// 免验证工具
const bypassValidationTools = [
'Read',
'BackgroundRead',
'TodoWrite',
'NotebookEdit',
]
// 需要路径验证的工具
const pathValidationTools = [
'Bash',
'Write',
'Edit',
'Read',
]
2.7 MDM 配置 (mdm/)
目录: src/utils/settings/mdm/
支持移动设备管理 (Mobile Device Management) 配置。
mdm/
└── settings.ts # MDM 设置加载
2.8 类型定义 (types.ts)
文件: src/utils/settings/types.ts (~43KB)
定义所有设置相关的类型。
// 设置 JSON 结构
type SettingsJson = {
// 基本设置
model?: string
theme?: 'dark' | 'light' | 'system'
// MCP
mcpServers?: Record<string, McpServerConfig>
// 权限
permissionRules?: PermissionRule[]
// 实验性功能
experimental?: Record<string, boolean>
}
// 设置来源
type SettingSource =
| 'default'
| 'managed'
| 'user'
// 可编辑的设置源
type EditableSettingSource = 'user'
3. 迁移系统 (migrations/)
3.1 迁移文件列表
| 文件 | 用途 |
|---|---|
migrateAutoUpdatesToSettings.ts |
自动更新迁移 |
migrateBypassPermissionsAcceptedToSettings.ts |
绕过权限迁移 |
migrateEnableAllProjectMcpServersToSettings.ts |
MCP 服务器迁移 |
migrateFennecToOpus.ts |
Fennec → Opus 模型迁移 |
migrateLegacyOpusToCurrent.ts |
Legacy Opus 迁移 |
migrateOpusToOpus1m.ts |
Opus → Opus 1M 迁移 |
migrateReplBridgeEnabledToRemoteControlAtStartup.ts |
REPL 桥接迁移 |
migrateSonnet1mToSonnet45.ts |
Sonnet 1M → 4.5 迁移 |
migrateSonnet45ToSonnet46.ts |
Sonnet 4.5 → 4.6 迁移 |
resetAutoModeOptInForDefaultOffer.ts |
自动模式重置 |
resetProToOpusDefault.ts |
Pro → Opus 默认重置 |
3.2 迁移示例
migrateOpusToOpus1m.ts:
export function migrateOpusToOpus1m(
oldSettings: LegacySettings
): NewSettings {
return {
...oldSettings,
model: oldSettings.model === 'opus' ? 'opus-3-5-20241120' : oldSettings.model,
}
}
3.3 迁移执行时机
迁移在以下时机执行:
- 应用启动时
- 设置加载前
- 版本检测后
4. 常量 (constants.ts)
文件: src/utils/settings/constants.ts (~5.5KB)
// 设置源优先级
const SETTING_SOURCE_PRIORITY: Record<SettingSource, number> = {
default: 0,
managed: 50,
user: 100,
}
// 设置路径
const SETTINGS_DIR = 'settings'
const SETTINGS_FILE = 'settings.json'
const MANAGED_SETTINGS_FILE = 'managed-settings.json'
const MANAGED_SETTINGS_DROPIN_DIR = 'managed-settings.d'
// 默认值
const DEFAULT_MODEL = 'claude-opus-4-5'
const DEFAULT_THEME = 'dark'
const DEFAULT_MAX_TOKENS = 8192
5. 缓存管理 (settingsCache.ts)
文件: src/utils/settings/settingsCache.ts (~2.4KB)
// 缓存接口
interface SettingsCache {
get(key: string): SettingsJson | null
set(key: string, value: SettingsJson): void
invalidate(key: string): void
clear(): void
}
// 缓存策略
const CACHE_TTL = 5 * 60 * 1000 // 5 分钟
const MAX_CACHE_SIZE = 10
6. 托管设置系统详解
6.1 Drop-in 机制
托管设置支持 Drop-in 目录机制,允许多个配置文件按优先级合并:
~/.claude/settings.json # 用户设置
/etc/claude/managed-settings.json # 系统托管基础
/etc/claude/managed-settings.d/
├── 10-base.json # 优先级 10
├── 20-security.json # 优先级 20
└── 30-otel.json # 优先级 30
6.2 合并规则
- 基础文件先加载
- Drop-in 文件按文件名排序后加载
- 后加载的文件优先级更高
- 数组字段替换,非数组字段合并
7. 配置验证规则
7.1 路径验证
function validatePath(path: string): boolean {
// 禁止危险路径
if (path.includes('..')) return false
if (path.startsWith('/etc/')) return false
if (path.startsWith('/sys/')) return false
// 检查权限
if (!canAccessPath(path)) return false
return true
}
7.2 命令验证
function validateCommand(command: string): boolean {
// 白名单检查
const allowedCommands = ['read', 'edit', 'bash']
return allowedCommands.includes(command)
}
7.3 模型名称验证
const VALID_MODELS = [
'claude-opus-4-5',
'claude-sonnet-4-6',
'claude-opus-3-5-20241120',
// ...
]
function validateModel(model: string): boolean {
return VALID_MODELS.includes(model)
}
8. 内部写入标识 (internalWrites.ts)
文件: src/utils/settings/internalWrites.ts
标识由系统内部触发的设置写入,防止来自用户配置文件的覆盖。
// 标记内部写入
export function markInternalWrite(key: string): void {
internalWrites.add(key)
}
// 检查是否为内部写入
export function isInternalWrite(key: string): boolean {
return internalWrites.has(key)
}