Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"hooks": {
"PreToolUse": [
{
"extraField": "should not be allowed",
"hooks": [
{
"command": "echo 'test'",
"type": "command",
"unknownProperty": "not allowed"
}
],
"matcher": "Write"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"forceLoginMethod": "github",
"permissions": {
"defaultMode": "invalid-mode"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"env": {
"HAS SPACES": "should fail",
"has-dashes": "should fail",
"lowercase": "should fail",
"valid_VAR": "ok",
"123STARTS_WITH_NUMBER": "should fail"
}
}
15 changes: 15 additions & 0 deletions src/negative_test/claude-code-settings/invalid-hook-type.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "echo 'Invalid type - should be command'",
"type": "script"
}
],
"matcher": "Write"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"InvalidTool",
"Bash without parentheses",
"Read[wrong-brackets]",
"WebFetch(invalid:syntax"
]
}
}
15 changes: 15 additions & 0 deletions src/negative_test/claude-code-settings/invalid-timeout-value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "echo 'test'",
"timeout": 0,
"type": "command"
}
]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command"
}
]
}
]
}
}
10 changes: 10 additions & 0 deletions src/negative_test/claude-code-settings/wrong-property-types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"cleanupPeriodDays": "thirty",
"enableAllProjectMcpServers": 1,
"includeCoAuthoredBy": "yes",
"learnMode": "true",
"permissions": {
"additionalDirectories": "should be array",
"allow": "should be array"
}
}
166 changes: 131 additions & 35 deletions src/schemas/json/claude-code-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,48 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://json.schemastore.org/claude-code-settings.json",
"$defs": {
"rule": {
"hookCommand": {
"type": "object",
"description": "Hook command configuration",
"additionalProperties": false,
"required": ["type", "command"],
"properties": {
"type": {
"type": "string",
"description": "Type of hook implementation",
"const": "command"
},
"command": {
"type": "string",
"description": "Shell command to execute"
},
"timeout": {
"type": "number",
"description": "Optional timeout in seconds for this specific command",
"exclusiveMinimum": 0
}
}
},
"hookMatcher": {
"type": "object",
"description": "Hook matcher configuration with multiple hooks",
"additionalProperties": false,
"required": ["hooks"],
"properties": {
"matcher": {
"type": "string",
"description": "String (e.g. Write) to match values related to the hook event, e.g. tool names"
},
"hooks": {
"type": "array",
"description": "Array of hooks to execute",
"items": {
"$ref": "#/$defs/hookCommand"
}
}
}
},
"permissionRule": {
"type": "string",
"description": "Tool permission rule (e.g., 'Bash(ls:*)', 'Read(~/.zshrc)', 'WebFetch(domain:github.com)')",
"pattern": "^(Agent|Bash|Edit|Glob|Grep|LS|MultiEdit|NotebookEdit|NotebookRead|Read|TodoRead|TodoWrite|WebFetch|WebSearch|Write)\\(?|^mcp__"
Expand All @@ -21,14 +62,8 @@
"type": "string",
"description": "Custom script path to generate an auth value"
},
"autoUpdaterStatus": {
"type": "string",
"description": "Enable or disable the auto-updater",
"enum": ["enabled", "disabled"],
"default": "enabled"
},
"cleanupPeriodDays": {
"type": "number",
"type": "integer",
"description": "How long to locally retain chat transcripts (in days)",
"default": 30,
"minimum": 0
Expand All @@ -52,8 +87,7 @@
},
"model": {
"type": "string",
"description": "Claude model to use",
"enum": ["opus", "sonnet"]
"description": "Deprecated: use env.ANTHROPIC_MODEL and env.ANTHROPIC_SMALL_FAST_MODEL instead. Either \"sonnet\", \"opus\", or a specific Claude model ID (see https://docs.anthropic.com/en/docs/about-claude/models/overview)"
},
"permissions": {
"type": "object",
Expand All @@ -62,42 +96,104 @@
"properties": {
"allow": {
"type": "array",
"description": "List of allowed tool rules",
"items": { "$ref": "#/$defs/rule" },
"description": "List of allowed tool permission rules",
"items": { "$ref": "#/$defs/permissionRule" },
"uniqueItems": true
},
"deny": {
"type": "array",
"description": "List of denied tool rules",
"items": { "$ref": "#/$defs/rule" },
"description": "List of denied tool permission rules",
"items": { "$ref": "#/$defs/permissionRule" },
"uniqueItems": true
},
"defaultMode": {
"type": "string",
"description": "Default permission mode for tool execution",
"enum": ["acceptEdits", "bypassPermissions", "default", "plan"]
},
"disableBypassPermissionsMode": {
"type": "string",
"description": "Disable bypass permissions mode",
"const": "disable"
},
"additionalDirectories": {
"type": "array",
"description": "Paths to additional directories Claude can access beyond the working directory",
"items": {
"type": "string"
},
"uniqueItems": true
}
},
"default": {
"allow": [],
"deny": []
}
},
"preferredNotifChannel": {
"type": "string",
"description": "Preferred notification channel",
"enum": [
"iterm2",
"iterm2_with_bell",
"terminal_bell",
"notifications_disabled"
],
"default": "iterm2"
"enableAllProjectMcpServers": {
"type": "boolean",
"description": "Whether to automatically approve all MCP servers in the project"
},
"theme": {
"type": "string",
"description": "UI theme configuration",
"enum": ["dark", "light", "light-daltonized", "dark-daltonized"]
"enabledMcpjsonServers": {
"type": "array",
"description": "List of allowed MCP servers from .mcp.json",
"items": {
"type": "string"
}
},
"disabledMcpjsonServers": {
"type": "array",
"description": "List of denied MCP servers from .mcp.json",
"items": {
"type": "string"
}
},
"hooks": {
"type": "object",
"description": "Hooks configuration for executing commands at specific points in Claude Code's lifecycle",
"additionalProperties": false,
"properties": {
"PreToolUse": {
"type": "array",
"description": "Hooks that run before tool calls",
"items": {
"$ref": "#/$defs/hookMatcher"
}
},
"PostToolUse": {
"type": "array",
"description": "Hooks that run after tool completion",
"items": {
"$ref": "#/$defs/hookMatcher"
}
},
"Notification": {
"type": "array",
"description": "Hooks that trigger on notifications",
"items": {
"$ref": "#/$defs/hookMatcher"
}
},
"Stop": {
"type": "array",
"description": "Hooks that run when agents finish responding",
"items": {
"$ref": "#/$defs/hookMatcher"
}
},
"SubagentStop": {
"type": "array",
"description": "Hooks that run when subagents finish responding",
"items": {
"$ref": "#/$defs/hookMatcher"
}
}
}
},
"verbose": {
"learnMode": {
"type": "boolean",
"description": "Show full bash and command outputs",
"default": false
"description": "Request the model focuses more on educating and co-creating with the user, rather than just completing tasks"
},
"forceLoginMethod": {
"type": "string",
"description": "Force a specific login method, and skip the login method selection screen",
"enum": ["claudeai", "console"]
}
}
}
68 changes: 68 additions & 0 deletions src/test/claude-code-settings/hooks-complete.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"hooks": {
"Notification": [
{
"hooks": [
{
"command": "osascript -e 'display notification \"Claude task complete\" with title \"Claude Code\"'",
"type": "command"
}
]
}
],
"PostToolUse": [
{
"hooks": [
{
"command": "git diff",
"type": "command"
}
],
"matcher": "Edit"
}
],
"PreToolUse": [
{
"hooks": [
{
"command": "echo 'About to write file' >> /tmp/claude-log.txt",
"type": "command"
}
],
"matcher": "Write"
},
{
"hooks": [
{
"command": "echo 'Running bash command' >> /tmp/claude-log.txt",
"timeout": 5,
"type": "command"
}
],
"matcher": "Bash"
}
],
"Stop": [
{
"hooks": [
{
"command": "echo 'Claude finished' | tee -a /tmp/claude-session.log",
"type": "command"
}
]
}
],
"SubagentStop": [
{
"hooks": [
{
"command": "echo 'Subagent completed' >> /tmp/claude-subagent.log",
"timeout": 2,
"type": "command"
}
],
"matcher": "Agent"
}
]
}
}
5 changes: 5 additions & 0 deletions src/test/claude-code-settings/mcp-servers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"disabledMcpjsonServers": ["experimental-server", "legacy-api"],
"enableAllProjectMcpServers": false,
"enabledMcpjsonServers": ["filesystem", "github", "database-reader"]
}
Loading