Compare commits

..

8 Commits

Author SHA1 Message Date
igorkofman
bf614aa201 Update CHANGELOG.md 2025-04-17 11:24:11 -07:00
GitHub Actions
071480a9c6 chore: Update CHANGELOG.md 2025-04-17 17:03:29 +00:00
Catherine Wu
d1bb18a158 Merge pull request #713 from anthropics/catherinewu-patch-1
Update LICENSE.md
2025-04-15 22:12:00 -07:00
Ashwin Bhat
16c5dff959 Merge pull request #794 from anthropics/ashwin/triageaction
Add GitHub workflow for issue triage with available labels
2025-04-15 10:49:52 -07:00
Ashwin Bhat
1183388fdf Add GitHub workflow for issue triage with available labels
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-04-14 17:20:21 -07:00
Catherine Wu
062d4ee6f8 Update LICENSE.md 2025-04-04 19:00:54 -07:00
Ashwin Bhat
5eb232b866 Merge pull request #698 from anthropics/ashwin/changelog
post changelog file
2025-04-02 21:01:32 -07:00
Ashwin Bhat
ccfdadbd44 post changelog file 2025-04-02 18:24:44 -07:00
9 changed files with 371 additions and 131 deletions

View File

@@ -69,10 +69,10 @@ RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/
# Install Claude
RUN npm install -g @anthropic-ai/claude-code
# Copy and set up scripts
COPY init-firewall.sh cache-github-api.sh /usr/local/bin/
# Copy and set up firewall script
COPY init-firewall.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/init-firewall.sh /usr/local/bin/cache-github-api.sh && \
RUN chmod +x /usr/local/bin/init-firewall.sh && \
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
chmod 0440 /etc/sudoers.d/node-firewall
USER node

View File

@@ -1,109 +0,0 @@
#!/bin/bash
set -e
# Script to cache GitHub API data
# Used to prevent rate limiting during container builds
# Configuration
# Store cache in the home directory
CACHE_DIR="${HOME}/.github-meta-cache"
CACHE_FILE="${CACHE_DIR}/meta.json"
TIMESTAMP_FILE="${CACHE_DIR}/meta-timestamp.txt"
MAX_AGE_SECONDS=3600 # Cache expires after 1 hour
# Create cache directory if it doesn't exist
mkdir -p "${CACHE_DIR}"
# Function to get current timestamp
get_timestamp() {
date +%s
}
# Function to check if cache is valid
is_cache_valid() {
if [[ ! -f "${CACHE_FILE}" || ! -f "${TIMESTAMP_FILE}" ]]; then
return 1
fi
local cache_time=$(cat "${TIMESTAMP_FILE}")
local current_time=$(get_timestamp)
local age=$((current_time - cache_time))
if [[ ${age} -gt ${MAX_AGE_SECONDS} ]]; then
echo "Cache is expired (${age} seconds old)"
return 1
fi
echo "Using cached GitHub API data (${age} seconds old)"
return 0
}
# Function to fetch data using authenticated gh cli
fetch_with_gh() {
echo "Attempting to fetch GitHub API data using authenticated gh CLI..."
if gh auth status &>/dev/null; then
gh api meta > "${CACHE_FILE}" &&
get_timestamp > "${TIMESTAMP_FILE}" &&
echo "Successfully fetched and cached GitHub API data using gh CLI"
return $?
else
echo "gh CLI not authenticated"
return 1
fi
}
# Function to fetch data using curl
fetch_with_curl() {
echo "Attempting to fetch GitHub API data using curl..."
# First try with GITHUB_TOKEN if available
if [[ -n "${GITHUB_TOKEN}" ]]; then
echo "Using GITHUB_TOKEN for authentication"
curl -s -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/meta > "${CACHE_FILE}" &&
get_timestamp > "${TIMESTAMP_FILE}" &&
echo "Successfully fetched and cached GitHub API data using curl with token"
return $?
else
# Fall back to unauthenticated request
echo "No GITHUB_TOKEN found, making unauthenticated request (may be rate limited)"
curl -s https://api.github.com/meta > "${CACHE_FILE}"
# Check if the response indicates rate limiting
if grep -q "API rate limit exceeded" "${CACHE_FILE}"; then
echo "Rate limit exceeded for unauthenticated request"
return 1
else
get_timestamp > "${TIMESTAMP_FILE}"
echo "Successfully fetched and cached GitHub API data using curl without auth"
return 0
fi
fi
}
# Main logic
if is_cache_valid; then
echo "Using existing cache from $(cat ${TIMESTAMP_FILE})"
exit 0
fi
# Try with gh CLI first
if ! fetch_with_gh; then
# Fall back to curl
if ! fetch_with_curl; then
# Both methods failed, check if we have an existing cache file
if [[ -f "${CACHE_FILE}" ]]; then
echo "Warning: Failed to update cache, using existing cached data (which may be expired)"
exit 0
else
echo "Error: Failed to fetch GitHub API data and no cache exists"
exit 1
fi
fi
fi
# Display a summary of the cached data
echo "GitHub API meta data cached successfully. Summary:"
jq -r '.domains.actions | length' "${CACHE_FILE}" > /dev/null 2>&1 &&
echo "- Actions domains: $(jq -r '.domains.actions | length' "${CACHE_FILE}")" ||
echo "- Could not parse actions domains from cache file"
exit 0

