-
Notifications
You must be signed in to change notification settings - Fork 68
Description
I've been using copilot as one of my review agents for a while and only recently noticed the reviews felt shallow compared to other agents. Looking at the job output more carefully, I found the copilot CLI is hitting permission denials on most of its tool calls when run by the daemon.
Here's a trimmed example from a recent review:
✓ git --no-pager show --name-status --format=fuller --no-patch b75995e
24 lines...
✗ Get changed file paths and statuses (shell)
git --no-pager diff-tree --no-commit-id --name-status -r b75995e
Permission denied and could not request permission from user
✗ Validate JSONL and list new issues (shell)
python -c "import subprocess,json,sys; ..."
Permission denied and could not request permission from user
✓ Show diff for issues jsonl (shell)
git --no-pager show b75995e -- .beads/issues.jsonl
141 lines...
✗ Check issues jsonl validity and duplicates (shell)
python -c "import json,subprocess,collections; ..."
Permission denied and could not request permission from user
About half the tool calls fail. The first git command succeeds (likely auto-approved by copilot's defaults), but subsequent shell commands get denied because there's no user to approve them in the daemon context.
Looking at internal/agent/copilot.go, the current implementation passes no permission or non-interactive flags — it pipes the prompt via stdin and runs with default permissions:
cmd := exec.CommandContext(ctx, a.Command, args...)
cmd.Stdin = strings.NewReader(prompt)What the copilot CLI supports
The copilot CLI has several capabilities relevant to non-interactive use (from copilot --help, copilot help permissions, and the GitHub docs):
-p/--promptfor non-interactive mode ("exits after completion")-s/--silentto suppress stats, "useful for scripting with -p"--allow-all-toolsto auto-approve everything (the help says this is "required for non-interactive mode")- Granular
--allow-toolpatterns, e.g.--allow-tool='shell(git:*)'to allow git commands specifically --deny-toolto block specific commands (deny takes precedence over allow)--available-toolsto limit which tools the model can even see
The granular permission system is interesting because roborev's daemon is read-only by design. Something like --allow-tool='shell(git:*)' with --deny-tool='shell(git push)' could be a safer fit than blanket --allow-all-tools.
No per-repo permission config on copilot's side
Unlike Claude Code's .claude/settings.json which supports per-project permission overrides, the copilot CLI has no repo-level configuration for tool permissions. The closest repo-level files are .github/copilot-instructions.md (prompts, not permissions), .github/hooks/*.json (lifecycle hooks), and AGENTS.md (agent instructions) — none of which can set --allow-tool/--deny-tool defaults.
Permission configuration in copilot is strictly CLI flags at invocation time, the COPILOT_ALLOW_ALL env var, or interactive session prompts. So roborev would need to be the one passing these flags — users can't configure them on the copilot side per-repo. Something in .roborev.toml to expose agent-specific CLI flags could let users tune this per project.
Open questions
- Does stdin piping work as a prompt source, or is
-pneeded for proper non-interactive behavior? The help says-p"exits after completion" which suggests it changes the execution mode, not just the input source. - What's the right default permission set for a read-only review workflow?
Environment
- roborev v0.45.1
- copilot 1.0.10
- Windows 11, Git Bash