Compare commits

...

22 Commits

Author SHA1 Message Date
GitHub Actions
ef50f123a3 chore: bump Claude Code to 2.1.123 and Agent SDK to 0.2.123 2026-04-29 03:29:24 +00:00
GitHub Actions
b3c0320e7e chore: bump Claude Code to 2.1.122 and Agent SDK to 0.2.122 2026-04-28 22:05:53 +00:00
Octavian Guzu
c93e8fe879
docs: pull_request_target guidance and base-action trust model (#1250)
* docs: add pull_request_target/workflow_run guidance and base-action trust model

Adds a security.md section on safe checkout patterns under
pull_request_target/workflow_run, and a trust-model section to the
base-action README clarifying that callers are responsible for the
working directory and prompt being trusted.

🏠 Remote-Dev: homespace

* docs: refine PRT/workflow_run guidance — root checkout + workflow_run ref

Second example now checks out the base ref at the workspace root before
the head-ref subdirectory checkout (this action expects a git repo at
the root). Adds the workflow_run ref form, drops the PRT-specific
gh-pr-diff hint from the first example, and generalises the closing
line to cover both event types.

🏠 Remote-Dev: homespace

* docs: use actions/checkout@v6 in examples (consistency)

🏠 Remote-Dev: homespace
2026-04-28 10:01:48 -07:00
GitHub Actions
11a9dadd19 chore: bump Claude Code to 2.1.121 and Agent SDK to 0.2.121 2026-04-28 00:31:46 +00:00
GitHub Actions
567fe954a4 chore: bump Claude Code to 2.1.119 and Agent SDK to 0.2.119 2026-04-25 01:55:30 +00:00
GitHub Actions
2da6cfae68 chore: bump Claude Code to 2.1.120 and Agent SDK to 0.2.120 2026-04-25 00:15:05 +00:00
GitHub Actions
e58dfa5555 chore: bump Claude Code to 2.1.119 and Agent SDK to 0.2.119 2026-04-23 23:24:21 +00:00
Naoyoshi Aikawa
6ee201f023
fix: allow + in branch names (generated by Claude Code EnterWorktree) (#1248)
Claude Code's EnterWorktree tool converts "/" to "+" when generating
branch names from worktree names (e.g. EnterWorktree("feat/foo") creates
branch "worktree-feat+foo"). The strict whitelist in validateBranchName
rejected these names, causing claude-code-action to fail on any PR opened
from an EnterWorktree-generated branch.

Since all git calls use execFileSync (not shell interpolation), "+" carries
no command injection risk — the same rationale used for allowing "#".
Git itself permits "+" in branch names per git-check-ref-format.

Fixes: https://github.com/anthropics/claude-code-action/issues/1244

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 22:17:44 -07:00
GitHub Actions
b4d6741327 chore: bump Claude Code to 2.1.118 and Agent SDK to 0.2.118 2026-04-23 00:42:34 +00:00
GitHub Actions
4e5d8b13ca chore: bump Claude Code to 2.1.117 and Agent SDK to 0.2.117 2026-04-22 00:04:56 +00:00
GitHub Actions
5d5c10a4f3 chore: bump Claude Code to 2.1.116 and Agent SDK to 0.2.116 2026-04-20 22:18:45 +00:00
Octavian Guzu
632a368e81
docs: nit updates to security.md (#1240)
🏠 Remote-Dev: homespace
2026-04-20 15:00:35 +01:00
Ashwin Bhat
4c682d8b65
chore: bump oven-sh/setup-bun to v2.2.0 (Node.js 24) (#1238)
setup-bun v2.1.2 runs on Node.js 20, which GitHub will stop supporting
on June 2, 2026. v2.2.0 updates the action runtime to Node.js 24.

Fixes #1237
2026-04-19 17:53:46 -07:00
GitHub Actions
38ec876110 chore: bump Claude Code to 2.1.114 and Agent SDK to 0.2.114 2026-04-18 01:38:24 +00:00
Ashwin Bhat
0d2971c794
fix: pass install.sh binary path explicitly to Agent SDK (#1235)
Agent SDK 0.2.113 dropped vendor/ripgrep and now ships native binaries
via per-platform optionalDependencies. Two breakages:

- action.yml chmod'd vendor/ripgrep which no longer exists, failing the
  Install Dependencies step with find exit 1.
- The SDK auto-resolves its bundled binary by trying the -musl platform
  package before the glibc one. bun install does not respect the
  package.json libc field and installs both on glibc Linux, so the SDK
  picks the musl binary and spawn fails with ENOENT.

Remove the obsolete ripgrep chmod. Make installClaudeCode() return the
install.sh binary path and pass it explicitly as
pathToClaudeCodeExecutable so the SDK skips auto-resolution entirely.
2026-04-17 15:50:46 -07:00
GitHub Actions
c68f82cb11 chore: bump Claude Code to 2.1.113 and Agent SDK to 0.2.113 2026-04-17 19:40:20 +00:00
Ashwin Bhat
78758edf84
chore: bump model version in workflows (#1227)
https://claude.ai/code/session_01Mc8dExn9NcARLohJ1XG5kv

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-16 15:25:28 -07:00
GitHub Actions
c3d45e8e94 chore: bump Claude Code to 2.1.112 and Agent SDK to 0.2.112 2026-04-16 20:00:08 +00:00
GitHub Actions
931e620273 chore: bump Claude Code to 2.1.111 and Agent SDK to 0.2.111 2026-04-16 15:22:22 +00:00
GitHub Actions
905d4eb99a chore: bump Claude Code to 2.1.110 and Agent SDK to 0.2.110 2026-04-15 22:06:40 +00:00
GitHub Actions
5fb899572b chore: bump Claude Code to 2.1.109 and Agent SDK to 0.2.109 2026-04-15 04:05:34 +00:00
不做了睡大觉
c3bf66dbc2
fix: handle fork PRs by fetching via refs/pull/N/head (#962) (#963)
When a PR originates from a fork, `git fetch origin <branch>` fails
because the branch only exists on the fork's remote.

Fix: detect cross-repository PRs via the `isCrossRepository` GraphQL
field and fetch using `pull/<number>/head:<branch>` refspec instead,
which is the standard GitHub mechanism for accessing fork PR branches.

Changes:
- Add `isCrossRepository` and `headRepository` to PR GraphQL query
- Add corresponding fields to GitHubPullRequest type
- Branch checkout uses pull ref for fork PRs
- Update test fixtures with new fields

Co-authored-by: User <user@example.com>
2026-04-14 20:33:04 -07:00
20 changed files with 159 additions and 98 deletions

View File

@ -25,4 +25,4 @@ jobs:
prompt: "/review-pr REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }}" prompt: "/review-pr REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }}"
claude_args: | claude_args: |
--allowedTools "mcp__github_inline_comment__create_inline_comment" --allowedTools "mcp__github_inline_comment__create_inline_comment"
--model "claude-opus-4-6" --model "claude-opus-4-7"

View File

@ -36,4 +36,4 @@ jobs:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
claude_args: | claude_args: |
--allowedTools "Bash(bun install),Bash(bun test:*),Bash(bun run format),Bash(bun typecheck)" --allowedTools "Bash(bun install),Bash(bun test:*),Bash(bun run format),Bash(bun typecheck)"
--model "claude-opus-4-6" --model "claude-opus-4-7"

View File

@ -173,7 +173,7 @@ runs:
steps: steps:
- name: Install Bun - name: Install Bun
if: inputs.path_to_bun_executable == '' if: inputs.path_to_bun_executable == ''
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # https://github.com/oven-sh/setup-bun/releases/tag/v2.1.2 uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # https://github.com/oven-sh/setup-bun/releases/tag/v2.2.0
with: with:
bun-version: 1.3.6 bun-version: 1.3.6
token: ${{ inputs.github_token || github.token }} token: ${{ inputs.github_token || github.token }}
@ -194,10 +194,6 @@ runs:
run: | run: |
cd ${GITHUB_ACTION_PATH} cd ${GITHUB_ACTION_PATH}
bun install --production bun install --production
# bun install --production strips execute bits from vendored binaries (bun issue #1140).
# Restore +x on the ripgrep binaries so the Claude Agent SDK can exec them.
find "${GITHUB_ACTION_PATH}/node_modules/@anthropic-ai/claude-agent-sdk/vendor/ripgrep" \
-name "rg" -type f -exec chmod +x {} \;
- name: Install subprocess isolation dependencies - name: Install subprocess isolation dependencies
# Install subprocess isolation dependencies when processing content from non-write users. # Install subprocess isolation dependencies when processing content from non-write users.

View File

@ -4,6 +4,14 @@ This GitHub Action allows you to run [Claude Code](https://www.anthropic.com/cla
For simply tagging @claude in issues and PRs out of the box, [check out the Claude Code action and GitHub app](https://github.com/anthropics/claude-code-action). For simply tagging @claude in issues and PRs out of the box, [check out the Claude Code action and GitHub app](https://github.com/anthropics/claude-code-action).
## Trust model
This action is a thin wrapper that installs and runs Claude Code with the inputs you provide. It does **not** enforce any trust boundaries on its own. Running this action in a directory is equivalent to running Claude Code in that directory — Claude reads project-level configuration (`.claude/`, `CLAUDE.md`, `.mcp.json`, etc.) from the working directory, and the action's own setup steps run from there as well.
**The caller is responsible for ensuring the working directory and prompt are trusted.** If your workflow processes untrusted input (issues, fork pull requests, external comments), use [`anthropics/claude-code-action`](https://github.com/anthropics/claude-code-action) instead — it provides actor permission checks, restores project configuration from the base ref in PR contexts, and is the supported path for those scenarios.
See [Claude Code's security documentation](https://docs.anthropic.com/en/docs/claude-code/security) and the [GitHub Actions guidance on `pull_request_target`](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) for background.
## Usage ## Usage
Add the following to your workflow file: Add the following to your workflow file:

View File

@ -97,7 +97,7 @@ runs:
- name: Install Bun - name: Install Bun
if: inputs.path_to_bun_executable == '' if: inputs.path_to_bun_executable == ''
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # https://github.com/oven-sh/setup-bun/releases/tag/v2.1.2 uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # https://github.com/oven-sh/setup-bun/releases/tag/v2.2.0
with: with:
bun-version: 1.3.6 bun-version: 1.3.6
@ -124,7 +124,7 @@ runs:
PATH_TO_CLAUDE_CODE_EXECUTABLE: ${{ inputs.path_to_claude_code_executable }} PATH_TO_CLAUDE_CODE_EXECUTABLE: ${{ inputs.path_to_claude_code_executable }}
run: | run: |
if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then if [ -z "$PATH_TO_CLAUDE_CODE_EXECUTABLE" ]; then
CLAUDE_CODE_VERSION="2.1.108" CLAUDE_CODE_VERSION="2.1.123"
echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..." echo "Installing Claude Code v${CLAUDE_CODE_VERSION}..."
for attempt in 1 2 3; do for attempt in 1 2 3; do
echo "Installation attempt $attempt..." echo "Installation attempt $attempt..."

View File

@ -6,7 +6,7 @@
"name": "@anthropic-ai/claude-code-base-action", "name": "@anthropic-ai/claude-code-base-action",
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@anthropic-ai/claude-agent-sdk": "^0.2.108", "@anthropic-ai/claude-agent-sdk": "^0.2.123",
"shell-quote": "^1.8.3", "shell-quote": "^1.8.3",
}, },
"devDependencies": { "devDependencies": {
@ -27,7 +27,23 @@
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="], "@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.108", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.34.2", "@img/sharp-darwin-x64": "^0.34.2", "@img/sharp-linux-arm": "^0.34.2", "@img/sharp-linux-arm64": "^0.34.2", "@img/sharp-linux-x64": "^0.34.2", "@img/sharp-linuxmusl-arm64": "^0.34.2", "@img/sharp-linuxmusl-x64": "^0.34.2", "@img/sharp-win32-arm64": "^0.34.2", "@img/sharp-win32-x64": "^0.34.2" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-B6DDuzuguNu2P2rzVcEf0P0hKwEWqqwoXU9UsmYONFuTOHIqfvK8d8oDBwPCctQ/fG7nnJOf796RNAb/ZXM+Zg=="], "@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.123", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.123", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.123" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-a4TysYoR9DBdkM9Uwh4J5ub7TwKmRPe5hFiWh4En+IKC+qkk5UFkxFM22c//cZjYZKynHX0ah2t6LUqb+najYA=="],
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.123", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tYAXCjlXZQklsUs0J//gip3fZQRzhlH5OCgvNXV70qe7A1iiwHqO2KPGvEHV1L+deEKQoMZmTaCOrQpN6zju3w=="],
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.123", "", { "os": "darwin", "cpu": "x64" }, "sha512-AcUC6sTon6z6HculP87KsAOeTMRLBwpovdhcXUTjXUpo/8nplJ7lBEzWjZCHt8FF1KuN/WBy1Z4bDg/59TQDmA=="],
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.123", "", { "os": "linux", "cpu": "arm64" }, "sha512-7+GnbcF3/aZ8RJ1WmU/ogtPsOpknBAoUPer90MvZuFYBLPT9iI/U7f24gjrOHuYdcbDA5n7jFlhcfIO26F5DJQ=="],
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.123", "", { "os": "linux", "cpu": "arm64" }, "sha512-bYgRiaf2q+yVbGAoUluuhqrEW1zexL34+3HDmK9DneKXa2K2EJpw4M6Sq4XoBD/JezGaemoAP78Xv/M/QUS1OQ=="],
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.2.123", "", { "os": "linux", "cpu": "x64" }, "sha512-Xi+Rwk8uP5vWEnawJOlsk179fr0ATLl5J90MlbLj+puKaX5svEq8ljS+P3zq6zHTJeKh9GKLzPf7bc5YJKwcew=="],
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.123", "", { "os": "linux", "cpu": "x64" }, "sha512-IX95lFKhmmndY/YPfWPsVV+C3rLYJmuuq5wCS53p6jYIkCMxH1iGfhBGF1EUWcXO4Uc8yqXFmQ3aaxMzOOPrwA=="],
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.123", "", { "os": "win32", "cpu": "arm64" }, "sha512-WDZmAQG1rOiqNLZlSXaCjSWmqJvLk2io+vFQWWqSy2b5HCk9pa3PadLiaLztiihyk81wPhH9Q/44kOxdyfEGMw=="],
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.2.123", "", { "os": "win32", "cpu": "x64" }, "sha512-588xrd1i6d4kXQ6FqwL+cgBiN4evRQSi5DCtPa02CZ3VEbuVQBeFlyPlD8tfWtNNeGZ4NM8kjPNNzZz5omezPA=="],
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="], "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="],
@ -37,38 +53,6 @@
"@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="], "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
"@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="], "@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="],

View File

@ -11,7 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@anthropic-ai/claude-agent-sdk": "^0.2.108", "@anthropic-ai/claude-agent-sdk": "^0.2.123",
"shell-quote": "^1.8.3" "shell-quote": "^1.8.3"
}, },
"devDependencies": { "devDependencies": {

View File

@ -11,6 +11,14 @@ async function run() {
try { try {
validateEnvironmentVariables(); validateEnvironmentVariables();
// The composite action's "Install Claude Code" step writes the binary to
// ~/.local/bin/claude. Pass that path explicitly so the Agent SDK doesn't
// fall back to its bundled platform package, which bun may resolve to the
// wrong libc variant on Linux.
const claudeExecutable =
process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE ||
`${process.env.HOME}/.local/bin/claude`;
await setupClaudeCodeSettings( await setupClaudeCodeSettings(
process.env.INPUT_SETTINGS, process.env.INPUT_SETTINGS,
undefined, // homeDir undefined, // homeDir
@ -20,7 +28,7 @@ async function run() {
await installPlugins( await installPlugins(
process.env.INPUT_PLUGIN_MARKETPLACES, process.env.INPUT_PLUGIN_MARKETPLACES,
process.env.INPUT_PLUGINS, process.env.INPUT_PLUGINS,
process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE, claudeExecutable,
); );
const promptConfig = await preparePrompt({ const promptConfig = await preparePrompt({
@ -38,8 +46,7 @@ async function run() {
appendSystemPrompt: process.env.INPUT_APPEND_SYSTEM_PROMPT, appendSystemPrompt: process.env.INPUT_APPEND_SYSTEM_PROMPT,
fallbackModel: process.env.INPUT_FALLBACK_MODEL, fallbackModel: process.env.INPUT_FALLBACK_MODEL,
model: process.env.ANTHROPIC_MODEL, model: process.env.ANTHROPIC_MODEL,
pathToClaudeCodeExecutable: pathToClaudeCodeExecutable: claudeExecutable,
process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE,
showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT, showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT,
}); });

View File

@ -7,7 +7,7 @@
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@actions/github": "^6.0.1", "@actions/github": "^6.0.1",
"@anthropic-ai/claude-agent-sdk": "^0.2.108", "@anthropic-ai/claude-agent-sdk": "^0.2.123",
"@modelcontextprotocol/sdk": "^1.11.0", "@modelcontextprotocol/sdk": "^1.11.0",
"@octokit/graphql": "^8.2.2", "@octokit/graphql": "^8.2.2",
"@octokit/rest": "^21.1.1", "@octokit/rest": "^21.1.1",
@ -37,7 +37,23 @@
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="], "@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.108", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "^0.34.2", "@img/sharp-darwin-x64": "^0.34.2", "@img/sharp-linux-arm": "^0.34.2", "@img/sharp-linux-arm64": "^0.34.2", "@img/sharp-linux-x64": "^0.34.2", "@img/sharp-linuxmusl-arm64": "^0.34.2", "@img/sharp-linuxmusl-x64": "^0.34.2", "@img/sharp-win32-arm64": "^0.34.2", "@img/sharp-win32-x64": "^0.34.2" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-B6DDuzuguNu2P2rzVcEf0P0hKwEWqqwoXU9UsmYONFuTOHIqfvK8d8oDBwPCctQ/fG7nnJOf796RNAb/ZXM+Zg=="], "@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.123", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.123", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.123", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.123", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.123" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-a4TysYoR9DBdkM9Uwh4J5ub7TwKmRPe5hFiWh4En+IKC+qkk5UFkxFM22c//cZjYZKynHX0ah2t6LUqb+najYA=="],
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.123", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tYAXCjlXZQklsUs0J//gip3fZQRzhlH5OCgvNXV70qe7A1iiwHqO2KPGvEHV1L+deEKQoMZmTaCOrQpN6zju3w=="],
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.123", "", { "os": "darwin", "cpu": "x64" }, "sha512-AcUC6sTon6z6HculP87KsAOeTMRLBwpovdhcXUTjXUpo/8nplJ7lBEzWjZCHt8FF1KuN/WBy1Z4bDg/59TQDmA=="],
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.123", "", { "os": "linux", "cpu": "arm64" }, "sha512-7+GnbcF3/aZ8RJ1WmU/ogtPsOpknBAoUPer90MvZuFYBLPT9iI/U7f24gjrOHuYdcbDA5n7jFlhcfIO26F5DJQ=="],
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.123", "", { "os": "linux", "cpu": "arm64" }, "sha512-bYgRiaf2q+yVbGAoUluuhqrEW1zexL34+3HDmK9DneKXa2K2EJpw4M6Sq4XoBD/JezGaemoAP78Xv/M/QUS1OQ=="],
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.2.123", "", { "os": "linux", "cpu": "x64" }, "sha512-Xi+Rwk8uP5vWEnawJOlsk179fr0ATLl5J90MlbLj+puKaX5svEq8ljS+P3zq6zHTJeKh9GKLzPf7bc5YJKwcew=="],
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.123", "", { "os": "linux", "cpu": "x64" }, "sha512-IX95lFKhmmndY/YPfWPsVV+C3rLYJmuuq5wCS53p6jYIkCMxH1iGfhBGF1EUWcXO4Uc8yqXFmQ3aaxMzOOPrwA=="],
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.123", "", { "os": "win32", "cpu": "arm64" }, "sha512-WDZmAQG1rOiqNLZlSXaCjSWmqJvLk2io+vFQWWqSy2b5HCk9pa3PadLiaLztiihyk81wPhH9Q/44kOxdyfEGMw=="],
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.2.123", "", { "os": "win32", "cpu": "x64" }, "sha512-588xrd1i6d4kXQ6FqwL+cgBiN4evRQSi5DCtPa02CZ3VEbuVQBeFlyPlD8tfWtNNeGZ4NM8kjPNNzZz5omezPA=="],
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="], "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="],
@ -47,38 +63,6 @@
"@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.16.0", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-8ofX7gkZcLj9H9rSd50mCgm3SSF8C7XoclxJuLoV0Cz3rEQ1tv9MZRYYvJtm9n1BiEQQMzSmE/w2AEkNacLYfg=="], "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.16.0", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-8ofX7gkZcLj9H9rSd50mCgm3SSF8C7XoclxJuLoV0Cz3rEQ1tv9MZRYYvJtm9n1BiEQQMzSmE/w2AEkNacLYfg=="],
"@octokit/auth-token": ["@octokit/auth-token@4.0.0", "", {}, "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="], "@octokit/auth-token": ["@octokit/auth-token@4.0.0", "", {}, "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="],

View File

@ -15,11 +15,44 @@
- Is designed for automation workflows where user permissions are already restricted by the workflow's permission scope - Is designed for automation workflows where user permissions are already restricted by the workflow's permission scope
- When set, Claude does a best-effort scrub of Anthropic, cloud, and GitHub Actions secrets from subprocess environments. On Linux runners with bubblewrap available, subprocesses additionally run with PID-namespace isolation. This reduces but does not eliminate prompt injection risk — keep workflow permissions minimal and validate all outputs. Set `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: 0` in your workflow or job `env:` block to opt out. - When set, Claude does a best-effort scrub of Anthropic, cloud, and GitHub Actions secrets from subprocess environments. On Linux runners with bubblewrap available, subprocesses additionally run with PID-namespace isolation. This reduces but does not eliminate prompt injection risk — keep workflow permissions minimal and validate all outputs. Set `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: 0` in your workflow or job `env:` block to opt out.
- Optionally set `CLAUDE_CODE_SCRIPT_CAPS` in your workflow `env:` block to limit how many times Claude can call specific scripts per run. Value is JSON: `{"script-name.sh": maxCalls}`. Example: `CLAUDE_CODE_SCRIPT_CAPS: '{"edit-issue-labels.sh":2}'` allows at most 2 calls to `edit-issue-labels.sh`. Useful for write-capable helper scripts. - Optionally set `CLAUDE_CODE_SCRIPT_CAPS` in your workflow `env:` block to limit how many times Claude can call specific scripts per run. Value is JSON: `{"script-name.sh": maxCalls}`. Example: `CLAUDE_CODE_SCRIPT_CAPS: '{"edit-issue-labels.sh":2}'` allows at most 2 calls to `edit-issue-labels.sh`. Useful for write-capable helper scripts.
- When using `allowed_non_write_users`, always pass `github_token: ${{ secrets.GITHUB_TOKEN }}`. The auto-generated workflow token is scoped to the job's declared permissions and expires when the job completes. **Do not use a personal access token** — a static token does not rotate between runs, and depending on the tools allowed via `claude_args`, the model could be used to recover part or all of it. We recommend restricting allowed tools (e.g. `claude_args: '--allowedTools "Bash(gh issue view:*)"'`) to the minimum required when using `allowed_non_write_users`. - When using `allowed_non_write_users`, always pass `github_token: ${{ secrets.GITHUB_TOKEN }}`. The auto-generated workflow token is scoped to the job's declared permissions and expires when the job completes. **Do not use a personal access token** — a static token does not rotate between runs and could be partially or fully recovered over time via prompt injection. Restricting allowed tools via `claude_args` reduces the rate of recovery but may not eliminate the risk. We recommend restricting allowed tools (e.g. `claude_args: '--allowedTools "Bash(gh issue view:*)"'`) to the minimum required when using `allowed_non_write_users`.
- **Token Permissions**: The GitHub app receives only a short-lived token scoped specifically to the repository it's operating in - **Token Permissions**: The GitHub app receives only a short-lived token scoped specifically to the repository it's operating in
- **No Cross-Repository Access**: Each action invocation is limited to the repository where it was triggered - **No Cross-Repository Access**: Each action invocation is limited to the repository where it was triggered
- **Limited Scope**: The token cannot access other repositories or perform actions beyond the configured permissions - **Limited Scope**: The token cannot access other repositories or perform actions beyond the configured permissions
## Using this action with `pull_request_target` or `workflow_run`
`pull_request_target` and `workflow_run` execute with the **base repository's secrets**. If your workflow checks out the PR head (`ref: ${{ github.event.pull_request.head.sha }}` for `pull_request_target`, `ref: ${{ github.event.workflow_run.head_sha }}` for `workflow_run`) into `$GITHUB_WORKSPACE` before this action, the action and Claude run with that checkout as the working directory.
**Do not check out an untrusted ref into the workspace root before this action.** Use one of these patterns instead:
```yaml
# Preferred — check out the base ref (default).
- uses: actions/checkout@v6 # no `ref:` → base branch
- uses: anthropics/claude-code-action@v1
```
```yaml
# If you need the PR's files locally — check out the base ref at the workspace
# root (this action expects a git repo there), then check out the head ref into
# a subdirectory and pass it via --add-dir.
- uses: actions/checkout@v6 # no `ref:` → base branch at workspace root
- uses: actions/checkout@v6
with:
# For workflow_run use: ${{ github.event.workflow_run.head_sha }}
ref: ${{ github.event.pull_request.head.sha }}
path: pr-head
- uses: anthropics/claude-code-action@v1
with:
claude_args: "--add-dir pr-head"
```
This is general guidance for these event types — see [GitHub's documentation](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
### `claude-code-action` vs `claude-code-base-action`
`claude-code-base-action` is a lower-level building block that installs and runs Claude Code with the inputs you provide. It does not perform actor permission checks or restore project configuration from the base ref. If you need those behaviors, use this action (`claude-code-action`). See the [base-action README](../base-action/README.md#trust-model) for details.
## Pull Request Creation ## Pull Request Creation
In its default configuration, **Claude does not create pull requests automatically** when responding to `@claude` mentions. Instead: In its default configuration, **Claude does not create pull requests automatically** when responding to `@claude` mentions. Instead:

View File

@ -12,7 +12,7 @@
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@actions/github": "^6.0.1", "@actions/github": "^6.0.1",
"@anthropic-ai/claude-agent-sdk": "^0.2.108", "@anthropic-ai/claude-agent-sdk": "^0.2.123",
"@modelcontextprotocol/sdk": "^1.11.0", "@modelcontextprotocol/sdk": "^1.11.0",
"@octokit/graphql": "^8.2.2", "@octokit/graphql": "^8.2.2",
"@octokit/rest": "^21.1.1", "@octokit/rest": "^21.1.1",

View File

@ -43,8 +43,9 @@ import type { ClaudeRunResult } from "../../base-action/src/run-claude-sdk";
/** /**
* Install Claude Code CLI, handling retry logic and custom executable paths. * Install Claude Code CLI, handling retry logic and custom executable paths.
* Returns the absolute path to the claude executable.
*/ */
async function installClaudeCode(): Promise<void> { async function installClaudeCode(): Promise<string> {
const customExecutable = process.env.PATH_TO_CLAUDE_CODE_EXECUTABLE; const customExecutable = process.env.PATH_TO_CLAUDE_CODE_EXECUTABLE;
if (customExecutable) { if (customExecutable) {
if (/[\x00-\x1f\x7f]/.test(customExecutable)) { if (/[\x00-\x1f\x7f]/.test(customExecutable)) {
@ -61,10 +62,10 @@ async function installClaudeCode(): Promise<void> {
} }
// Also add to current process PATH // Also add to current process PATH
process.env.PATH = `${claudeDir}:${process.env.PATH}`; process.env.PATH = `${claudeDir}:${process.env.PATH}`;
return; return customExecutable;
} }
const claudeCodeVersion = "2.1.108"; const claudeCodeVersion = "2.1.123";
console.log(`Installing Claude Code v${claudeCodeVersion}...`); console.log(`Installing Claude Code v${claudeCodeVersion}...`);
for (let attempt = 1; attempt <= 3; attempt++) { for (let attempt = 1; attempt <= 3; attempt++) {
@ -93,7 +94,7 @@ async function installClaudeCode(): Promise<void> {
await appendFile(githubPath, `${homeBin}\n`); await appendFile(githubPath, `${homeBin}\n`);
} }
process.env.PATH = `${homeBin}:${process.env.PATH}`; process.env.PATH = `${homeBin}:${process.env.PATH}`;
return; return `${homeBin}/claude`;
} catch (error) { } catch (error) {
if (attempt === 3) { if (attempt === 3) {
throw new Error( throw new Error(
@ -104,6 +105,7 @@ async function installClaudeCode(): Promise<void> {
await new Promise((resolve) => setTimeout(resolve, 5000)); await new Promise((resolve) => setTimeout(resolve, 5000));
} }
} }
throw new Error("unreachable");
} }
/** /**
@ -220,7 +222,7 @@ async function run() {
prepareCompleted = true; prepareCompleted = true;
// Phase 2: Install Claude Code CLI // Phase 2: Install Claude Code CLI
await installClaudeCode(); const claudeExecutable = await installClaudeCode();
// Phase 3: Run Claude (import base-action directly) // Phase 3: Run Claude (import base-action directly)
// Set env vars needed by the base-action code // Set env vars needed by the base-action code
@ -259,7 +261,7 @@ async function run() {
await installPlugins( await installPlugins(
process.env.INPUT_PLUGIN_MARKETPLACES, process.env.INPUT_PLUGIN_MARKETPLACES,
process.env.INPUT_PLUGINS, process.env.INPUT_PLUGINS,
process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE, claudeExecutable,
); );
const promptFile = const promptFile =
@ -274,8 +276,7 @@ async function run() {
claudeArgs: prepareResult.claudeArgs, claudeArgs: prepareResult.claudeArgs,
appendSystemPrompt: process.env.APPEND_SYSTEM_PROMPT, appendSystemPrompt: process.env.APPEND_SYSTEM_PROMPT,
model: process.env.ANTHROPIC_MODEL, model: process.env.ANTHROPIC_MODEL,
pathToClaudeCodeExecutable: pathToClaudeCodeExecutable: claudeExecutable,
process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE,
showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT, showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT,
}); });

View File

@ -12,6 +12,13 @@ export const PR_QUERY = `
baseRefName baseRefName
headRefName headRefName
headRefOid headRefOid
isCrossRepository
headRepository {
owner {
login
}
name
}
createdAt createdAt
updatedAt updatedAt
lastEditedAt lastEditedAt

View File

@ -58,14 +58,16 @@ export function validateBranchName(branchName: string): void {
); );
} }
// Strict whitelist pattern: alphanumeric start, then alphanumeric/slash/hyphen/underscore/period/hash. // Strict whitelist pattern: alphanumeric start, then alphanumeric/slash/hyphen/underscore/period/hash/plus.
// # is valid per git-check-ref-format and commonly used in branch names like "fix/#123-description". // # is valid per git-check-ref-format and commonly used in branch names like "fix/#123-description".
// All git calls use execFileSync (not shell interpolation), so # carries no injection risk. // + is valid per git-check-ref-format and generated by Claude Code's EnterWorktree tool when
const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9/_.#-]*$/; // converting worktree names containing "/" (e.g. "feat/foo" becomes "worktree-feat+foo").
// All git calls use execFileSync (not shell interpolation), so neither # nor + carries injection risk.
const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9/_.#+-]*$/;
if (!validPattern.test(branchName)) { if (!validPattern.test(branchName)) {
throw new Error( throw new Error(
`Invalid branch name: "${branchName}". Branch names must start with an alphanumeric character and contain only alphanumeric characters, forward slashes, hyphens, underscores, periods, or hashes (#).`, `Invalid branch name: "${branchName}". Branch names must start with an alphanumeric character and contain only alphanumeric characters, forward slashes, hyphens, underscores, periods, hashes (#), or plus signs (+).`,
); );
} }
@ -166,9 +168,23 @@ export async function setupBranch(
// Validate branch names before use to prevent command injection // Validate branch names before use to prevent command injection
validateBranchName(branchName); validateBranchName(branchName);
// For cross-repository (fork) PRs, fetch via the pull ref since the
// branch only exists on the fork's remote, not on origin.
if (prData.isCrossRepository) {
console.log(
`PR #${entityNumber} is from a fork, fetching via refs/pull/${entityNumber}/head...`,
);
execGit([
"fetch",
"origin",
`--depth=${fetchDepth}`,
`pull/${entityNumber}/head:${branchName}`,
]);
} else {
// Execute git commands to checkout PR branch (dynamic depth based on PR size) // Execute git commands to checkout PR branch (dynamic depth based on PR size)
// Using execFileSync instead of shell template literals for security // Using execFileSync instead of shell template literals for security
execGit(["fetch", "origin", `--depth=${fetchDepth}`, branchName]); execGit(["fetch", "origin", `--depth=${fetchDepth}`, branchName]);
}
execGit(["checkout", branchName, "--"]); execGit(["checkout", branchName, "--"]);
console.log(`Successfully checked out PR branch for PR #${entityNumber}`); console.log(`Successfully checked out PR branch for PR #${entityNumber}`);

View File

@ -57,6 +57,13 @@ export type GitHubPullRequest = {
baseRefName: string; baseRefName: string;
headRefName: string; headRefName: string;
headRefOid: string; headRefOid: string;
isCrossRepository: boolean;
headRepository: {
owner: {
login: string;
};
name: string;
} | null;
createdAt: string; createdAt: string;
updatedAt?: string; updatedAt?: string;
lastEditedAt?: string; lastEditedAt?: string;

View File

@ -27,6 +27,8 @@ describe("generatePrompt", () => {
baseRefName: "main", baseRefName: "main",
headRefName: "feature-branch", headRefName: "feature-branch",
headRefOid: "abc123", headRefOid: "abc123",
isCrossRepository: false,
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
commits: { commits: {
totalCount: 2, totalCount: 2,
nodes: [ nodes: [

View File

@ -1006,6 +1006,8 @@ describe("fetchGitHubData integration with time filtering", () => {
baseRefName: "main", baseRefName: "main",
headRefName: "feature", headRefName: "feature",
headRefOid: "abc123", headRefOid: "abc123",
isCrossRepository: false,
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
createdAt: "2024-01-15T10:00:00Z", createdAt: "2024-01-15T10:00:00Z",
updatedAt: "2024-01-15T12:30:00Z", // Edited after trigger updatedAt: "2024-01-15T12:30:00Z", // Edited after trigger
lastEditedAt: "2024-01-15T12:30:00Z", // Edited after trigger lastEditedAt: "2024-01-15T12:30:00Z", // Edited after trigger

View File

@ -24,6 +24,8 @@ describe("formatContext", () => {
baseRefName: "main", baseRefName: "main",
headRefName: "feature/test", headRefName: "feature/test",
headRefOid: "abc123", headRefOid: "abc123",
isCrossRepository: false,
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
createdAt: "2023-01-01T00:00:00Z", createdAt: "2023-01-01T00:00:00Z",
additions: 50, additions: 50,
deletions: 30, deletions: 30,

View File

@ -17,6 +17,8 @@ describe("pull_request_target event support", () => {
baseRefName: "main", baseRefName: "main",
headRefName: "feature-branch", headRefName: "feature-branch",
headRefOid: "abc123", headRefOid: "abc123",
isCrossRepository: false,
headRepository: { owner: { login: "testowner" }, name: "testrepo" },
commits: { commits: {
totalCount: 2, totalCount: 2,
nodes: [ nodes: [

View File

@ -45,6 +45,16 @@ describe("validateBranchName", () => {
).not.toThrow(); ).not.toThrow();
expect(() => validateBranchName("fix/issue-#42")).not.toThrow(); expect(() => validateBranchName("fix/issue-#42")).not.toThrow();
}); });
it("should accept branch names containing + (generated by Claude Code EnterWorktree)", () => {
// EnterWorktree converts "/" in worktree names to "+" when generating branch names.
// e.g. EnterWorktree("feat/skill-consolidation") → branch "worktree-feat+skill-consolidation"
expect(() =>
validateBranchName("worktree-feat+skill-consolidation"),
).not.toThrow();
expect(() => validateBranchName("fix+issue-123")).not.toThrow();
expect(() => validateBranchName("feature+new-thing")).not.toThrow();
});
}); });
describe("command injection attempts", () => { describe("command injection attempts", () => {