View File

@@ -4,9 +4,6 @@
"dockerfile": "Dockerfile",
"args": {
"TZ": "${localEnv:TZ:America/Los_Angeles}"
},
"prebuild": {
"command": "bash -c '${localWorkspaceFolder}/.devcontainer/cache-github-api.sh || echo \"Warning: Failed to cache GitHub API data\"'"
}
},
"runArgs": [
@@ -42,8 +39,7 @@
"remoteUser": "node",
"mounts": [
"source=claude-code-bashhistory,target=/commandhistory,type=volume",
"source=claude-code-config,target=/home/node/.claude,type=volume",
"type=bind,source=${localEnv:HOME}/.github-meta-cache,target=/github-meta-cache,consistency=cached"
"source=claude-code-config,target=/home/node/.claude,type=volume"
],
"remoteEnv": {
"NODE_OPTIONS": "--max-old-space-size=4096",

View File

@@ -27,20 +27,16 @@ iptables -A OUTPUT -o lo -j ACCEPT
# Create ipset with CIDR support
ipset create allowed-domains hash:net
# Use cached GitHub meta information from mounted volume
CACHE_FILE="/github-meta-cache/meta.json"
# Fetch GitHub meta information and aggregate + add their IP ranges
echo "Fetching GitHub IP ranges..."
gh_ranges=$(curl -s https://api.github.com/meta)
if [ -z "$gh_ranges" ]; then
echo "ERROR: Failed to fetch GitHub IP ranges"
exit 1
fi
echo "Using cached GitHub IP ranges..."
if [ -f "${CACHE_FILE}" ]; then
gh_ranges=$(cat "${CACHE_FILE}")
# Verify the cached data is valid
if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
echo "ERROR: Cached GitHub API data is invalid"
exit 1
fi
else
echo "ERROR: No cached GitHub IP ranges found"
if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
echo "ERROR: GitHub API response missing required fields"
exit 1
fi

View File

@@ -0,0 +1,136 @@
name: "Claude Code Action"
description: "Run Claude Code in GitHub Actions workflows"
inputs:
github_token:
description: "GitHub token with repo and issues permissions"
required: true
anthropic_api_key:
description: "Anthropic API key"
required: true
prompt:
description: "The prompt to send to Claude Code"
required: false
default: ""
prompt_file:
description: "Path to a file containing the prompt to send to Claude Code"
required: false
default: ""
allowed_tools:
description: "Comma-separated list of allowed tools for Claude Code to use"
required: false
default: ""
output_file:
description: "File to save Claude Code output to (optional)"
required: false
default: ""
timeout_minutes:
description: "Timeout in minutes for Claude Code execution"
required: false
default: "10"
install_github_mcp:
description: "Whether to install the GitHub MCP server"
required: false
default: "false"
runs:
using: "composite"
steps:
- name: Install Claude Code
shell: bash
run: npm install -g @anthropic-ai/claude-code
- name: Install GitHub MCP Server
if: inputs.install_github_mcp == 'true'
shell: bash
run: |
claude mcp add-json github '{
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:sha-ff3036d"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.GITHUB_TOKEN }}"
}
}'
- name: Prepare Prompt File
shell: bash
id: prepare_prompt
run: |
# Check if either prompt or prompt_file is provided
if [ -z "${{ inputs.prompt }}" ] && [ -z "${{ inputs.prompt_file }}" ]; then
echo "::error::Neither 'prompt' nor 'prompt_file' was provided. At least one is required."
exit 1
fi
# Determine which prompt source to use
if [ ! -z "${{ inputs.prompt_file }}" ]; then
# Check if the prompt file exists
if [ ! -f "${{ inputs.prompt_file }}" ]; then
echo "::error::Prompt file '${{ inputs.prompt_file }}' does not exist."
exit 1
fi
# Use the provided prompt file
PROMPT_PATH="${{ inputs.prompt_file }}"
else
mkdir -p /tmp/claude-action
PROMPT_PATH="/tmp/claude-action/prompt.txt"
echo "${{ inputs.prompt }}" > "$PROMPT_PATH"
fi
# Verify the prompt file is not empty
if [ ! -s "$PROMPT_PATH" ]; then
echo "::error::Prompt is empty. Please provide a non-empty prompt."
exit 1
fi
# Save the prompt path for the next step
echo "PROMPT_PATH=$PROMPT_PATH" >> $GITHUB_ENV
- name: Run Claude Code
shell: bash
id: run_claude
run: |
ALLOWED_TOOLS_ARG=""
if [ ! -z "${{ inputs.allowed_tools }}" ]; then
ALLOWED_TOOLS_ARG="--allowedTools ${{ inputs.allowed_tools }}"
fi
# Set a timeout to ensure the command doesn't run indefinitely
timeout_seconds=$((${{ inputs.timeout_minutes }} * 60))
if [ -z "${{ inputs.output_file }}" ]; then
# Run Claude Code and output to console
timeout $timeout_seconds claude \
-p \
--verbose \
--output-format stream-json \
"$(cat ${{ env.PROMPT_PATH }})" \
${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }}
else
# Run Claude Code and tee output to console and file
timeout $timeout_seconds claude \
-p \
--verbose \
--output-format stream-json \
"$(cat ${{ env.PROMPT_PATH }})" \
${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} | tee output.txt
# Process output.txt into JSON in a separate step
jq -s '.' output.txt > output.json
# Extract the result from the last item in the array (system message)
jq -r '.[-1].result' output.json > "${{ inputs.output_file }}"
echo "Complete output saved to output.json, final response saved to ${{ inputs.output_file }}"
fi
env:
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
GITHUB_TOKEN: ${{ inputs.github_token }}

