Skip to content

restoreConfigFromBase snapshot at .claude-pr/ gets committed to PR branch when bot pushes a fix #1275

@awakia

Description

@awakia

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:

  1. A PR is opened. Claude PR Review runs and posts a review comment with a suggestion.
  2. A maintainer comments @claude please address that suggestion.
  3. 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.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingp2Non-showstopper bug or popular feature request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions