fix: Bash(:*) is invalid; use unconstrained Bash instead

Claude Code rejects "Bash(:*)" with "Prefix cannot be empty before :*" —
the rule is silently skipped, which since 5b48f0d0 left no Bash entry
in the allowlist at all. Every coder agent's Bash call has been
auto-denying since that commit landed (~840 of 1.4k denials in the sled
log).

The canonical form for "allow all bash commands" is the tool name alone:
"Bash" (no parens). Apply it in three places that 5b48f0d0 touched:
  - .claude/settings.json (project root, inherited by new worktrees)
  - server/src/io/fs/scaffold/templates.rs (huskies init template)
  - server/src/io/fs/scaffold/tests.rs (assertion now checks "Bash")

The gateway settings.json at ~/Desktop/huskies/.claude/settings.json and
the four live worktrees (810, 888, 890, 894) were also corrected — not
in this commit since they live outside the repo.

Surfaced via /doctor; reported with rule "Invalid permission rule
Bash(:*) was skipped: Prefix cannot be empty before :*".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Timmy
2026-05-12 12:46:34 +01:00
parent 9be438e6d3
commit cd12cb5e2c
3 changed files with 11 additions and 9 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(:*)", "Bash",
"Read", "Read",
"Edit", "Edit",
"Write", "Write",
+1 -1
View File
@@ -70,7 +70,7 @@ setup wizard instructions and guide the user through it conversationally.\n";
pub(super) const STORY_KIT_CLAUDE_SETTINGS: &str = r#"{ pub(super) const STORY_KIT_CLAUDE_SETTINGS: &str = r#"{
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(:*)", "Bash",
"Read", "Read",
"Edit", "Edit",
"Write", "Write",
+9 -7
View File
@@ -614,13 +614,15 @@ fn scaffold_story_kit_claude_settings_uses_canonical_bash_syntax() {
); );
} }
// The wildcard `Bash(:*)` must be present — covers all bash commands. // The unconstrained `Bash` rule must be present — covers all bash commands.
// (Previously this asserted a curated per-command list; replaced with a // (Previously this asserted a curated per-command list; replaced with the
// single wildcard since coders kept hitting auto-deny on patterns the // tool-only form since coders kept hitting auto-deny on patterns the list
// list missed, and the per-command gate offers no real safety in this // missed, and the per-command gate offers no real safety in this trusted
// trusted single-user deployment.) // single-user deployment. The earlier `Bash(:*)` form was tried and
// rejected by Claude Code — empty prefix before `:*` is invalid and
// silently skipped.)
assert!( assert!(
settings.contains(r#""Bash(:*)""#), settings.contains(r#""Bash""#),
"settings.json missing wildcard Bash allowlist: {settings}" "settings.json missing unconstrained Bash allowlist: {settings}"
); );
} }