diff --git a/src/helpers/coverage.js b/src/helpers/coverage.js index 63047dea54f..f52d4c3c483 100644 --- a/src/helpers/coverage.js +++ b/src/helpers/coverage.js @@ -84,6 +84,24 @@ function collectValuesByPath(data, path) { } } deepCollect(data) + // If name-based search found nothing (def is used as array items or + // additionalProperties values, not as a named key), fall back to all + // string values in the data. Covers permissionRule, builtinAction, etc. + if (values.length === 0) { + function collectAllStrings(current) { + if (typeof current === 'string') { + values.push(current) + return + } + if (!current || typeof current !== 'object') return + if (Array.isArray(current)) { + for (const item of current) collectAllStrings(item) + return + } + for (const val of Object.values(current)) collectAllStrings(val) + } + collectAllStrings(data) + } return values } @@ -226,10 +244,25 @@ function walkProperties(schema, currentPath = '') { if (defs && typeof defs === 'object' && !Array.isArray(defs)) { for (const [defName, defSchema] of Object.entries(defs)) { if (defSchema && typeof defSchema === 'object') { + const defPath = `#${defsKey}/${defName}` + // Emit the def itself if it is a leaf schema (enum/pattern/type + // directly on the def, not via child properties). This covers + // reusable string-enum defs like context or builtinAction. + if ( + Array.isArray(defSchema.enum) || + typeof defSchema.pattern === 'string' || + (defSchema.type && !defSchema.properties) + ) { + results.push({ + path: defPath, + name: defName, + propSchema: /** @type {Record} */ (defSchema), + }) + } results.push( ...walkProperties( /** @type {Record} */ (defSchema), - `#${defsKey}/${defName}`, + defPath, ), ) } @@ -367,7 +400,7 @@ export function checkDescriptionCoverage(schema) { status: missing.length === 0 ? 'pass' : 'fail', totalProperties: nonDefProps.length, missingCount: missing.length, - missing: missing.slice(0, 20).map((p) => p.path), + missing: missing.map((p) => p.path), } } @@ -438,7 +471,7 @@ export function checkEnumCoverage(schema, positiveTests, negativeTests) { issues.push({ path: ePath, type: 'positive_uncovered', - values: uncovered.slice(0, 10), + values: uncovered, testedFiles, }) } @@ -457,7 +490,7 @@ export function checkEnumCoverage(schema, positiveTests, negativeTests) { return { status: issues.length === 0 ? 'pass' : 'fail', totalEnums: enums.length, - issues: issues.slice(0, 20), + issues: issues, } } @@ -536,7 +569,7 @@ export function checkPatternCoverage(schema, positiveTests, negativeTests) { return { status: issues.length === 0 ? 'pass' : 'fail', totalPatterns: patterns.length, - issues: issues.slice(0, 20), + issues: issues, } } @@ -588,7 +621,7 @@ export function checkRequiredCoverage(schema, negativeTests) { status: issues.length === 0 ? 'pass' : 'warn', totalRequiredGroups: requiredGroups.length, note: 'Heuristic: name-based matching, not path-aware', - uncovered: issues.slice(0, 20), + uncovered: issues, } } @@ -649,7 +682,7 @@ export function checkDefaultCoverage(schema, positiveTests) { return { status: issues.length === 0 ? 'pass' : 'fail', totalDefaults: defaults.length, - issues: issues.slice(0, 20), + issues: issues, } } @@ -820,7 +853,7 @@ export function checkNegativeIsolation(schema, negativeTests) { status: multiViolationFiles.length === 0 ? 'pass' : 'warn', totalNegativeTests: negativeTests.size, note: 'Heuristic — all checks match by property name, not JSON path. When the same name (e.g., "source", "type") appears at different schema depths with different constraints, violations may be misattributed. For each flagged file, verify that reported violation types reflect intentional test inputs at the correct nesting level, not collisions between unrelated schema depths', - multiViolationFiles: multiViolationFiles.slice(0, 20), + multiViolationFiles: multiViolationFiles, } } diff --git a/src/negative_test/claude-code-keybindings/duplicate-context.json b/src/negative_test/claude-code-keybindings/duplicate-context.json new file mode 100644 index 00000000000..46dac30de96 --- /dev/null +++ b/src/negative_test/claude-code-keybindings/duplicate-context.json @@ -0,0 +1,16 @@ +{ + "bindings": [ + { + "bindings": { + "ctrl+c": "app:interrupt" + }, + "context": "Global" + }, + { + "bindings": { + "ctrl+d": "app:exit" + }, + "context": "Global" + } + ] +} diff --git a/src/negative_test/claude-code-settings/invalid-enum-values.json b/src/negative_test/claude-code-settings/invalid-enum-values.json index 5ed0d2d0b1e..f2d744c8c10 100644 --- a/src/negative_test/claude-code-settings/invalid-enum-values.json +++ b/src/negative_test/claude-code-settings/invalid-enum-values.json @@ -1,7 +1,9 @@ { "autoUpdatesChannel": "beta", "defaultShell": "zsh", + "disableAutoMode": "enabled", "disableDeepLinkRegistration": "enabled", + "editorMode": "emacs", "effortLevel": "extreme", "env": { "ANTHROPIC_BEDROCK_SERVICE_TIER": "turbo", @@ -12,11 +14,13 @@ "CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "yes", "CLAUDE_CODE_ACCESSIBILITY": "enable", "CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD": "on", + "CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT": "yes", "CLAUDE_CODE_ATTRIBUTION_HEADER": "yes", "CLAUDE_CODE_AUTO_CONNECT_IDE": "1", "CLAUDE_CODE_DEBUG_LOG_LEVEL": "trace", "CLAUDE_CODE_DISABLE_1M_CONTEXT": "yes", "CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING": "true", + "CLAUDE_CODE_DISABLE_AGENT_VIEW": "true", "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN": "yes", "CLAUDE_CODE_DISABLE_ATTACHMENTS": "off", "CLAUDE_CODE_DISABLE_AUTO_MEMORY": "yes", @@ -55,6 +59,7 @@ "CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL": "yes", "CLAUDE_CODE_IDE_SKIP_VALID_CHECK": "true", "CLAUDE_CODE_MCP_ALLOWLIST_ENV": "all", + "CLAUDE_CODE_NATIVE_CURSOR": "enable", "CLAUDE_CODE_NEW_INIT": "start", "CLAUDE_CODE_NO_FLICKER": "maybe", "CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE": "yes", @@ -94,6 +99,7 @@ "disableAutoMode": "enabled", "disableBypassPermissionsMode": "enabled" }, + "preferredNotifChannel": "slack", "skillOverrides": { "test-skill": "invalid-mode" }, @@ -104,6 +110,9 @@ "teammateMode": "split", "tui": "mini", "viewMode": "list", + "voice": { + "mode": "continuous" + }, "worktree": { "baseRef": "invalid-ref", "bgIsolation": "isolated" diff --git a/src/negative_test/claude-code-settings/wrong-property-types.json b/src/negative_test/claude-code-settings/wrong-property-types.json index 6877a4d055a..93b9d9ed03d 100644 --- a/src/negative_test/claude-code-settings/wrong-property-types.json +++ b/src/negative_test/claude-code-settings/wrong-property-types.json @@ -1,4 +1,5 @@ { + "allowedChannelPlugins": ["internal-notifier@corp"], "cleanupPeriodDays": "thirty", "enableAllProjectMcpServers": 1, "fastMode": "yes", diff --git a/src/schema-validation.jsonc b/src/schema-validation.jsonc index 2c82b9431fb..0204b7aadb7 100644 --- a/src/schema-validation.jsonc +++ b/src/schema-validation.jsonc @@ -462,6 +462,10 @@ { "schema": "claude-code-settings.json", "strict": true + }, + { + "schema": "claude-code-keybindings.json", + "strict": true } ], "catalogEntryNoLintNameOrDescription": [ diff --git a/src/schemas/json/claude-code-keybindings.json b/src/schemas/json/claude-code-keybindings.json index b2610e08a4a..0d40ad47692 100644 --- a/src/schemas/json/claude-code-keybindings.json +++ b/src/schemas/json/claude-code-keybindings.json @@ -44,7 +44,9 @@ "DiffDialog", "ModelPicker", "Select", - "Plugin" + "Plugin", + "Scroll", + "Doctor" ] }, "keystrokePattern": { @@ -72,6 +74,8 @@ "enum": [ "app:interrupt", "app:exit", + "app:redraw", + "app:toggleBrief", "app:toggleTodos", "app:toggleTranscript", "app:toggleTeammatePreview", @@ -79,14 +83,20 @@ "history:previous", "history:next", "chat:cancel", + "chat:clearInput", + "chat:clearScreen", "chat:cycleMode", + "chat:fastMode", + "chat:imagePaste", + "chat:killAgents", "chat:modelPicker", - "chat:thinkingToggle", + "chat:newline", + "chat:stash", "chat:submit", + "chat:thinkingToggle", "chat:undo", "chat:externalEditor", - "chat:stash", - "chat:imagePaste", + "voice:pushToTalk", "autocomplete:accept", "autocomplete:dismiss", "autocomplete:previous", @@ -98,6 +108,7 @@ "confirm:nextField", "confirm:previousField", "confirm:cycleMode", + "confirm:toggle", "confirm:toggleExplanation", "tabs:next", "tabs:previous", @@ -106,9 +117,11 @@ "historySearch:next", "historySearch:accept", "historySearch:cancel", + "historySearch:cycleScope", "historySearch:execute", "task:background", "theme:toggleSyntaxHighlighting", + "theme:editCustom", "help:dismiss", "attachments:next", "attachments:previous", @@ -116,6 +129,8 @@ "attachments:exit", "footer:next", "footer:previous", + "footer:up", + "footer:down", "footer:openSelected", "footer:clearSelection", "messageSelector:up", @@ -132,15 +147,44 @@ "diff:nextFile", "modelPicker:decreaseEffort", "modelPicker:increaseEffort", + "modelPicker:setAsDefault", "select:next", "select:previous", + "select:pageUp", + "select:pageDown", + "select:first", + "select:last", "select:accept", "select:cancel", "plugin:toggle", "plugin:install", + "plugin:favorite", "permission:toggleDebug", + "settings:close", + "settings:periodDay", + "settings:periodWeek", + "settings:retry", "settings:search", - "settings:retry" + "settings:sortByTokens", + "doctor:fix", + "scroll:lineUp", + "scroll:lineDown", + "scroll:pageUp", + "scroll:pageDown", + "scroll:top", + "scroll:bottom", + "scroll:halfPageUp", + "scroll:halfPageDown", + "scroll:fullPageUp", + "scroll:fullPageDown", + "selection:copy", + "selection:clear", + "selection:extendLeft", + "selection:extendRight", + "selection:extendUp", + "selection:extendDown", + "selection:extendLineStart", + "selection:extendLineEnd" ] }, "commandBinding": { @@ -166,7 +210,8 @@ "type": "array", "items": { "$ref": "#/$defs/keybindingBlock" - } + }, + "uniqueItemProperties": ["context"] } }, "required": ["bindings"], diff --git a/src/schemas/json/claude-code-settings.json b/src/schemas/json/claude-code-settings.json index de4b597fd8b..ef6a562ddb4 100644 --- a/src/schemas/json/claude-code-settings.json +++ b/src/schemas/json/claude-code-settings.json @@ -156,7 +156,7 @@ }, { "type": "object", - "description": "HTTP webhook hook. POST JSON to a URL and receive JSON response. See https://code.claude.com/docs/en/hooks#http-hook-fields", + "description": "HTTP webhook hook. POST JSON to a URL and receive JSON response. See https://code.claude.com/docs/en/hooks#http-hook-fields. Default timeout: 600 seconds.", "additionalProperties": false, "required": ["type", "url"], "properties": { @@ -187,7 +187,7 @@ }, "timeout": { "type": "number", - "description": "Optional timeout in seconds (default: 30)", + "description": "Optional timeout in seconds (default: 600)", "exclusiveMinimum": 0 }, "if": { @@ -228,7 +228,7 @@ }, "timeout": { "type": "number", - "description": "Optional timeout in seconds (default: 60)", + "description": "Optional timeout in seconds (default: 600)", "exclusiveMinimum": 0 }, "if": { @@ -291,13 +291,13 @@ }, "awsCredentialExport": { "type": "string", - "description": "Path to a script that exports AWS credentials. See https://code.claude.com/docs/en/settings#available-settings", + "description": "Command that outputs AWS credentials as JSON (`{\"Credentials\": {\"AccessKeyId\": ..., \"SecretAccessKey\": ..., \"SessionToken\": ...}}`). Output is silently captured. Use when you cannot modify `.aws` and must return credentials directly. See https://code.claude.com/docs/en/amazon-bedrock#advanced-credential-configuration", "examples": ["/bin/generate_aws_grant.sh"], "minLength": 1 }, "awsAuthRefresh": { "type": "string", - "description": "Path to a script that refreshes AWS authentication. See https://code.claude.com/docs/en/settings#available-settings", + "description": "Command to run to refresh AWS authentication when credentials are expired or unavailable. See https://code.claude.com/docs/en/amazon-bedrock#advanced-credential-configuration", "examples": ["aws sso login --profile myprofile"], "minLength": 1 }, @@ -345,6 +345,18 @@ "type": "string", "description": "Override API endpoint URL for proxy or gateway routing" }, + "ANTHROPIC_AWS_API_KEY": { + "type": "string", + "description": "Workspace API key for Claude Platform on AWS." + }, + "ANTHROPIC_AWS_BASE_URL": { + "type": "string", + "description": "Override Claude Platform on AWS endpoint URL." + }, + "ANTHROPIC_AWS_WORKSPACE_ID": { + "type": "string", + "description": "Workspace ID for Claude Platform on AWS. Required on every request." + }, "ANTHROPIC_BEDROCK_BASE_URL": { "type": "string", "description": "Override Amazon Bedrock endpoint URL" @@ -414,6 +426,10 @@ "type": "string", "description": "Model to use for background and low-complexity tasks (e.g., 'claude-3-5-haiku-latest')" }, + "ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION": { + "type": "string", + "description": "AWS region override for the Haiku-class model on Bedrock and Mantle." + }, "ANTHROPIC_VERTEX_BASE_URL": { "type": "string", "description": "Override Google Vertex AI endpoint URL" @@ -434,6 +450,10 @@ "type": "string", "description": "Bearer token for Bedrock API authentication" }, + "AWS_REGION": { + "type": "string", + "description": "AWS region for Amazon Bedrock and Claude Platform on AWS (e.g. `us-east-1`)." + }, "BASH_DEFAULT_TIMEOUT_MS": { "type": "string", "description": "Default bash command timeout in milliseconds (default: 120000)" @@ -465,6 +485,10 @@ "type": "string", "description": "Context capacity percentage threshold for auto-compaction (1-100)" }, + "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": { + "type": "string", + "description": "Stall timeout for background subagents in milliseconds (default: 600000)." + }, "CLAUDE_AUTO_BACKGROUND_TASKS": { "type": "string", "description": "Force-enable automatic backgrounding of tasks", @@ -477,7 +501,7 @@ }, "CLAUDE_CODE_ACCESSIBILITY": { "type": "string", - "description": "Keep native cursor visible for screen magnifiers and assistive tools", + "description": "Set to `1` to keep the native terminal cursor visible and disable the inverted-text cursor indicator. Allows screen magnifiers like macOS Zoom to track cursor position.", "enum": ["0", "1"] }, "CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD": { @@ -485,6 +509,11 @@ "description": "Load CLAUDE.md memory files from additional directories", "enum": ["0", "1"] }, + "CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT": { + "type": "string", + "description": "Set to `1` to repaint the entire screen on every frame in fullscreen instead of sending incremental updates.", + "enum": ["0", "1"] + }, "CLAUDE_CODE_API_KEY_HELPER_TTL_MS": { "type": "string", "description": "Credential helper refresh interval in milliseconds" @@ -538,6 +567,11 @@ "description": "Disable adaptive reasoning", "enum": ["0", "1"] }, + "CLAUDE_CODE_DISABLE_AGENT_VIEW": { + "type": "string", + "description": "Set to `1` to disable background agents and agent view.", + "enum": ["0", "1"] + }, "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN": { "type": "string", "description": "Disable alternate screen buffer rendering. When set to 1, keeps conversation in native scrollback instead of fullscreen renderer", @@ -605,7 +639,7 @@ }, "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": { "type": "string", - "description": "Disable auto-update checks, telemetry, and feedback in one setting", + "description": "Convenience alias that simultaneously sets DISABLE_AUTOUPDATER, DISABLE_FEEDBACK_COMMAND, DISABLE_ERROR_REPORTING, and DISABLE_TELEMETRY.", "enum": ["0", "1"] }, "CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK": { @@ -645,7 +679,7 @@ }, "CLAUDE_CODE_ENABLE_AWAY_SUMMARY": { "type": "string", - "description": "Override session recap/away summary availability", + "description": "Override session recap availability. Set to `0` to force recaps off regardless of the awaySummaryEnabled setting and /config toggle. Set to `1` to force recaps on even when awaySummaryEnabled is false.", "enum": ["0", "1"] }, "CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH": { @@ -768,6 +802,11 @@ "description": "Isolate MCP server environments to allowlisted variables", "enum": ["0", "1"] }, + "CLAUDE_CODE_NATIVE_CURSOR": { + "type": "string", + "description": "Set to `1` to show terminal's native cursor instead of block cursor in fullscreen.", + "enum": ["0", "1"] + }, "CLAUDE_CODE_NEW_INIT": { "type": "string", "description": "Use the interactive /init setup flow", @@ -997,7 +1036,7 @@ }, "DISABLE_TELEMETRY": { "type": "string", - "description": "Disable Statsig telemetry collection", + "description": "Set to `1` to opt out of telemetry. Telemetry events do not include user data like code, file paths, or bash commands. Also disables feature-flag fetching with the same effect as `DISABLE_GROWTHBOOK`, so some flagged features may be unavailable.", "enum": ["0", "1"] }, "DISABLE_UPDATES": { @@ -1007,7 +1046,7 @@ }, "ENABLE_CLAUDEAI_MCP_SERVERS": { "type": "string", - "description": "Opt in/out of claude.ai MCP servers. See https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2163", + "description": "Opt in/out of claude.ai MCP servers. See https://code.claude.com/docs/en/mcp#use-mcp-servers-from-claudeai", "enum": ["true", "false"] }, "HTTPS_PROXY": { @@ -1152,6 +1191,11 @@ } ] }, + "leftArrowOpensAgents": { + "type": "boolean", + "default": true, + "description": "When true (default), pressing `←` on an empty prompt backgrounds the current session and opens agent view. See https://code.claude.com/docs/en/agent-view#attach-to-a-session" + }, "language": { "type": "string", "description": "Configure Claude's preferred response language (e.g., \"japanese\", \"spanish\", \"french\"). Claude will respond in this language by default. Also sets the voice dictation language and terminal tab session title generation. See https://code.claude.com/docs/en/settings#available-settings", @@ -1181,6 +1225,12 @@ } ] }, + "editorMode": { + "type": "string", + "enum": ["normal", "vim"], + "default": "normal", + "description": "Edit prompts with Vim keybindings. Set to `\"vim\"` to enable Vim keybindings in the prompt editor. See https://code.claude.com/docs/en/terminal-config#edit-prompts-with-vim-keybindings" + }, "effortLevel": { "type": "string", "enum": ["low", "medium", "high", "xhigh", "max"], @@ -1460,14 +1510,14 @@ }, "Setup": { "type": "array", - "description": "UNDOCUMENTED. Hooks that run during repository initialization (--init, --init-only) or maintenance (--maintenance)", + "description": "Hooks that run when Claude Code starts with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. Supported matchers: `init` (fires on --init-only or -p --init) and `maintenance` (fires on -p --maintenance). Does not fire on normal interactive startup. See https://code.claude.com/docs/en/hooks#setup", "items": { "$ref": "#/$defs/hookMatcher" } }, "InstructionsLoaded": { "type": "array", - "description": "Hooks that run when a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded (e.g., nested traversal, path glob match). No decision control; used for audit logging and observability. Does not support matchers. See https://code.claude.com/docs/en/hooks#instructionsloaded", + "description": "Hooks that run when a CLAUDE.md or .claude/rules/*.md file is loaded into context. Fires at session start and when files are lazily loaded (e.g., nested traversal, path glob match). No decision control; used for audit logging and observability. Supported matchers: `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact`. See https://code.claude.com/docs/en/hooks#instructionsloaded", "items": { "$ref": "#/$defs/hookMatcher" } @@ -1551,6 +1601,10 @@ } } }, + "disableAgentView": { + "type": "boolean", + "description": "Disable `claude agents`, background sessions, `/background`, and the on-demand supervisor. Also configurable via `CLAUDE_CODE_DISABLE_AGENT_VIEW` environment variable. See https://code.claude.com/docs/en/agent-view#turn-off-agent-view" + }, "disableAllHooks": { "type": "boolean", "description": "Disable all hooks and statusLine execution. When true in managed settings, user and project-level disableAllHooks cannot override it. See https://code.claude.com/docs/en/hooks#disable-or-remove-hooks" @@ -1558,10 +1612,25 @@ "allowedChannelPlugins": { "type": "array", "items": { - "type": "string", - "minLength": 1 + "type": "object", + "properties": { + "marketplace": { + "type": "string", + "description": "Marketplace identifier (e.g. `claude-plugins-official`)." + }, + "plugin": { + "type": "string", + "description": "Plugin identifier within the marketplace." + } + }, + "required": ["marketplace", "plugin"], + "additionalProperties": false }, - "description": "(Managed settings only) Allowlist of plugin IDs whose MCP servers may advertise channel notifications when channelsEnabled is true. When set, only the listed plugins can push inbound messages. See https://code.claude.com/docs/en/mcp" + "description": "(Managed settings only) Allowlist of channel plugins whose MCP servers may advertise channel notifications when channelsEnabled is true. When set, only the listed plugins can register as a channel. See https://code.claude.com/docs/en/channels#restrict-which-channel-plugins-can-run" + }, + "allowAllClaudeAiMcps": { + "type": "boolean", + "description": "UNDOCUMENTED. (Managed settings only) When true, loads all claude.ai cloud MCP connectors alongside `managed-mcp.json`." }, "allowedHttpHookUrls": { "type": "array", @@ -1580,6 +1649,48 @@ "type": "boolean", "description": "(Managed settings only) Prevent user and project settings from defining allow, ask, or deny permission rules. Only rules in managed settings apply. See https://code.claude.com/docs/en/settings#permission-settings" }, + "sshConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for this SSH connection" + }, + "name": { + "type": "string", + "description": "Display name shown in the environment dropdown" + }, + "sshHost": { + "type": "string", + "description": "SSH host to connect to" + }, + "sshPort": { + "type": "integer", + "description": "SSH port (default: 22)" + }, + "sshIdentityFile": { + "type": "string", + "description": "Path to SSH identity file" + }, + "startDirectory": { + "type": "string", + "description": "Initial working directory after connecting" + } + }, + "required": ["id", "name", "sshHost"], + "additionalProperties": false + }, + "description": "Pre-configure SSH connections that appear in the Desktop app's environment dropdown. Managed connections cannot be edited or deleted by users. See https://code.claude.com/docs/en/desktop#pre-configure-ssh-connections-for-your-team" + }, + "sshHostAllowlist": { + "type": "array", + "items": { + "type": "string" + }, + "description": "(Managed settings only) Restrict Desktop SSH sessions to hosts whose resolved hostname matches one of these patterns. An empty array disables SSH sessions entirely. See https://code.claude.com/docs/en/desktop#restrict-which-ssh-hosts-users-can-connect-to" + }, "statusLine": { "type": "object", "properties": { @@ -2005,6 +2116,11 @@ }, "description": "List of plugin IDs (plugin@marketplace format) the user has chosen not to install when prompted" }, + "gcpAuthRefresh": { + "type": "string", + "minLength": 1, + "description": "Command to run to refresh GCP authentication when credentials are expired or unavailable. The command's output is displayed to the user, but interactive input is not supported. Times out after three minutes. See https://code.claude.com/docs/en/google-vertex-ai#advanced-credential-configuration" + }, "forceLoginMethod": { "type": "string", "enum": ["claudeai", "console"], @@ -2012,20 +2128,37 @@ "examples": ["claudeai"] }, "forceLoginOrgUUID": { - "type": "string", - "description": "Organization UUID to use for OAuth login", - "examples": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], - "minLength": 1 + "oneOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + } + } + ], + "description": "Organization UUID (or array of UUIDs) to use for OAuth login. When an array is provided, any of the listed organizations may be used.", + "examples": [ + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + [ + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" + ] + ] }, "otelHeadersHelper": { "type": "string", - "description": "Path to a script that outputs OpenTelemetry headers", + "description": "Path to a script that outputs OpenTelemetry headers. Set the refresh interval with `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS`.", "minLength": 1 }, "outputStyle": { "type": "string", "description": "Controls the output style for assistant responses. Built-in styles: default, Explanatory, Learning. Custom styles can be added in ~/.claude/output-styles/ or .claude/output-styles/. See https://code.claude.com/docs/en/output-styles", - "examples": ["default", "Explanatory", "Learning"], + "examples": ["default", "Explanatory", "Learning", "Proactive"], "minLength": 1 }, "skipWebFetchPreflight": { @@ -2278,6 +2411,11 @@ "description": "Show turn duration messages after responses (e.g., \"Cooked for 1m 6s\"). Set to false to hide these messages (default: true)", "default": true }, + "skillListingBudgetFraction": { + "type": "number", + "default": 0.01, + "description": "Fraction of the model's context window reserved for the skill listing. When the listing exceeds the budget, descriptions for the least-used skills are collapsed. See https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short" + }, "skillOverrides": { "type": "object", "additionalProperties": { @@ -2292,6 +2430,20 @@ } ] }, + "preferredNotifChannel": { + "type": "string", + "enum": [ + "auto", + "terminal_bell", + "iterm2", + "iterm2_with_bell", + "kitty", + "ghostty", + "notifications_disabled" + ], + "default": "auto", + "description": "Preferred notification channel for task completion alerts. See https://code.claude.com/docs/en/terminal-config#get-a-terminal-bell-or-notification" + }, "prefersReducedMotion": { "type": "boolean", "description": "Reduce or disable UI animations (spinners, shimmer, flash effects) for accessibility", @@ -2345,6 +2497,13 @@ "enum": ["worktree", "none"], "default": "worktree", "description": "Isolation mode for background sessions. \"worktree\" blocks Edit/Write in main checkout until EnterWorktree is called; \"none\" lets background jobs edit the working copy directly without EnterWorktree, for repos where worktrees are impractical. See https://code.claude.com/docs/en/settings#worktree-settings" + }, + "symlinkDirectories": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Directories to symlink from the main repository into each worktree to avoid duplicating large directories on disk. See https://code.claude.com/docs/en/settings#worktree-settings" } } }, @@ -2420,7 +2579,7 @@ }, "allowManagedMcpServersOnly": { "type": "boolean", - "description": "(Managed settings only) Only allowedMcpServers from managed settings are respected. deniedMcpServers still merges from all sources. Users can still add their own MCP servers, but only the admin-defined allowlist applies." + "description": "(Managed settings only) When true, only `allowedMcpServers` from managed settings are respected. `deniedMcpServers` still merges from all sources." }, "blockedMarketplaces": { "type": "array", @@ -2593,9 +2752,19 @@ "description": "Custom directory path for auto-memory storage. Supports ~/ prefix for home-directory expansion. Ignored if set in checked-in project settings (.claude/settings.json) for security. Defaults to ~/.claude/projects//memory/ when unset. See https://code.claude.com/docs/en/memory", "minLength": 1 }, + "autoScrollEnabled": { + "type": "boolean", + "default": true, + "description": "Auto-scroll to bottom when new output arrives in fullscreen mode. See https://code.claude.com/docs/en/fullscreen#auto-follow" + }, + "awaySummaryEnabled": { + "type": "boolean", + "default": true, + "description": "Show a one-line session recap when you return to the terminal after a few minutes away. Also overridable via `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` environment variable (takes precedence over this setting and the /config toggle). See https://code.claude.com/docs/en/interactive-mode#session-recap" + }, "autoMode": { "type": "object", - "description": "Customization for the auto mode classifier prompt. Typically configured in managed settings to tune the allow/deny rules used when permissions.defaultMode is \"auto\". By default, allow, soft_deny, and environment REPLACE the corresponding built-in classifier section entirely. Include the literal string \"$defaults\" as an array entry (added in v2.1.118) to splice the built-in defaults in at that position alongside your custom rules. See https://code.claude.com/docs/en/permissions", + "description": "Customization for the auto mode classifier prompt. Typically configured in managed settings to tune the allow/deny rules used when permissions.defaultMode is \"auto\". By default, allow, soft_deny, and environment REPLACE the corresponding built-in classifier section entirely. Include the literal string \"$defaults\" as an array entry (added in v2.1.118) to splice the built-in defaults in at that position alongside your custom rules. See https://code.claude.com/docs/en/auto-mode-config", "additionalProperties": false, "properties": { "allow": { @@ -2630,14 +2799,18 @@ }, "channelsEnabled": { "type": "boolean", - "description": "(Teams/Enterprise) Opt-in for channel notifications — MCP servers with the claude/channel capability pushing inbound messages. Default off. When true, users can select servers via --channels. See https://code.claude.com/docs/en/mcp", - "default": false + "description": "Master switch for channel notifications. Pro and Max users without an organization skip these checks entirely. Teams/Enterprise: channels are blocked when not configured. Anthropic Console with API key authentication: channels are permitted by default; only needed if managed settings are deployed. When true, users can select servers via `--channels`. See https://code.claude.com/docs/en/channels#enterprise-controls" }, "defaultShell": { "type": "string", "enum": ["bash", "powershell"], "description": "Default shell for input-box ! commands. Default: bash. Using \"powershell\" routes ! commands through PowerShell on Windows and requires CLAUDE_CODE_USE_POWERSHELL_TOOL=1 with pwsh on PATH. See https://code.claude.com/docs/en/settings#available-settings" }, + "disableAutoMode": { + "type": "string", + "enum": ["disable"], + "description": "Set to `\"disable\"` to prevent auto mode from being activated. Removes `auto` from the Shift+Tab cycle and rejects `--permission-mode auto` at startup. Most useful in managed settings where users cannot override it. See https://code.claude.com/docs/en/permission-modes#eliminate-prompts-with-auto-mode" + }, "disableDeepLinkRegistration": { "type": "string", "enum": ["disable"], @@ -2651,6 +2824,11 @@ "type": "boolean", "description": "(Managed settings only) Block CLI startup until remote managed settings are freshly fetched from the server. If the fetch fails, the CLI exits (fail-closed) rather than continuing with cached settings. When not set, startup continues without waiting for remote settings. See https://code.claude.com/docs/en/server-managed-settings" }, + "maxSkillDescriptionChars": { + "type": "number", + "default": 1536, + "description": "Per-skill character cap on the combined description and when_to_use text shown in the skill listing. See https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short" + }, "minimumVersion": { "type": "string", "description": "Minimum Claude Code version to stay on. Prevents downgrades when switching release channels. See https://code.claude.com/docs/en/settings#available-settings", @@ -2664,7 +2842,7 @@ }, "showThinkingSummaries": { "type": "boolean", - "description": "Show thinking summaries in the transcript view (Ctrl+O). Thinking summaries are not generated by default in interactive sessions; set to true to restore. See https://code.claude.com/docs/en/settings#available-settings", + "description": "Show thinking summaries in the transcript view (Ctrl+O). Thinking summaries are not generated by default in interactive sessions; set to true to restore. See https://code.claude.com/docs/en/model-config#extended-thinking", "default": false }, "skipDangerousModePermissionPrompt": { @@ -2701,9 +2879,30 @@ "type": "boolean", "description": "When true, apply the auto mode classifier during plan mode to auto-approve safe read-only tool calls while planning. Has no effect unless permissions.defaultMode allows auto. See https://code.claude.com/docs/en/permissions" }, + "voice": { + "type": "object", + "description": "Voice dictation settings. See https://code.claude.com/docs/en/voice-dictation#enable-voice-dictation", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable voice dictation (requires a Claude.ai account)." + }, + "mode": { + "type": "string", + "enum": ["hold", "tap"], + "default": "hold", + "description": "Hold down key to record, or tap to toggle recording." + }, + "autoSubmit": { + "type": "boolean", + "description": "In hold mode, send the prompt automatically on key release when the transcript is at least three words long." + } + } + }, "voiceEnabled": { "type": "boolean", - "description": "Enable push-to-talk voice dictation. Typically written automatically when /voice is used. Requires a Claude.ai account. See https://code.claude.com/docs/en/settings#available-settings" + "description": "Deprecated. Use the `voice` object instead. Enable push-to-talk voice dictation. Typically written automatically when /voice is used. Requires a Claude.ai account. See https://code.claude.com/docs/en/settings#available-settings" }, "wslInheritsWindowsSettings": { "type": "boolean", diff --git a/src/test/claude-code-keybindings/all-contexts.json b/src/test/claude-code-keybindings/all-contexts.json index d74589c2609..6838b2e6752 100644 --- a/src/test/claude-code-keybindings/all-contexts.json +++ b/src/test/claude-code-keybindings/all-contexts.json @@ -2,13 +2,25 @@ "bindings": [ { "bindings": { - "ctrl+c": "app:interrupt" + "ctrl+c": "app:interrupt", + "ctrl+d": "app:exit", + "ctrl+o": "app:toggleTranscript", + "ctrl+r": "app:redraw", + "ctrl+shift+b": "app:toggleBrief", + "ctrl+shift+o": "app:toggleTeammatePreview", + "ctrl+t": "app:toggleTodos" }, "context": "Global" }, { "bindings": { - "enter": "chat:submit" + "cmd+k": "chat:clearScreen", + "ctrl+j": "chat:newline", + "ctrl+l": "chat:clearInput", + "ctrl+x ctrl+k": "chat:killAgents", + "enter": "chat:submit", + "meta+o": "chat:fastMode", + "space": "voice:pushToTalk" }, "context": "Chat" }, @@ -20,6 +32,7 @@ }, { "bindings": { + "space": "confirm:toggle", "y": "confirm:yes" }, "context": "Confirmation" @@ -38,6 +51,7 @@ }, { "bindings": { + "ctrl+s": "historySearch:cycleScope", "escape": "historySearch:cancel" }, "context": "HistorySearch" @@ -50,13 +64,18 @@ }, { "bindings": { + "ctrl+e": "theme:editCustom", "s": "theme:toggleSyntaxHighlighting" }, "context": "ThemePicker" }, { "bindings": { - "/": "settings:search" + "/": "settings:search", + "d": "settings:periodDay", + "escape": "settings:close", + "t": "settings:sortByTokens", + "w": "settings:periodWeek" }, "context": "Settings" }, @@ -74,7 +93,9 @@ }, { "bindings": { - "enter": "footer:openSelected" + "down": "footer:down", + "enter": "footer:openSelected", + "up": "footer:up" }, "context": "Footer" }, @@ -92,21 +113,56 @@ }, { "bindings": { + "d": "modelPicker:setAsDefault", "left": "modelPicker:decreaseEffort" }, "context": "ModelPicker" }, { "bindings": { - "enter": "select:accept" + "end": "select:last", + "enter": "select:accept", + "home": "select:first", + "pagedown": "select:pageDown", + "pageup": "select:pageUp" }, "context": "Select" }, { "bindings": { + "f": "plugin:favorite", "i": "plugin:install" }, "context": "Plugin" + }, + { + "bindings": { + "ctrl+b": "scroll:fullPageUp", + "ctrl+d": "scroll:halfPageDown", + "ctrl+f": "scroll:fullPageDown", + "ctrl+shift+c": "selection:copy", + "ctrl+u": "scroll:halfPageUp", + "down": "scroll:lineDown", + "end": "scroll:bottom", + "escape": "selection:clear", + "home": "scroll:top", + "pagedown": "scroll:pageDown", + "pageup": "scroll:pageUp", + "shift+down": "selection:extendDown", + "shift+end": "selection:extendLineEnd", + "shift+home": "selection:extendLineStart", + "shift+left": "selection:extendLeft", + "shift+right": "selection:extendRight", + "shift+up": "selection:extendUp", + "up": "scroll:lineUp" + }, + "context": "Scroll" + }, + { + "bindings": { + "f": "doctor:fix" + }, + "context": "Doctor" } ] } diff --git a/src/test/claude-code-keybindings/basic-bindings.json b/src/test/claude-code-keybindings/basic-bindings.json index 44a4bba835e..baa06936855 100644 --- a/src/test/claude-code-keybindings/basic-bindings.json +++ b/src/test/claude-code-keybindings/basic-bindings.json @@ -3,17 +3,134 @@ { "bindings": { "ctrl+c": "app:interrupt", - "ctrl+d": "app:exit" + "ctrl+d": "app:exit", + "ctrl+r": "history:search", + "ctrl+shift+d": "permission:toggleDebug", + "down": "history:next", + "up": "history:previous" }, "context": "Global" }, { "bindings": { "ctrl+e": "chat:externalEditor", + "ctrl+s": "chat:stash", + "ctrl+v": "chat:imagePaste", "ctrl+z": "chat:undo", - "enter": "chat:submit" + "enter": "chat:submit", + "escape": "chat:cancel", + "meta+p": "chat:modelPicker", + "meta+t": "chat:thinkingToggle", + "shift+tab": "chat:cycleMode" }, "context": "Chat" + }, + { + "bindings": { + "down": "autocomplete:next", + "escape": "autocomplete:dismiss", + "up": "autocomplete:previous" + }, + "context": "Autocomplete" + }, + { + "bindings": { + "ctrl+e": "confirm:toggleExplanation", + "ctrl+m": "confirm:cycleMode", + "down": "confirm:next", + "n": "confirm:no", + "shift+tab": "confirm:previousField", + "tab": "confirm:nextField", + "up": "confirm:previous" + }, + "context": "Confirmation" + }, + { + "bindings": { + "shift+tab": "tabs:previous" + }, + "context": "Tabs" + }, + { + "bindings": { + "ctrl+e": "transcript:toggleShowAll" + }, + "context": "Transcript" + }, + { + "bindings": { + "ctrl+r": "historySearch:next", + "ctrl+s": "historySearch:cycleScope", + "enter": "historySearch:execute", + "escape": "historySearch:cancel", + "tab": "historySearch:accept" + }, + "context": "HistorySearch" + }, + { + "bindings": { + "escape": "attachments:exit", + "left": "attachments:previous", + "right": "attachments:next" + }, + "context": "Attachments" + }, + { + "bindings": { + "escape": "footer:clearSelection", + "left": "footer:previous", + "right": "footer:next" + }, + "context": "Footer" + }, + { + "bindings": { + "ctrl+down": "messageSelector:bottom", + "ctrl+up": "messageSelector:top", + "down": "messageSelector:down", + "enter": "messageSelector:select", + "up": "messageSelector:up" + }, + "context": "MessageSelector" + }, + { + "bindings": { + "down": "diff:nextFile", + "enter": "diff:viewDetails", + "escape": "diff:back", + "left": "diff:previousSource", + "right": "diff:nextSource", + "up": "diff:previousFile" + }, + "context": "DiffDialog" + }, + { + "bindings": { + "d": "modelPicker:setAsDefault", + "left": "modelPicker:decreaseEffort", + "right": "modelPicker:increaseEffort" + }, + "context": "ModelPicker" + }, + { + "bindings": { + "down": "select:next", + "escape": "select:cancel", + "up": "select:previous" + }, + "context": "Select" + }, + { + "bindings": { + "space": "plugin:toggle" + }, + "context": "Plugin" + }, + { + "bindings": { + "r": "settings:retry" + }, + "context": "Settings" } ] } diff --git a/src/test/claude-code-settings/complete-config.json b/src/test/claude-code-settings/complete-config.json index cd30f417f74..8702ee9e323 100644 --- a/src/test/claude-code-settings/complete-config.json +++ b/src/test/claude-code-settings/complete-config.json @@ -24,5 +24,6 @@ "WebFetch(domain:bad.actor.com)" ] }, + "preferredNotifChannel": "terminal_bell", "viewMode": "default" } diff --git a/src/test/claude-code-settings/edge-cases.json b/src/test/claude-code-settings/edge-cases.json index 1f85fa4234f..4c91370b42c 100644 --- a/src/test/claude-code-settings/edge-cases.json +++ b/src/test/claude-code-settings/edge-cases.json @@ -1,16 +1,23 @@ { + "autoScrollEnabled": false, "autoUpdatesChannel": "stable", + "awaySummaryEnabled": false, "cleanupPeriodDays": 1, + "editorMode": "normal", "effortLevel": "low", "env": { + "CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT": "0", "CLAUDE_CODE_DEBUG_LOG_LEVEL": "info", + "CLAUDE_CODE_DISABLE_AGENT_VIEW": "0", "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN": "0", "CLAUDE_CODE_DISABLE_ATTACHMENTS": "0", "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "0", + "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "0", "CLAUDE_CODE_EFFORT_LEVEL": "max", "CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL": "0", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "0", "CLAUDE_CODE_FORCE_SYNC_OUTPUT": "0", + "CLAUDE_CODE_NATIVE_CURSOR": "0", "CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE": "0", "CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE": "0", "CLAUDE_CODE_PLUGIN_PREFER_HTTPS": "0", @@ -18,6 +25,8 @@ }, "fastMode": false, "forceLoginMethod": "claudeai", + "leftArrowOpensAgents": false, + "maxSkillDescriptionChars": 512, "parentSettingsBehavior": "first-wins", "permissions": { "allow": [], @@ -25,9 +34,11 @@ "defaultMode": "dontAsk", "deny": [] }, + "preferredNotifChannel": "iterm2_with_bell", "prefersReducedMotion": false, "respectGitignore": true, "showTurnDuration": true, + "skillListingBudgetFraction": 0.05, "skillOverrides": { "custom-skill": "on" }, @@ -38,6 +49,10 @@ }, "teammateMode": "in-process", "terminalProgressBarEnabled": true, + "voice": { + "enabled": false, + "mode": "hold" + }, "worktree": { "baseRef": "fresh", "bgIsolation": "worktree" diff --git a/src/test/claude-code-settings/model-opus.json b/src/test/claude-code-settings/model-opus.json index 3f9baf3a986..e57634c39cc 100644 --- a/src/test/claude-code-settings/model-opus.json +++ b/src/test/claude-code-settings/model-opus.json @@ -4,5 +4,6 @@ "CLAUDE_CODE_EFFORT_LEVEL": "auto" }, "includeCoAuthoredBy": true, - "model": "opus" + "model": "opus", + "preferredNotifChannel": "ghostty" } diff --git a/src/test/claude-code-settings/modern-complete-config.json b/src/test/claude-code-settings/modern-complete-config.json index 73c63c28b2e..6e8be4d813e 100644 --- a/src/test/claude-code-settings/modern-complete-config.json +++ b/src/test/claude-code-settings/modern-complete-config.json @@ -1,9 +1,15 @@ { "$schema": "https://www.schemastore.org/claude-code-settings.json", "agent": "code-reviewer", + "allowAllClaudeAiMcps": false, "allowManagedHooksOnly": false, "allowManagedPermissionRulesOnly": false, - "allowedChannelPlugins": ["internal-notifier@corp"], + "allowedChannelPlugins": [ + { + "marketplace": "claude-plugins-official", + "plugin": "internal-notifier" + } + ], "allowedHttpHookUrls": ["https://hooks.example.com/*", "http://localhost:*"], "alwaysThinkingEnabled": false, "apiKeyHelper": "/usr/local/bin/claude-auth-helper", @@ -19,8 +25,10 @@ "hard_deny": ["Running executable files", "Writing to system directories"], "soft_deny": ["$defaults", "Deleting files"] }, + "autoScrollEnabled": true, "autoUpdatesChannel": "latest", "availableModels": ["sonnet", "haiku"], + "awaySummaryEnabled": true, "awsAuthRefresh": "aws sso login --profile myprofile", "awsCredentialExport": "/bin/generate_aws_grant.sh", "blockedMarketplaces": [ @@ -37,10 +45,13 @@ "cleanupPeriodDays": 60, "companyAnnouncements": ["Welcome to the team!"], "defaultShell": "powershell", + "disableAgentView": false, "disableAllHooks": false, + "disableAutoMode": "disable", "disableDeepLinkRegistration": "disable", "disableSkillShellExecution": false, "disabledMcpjsonServers": ["untrusted-server"], + "editorMode": "vim", "effortLevel": "max", "enableAllProjectMcpServers": true, "enabledPlugins": { @@ -51,13 +62,17 @@ "ANTHROPIC_MODEL": "claude-3-5-sonnet-20241022", "ANTHROPIC_SMALL_FAST_MODEL": "claude-3-5-haiku-20241022", "ANTHROPIC_WORKSPACE_ID": "ws-abc123", + "CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT": "1", + "CLAUDE_CODE_DISABLE_AGENT_VIEW": "1", "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN": "1", "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1", + "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1", "CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL": "1", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1", "CLAUDE_CODE_FORCE_SYNC_OUTPUT": "1", "CLAUDE_CODE_FORK_SUBAGENT": "1", "CLAUDE_CODE_HIDE_CWD": "1", + "CLAUDE_CODE_NATIVE_CURSOR": "1", "CLAUDE_CODE_OPUS_4_6_FAST_MODE_OVERRIDE": "1", "CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE": "1", "CLAUDE_CODE_PLUGIN_PREFER_HTTPS": "1", @@ -84,6 +99,7 @@ "forceLoginMethod": "console", "forceLoginOrgUUID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "forceRemoteSettingsRefresh": false, + "gcpAuthRefresh": "gcloud auth application-default login", "hooks": { "ConfigChange": [ { @@ -267,6 +283,8 @@ "includeCoAuthoredBy": true, "includeGitInstructions": false, "language": "english", + "leftArrowOpensAgents": true, + "maxSkillDescriptionChars": 1536, "minimumVersion": "2.1.0", "model": "opus", "modelOverrides": { @@ -318,6 +336,7 @@ }, "pluginTrustMessage": "All plugins from our internal marketplace are pre-approved by the security team.", "prUrlTemplate": "https://reviews.example.com/{owner}/{repo}/pull/{number}", + "preferredNotifChannel": "iterm2", "prefersReducedMotion": true, "respectGitignore": false, "sandbox": { @@ -356,6 +375,7 @@ "showClearContextOnPlanAccept": true, "showThinkingSummaries": true, "showTurnDuration": false, + "skillListingBudgetFraction": 0.01, "skillOverrides": { "deploy": "off", "internal-tool": "user-invocable-only", @@ -374,6 +394,17 @@ "mode": "replace", "verbs": ["Analyzing", "Building"] }, + "sshConfigs": [ + { + "id": "dev-server", + "name": "Development Server", + "sshHost": "dev.example.com", + "sshIdentityFile": "~/.ssh/id_rsa", + "sshPort": 22, + "startDirectory": "/home/user/projects" + } + ], + "sshHostAllowlist": ["dev.example.com", "*.corp.example.com"], "statusLine": { "command": "~/.claude/statusline.sh", "hideVimModeIndicator": true, @@ -391,11 +422,17 @@ "tui": "default", "useAutoModeDuringPlan": true, "viewMode": "focus", + "voice": { + "autoSubmit": true, + "enabled": true, + "mode": "tap" + }, "voiceEnabled": true, "worktree": { "baseRef": "head", "bgIsolation": "none", - "sparsePaths": ["packages/my-app", "shared/utils"] + "sparsePaths": ["packages/my-app", "shared/utils"], + "symlinkDirectories": ["node_modules", ".pnp"] }, "wslInheritsWindowsSettings": false } diff --git a/src/test/claude-code-settings/notifications.json b/src/test/claude-code-settings/notifications.json index ea681d3cd20..9d989fd61d7 100644 --- a/src/test/claude-code-settings/notifications.json +++ b/src/test/claude-code-settings/notifications.json @@ -1,4 +1,4 @@ { - "preferredNotifChannel": "terminal_bell", + "preferredNotifChannel": "kitty", "theme": "dark-daltonized" } diff --git a/src/test/claude-code-settings/with-schema.json b/src/test/claude-code-settings/with-schema.json index 5be7ec4d75b..c3c8e132e83 100644 --- a/src/test/claude-code-settings/with-schema.json +++ b/src/test/claude-code-settings/with-schema.json @@ -1,6 +1,7 @@ { "$schema": "https://www.schemastore.org/claude-code-settings.json", "model": "sonnet", + "preferredNotifChannel": "auto", "theme": "light", "verbose": false }