Config Schemas
- Entity ID:
ent-20260410-8260003548dd - Type:
concept - Scope:
shared - Status:
active - Aliases: settings schema, settings.json, configuration, SettingsSchema
Description
The configuration schema system uses Zod v4 to validate all settings.json files across 5 configuration scopes. It defines the structure for user settings, project settings, enterprise policies, permission rules, hooks, MCP server configs, and sandbox settings. Managed settings follow a systemd-style drop-in convention for enterprise customization.
Configuration scopes
5 setting sources with defined precedence (later overrides earlier):
| Priority | Source | Location | Editable |
|---|---|---|---|
| 1 | userSettings |
~/.claude/settings.json |
Yes |
| 2 | projectSettings |
.claude/settings.json (shared) |
Yes |
| 3 | localSettings |
Gitignored project-local | Yes |
| 4 | flagSettings |
--settings CLI flag |
No |
| 5 | policySettings |
managed-settings.json or remote API |
No |
policySettings and flagSettings are always loaded. User/project/local sources can be selectively enabled via --setting-sources user,project,local.
SettingsSchema structure
The unified SettingsSchema (in src/utils/settings/types.ts) covers all configuration:
Authentication
apiKeyHelper— script path for API key retrievalawsCredentialExport,awsAuthRefresh,gcpAuthRefresh— cloud auth scriptsforceLoginMethod— 'claudeai' or 'console'forceLoginOrgUUID
Permissions
permissions.allow/permissions.deny/permissions.ask— tool permission rulespermissions.defaultMode— default permission modepermissions.disableBypassPermissionsMode— lock out bypass modepermissions.additionalDirectories— extra allowed directories
MCP
enableAllProjectMcpServers,enabledMcpjsonServers,disabledMcpjsonServersallowedMcpServers,deniedMcpServers— enterprise allow/deny lists
Hooks
hooks—HooksSchema: per-event hook arrays with matchersdisableAllHooks,allowManagedHooksOnlyallowedHttpHookUrls,httpHookAllowedEnvVars— HTTP hook security
Model and behavior
model— model overrideavailableModels— enterprise model allowlistmodelOverrides— map from Anthropic model ID to provider-specific IDeffortLevel— low/medium/high/maxfastMode,fastModePerSessionOptInalwaysThinkingEnabled,advisorModeloutputStyle,language
UI and display
statusLine—{ type: 'command', command: string, padding? }syntaxHighlightingDisabledterminalTitleFromRenamespinnerTipsEnabled,spinnerVerbs,spinnerTipsOverridepromptSuggestionEnabled
Enterprise
allowManagedPermissionRulesOnly,allowManagedMcpServersOnlystrictPluginOnlyCustomization— boolean or array of categoriescompanyAnnouncements— startup announcements
Other
env— environment variables (record of string -> coerced string)attribution—{ commit?: string, pr?: string }for git commits/PRscleanupPeriodDays— transcript retention (0 disables)respectGitignore— booleansandbox—SandboxSettingsSchemaworktree—{ symlinkDirectories?, sparsePaths? }enabledPlugins,pluginConfigsfeedbackSurveyRate— 0-1 probability
Hook schemas
Hooks are defined in src/schemas/hooks.ts (extracted to break import cycles). Four hook types:
| Type | Key fields |
|---|---|
command (bash) |
command, if (matcher), shell, timeout, once, async |
prompt |
prompt (with $ARGUMENTS), if, model, timeout, once |
http |
url, headers (with $VAR_NAME interpolation), allowedEnvVars, timeout |
agent |
prompt, if, model, timeout, once |
All hooks support: statusMessage, once (run only first time), and if condition (permission rule syntax like "Bash(git *)" to filter when the hook fires).
Validation approach
- Zod v4 for all schema validation with
lazySchema()wrapper for deferred evaluation .passthrough()on permissions preserves unknown fields (backward compatibility)z.coercefor type coercion (env vars converting numbers to strings).catch(undefined)prevents individual field failures from nulling the entire config- Invalid settings are preserved in the file but not applied (graceful degradation)
- Published to JSON Schema Store:
https://json.schemastore.org/claude-code-settings.json
Managed settings
loadManagedFileSettings() follows the systemd/sudoers drop-in convention:
- Load
managed-settings.jsonfrom platform-specific managed path - Load
managed-settings.d/*.json(sorted alphabetically) - Merge using
lodash-es/mergeWithwithsettingsMergeCustomizer
Base file provides defaults; drop-in files customize for specific teams or environments.
Trade-offs
- Single unified schema — all scopes use the same
SettingsSchema, making it easy to understand but meaning every scope can potentially set any field (policy enforcement must be separate from validation). - Graceful degradation — invalid fields are ignored rather than rejecting the whole file. Good for forward compatibility but can mask configuration errors silently.
- Drop-in convention — flexible for enterprise deployment but adds precedence complexity beyond the 5-scope hierarchy.
lazySchema()wrapper — breaks import cycles but makes the schema harder to inspect statically.
Depends on
- Zod v4 — schema definition and validation
lodash-es/mergeWith— settings merge
Key claims
- 5 configuration scopes with defined precedence (user < project < local < flag < policy)
- Invalid settings are preserved in file but not applied (graceful degradation)
- Hook schemas support 4 types: bash command, prompt, HTTP, and agent
- Managed settings follow systemd drop-in convention (base file + .d/ directory)
Relations
used_byentrypoint-systemused_bymcp-server-discoveryused_bypermission-pipelineused_byhooks-system
Sources
src-20260409-a5fc157bc756, source code analysis of src/schemas/hooks.ts, src/utils/settings/types.ts, src/utils/settings/constants.ts