mirror of
https://github.com/anthropics/claude-code.git
synced 2026-06-20 14:43:30 +00:00
Compare commits
1 Commits
ashwin/tri
...
github-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc84d5711b |
@@ -69,10 +69,10 @@ RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/
|
|||||||
# Install Claude
|
# Install Claude
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
RUN npm install -g @anthropic-ai/claude-code
|
||||||
|
|
||||||
# Copy and set up firewall script
|
# Copy and set up scripts
|
||||||
COPY init-firewall.sh /usr/local/bin/
|
COPY init-firewall.sh cache-github-api.sh /usr/local/bin/
|
||||||
USER root
|
USER root
|
||||||
RUN chmod +x /usr/local/bin/init-firewall.sh && \
|
RUN chmod +x /usr/local/bin/init-firewall.sh /usr/local/bin/cache-github-api.sh && \
|
||||||
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
|
echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \
|
||||||
chmod 0440 /etc/sudoers.d/node-firewall
|
chmod 0440 /etc/sudoers.d/node-firewall
|
||||||
USER node
|
USER node
|
||||||
|
|||||||
109
.devcontainer/cache-github-api.sh
Executable file
109
.devcontainer/cache-github-api.sh
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/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
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"args": {
|
"args": {
|
||||||
"TZ": "${localEnv:TZ:America/Los_Angeles}"
|
"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": [
|
"runArgs": [
|
||||||
@@ -39,7 +42,8 @@
|
|||||||
"remoteUser": "node",
|
"remoteUser": "node",
|
||||||
"mounts": [
|
"mounts": [
|
||||||
"source=claude-code-bashhistory,target=/commandhistory,type=volume",
|
"source=claude-code-bashhistory,target=/commandhistory,type=volume",
|
||||||
"source=claude-code-config,target=/home/node/.claude,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"
|
||||||
],
|
],
|
||||||
"remoteEnv": {
|
"remoteEnv": {
|
||||||
"NODE_OPTIONS": "--max-old-space-size=4096",
|
"NODE_OPTIONS": "--max-old-space-size=4096",
|
||||||
|
|||||||
@@ -27,16 +27,20 @@ iptables -A OUTPUT -o lo -j ACCEPT
|
|||||||
# Create ipset with CIDR support
|
# Create ipset with CIDR support
|
||||||
ipset create allowed-domains hash:net
|
ipset create allowed-domains hash:net
|
||||||
|
|
||||||
# Fetch GitHub meta information and aggregate + add their IP ranges
|
# Use cached GitHub meta information from mounted volume
|
||||||
echo "Fetching GitHub IP ranges..."
|
CACHE_FILE="/github-meta-cache/meta.json"
|
||||||
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
|
|
||||||
|
|
||||||
if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
|
echo "Using cached GitHub IP ranges..."
|
||||||
echo "ERROR: GitHub API response missing required fields"
|
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"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
136
.github/actions/claude-code-action/action.yml
vendored
136
.github/actions/claude-code-action/action.yml
vendored
@@ -1,136 +0,0 @@
|
|||||||
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 }}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
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 }}
|
|
||||||
23
.github/workflows/claude-issue-triage.yml
vendored
23
.github/workflows/claude-issue-triage.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
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 }}
|
|
||||||
87
CHANGELOG.md
87
CHANGELOG.md
@@ -1,87 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 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
|
|
||||||
Reference in New Issue
Block a user