Summary
The .claude-pr/ snapshot directory created by restoreConfigFromBase (introduced in #1172) is unintentionally committed to the user's PR branch whenever the Claude bot makes a fix-up commit during a PR-context run. This results in stealth commits that the bot's own reply comment doesn't acknowledge, polluting the PR with unrelated files.
Reproduction
Repository conditions:
- Has any of the
SENSITIVE_PATHS checked into the repo (most commonly .claude/ and/or CLAUDE.md).
- Uses
claude-code-action@v1 with @claude mention triggers (issue_comment event on a PR).
Steps:
- A PR is opened.
Claude PR Review runs and posts a review comment with a suggestion.
- A maintainer comments
@claude please address that suggestion.
- The action runs:
restoreConfigFromBase snapshots PR-authored .claude/ and CLAUDE.md to .claude-pr/.claude/ and .claude-pr/CLAUDE.md.
- The CLI makes the requested fix to the actual source file (e.g.
tools/foo/bar.gs).
- The CLI commits with
git add -A (or equivalent) and pushes.
- Two commits land on the PR branch: the requested fix, plus a chore commit dragging in the entire
.claude-pr/ snapshot.
The bot's reply comment only mentions the requested fix — there is no mention of the .claude-pr/ commit, so the user has no signal that this happened until they read git log.
Expected
.claude-pr/ is described in restore-config.ts as data "for review agents (not executed)" — i.e. an ephemeral runner-side artifact. It should never be committed to the user's repository.
Actual
The directory is committed verbatim, often containing dozens to hundreds of files (every file under .claude/skills/ etc.). On subsequent @claude runs, the now-tracked .claude-pr/ shows diffs against the freshly-snapshotted version, causing repeated chore commits.
Existing partial mitigation
restoreConfigFromBase already runs git reset -- ${SENSITIVE_PATHS} to unstage the base-branch revert of .claude/, CLAUDE.md, etc., precisely to keep them out of the CLI's later commits. The same protection is missing for .claude-pr/ itself.
Suggested fix
In restoreConfigFromBase, after creating .claude-pr/, append it to .git/info/exclude so it is invisible to git add regardless of the CLI's staging strategy:
if (existsSync(\".claude-pr\")) {
appendFileSync(\".git/info/exclude\", \"\\n.claude-pr/\\n\");
}
.git/info/exclude is preferred over modifying .gitignore because it does not mutate any tracked file in the user's repo, matching the design intent that .claude-pr/ is a pure runner-side artifact.
Real-world incidents
Two stealth commits in our private organization repo, both from bot runs:
- A chore commit adding the initial
.claude-pr/ (~100 files) on a PR about hardware OEM project structure — completely unrelated to the PR.
- A second chore commit re-syncing
.claude-pr/ on a different PR after a @claude fix-up request.
In both cases the bot's reply summarized only the requested change, so the maintainer only noticed the extra commit on review.
Workaround
Add .claude-pr/ to the consuming repo's .gitignore and git rm -r --cached .claude-pr/. This works but ideally the action would not require every adopter to discover and apply this fix individually — the symptom is delayed (only appears when @claude is invoked on a PR with sensitive paths) and the root cause is opaque from the repo side.
Summary
The
.claude-pr/snapshot directory created byrestoreConfigFromBase(introduced in #1172) is unintentionally committed to the user's PR branch whenever the Claude bot makes a fix-up commit during a PR-context run. This results in stealth commits that the bot's own reply comment doesn't acknowledge, polluting the PR with unrelated files.Reproduction
Repository conditions:
SENSITIVE_PATHSchecked into the repo (most commonly.claude/and/orCLAUDE.md).claude-code-action@v1with@claudemention triggers (issue_commentevent on a PR).Steps:
Claude PR Reviewruns and posts a review comment with a suggestion.@claude please address that suggestion.restoreConfigFromBasesnapshots PR-authored.claude/andCLAUDE.mdto.claude-pr/.claude/and.claude-pr/CLAUDE.md.tools/foo/bar.gs).git add -A(or equivalent) and pushes..claude-pr/snapshot.The bot's reply comment only mentions the requested fix — there is no mention of the
.claude-pr/commit, so the user has no signal that this happened until they readgit log.Expected
.claude-pr/is described inrestore-config.tsas data "for review agents (not executed)" — i.e. an ephemeral runner-side artifact. It should never be committed to the user's repository.Actual
The directory is committed verbatim, often containing dozens to hundreds of files (every file under
.claude/skills/etc.). On subsequent@clauderuns, the now-tracked.claude-pr/shows diffs against the freshly-snapshotted version, causing repeated chore commits.Existing partial mitigation
restoreConfigFromBasealready runsgit reset -- ${SENSITIVE_PATHS}to unstage the base-branch revert of.claude/,CLAUDE.md, etc., precisely to keep them out of the CLI's later commits. The same protection is missing for.claude-pr/itself.Suggested fix
In
restoreConfigFromBase, after creating.claude-pr/, append it to.git/info/excludeso it is invisible togit addregardless of the CLI's staging strategy:.git/info/excludeis preferred over modifying.gitignorebecause it does not mutate any tracked file in the user's repo, matching the design intent that.claude-pr/is a pure runner-side artifact.Real-world incidents
Two stealth commits in our private organization repo, both from bot runs:
.claude-pr/(~100 files) on a PR about hardware OEM project structure — completely unrelated to the PR..claude-pr/on a different PR after a@claudefix-up request.In both cases the bot's reply summarized only the requested change, so the maintainer only noticed the extra commit on review.
Workaround
Add
.claude-pr/to the consuming repo's.gitignoreandgit rm -r --cached .claude-pr/. This works but ideally the action would not require every adopter to discover and apply this fix individually — the symptom is delayed (only appears when@claudeis invoked on a PR with sensitive paths) and the root cause is opaque from the repo side.