View File

@@ -0,0 +1,87 @@
name: "Claude Issue Triage Action"
description: "Automatically triage GitHub issues using Claude Code"
inputs:
timeout_minutes:
description: "Timeout in minutes for execution"
required: false
default: "5"
anthropic_api_key:
description: "Anthropic API key"
required: true
github_token:
description: "GitHub token with repo and issues permissions"
required: true
runs:
using: "composite"
steps:
- name: Checkout repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create prompt file
shell: bash
run: |
mkdir -p /tmp/claude-prompts
cat > /tmp/claude-prompts/claude-issue-triage-prompt.txt << 'EOF'
You're an issue triage assistant for GitHub issues. Your task is to analyze the issue and select appropriate labels from the provided list.
IMPORTANT: Don't post any comments or messages to the issue. Your only action should be to apply labels.
Issue Information:
- REPO: ${{ github.repository }}
- ISSUE_NUMBER: ${{ github.event.issue.number }}
TASK OVERVIEW:
1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else.
2. Next, use the GitHub tools to get context about the issue:
- You have access to these tools:
- mcp__github__get_issue: Use this to retrieve the current issue's details including title, description, and existing labels
- mcp__github__get_issue_comments: Use this to read any discussion or additional context provided in the comments
- mcp__github__update_issue: Use this to apply labels to the issue (do not use this for commenting)
- mcp__github__search_issues: Use this to find similar issues that might provide context for proper categorization and to identify potential duplicate issues
- mcp__github__list_issues: Use this to understand patterns in how other issues are labeled
- Start by using mcp__github__get_issue to get the issue details
3. Analyze the issue content, considering:
- The issue title and description
- The type of issue (bug report, feature request, question, etc.)
- Technical areas mentioned
- Severity or priority indicators
- User impact
- Components affected
4. Select appropriate labels from the available labels list provided above:
- Choose labels that accurately reflect the issue's nature
- Be specific but comprehensive
- Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority)
- Consider platform labels (android, ios) if applicable
- If you find similar issues using mcp__github__search_issues, consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
5. Apply the selected labels:
- Use mcp__github__update_issue to apply your selected labels
- DO NOT post any comments explaining your decision
- DO NOT communicate directly with users
- If no labels are clearly applicable, do not apply any labels
IMPORTANT GUIDELINES:
- Be thorough in your analysis
- Only select labels from the provided list above
- DO NOT post any comments to the issue
- Your ONLY action should be to apply labels using mcp__github__update_issue
- It's okay to not add any labels if none are clearly applicable
EOF
- name: Run Claude Code
uses: ./.github/actions/claude-code-action
with:
prompt_file: /tmp/claude-prompts/claude-issue-triage-prompt.txt
allowed_tools: "Bash(gh label list),mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__search_issues,mcp__github__list_issues"
install_github_mcp: "true"
timeout_minutes: ${{ inputs.timeout_minutes }}
anthropic_api_key: ${{ inputs.anthropic_api_key }}
github_token: ${{ inputs.github_token }}

View File

@@ -0,0 +1,23 @@
name: Claude Issue Triage
description: "Automatically triage GitHub issues using Claude Code"
on:
issues:
types: [opened]
jobs:
triage-issue:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Claude Issue Triage
uses: ./.github/actions/claude-issue-triage-action
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}

111
CHANGELOG.md Normal file
View File

@@ -0,0 +1,111 @@
# Changelog
## 0.2.70
- Network commands like curl are now available for Claude to use
- Claude can now run multiple web queries in parallel
- Pressing ESC once immediately interrupts Claude in Auto-accept mode
## 0.2.69
- Fixed UI glitches with improved Select component behavior
- Enhanced terminal output display with better text truncation logic
## 0.2.67
- Shared project permission rules can be saved in .claude/settings.json
## 0.2.66
- Print mode (-p) now supports streaming output via --output-format=stream-json
- Fixed issue where pasting could trigger memory or bash mode unexpectedly
## 0.2.63
- Fixed an issue where MCP tools were loaded twice, which caused tool call errors
## 0.2.61
- Navigate menus with vim-style keys (j/k) or bash/emacs shortcuts (Ctrl+n/p) for faster interaction
- Enhanced image detection for more reliable clipboard paste functionality
- Fixed an issue where ESC key could crash the conversation history selector
## 0.2.59
- Copy+paste images directly into your prompt
- Improved progress indicators for bash and fetch tools
- Bugfixes for non-interactive mode (-p)
## 0.2.54
- Quickly add to Memory by starting your message with '#'
- Press ctrl+r to see full output for long tool results
- Added support for MCP SSE transport
## 0.2.53
- New web fetch tool lets Claude view URLs that you paste in
- Fixed a bug with JPEG detection
## 0.2.50
- New MCP "project" scope now allows you to add MCP servers to .mcp.json files and commit them to your repository
## 0.2.49
- Previous MCP server scopes have been renamed: previous "project" scope is now "local" and "global" scope is now "user"
## 0.2.47
- Press Tab to auto-complete file and folder names
- Press Shift + Tab to toggle auto-accept for file edits
- Automatic conversation compaction for infinite conversation length (toggle with /config)
## 0.2.44
- Ask Claude to make a plan with thinking mode: just say 'think' or 'think harder' or even 'ultrathink'
## 0.2.41
- MCP server startup timeout can now be configured via MCP_TIMEOUT environment variable
- MCP server startup no longer blocks the app from starting up
## 0.2.37
- New /release-notes command lets you view release notes at any time
- `claude config add/remove` commands now accept multiple values separated by commas or spaces
## 0.2.36
- Import MCP servers from Claude Desktop with `claude mcp add-from-claude-desktop`
- Add MCP servers as JSON strings with `claude mcp add-json <n> <json>`
## 0.2.34
- Vim bindings for text input - enable with /vim or /config
## 0.2.32
- Interactive MCP setup wizard: Run "claude mcp add" to add MCP servers with a step-by-step interface
- Fix for some PersistentShell issues
## 0.2.31
- Custom slash commands: Markdown files in .claude/commands/ directories now appear as custom slash commands to insert prompts into your conversation
- MCP debug mode: Run with --mcp-debug flag to get more information about MCP server errors
## 0.2.30
- Added ANSI color theme for better terminal compatibility
- Fixed issue where slash command arguments weren't being sent properly
- (Mac-only) API keys are now stored in macOS Keychain
## 0.2.26
- New /approved-tools command for managing tool permissions
- Word-level diff display for improved code readability
- Fuzzy matching for slash commands
## 0.2.21
- Fuzzy matching for /commands

View File

@@ -1,3 +1,3 @@
Claude Code is a Beta research preview per our [Commercial Terms of Service](https://www.anthropic.com/legal/commercial-terms). When you use Claude Code, we collect Feedback, which includes usage data such as code acceptance or rejections, as well as associated conversation data. We may use this Feedback to improve our products, although we will not train models using your Feedback from Claude Code.
Claude Code is a Beta research preview per our [Commercial Terms of Service](https://www.anthropic.com/legal/commercial-terms). If Customer chooses to send us feedback about Claude Code, such as transcripts of Customer Claude Code usage, Anthropic may use that feedback to debug related issues or to improve Claude Codes functionality (e.g., to reduce the risk of similar bugs occurring in the future). Anthropic will not train models using feedback from Claude Code.
© Anthropic PBC. All rights reserved. Use is subject to Anthropic's [Commercial Terms of Service](https://www.anthropic.com/legal/commercial-terms).