fix: respect Claude's defaultMode from settings.json as permission mode default#528
fix: respect Claude's defaultMode from settings.json as permission mode default#528ye4241 wants to merge 1 commit intotiann:mainfrom
Conversation
…de default When hapi spawns a session without an explicit permissionMode, it was hardcoded to 'default', ignoring the user's `permissions.defaultMode` setting in ~/.claude/settings.json (e.g. 'auto'). Now reads Claude's settings.json via the existing readClaudeSettings() utility and uses its defaultMode as the fallback, keeping 'default' as the final fallback for users without the setting configured.
There was a problem hiding this comment.
Pull request overview
Adjusts Claude session startup so hapi can respect the user’s configured default permission mode from ~/.claude/settings.json instead of always falling back to 'default', reducing unexpected permission prompts.
Changes:
- Import and call
readClaudeSettings()duringrunClaude()startup. - Derive a
claudeDefaultModefromclaudeSettings?.permissions?.defaultMode. - Use Claude’s default mode as the fallback when
options.permissionModeis not provided.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let currentPermissionMode: PermissionMode = options.permissionMode ?? 'default'; | ||
| const claudeSettings = readClaudeSettings(); | ||
| const claudeDefaultMode = claudeSettings?.permissions?.defaultMode as PermissionMode | undefined; | ||
| let currentPermissionMode: PermissionMode = options.permissionMode ?? claudeDefaultMode ?? 'default'; |
| // Forward messages to the queue | ||
| let currentPermissionMode: PermissionMode = options.permissionMode ?? 'default'; | ||
| const claudeSettings = readClaudeSettings(); | ||
| const claudeDefaultMode = claudeSettings?.permissions?.defaultMode as PermissionMode | undefined; |
There was a problem hiding this comment.
Findings
- [Major] Validate
permissions.defaultModebefore using it as a HAPI permission mode —settings.jsonis arbitrary JSON, but the new cast accepts any value. HAPI's Claude mode set isdefault | acceptEdits | bypassPermissions | plan, so values such as the PR'sautoexample can be forwarded as runtime permission modes and then passed to Claude as--permission-mode <value>, which can break remote startup or leave HAPI's permission handler in an unsupported mode. Evidence:cli/src/claude/runClaude.ts:156.
Suggested fix:If Claude settings can use aliases such asconst configuredDefaultMode = claudeSettings?.permissions?.defaultMode; const parsedDefaultMode = PermissionModeSchema.safeParse(configuredDefaultMode); const claudeDefaultMode: PermissionMode | undefined = parsedDefaultMode.success && isPermissionModeAllowedForFlavor(parsedDefaultMode.data, 'claude') ? parsedDefaultMode.data as PermissionMode : undefined;
auto, normalize those aliases before this validation.
Summary
- Review mode: initial
- One major issue found: unsupported Claude settings values can now escape the type system and become active HAPI permission modes.
Testing
- Not run (automation)
HAPI Bot
| // Forward messages to the queue | ||
| let currentPermissionMode: PermissionMode = options.permissionMode ?? 'default'; | ||
| const claudeSettings = readClaudeSettings(); | ||
| const claudeDefaultMode = claudeSettings?.permissions?.defaultMode as PermissionMode | undefined; |
There was a problem hiding this comment.
[MAJOR] Validate permissions.defaultMode before using it as a HAPI permission mode.
This cast turns arbitrary settings.json content into PermissionMode. HAPI's Claude modes are default | acceptEdits | bypassPermissions | plan, so values such as the PR's auto example can flow into the message queue and then to Claude as --permission-mode <value>. That can break remote startup or leave HAPI's permission handler in an unsupported mode.
Suggested fix:
const configuredDefaultMode = claudeSettings?.permissions?.defaultMode;
const parsedDefaultMode = PermissionModeSchema.safeParse(configuredDefaultMode);
const claudeDefaultMode: PermissionMode | undefined =
parsedDefaultMode.success && isPermissionModeAllowedForFlavor(parsedDefaultMode.data, 'claude')
? parsedDefaultMode.data as PermissionMode
: undefined;If Claude settings can use aliases such as auto, normalize those aliases before this validation.
|
Closing in favor of #529 which includes this backend fix along with the full permission mode selector UI feature. |
Problem
When hapi spawns a Claude session (especially via runner), the
permissionModeis hardcoded to'default':This ignores the user's
permissions.defaultModeconfigured in~/.claude/settings.json. For example, users who set"defaultMode": "auto"in their Claude settings will find that hapi overrides it withdefault, causing unexpected permission prompts on every tool call.Fix
Use the existing
readClaudeSettings()utility (already imported in the codebase forincludeCoAuthoredBy) to readpermissions.defaultModefrom Claude's settings and use it as the fallback:Priority: explicit hapi
permissionMode> Claude'sdefaultMode>'default'Test
"permissions": { "defaultMode": "auto" }in~/.claude/settings.jsonpermissionMode=autoinstead ofpermissionMode=default