claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

Cycleable Scope for "Don't Ask Again" Permission Prompts

Open 4umo opened this issue 1 month ago • 2 comments

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Claude Code appropriately asks for permission before using tools. However, when I select "Yes, and don't ask again for [tool]," the decision only saves to my local project settings. Since I work across many projects, this creates a workflow problem: I must either manually copy (and generalize) permission rules from .claude/settings.local.json to my project settings or global settings in ~/.claude/settings.json, or tolerate repeated approval prompts for the same tools in every project.

This friction significantly slows my workflow. While maintaining granular control over tool permissions is essential for security, the current implementation makes it unnecessarily tedious to uphold least-privilege principles across multiple projects.

Proposed Solution

Feature Request: Cycleable Scope for "Don't Ask Again" Permission Prompts

Summary

Enhance the "don't ask again" option in tool permission prompts to allow users to cycle between different scopes (local project, user, project) using the Tab key, rather than requiring separate menu options.

Current Behavior

When Claude Code requests permission to use a tool, users see three options:

Do you want to allow Claude to fetch this content?
❯ 1. Yes
  2. Yes, and don't ask again for github.com
  3. No, and tell Claude what to do differently (esc)

Option 2 saves the preference to .claude/settings.local.json (local project settings, git-ignored) only.

Proposed Behavior

Option 2 becomes cycleable - pressing Tab rotates through available scopes:

Do you want to allow Claude to fetch this content?
❯ 1. Yes
  2. Yes, and don't ask again for github.com (local project) [Tab to cycle]
  3. No, and tell Claude what to do differently (esc)

Pressing Tab on option 2 cycles through:

  1. Local project.claude/settings.local.json (git-ignored) - Default
  2. User~/.claude/settings.json (applies to all projects)
  3. Project.claude/settings.json (shared with team, version controlled)
  4. Back to Local project (cycles continuously)

Visual feedback as user tabs:

  2. Yes, and don't ask again for github.com (local project) [Tab to cycle]
[Tab pressed]
  2. Yes, and don't ask again for github.com (user) [Tab to cycle]
[Tab pressed]
  2. Yes, and don't ask again for github.com (project) [Tab to cycle]
[Tab pressed]
  2. Yes, and don't ask again for github.com (local project) [Tab to cycle]

Alternative Solutions

Currently I have to periodically manually copy and generalize rules from my local settings to my project and user settings. It's tedious.

Priority

Medium - Would be very helpful

Feature Category

Interactive mode (TUI)

Use Case Example

Use Cases

1. Trusted Tools/Domains (User Scope)

Users who frequently work with trusted tools can Tab to "user" to approve once across all projects.

2. Team Conventions (Project Scope)

Teams can Tab to "project" to version-control shared approval preferences (e.g., allow WebFetch to company docs).

3. Personal Experiments (Local Project Scope)

Developers can keep experimental approvals in local project settings, git-ignored (default behavior).

4. Quick Decision Making

Single option with Tab cycling is faster than navigating through 4-5 menu options, while still providing full control.

Additional Context

Estimated Implementation Details

Code Location

The approval prompt logic is in the compiled cli.js at approximately line 2028:

A.onAllow(A.input, [
  {
    type: "addRules",
    rules: [{ toolName: A.tool.name }],
    behavior: "allow",
    destination: "localSettings", // Currently hardcoded
  },
]);

Proposed Changes

The codebase already supports multiple destination types:

  • "localSettings" - .claude/settings.local.json (project, git-ignored)
  • "userSettings" - ~/.claude/settings.json (global, all projects)
  • "projectSettings" - .claude/settings.json (project, version controlled)

Implementation Approach

  1. Add state tracking for scope cycling:

    • Track current scope selection in prompt state
    • Default to "localSettings" (maintains current behavior)
    • Tab key cycles through: local project → user → project → local project
  2. Update prompt rendering:

    • Display current scope in parentheses: (local project), (user), (project)
    • Show [Tab to cycle] hint
    • Update display in real-time as user tabs
  3. Modify destination assignment:

    • Read the current scope state when user selects option 2
    • Map scope to destination:
      • local project"localSettings"
      • user"userSettings"
      • project"projectSettings"
  4. Conditional availability:

    • Apply existing logic that determines when "don't ask again" is available
    • If available, all three scopes should be cycleable
    • Maintain existing restrictions for context-specific actions

Similar Patterns in Codebase

