# 配置与迁移系统 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 核心模式示例 ```typescript // 基础设置模式 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)` | 解析设置文件 | **设置加载优先级** (从低到高): 1. 默认值 2. 托管设置文件 (`managed-settings.json`) 3. 托管设置 Drop-in 目录 (`managed-settings.d/*.json`) 4. 用户设置文件 (`~/.claude/settings.json`) **托管设置系统**: ```typescript // 加载托管文件设置 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` 应用设置变更到运行时系统。 ```typescript // 示例:应用主题变更 async function applyThemeChange(theme: Theme): Promise { // 1. 更新渲染器主题 // 2. 通知所有订阅者 // 3. 持久化到磁盘 } ``` ### 2.4 验证 (validation.ts) **文件**: `src/utils/settings/validation.ts` (~8KB) **主要函数**: | 函数 | 用途 | |------|------| | `validateSettings(settings)` | 验证完整设置 | | `validateSetting(key, value)` | 验证单个设置 | | `formatZodError(error)` | 格式化 Zod 错误 | | `filterInvalidPermissionRules(rules)` | 过滤无效权限规则 | **验证流程**: ```typescript 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) 验证权限规则的有效性。 **权限规则结构**: ```typescript interface PermissionRule { tool: string // 工具名称 path?: string // 路径模式 deny?: boolean // 拒绝还是允许 reason?: string // 原因说明 } ``` **验证规则**: 1. 工具名称必须有效 2. 路径模式必须是有效的 glob 或正则 3. 冲突规则被拒绝 ### 2.6 工具验证配置 (toolValidationConfig.ts) **文件**: `src/utils/settings/toolValidationConfig.ts` 配置哪些工具需要验证或可以直接执行。 ```typescript // 免验证工具 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) 定义所有设置相关的类型。 ```typescript // 设置 JSON 结构 type SettingsJson = { // 基本设置 model?: string theme?: 'dark' | 'light' | 'system' // MCP mcpServers?: Record // 权限 permissionRules?: PermissionRule[] // 实验性功能 experimental?: Record } // 设置来源 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**: ```typescript export function migrateOpusToOpus1m( oldSettings: LegacySettings ): NewSettings { return { ...oldSettings, model: oldSettings.model === 'opus' ? 'opus-3-5-20241120' : oldSettings.model, } } ``` ### 3.3 迁移执行时机 迁移在以下时机执行: 1. 应用启动时 2. 设置加载前 3. 版本检测后 ## 4. 常量 (constants.ts) **文件**: `src/utils/settings/constants.ts` (~5.5KB) ```typescript // 设置源优先级 const SETTING_SOURCE_PRIORITY: Record = { 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) ```typescript // 缓存接口 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 合并规则 1. 基础文件先加载 2. Drop-in 文件按文件名排序后加载 3. 后加载的文件优先级更高 4. 数组字段替换,非数组字段合并 ## 7. 配置验证规则 ### 7.1 路径验证 ```typescript 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 命令验证 ```typescript function validateCommand(command: string): boolean { // 白名单检查 const allowedCommands = ['read', 'edit', 'bash'] return allowedCommands.includes(command) } ``` ### 7.3 模型名称验证 ```typescript 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` 标识由系统内部触发的设置写入,防止来自用户配置文件的覆盖。 ```typescript // 标记内部写入 export function markInternalWrite(key: string): void { internalWrites.add(key) } // 检查是否为内部写入 export function isInternalWrite(key: string): boolean { return internalWrites.has(key) } ```