Problem
Every Claude Code session kicked off by /crow-workspace (and /crow-batch-workspace) lands in a fresh worktree directory and immediately starts prompting the user to approve common, low-risk commands that the prompt template itself instructs the session to run. Examples observed during a single session:
Bash(gh issue view <url> --comments)
Bash(gh issue view <number> --repo <owner/repo> --comments)
Bash(gh issue view ... 2>&1 | tee /tmp/claude/issue415.txt)
- Output redirection variants (
> /tmp/claude/..., tee ...)
Each prompt requires manual approval, which:
- Defeats the purpose of auto-launched sessions. The prompt template explicitly tells the session to call
gh issue view ... as step 1. The user has already implicitly authorized it by invoking /crow-workspace.
- Multiplies friction in batch mode. With
/crow-batch-workspace running 3–5 sessions in parallel, the user has to context-switch to each tab to approve the same commands.
- Has no analog in the Manager session, which already has a comprehensive allow list at
/Users/dustinhilgaertner/Dev2/.claude/settings.json (the dev root .claude/settings.json). Worktree sessions don't inherit this — they're rooted under {devRoot}/{workspace}/{repo}-{n}-{slug}/, and Claude Code only reads settings from the worktree (and ancestors) at launch time.
Root Cause
setup.sh creates the worktree, registers the session, writes the prompt file, and launches Claude Code — but it does not drop a .claude/settings.local.json (or equivalent) into the worktree with a baseline allow list. So the worktree session inherits whatever the repo itself ships (often nothing relevant) and prompts for everything.
Proposal
Scaffold a baseline .claude/settings.local.json into each worktree as part of setup.sh, before launching Claude Code. The contents should mirror the Manager's tested allow list, scoped to the kinds of commands the crow prompt template instructs sessions to run.
Suggested baseline allow list
Implementation sketch
In setup.sh, after setup_worktree and before launch_claude:
write_session_settings() {
local settings_dir="$WORKTREE_PATH/.claude"
local settings_path="$settings_dir/settings.local.json"
mkdir -p "$settings_dir"
# Don't clobber an existing settings.local.json (e.g. checked in by the repo)
if [[ -f "$settings_path" ]]; then
log "settings.local.json already exists, leaving untouched"
return
fi
# Source the baseline from a versioned template under the skill
cp "$SCRIPT_DIR/session-settings.template.json" "$settings_path"
log "Wrote baseline allow list to $settings_path"
}
The template lives next to setup.sh so it's editable in one place and version-controlled.
Open questions / things to bikeshed
- Location:
.claude/settings.local.json (gitignored by Claude Code's defaults) is the right choice — won't get committed by accident. Confirm Claude Code reads it.
- Merge vs. overwrite: if the repo already has a
.claude/settings.json with its own allow list, the worktree's settings.local.json will be merged on top. Verify the precedence works in our favor.
- Per-repo overrides: some repos might want different defaults (e.g. corveil might want
bun *, citadel might want go test *). Could support an optional per-repo template at {repo_root}/.claude/crow-session-allow.json that we additionally merge. Not blocking — punt to a follow-up.
- Skill files vs. dev-root: prefer dropping the template in the skill directory (
.claude/skills/crow-workspace/) over hardcoding in the script, so editing the allowlist doesn't require editing bash.
Acceptance criteria
Problem
Every Claude Code session kicked off by
/crow-workspace(and/crow-batch-workspace) lands in a fresh worktree directory and immediately starts prompting the user to approve common, low-risk commands that the prompt template itself instructs the session to run. Examples observed during a single session:Bash(gh issue view <url> --comments)Bash(gh issue view <number> --repo <owner/repo> --comments)Bash(gh issue view ... 2>&1 | tee /tmp/claude/issue415.txt)> /tmp/claude/...,tee ...)Each prompt requires manual approval, which:
gh issue view ...as step 1. The user has already implicitly authorized it by invoking/crow-workspace./crow-batch-workspacerunning 3–5 sessions in parallel, the user has to context-switch to each tab to approve the same commands./Users/dustinhilgaertner/Dev2/.claude/settings.json(the dev root.claude/settings.json). Worktree sessions don't inherit this — they're rooted under{devRoot}/{workspace}/{repo}-{n}-{slug}/, and Claude Code only reads settings from the worktree (and ancestors) at launch time.Root Cause
setup.shcreates the worktree, registers the session, writes the prompt file, and launches Claude Code — but it does not drop a.claude/settings.local.json(or equivalent) into the worktree with a baseline allow list. So the worktree session inherits whatever the repo itself ships (often nothing relevant) and prompts for everything.Proposal
Scaffold a baseline
.claude/settings.local.jsoninto each worktree as part ofsetup.sh, before launching Claude Code. The contents should mirror the Manager's tested allow list, scoped to the kinds of commands the crow prompt template instructs sessions to run.Suggested baseline allow list
{ "permissions": { "allow": [ // Ticket / PR inspection (the prompt template runs these on step 1) "Bash(gh issue view:*)", "Bash(gh issue list:*)", "Bash(gh issue edit:*)", "Bash(gh pr view:*)", "Bash(gh pr list:*)", "Bash(gh pr diff:*)", "Bash(gh pr checks:*)", "Bash(gh pr create:*)", "Bash(gh pr edit:*)", "Bash(gh pr review:*)", "Bash(gh pr comment:*)", "Bash(gh repo view:*)", "Bash(gh api graphql:*)", "Bash(gh api repos:*)", "Bash(gh auth status:*)", "Bash(gh search:*)", // GitLab equivalents "Bash(GITLAB_HOST=* glab issue view:*)", "Bash(GITLAB_HOST=* glab mr view:*)", "Bash(GITLAB_HOST=* glab mr list:*)", "Bash(GITLAB_HOST=* glab mr create:*)", "Bash(GITLAB_HOST=* glab auth status:*)", "Bash(glab issue view:*)", "Bash(glab mr view:*)", "Bash(glab mr list:*)", // Git operations a feature branch needs "Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(git show:*)", "Bash(git fetch:*)", "Bash(git pull:*)", "Bash(git push:*)", "Bash(git add:*)", "Bash(git commit:*)", "Bash(git checkout:*)", "Bash(git branch:*)", "Bash(git stash:*)", "Bash(git rebase:*)", "Bash(git merge:*)", "Bash(git -C:*)", "Bash(git ls-remote:*)", "Bash(git worktree:*)", // Shell utilities the agent reaches for constantly "Bash(cat:*)", "Bash(cat >:*)", "Bash(head:*)", "Bash(tail:*)", "Bash(grep:*)", "Bash(rg:*)", "Bash(ls:*)", "Bash(find:*)", "Bash(which:*)", "Bash(which -a:*)", "Bash(sleep:*)", "Bash(mkdir -p:*)", "Bash(tee:*)", "Bash(wc:*)", "Bash(jq:*)", // Output redirection to scratch space "Bash(* > $TMPDIR/*)", "Bash(* > /tmp/claude/*)", "Bash(* | tee $TMPDIR/*)", "Bash(* | tee /tmp/claude/*)", // crow CLI (sessions sometimes self-introspect) "Bash(crow get-session:*)", "Bash(crow list-worktrees:*)", "Bash(crow list-links:*)", "Bash(crow set-status:*)", // First-party Claude Code tools "Read", "Write", "Edit", "Glob", "Grep" ] } }Implementation sketch
In
setup.sh, aftersetup_worktreeand beforelaunch_claude:The template lives next to
setup.shso it's editable in one place and version-controlled.Open questions / things to bikeshed
.claude/settings.local.json(gitignored by Claude Code's defaults) is the right choice — won't get committed by accident. Confirm Claude Code reads it..claude/settings.jsonwith its own allow list, the worktree'ssettings.local.jsonwill be merged on top. Verify the precedence works in our favor.bun *, citadel might wantgo test *). Could support an optional per-repo template at{repo_root}/.claude/crow-session-allow.jsonthat we additionally merge. Not blocking — punt to a follow-up..claude/skills/crow-workspace/) over hardcoding in the script, so editing the allowlist doesn't require editing bash.Acceptance criteria
setup.shwrites a baseline.claude/settings.local.jsoninto each new worktree before launching Claude Code.gh issue view,glab issue view,gh pr view)..claude/settings.local.jsonfiles in a worktree are not overwritten./crow-workspaceruns the entire "study the ticket → propose plan" flow without permission prompts on the listed commands.