Based on code analysis, destination patterns exist for:

  • File path permissions: destination:"session" (line ~1343)
  • Bash commands: destination:"localSettings" (line ~2028)
  • These show the infrastructure already supports multiple scopes

UI/UX Details

Visual States

Default (no Tab pressed):

❯ 2. Yes, and don't ask again for github.com (local project) [Tab to cycle]

After Tab to user:

❯ 2. Yes, and don't ask again for github.com (user) [Tab to cycle]

After Tab to project:

❯ 2. Yes, and don't ask again for github.com (project) [Tab to cycle]

Keyboard Interaction

  • Arrow keys: Navigate between options 1, 2, 3
  • Tab key (when option 2 is selected): Cycle through scopes
  • Enter/Return: Confirm selection with current scope
  • Escape: Select option 3 (No)

Alternative: Shift+Tab for Reverse Cycling

Support both directions:

  • Tab: local project → user → project → local project
  • Shift+Tab: local project → project → user → local project

Benefits Over Multi-Option Approach

Advantages

  1. Cleaner UI: Three options instead of 5+
  2. Discoverability: [Tab to cycle] hint teaches the feature
  3. Muscle Memory: Tab is intuitive for cycling through alternatives
  4. Flexibility: Easy to add more scopes in future without UI clutter
  5. Speed: Fewer arrow key presses, faster decision-making

Comparison

Multi-option approach:

1. Yes
2. Yes, and don't ask again (local project)
3. Yes, and don't ask again (user)
4. Yes, and don't ask again (project)
5. No, and tell Claude what to do differently
  • Requires 4 arrow key presses to reach "No"
  • Visual clutter
  • Harder to scan

Cycleable approach:

1. Yes
2. Yes, and don't ask again (local project) [Tab to cycle]
3. No, and tell Claude what to do differently
  • Requires 2 arrow key presses to reach "No"
  • Clean, focused
  • Progressive disclosure of complexity

Risk Mitigation

Security Considerations

  1. Safe Default: Always starts at "local project" scope, maintaining current behavior
  2. Explicit Action: User must deliberately press Tab to change scope
  3. Clear Labels: Scope indicator makes the impact obvious
  4. Easy Reversal: All scopes can be edited via /permissions or settings files

Accidental Misuse

  • Tab is deliberate: Unlikely to be pressed accidentally
  • Visual feedback: Scope changes immediately on screen
  • Familiar pattern: Similar to IDE autocomplete cycling

User Understanding

  • First-time hint: Could show tooltip on first use explaining scopes
  • Documentation: Update /permissions help text to explain scopes
  • Consistent labels: Use same terminology everywhere (local project/user/project)

Edge Cases

1. Policy Restrictions

If enterprise policy prevents user settings, hide "user" from cycle:

2. Yes, and don't ask again (local project) [Tab to cycle]
   → Tabs to project, skips user, back to local project

2. Non-Git Repositories

If not in a git repo, "project" scope might be less relevant:

  • Option A: Still allow it (creates .claude/settings.json)
  • Option B: Skip "project" in cycle for non-git directories
  • Recommendation: Option A for consistency

3. Single Scope Available

If only one scope is allowed (e.g., due to policy), don't show [Tab to cycle]:

2. Yes, and don't ask again (local project)

4umo avatar Nov 05 '25 20:11 4umo

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 10 '25 10:12 github-actions[bot]

This is still a very good idea and much needed. "Housekeeping purposes" is poor justification for auto-closing a valid feature request which has not been responded to in a timely manner.

Auto-close bots are harmful to community contributions:

  • Auto-closing without proper resolution is disrespectful to the original reporter and anyone else who contributed to the report.
  • It just sweeps the issue under the carpet, blindly hoping that it will magically fix itself. (The fact that this can sometimes happen doesn't justify doing it in all the other cases.)
  • When issues or feature requests are marked as closed without resolution, then people are more likely to miss them, resulting in duplicate reports and consequently fragmented information.
  • People searching for ways to contribute are much more likely to miss closed issues too.
  • Long-standing issues are less likely to get resolved. Here's an example of a success story when issues remained open for a long time.

See also this post.

I understand it is annoying to have open issues going nowhere. One solution for this is to label short-lived and long-lived issues differently to distinguish them. Another is assigning issues to different milestones. This makes it clear to users which issues are likely to be fixed sooner rather than later.

aspiers avatar Dec 13 '25 00:12 aspiers