Permission patterns match subcommands in pipes, causing repeated prompts

Resolved 💬 3 comments Opened Feb 24, 2026 by ianegordon Closed Feb 27, 2026

Bug Description

Permission allow patterns match command names anywhere in a piped command, not just at the start. This causes repeated permission prompts that cannot be resolved.

Steps to Reproduce

  1. Add "Bash(tail *)" to ~/.claude/settings.json permissions allow list
  2. Run a command like swift test 2>&1 | tail -10
  3. Claude Code prompts for tail permission even though Bash(tail *) is in the allow list
  4. The command starts with swift test, not tail — but the permission system sees tail in the pipe

Additional Issue: Auto-append uses wrong syntax

When the user approves a prompted permission, it gets appended to settings.local.json using the :* syntax (e.g., "Bash(tail:*)") instead of the space syntax ("Bash(tail *)") documented in the settings. The colon syntax doesn't work, so:

  1. User gets prompted for tail
  2. User approves
  3. "Bash(tail:*)" is appended to settings (non-functional)
  4. Next time tail appears in a pipe, user is prompted again
  5. Loop repeats indefinitely

Expected Behavior

  • Bash(tail *) should match commands starting with tail, and should NOT trigger on tail appearing after a pipe character
  • OR piped subcommands should be individually matched against the allow list
  • Auto-appended permissions should use the working syntax format

Environment

  • macOS (Darwin 25.3.0)
  • Claude Code CLI
  • Model: claude-opus-4-6

Impact

This creates an infuriating user experience where the same permission is requested repeatedly despite being granted and saved. Users cannot resolve it through the normal approval flow.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