Skip to content

Render Claude permission suggestions as a selectable picker - #9

Merged
jason810496 merged 3 commits into
mainfrom
feat/claude-permission-picker
Jun 22, 2026
Merged

jason810496 merged 3 commits into
mainfrom
feat/claude-permission-picker

Conversation

@jason810496

Copy link
Copy Markdown
Owner

Render Claude permission suggestions as a selectable picker

Why

Claude permission requests can offer several suggestions at different scopes (the exact command, a prefix glob, all Bash, a permission mode, etc.), but the built-in dialog collapsed them behind a single Always Allow button that applied every suggestion and previewed only the first rule, so the user could neither see the full scope nor choose between them.

How

  • When a Claude PermissionRequest carries permission_suggestions, render a native choose from list picker instead of the three-button dialog.
    • The picker lists Allow once plus one entry per suggestion, labeled exactly as Claude sent the rule (for example Bash(git *), Edit(src/**), Write(src/**), or a non-rule scope such as mode: acceptEdits). No editorialized "Always allow" prefix, since every entry below Allow once is inherently an always-allow.
    • Selecting a rule returns behavior: "allow" with updatedPermissions containing only the chosen suggestion, scoped to session; Allow once allows with no persisted rule; Deny (or dismissing) denies.
  • The picker reuses the existing choose from list transport protocol. On non-macOS hosts, disabled osascript, or a picker failure it falls back to the standard three-button dialog, which now lists every suggested rule instead of only the first.
  • The picker is Claude-only and skips AskUserQuestion payloads, which keep their own picker flow.

What

  • New display models: PermissionChoice, PermissionChoiceDialogSpec, PermissionChoiceDialogResult; broaden DisplaySpec to include the picker and AskUserQuestion specs.
  • New packaged script permission_choice.applescript (choose from list with Select / Deny buttons).
  • Transport: show_permission_choice_dialog + cached script getter; rename the shared choose from list sentinels so the picker and AskUserQuestion flows reuse them.
  • Claude provider: is_permission_choice_payload, build_permission_choice_dialog, build_permission_choice_response, and describe_permission_rule / describe_permission_suggestion helpers; build_permission_dialog now lists every suggested rule (replacing the first-rule-only preview).
  • Default handler: handle_permission_choice wired into handle_permission_request ahead of the standard-dialog fallback.
  • Enum: add AppleScriptInvocation.PERMISSION_CHOICE.
  • Tests: picker presentation and gating, transport (selection / dismissal / script error / out-of-range index / osacompile), and the full handler flow (single-suggestion persistence, allow-once, deny, and skip/fail/no-picker fallbacks).
  • Docs: README and the Claude Code provider page.

Verification

  • uv run --group dev pytest -> 172 passed; ruff check clean; prek --all-files passes.
  • Manually rendered the native picker by piping crafted multi-suggestion payloads into agent-hooks callback --provider claude-code, confirming each suggestion appears as its own choice and that only the selected scope lands in updatedPermissions.

Claude permission requests can offer multiple permission suggestions (for example the exact command, a prefix glob, or all Bash). The built-in dialog previously collapsed them behind a single "Always Allow" button that applied every suggestion and only previewed the first rule.

Show each suggestion as its own choice in a native choose-from-list picker: "Allow once" plus one entry per suggestion, labeled exactly as Claude sent the rule. Selecting a rule persists only that suggestion as a session rule; Deny or dismiss denies. The three-button dialog remains the fallback for non-macOS hosts, disabled osascript, or picker failures, and now lists every suggested rule.
@jason810496

Copy link
Copy Markdown
Owner Author

/gemini review

@jason810496

Copy link
Copy Markdown
Owner Author

@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an interactive, native permission picker for Claude Code permission requests on macOS using AppleScript. Instead of collapsing all permission suggestions under a single "Always Allow" button, each suggestion is rendered as a separate choice in a list picker, allowing users to persist only the specific scope they select. A fallback to the standard three-button dialog is provided if the picker is unavailable or fails. The review feedback identifies two key improvement opportunities: first, handling duplicate suggestion labels to prevent AppleScript from incorrectly returning the index of the first matching string, and second, treating an invalid or unparseable choice index as a transport failure rather than a user dismissal to ensure a graceful fallback to the standard dialog.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/agent_hooks/providers/claude_code/presentation.py
Comment thread src/agent_hooks/transport.py Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements an interactive permission picker for Claude Code permission requests, allowing users to select specific permission suggestions to persist as session rules. It adds a native macOS picker using AppleScript, with a robust fallback to the standard three-button dialog on unsupported platforms or transport failures. The review feedback identifies a potential out-of-bounds error in the AppleScript loop when fewer than four arguments are provided, and notes a limitation where duplicate option labels in the picker will always resolve to the first occurrence.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/agent_hooks/assets/permission_choice.applescript
Comment thread src/agent_hooks/assets/permission_choice.applescript

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0870bcd9a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agent_hooks/assets/permission_choice.applescript
When two permission suggestions render to the same label, choose-from-list returns only the selected text and the picker maps it back by first match, so a later duplicate would persist the first suggestion's rule. Append a counted suffix to duplicate labels so each maps to the correct suggestion; unique labels are left untouched.

Also treat an "OK" picker status with a missing or out-of-range index as a transport failure rather than a successful dismissal, so the handler falls back to the standard dialog instead of silently denying the request.
@jason810496

Copy link
Copy Markdown
Owner Author

Round 1 review addressed in 76b0ba0:

Addressed (valid):

  • Duplicate picker labels (Gemini × @gemini-code-assist + Codex × @chatgpt-codex-connector): identical suggestion labels would all resolve to the first choose from list match and persist the wrong suggestion. build_permission_choice_dialog now appends a counted suffix (e.g. Bash(git *) (2)) to genuine duplicates so each maps to the correct suggestion_index; unique labels are left untouched. Added a regression test.
  • Unparseable/out-of-range choice index (Gemini): an OK status with a bad index returned SUCCEEDED + no choice, which the handler treated as a dismissal and silently denied. It now returns TransportStatus.FAILED so the handler falls back to the standard dialog. Updated the test accordingly.

Skipped (invalid):

  • repeat with i from 4 to (count of argv) out-of-bounds when <4 args (Gemini): verified empirically that AppleScript runs a backwards range with the default +1 step as 0 iterations (no backward iteration, no out-of-bounds), and the real script returns CANCELLED cleanly when invoked with 3 args. The premise that it loops backwards into item 4 is incorrect. The real code path also never passes <4 args, since the picker only renders when there is ≥1 suggestion. No change.

All 173 tests pass; ruff/prek clean.

@jason810496

Copy link
Copy Markdown
Owner Author

/gemini review

@jason810496

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an interactive permission picker for Claude Code permission requests, allowing users to select and persist specific permission suggestions as session rules on macOS using AppleScript, with a fallback to the standard dialog on other platforms or in case of failure. The feedback highlights a robustness issue in format_permission_suggestions_preview where suggestions with empty rules might be omitted entirely from the preview instead of falling back to non-rule fields, and suggests a code change to handle this fallback correctly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/agent_hooks/providers/claude_code/presentation.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 76b0ba0060

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agent_hooks/providers/claude_code/presentation.py Outdated
…sible

Round-2 review fixes:

- The duplicate-label suffix is now generated against the set of labels already used, not just the base label, so a synthetic suffix like "foo (2)" can no longer collide with another suggestion's real label and persist the wrong scope.
- format_permission_suggestions_preview now computes the non-empty rule labels first and falls back to the suggestion-level description (mode / directories / id) when a suggestion's rules all render empty, instead of dropping the suggestion from the fallback dialog.
@jason810496

Copy link
Copy Markdown
Owner Author

Round 2 review addressed in 939d6e3 (both findings valid):

  • Globally-unique picker labels (@chatgpt-codex-connector): the duplicate-label suffix is now bumped against the set of labels already rendered, not just the base label, so a synthesized foo (2) can no longer collide with another suggestion that is literally labeled foo (2) and persist the wrong scope. Added a regression test (dup (2), dup, dup -> dup (2), dup, dup (3)).
  • Preview keeps empty-rule suggestions (@gemini-code-assist): format_permission_suggestions_preview now collects non-empty rule labels first and falls back to the suggestion-level description (mode / directories / id) when all rules render empty, so such a suggestion is no longer dropped from the fallback dialog. Added a regression test.

All 175 tests pass; ruff/prek clean.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@jason810496

Copy link
Copy Markdown
Owner Author

/gemini review

@jason810496

Copy link
Copy Markdown
Owner Author

@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an interactive permission picker for Claude Code permission requests, allowing users to select and persist specific permission suggestions individually rather than accepting all suggestions at once. The implementation includes a new AppleScript picker (permission_choice.applescript) for macOS, updated schemas, fallback logic to standard dialogs when the picker is unavailable or fails, and comprehensive unit tests. No review comments were provided, and the implementation looks clean and complete.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 939d6e3394

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jason810496
jason810496 merged commit c56f4fb into main Jun 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant