mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-23 23:14:13 +08:00
Compare commits
25 Commits
lina/html_
...
ashwin/pin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58d4e0e991 | ||
|
|
3c6a85b54b | ||
|
|
cbc3ca285d | ||
|
|
6ce69a1db5 | ||
|
|
5b025a2e43 | ||
|
|
a29981fe38 | ||
|
|
c60a8fb69b | ||
|
|
f3bfb2a9ad | ||
|
|
36c5ee33cd | ||
|
|
8e84799f37 | ||
|
|
57ae256d38 | ||
|
|
d3bb4afed5 | ||
|
|
17cc868124 | ||
|
|
d822994da0 | ||
|
|
b129b800c5 | ||
|
|
80dbb4a5aa | ||
|
|
1e9ea49f7a | ||
|
|
08e084156a | ||
|
|
e67f992a13 | ||
|
|
be7f75d65a | ||
|
|
e3d126d058 | ||
|
|
11f5812e28 | ||
|
|
d15de3a8e3 | ||
|
|
9e23f6d9ed | ||
|
|
48b327f164 |
14
.github/workflows/claude.yml
vendored
14
.github/workflows/claude.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Claude
|
||||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
@@ -11,12 +11,12 @@ on:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude-pr:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -29,10 +29,8 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude PR Agent
|
||||
uses: anthropics/claude-code-action@main
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
timeout_minutes: "60"
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
allowed_tools: "Bash(bun install),Bash(bun test:*),Bash(bun run format),Bash(bun typecheck)"
|
||||
custom_instructions: "You have also been granted tools for editing files and running bun commands (install, run, test) for testing your changes."
|
||||
|
||||
42
README.md
42
README.md
@@ -1,3 +1,5 @@
|
||||

