feat(claude): leave only git fetch origin unasked #206

Merged
claudiomaradonna merged 2 commits from fetch-origin-exclusion into main 2026-11-09 15:13:19 +01:00
Collaborator

Why

Every change starts with open-worktree, which runs git fetch on the
main branch's remote. The Bash(git fetch *) ask rule made Claude Code
prompt for that fetch in every permission mode, bypassPermissions
included, so a session running several changes answered the same prompt
each time. The rule guarded the git fetch * sandbox exclusion, which a
quoted, escaped, or variable spelling of --upload-pack could ride out
of the sandbox past the text deny rule.

Set aside: keeping the ask rule, which keeps the prompt; a Bash
PreToolUse hook that checks which repository the fetch runs in, a new
mechanism that needs its own design; dropping the ask on git pull and
git push too, which saves no prompt a workflow meets.

What changed

Before, any git fetch left the sandbox and asked first. Now only the
exact command git fetch origin leaves it, with no ask rule: it follows
the permission mode, asking in Manual and acceptEdits unless a
developer's allow rule covers it, going to the classifier in auto mode,
and running unasked in bypassPermissions. A fetch with options, quotes,
escapes, or variables, or of another remote, runs sandboxed and falls to
the usual unsandboxed retry when it fails. git pull and git push keep
their exclusion and their ask rule.

The README's sandbox paragraph now names the three git commands that
leave the sandbox, says when each prompts in each mode and why pull and
push always ask, and states the residual below.

How to verify

In a Claude Code session on the branch where the sandbox starts, in
bypassPermissions mode, ask Claude to run git fetch origin: it runs
with no prompt, where main asks first. Then ask it to run
git fetch --prune origin: it runs sandboxed, and over SSH fails and is
retried outside the sandbox. git push origin <branch> still prompts.

On b9215a5, bash tests/verify-agent-config.sh (231 tests),
bash tests/check-work-folder.sh, .agents/hooks/shellcheck.sh repo,
prettier --check '**/*.md', scripts/verify-agent-config.sh, and
git diff --check main pass; the rewritten settings assertion fails on
main. Not tried: a live session, since the sandbox could not start in
the container the work ran in, so whether git fetch origin prompts in
Manual mode, outside Claude Code's read-only git set, is unconfirmed.

Considerations

The exact exclusion fixes the command text, not the repository it runs
in. A sandboxed command can prepare a repository outside the checkout's
protected .git, and the unasked fetch then runs with its
configuration, so an injected instruction could have it run a program on
the host with no prompt in auto mode or under a developer's allow rule.
The maintainer accepts that for the fetch every change starts with; in
bypassPermissions an unsandboxed retry already runs unasked.

## Why Every change starts with `open-worktree`, which runs `git fetch` on the main branch's remote. The `Bash(git fetch *)` ask rule made Claude Code prompt for that fetch in every permission mode, `bypassPermissions` included, so a session running several changes answered the same prompt each time. The rule guarded the `git fetch *` sandbox exclusion, which a quoted, escaped, or variable spelling of `--upload-pack` could ride out of the sandbox past the text deny rule. Set aside: keeping the ask rule, which keeps the prompt; a Bash `PreToolUse` hook that checks which repository the fetch runs in, a new mechanism that needs its own design; dropping the ask on `git pull` and `git push` too, which saves no prompt a workflow meets. ## What changed Before, any `git fetch` left the sandbox and asked first. Now only the exact command `git fetch origin` leaves it, with no ask rule: it follows the permission mode, asking in Manual and `acceptEdits` unless a developer's allow rule covers it, going to the classifier in auto mode, and running unasked in `bypassPermissions`. A fetch with options, quotes, escapes, or variables, or of another remote, runs sandboxed and falls to the usual unsandboxed retry when it fails. `git pull` and `git push` keep their exclusion and their ask rule. The README's sandbox paragraph now names the three git commands that leave the sandbox, says when each prompts in each mode and why pull and push always ask, and states the residual below. ## How to verify In a Claude Code session on the branch where the sandbox starts, in `bypassPermissions` mode, ask Claude to run `git fetch origin`: it runs with no prompt, where `main` asks first. Then ask it to run `git fetch --prune origin`: it runs sandboxed, and over SSH fails and is retried outside the sandbox. `git push origin <branch>` still prompts. On b9215a5, `bash tests/verify-agent-config.sh` (231 tests), `bash tests/check-work-folder.sh`, `.agents/hooks/shellcheck.sh repo`, `prettier --check '**/*.md'`, `scripts/verify-agent-config.sh`, and `git diff --check main` pass; the rewritten settings assertion fails on `main`. Not tried: a live session, since the sandbox could not start in the container the work ran in, so whether `git fetch origin` prompts in Manual mode, outside Claude Code's read-only git set, is unconfirmed. ## Considerations The exact exclusion fixes the command text, not the repository it runs in. A sandboxed command can prepare a repository outside the checkout's protected `.git`, and the unasked fetch then runs with its configuration, so an injected instruction could have it run a program on the host with no prompt in auto mode or under a developer's allow rule. The maintainer accepts that for the fetch every change starts with; in `bypassPermissions` an unsandboxed retry already runs unasked.
The ask rule on every git fetch prompted at the start of each change,
in every permission mode, since open-worktree fetches the main
branch's remote. The exclusion is now the exact command
git fetch origin, so a fetch with options, quotes, escapes, or
variables stays sandboxed, and it has no ask rule.

The fetch still runs with the configuration of the repository the
shell is in, which a sandboxed command can prepare outside the
checkout's own .git; the maintainer accepts that residual for the
fetch every change starts with, as the README states.
docs: say when git's network commands prompt
All checks were successful
Maintenance / checks (pull_request) Successful in 4m18s
Maintenance / checks (push) Successful in 3m47s
b9215a585f
claudiomaradonna deleted branch fetch-origin-exclusion 2026-11-09 15:13:26 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/agent-foundry!206
No description provided.