|
||||
|
||||
# Claude Code Action
|
||||
|
||||
A general-purpose [Claude Code](https://claude.ai/code) action for GitHub PRs and issues that can answer questions and implement code changes. This action listens for a trigger phrase in comments and activates Claude act on the request. It supports multiple authentication methods including Anthropic direct API, Amazon Bedrock, and Google Vertex AI.
|
||||
@@ -63,20 +65,21 @@ jobs:
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------- |
|
||||
| `anthropic_api_key` | Anthropic API key (required for direct API, not needed for Bedrock/Vertex) | No\* | - |
|
||||
| `direct_prompt` | Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows) | No | - |
|
||||
| `timeout_minutes` | Timeout in minutes for execution | No | `30` |
|
||||
| `github_token` | GitHub token for Claude to operate with. **Only include this if you're connecting a custom GitHub app of your own!** | No | - |
|
||||
| `anthropic_model` | Model to use (provider-specific format required for Bedrock/Vertex) | No | `claude-3-7-sonnet-20250219` |
|
||||
| `use_bedrock` | Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API | No | `false` |
|
||||
| `use_vertex` | Use Google Vertex AI with OIDC authentication instead of direct Anthropic API | No | `false` |
|
||||
| `allowed_tools` | Additional tools for Claude to use (the base GitHub tools will always be included) | No | "" |
|
||||
| `disallowed_tools` | Tools that Claude should never use | No | "" |
|
||||
| `custom_instructions` | Additional custom instructions to include in the prompt for Claude | No | "" |
|
||||
| `assignee_trigger` | The assignee username that triggers the action (e.g. @claude). Only used for issue assignment | No | - |
|
||||
| `trigger_phrase` | The trigger phrase to look for in comments, issue/PR bodies, and issue titles | No | `@claude` |
|
||||
| Input | Description | Required | Default |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | -------- | --------- |
|
||||
| `anthropic_api_key` | Anthropic API key (required for direct API, not needed for Bedrock/Vertex) | No\* | - |
|
||||
| `direct_prompt` | Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows) | No | - |
|
||||
| `timeout_minutes` | Timeout in minutes for execution | No | `30` |
|
||||
| `github_token` | GitHub token for Claude to operate with. **Only include this if you're connecting a custom GitHub app of your own!** | No | - |
|
||||
| `model` | Model to use (provider-specific format required for Bedrock/Vertex) | No | - |
|
||||
| `anthropic_model` | **DEPRECATED**: Use `model` instead. Kept for backward compatibility. | No | - |
|
||||
| `use_bedrock` | Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API | No | `false` |
|
||||
| `use_vertex` | Use Google Vertex AI with OIDC authentication instead of direct Anthropic API | No | `false` |
|
||||
| `allowed_tools` | Additional tools for Claude to use (the base GitHub tools will always be included) | No | "" |
|
||||
| `disallowed_tools` | Tools that Claude should never use | No | "" |
|
||||
| `custom_instructions` | Additional custom instructions to include in the prompt for Claude | No | "" |
|
||||
| `assignee_trigger` | The assignee username that triggers the action (e.g. @claude). Only used for issue assignment | No | - |
|
||||
| `trigger_phrase` | The trigger phrase to look for in comments, issue/PR bodies, and issue titles | No | `@claude` |
|
||||
|
||||
\*Required when using direct Anthropic API (default and when not using Bedrock or Vertex)
|
||||
|
||||
@@ -255,7 +258,7 @@ Use a specific Claude model:
|
||||
```yaml
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "claude-3-7-sonnet-20250219"
|
||||
# model: "claude-3-5-sonnet-20241022" # Optional: specify a different model
|
||||
# ... other inputs
|
||||
```
|
||||
|
||||
@@ -283,21 +286,20 @@ Use provider-specific model names based on your chosen provider:
|
||||
# For direct Anthropic API (default)
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "claude-3-7-sonnet-20250219"
|
||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
# ... other inputs
|
||||
|
||||
# For Amazon Bedrock with OIDC
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "anthropic.claude-3-7-sonnet-20250219-beta:0" # Cross-region inference
|
||||
model: "anthropic.claude-3-7-sonnet-20250219-beta:0" # Cross-region inference
|
||||
use_bedrock: "true"
|
||||
# ... other inputs
|
||||
|
||||
# For Google Vertex AI with OIDC
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "claude-3-7-sonnet@20250219"
|
||||
model: "claude-3-7-sonnet@20250219"
|
||||
use_vertex: "true"
|
||||
# ... other inputs
|
||||
```
|
||||
@@ -323,7 +325,7 @@ Both AWS Bedrock and GCP Vertex AI require OIDC authentication.
|
||||
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "anthropic.claude-3-7-sonnet-20250219-beta:0"
|
||||
model: "anthropic.claude-3-7-sonnet-20250219-beta:0"
|
||||
use_bedrock: "true"
|
||||
# ... other inputs
|
||||
|
||||
@@ -348,7 +350,7 @@ Both AWS Bedrock and GCP Vertex AI require OIDC authentication.
|
||||
|
||||
- uses: anthropics/claude-code-action@beta
|
||||
with:
|
||||
anthropic_model: "claude-3-7-sonnet@20250219"
|
||||
model: "claude-3-7-sonnet@20250219"
|
||||
use_vertex: "true"
|
||||
# ... other inputs
|
||||
|
||||
|
||||
14
action.yml
14
action.yml
@@ -14,10 +14,12 @@ inputs:
|
||||
required: false
|
||||
|
||||
# Claude Code configuration
|
||||
anthropic_model:
|
||||
model:
|
||||
description: "Model to use (provider-specific format required for Bedrock/Vertex)"
|
||||
required: false
|
||||
default: "claude-3-7-sonnet-20250219"
|
||||
anthropic_model:
|
||||
description: "DEPRECATED: Use 'model' instead. Model to use (provider-specific format required for Bedrock/Vertex)"
|
||||
required: false
|
||||
allowed_tools:
|
||||
description: "Additional tools for Claude to use (the base GitHub tools will always be included)"
|
||||
required: false
|
||||
@@ -65,7 +67,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # https://github.com/oven-sh/setup-bun/releases/tag/v2.0.2
|
||||
with:
|
||||
bun-version: 1.2.11
|
||||
|
||||
@@ -92,20 +94,20 @@ runs:
|
||||
- name: Run Claude Code
|
||||
id: claude-code
|
||||
if: steps.prepare.outputs.contains_trigger == 'true'
|
||||
uses: anthropics/claude-code-base-action@beta
|
||||
uses: anthropics/claude-code-base-action@5097b6cdfe5fc5a3ac0166cc344c34ed23c93982 # https://github.com/anthropics/claude-code-base-action/releases/tag/v0.0.5
|
||||
with:
|
||||
prompt_file: /tmp/claude-prompts/claude-prompt.txt
|
||||
allowed_tools: ${{ env.ALLOWED_TOOLS }}
|
||||
disallowed_tools: ${{ env.DISALLOWED_TOOLS }}
|
||||
timeout_minutes: ${{ inputs.timeout_minutes }}
|
||||
anthropic_model: ${{ inputs.anthropic_model }}
|
||||
model: ${{ inputs.model || inputs.anthropic_model }}
|
||||
mcp_config: ${{ steps.prepare.outputs.mcp_config }}
|
||||
use_bedrock: ${{ inputs.use_bedrock }}
|
||||
use_vertex: ${{ inputs.use_vertex }}
|
||||
anthropic_api_key: ${{ inputs.anthropic_api_key }}
|
||||
env:
|
||||
# Model configuration
|
||||
ANTHROPIC_MODEL: ${{ inputs.anthropic_model }}
|
||||
ANTHROPIC_MODEL: ${{ inputs.model || inputs.anthropic_model }}
|
||||
GITHUB_TOKEN: ${{ steps.prepare.outputs.GITHUB_TOKEN }}
|
||||
|
||||
# AWS configuration
|
||||
|
||||
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -434,9 +434,27 @@ ${
|
||||
eventData.eventName === "pull_request_review_comment"
|
||||
? `<comment_tool_info>
|
||||
IMPORTANT: For this inline PR review comment, you have been provided with ONLY the mcp__github__update_pull_request_comment tool to update this specific review comment.
|
||||
|
||||
Tool usage example for mcp__github__update_pull_request_comment:
|
||||
{
|
||||
"owner": "${context.repository.split("/")[0]}",
|
||||
"repo": "${context.repository.split("/")[1]}",
|
||||
"commentId": ${eventData.commentId || context.claudeCommentId},
|
||||
"body": "Your comment text here"
|
||||
}
|
||||
All four parameters (owner, repo, commentId, body) are required.
|
||||
</comment_tool_info>`
|
||||
: `<comment_tool_info>
|
||||
IMPORTANT: For this event type, you have been provided with ONLY the mcp__github__update_issue_comment tool to update comments.
|
||||
|
||||
Tool usage example for mcp__github__update_issue_comment:
|
||||
{
|
||||
"owner": "${context.repository.split("/")[0]}",
|
||||
"repo": "${context.repository.split("/")[1]}",
|
||||
"commentId": ${context.claudeCommentId},
|
||||
"body": "Your comment text here"
|
||||
}
|
||||
All four parameters (owner, repo, commentId, body) are required.
|
||||
</comment_tool_info>`
|
||||
}
|
||||
|
||||
@@ -547,6 +565,9 @@ Important Notes:
|
||||
- Use this spinner HTML when work is in progress: <img src="https://github.com/user-attachments/assets/5ac382c7-e004-429b-8e35-7feb3e8f9c6f" width="14px" height="14px" style="vertical-align: middle; margin-left: 4px;" />
|
||||
${eventData.isPR && !eventData.claudeBranch ? `- Always push to the existing branch when triggered on a PR.` : `- IMPORTANT: You are already on the correct branch (${eventData.claudeBranch || "the created branch"}). Never create new branches when triggered on issues or closed/merged PRs.`}
|
||||
- Use mcp__github_file_ops__commit_files for making commits (works for both new and existing files, single or multiple). Use mcp__github_file_ops__delete_files for deleting files (supports deleting single or multiple files atomically), or mcp__github__delete_file for deleting a single file. Edit files locally, and the tool will read the content from the same path on disk.
|
||||
Tool usage examples:
|
||||
- mcp__github_file_ops__commit_files: {"files": ["path/to/file1.js", "path/to/file2.py"], "message": "feat: add new feature"}
|
||||
- mcp__github_file_ops__delete_files: {"files": ["path/to/old.js"], "message": "chore: remove deprecated file"}
|
||||
- Display the todo list as a checklist in the GitHub comment and mark things off as you go.
|
||||
- REPOSITORY SETUP INSTRUCTIONS: The repository's CLAUDE.md file(s) contain critical repo-specific setup instructions, development guidelines, and preferences. Always read and follow these files, particularly the root CLAUDE.md, as they provide essential context for working with the codebase effectively.
|
||||
- Use h3 headers (###) for section titles in your comments, not h1 headers (#).
|
||||
|
||||
@@ -39,25 +39,19 @@ async function retryWithBackoff<T>(
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Operation failed after ${maxAttempts} attempts. Last error: ${
|
||||
lastError?.message ?? "Unknown error"
|
||||
}`,
|
||||
);
|
||||
console.error(`Operation failed after ${maxAttempts} attempts`);
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
async function getOidcToken(): Promise<string> {
|
||||
try {
|
||||
const oidcToken = await core.getIDToken("claude-code-github-action");
|
||||
|
||||
if (!oidcToken) {
|
||||
throw new Error("OIDC token not found");
|
||||
}
|
||||
|
||||
return oidcToken;
|
||||
} catch (error) {
|
||||
console.error("Failed to get OIDC token:", error);
|
||||
throw new Error(
|
||||
`Failed to get OIDC token: ${error instanceof Error ? error.message : String(error)}`,
|
||||
"Could not fetch an OIDC token. Did you remember to add `id-token: write` to your workflow permissions?",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -74,9 +68,15 @@ async function exchangeForAppToken(oidcToken: string): Promise<string> {
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`App token exchange failed: ${response.status} ${response.statusText}`,
|
||||
const responseJson = (await response.json()) as {
|
||||
error?: {
|
||||
message?: string;
|
||||
};
|
||||
};
|
||||
console.error(
|
||||
`App token exchange failed: ${response.status} ${response.statusText} - ${responseJson?.error?.message ?? "Unknown error"}`,
|
||||
);
|
||||
throw new Error(`${responseJson?.error?.message ?? "Unknown error"}`);
|
||||
}
|
||||
|
||||
const appTokenData = (await response.json()) as {
|
||||
@@ -117,7 +117,9 @@ export async function setupGitHubToken(): Promise<string> {
|
||||
core.setOutput("GITHUB_TOKEN", appToken);
|
||||
return appToken;
|
||||
} catch (error) {
|
||||
core.setFailed(`Failed to setup GitHub token: ${error}`);
|
||||
core.setFailed(
|
||||
`Failed to setup GitHub token: ${error}.\n\nIf you instead wish to use this action with a custom GitHub token or custom GitHub app, provide a \`github_token\` in the \`uses\` section of the app in your workflow yml file.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { z } from "zod";
|
||||
import { readFile } from "fs/promises";
|
||||
import { join } from "path";
|
||||
import fetch from "node-fetch";
|
||||
import { GITHUB_API_URL } from "../github/api/config";
|
||||
|
||||
@@ -36,6 +37,7 @@ type GitHubNewCommit = {
|
||||
const REPO_OWNER = process.env.REPO_OWNER;
|
||||
const REPO_NAME = process.env.REPO_NAME;
|
||||
const BRANCH_NAME = process.env.BRANCH_NAME;
|
||||
const REPO_DIR = process.env.REPO_DIR || process.cwd();
|
||||
|
||||
if (!REPO_OWNER || !REPO_NAME || !BRANCH_NAME) {
|
||||
console.error(
|
||||
@@ -71,18 +73,9 @@ server.tool(
|
||||
throw new Error("GITHUB_TOKEN environment variable is required");
|
||||
}
|
||||
|
||||
// Convert absolute paths to relative if they match CWD
|
||||
const cwd = process.cwd();
|
||||
const processedFiles = files.map((filePath) => {
|
||||
if (filePath.startsWith("/")) {
|
||||
if (filePath.startsWith(cwd)) {
|
||||
// Strip CWD from absolute path
|
||||
return filePath.slice(cwd.length + 1);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Path '${filePath}' must be relative to repository root or within current working directory`,
|
||||
);
|
||||
}
|
||||
return filePath.slice(1);
|
||||
}
|
||||
return filePath;
|
||||
});
|
||||
@@ -126,7 +119,11 @@ server.tool(
|
||||
// 3. Create tree entries for all files
|
||||
const treeEntries = await Promise.all(
|
||||
processedFiles.map(async (filePath) => {
|
||||
const content = await readFile(filePath, "utf-8");
|
||||
const fullPath = filePath.startsWith("/")
|
||||
? filePath
|
||||
: join(REPO_DIR, filePath);
|
||||
|
||||
const content = await readFile(fullPath, "utf-8");
|
||||
return {
|
||||
path: filePath,
|
||||
mode: "100644",
|
||||
@@ -232,13 +229,16 @@ server.tool(
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
text: `Error: ${errorMessage}`,
|
||||
},
|
||||
],
|
||||
error: errorMessage,
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
@@ -423,13 +423,16 @@ server.tool(
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
text: `Error: ${errorMessage}`,
|
||||
},
|
||||
],
|
||||
error: errorMessage,
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export async function prepareMcpConfig(
|
||||
REPO_OWNER: owner,
|
||||
REPO_NAME: repo,
|
||||
BRANCH_NAME: branch,
|
||||
REPO_DIR: process.env.GITHUB_WORKSPACE || process.cwd(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user