mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Merge branch 'main' into fix/pin-claude-version
This commit is contained in:
@@ -6,7 +6,8 @@ ENV TZ="$TZ"
|
|||||||
ARG CLAUDE_CODE_VERSION=latest
|
ARG CLAUDE_CODE_VERSION=latest
|
||||||
|
|
||||||
# Install basic development tools and iptables/ipset
|
# Install basic development tools and iptables/ipset
|
||||||
RUN apt update && apt install -y less \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
less \
|
||||||
git \
|
git \
|
||||||
procps \
|
procps \
|
||||||
sudo \
|
sudo \
|
||||||
@@ -21,7 +22,10 @@ RUN apt update && apt install -y less \
|
|||||||
iproute2 \
|
iproute2 \
|
||||||
dnsutils \
|
dnsutils \
|
||||||
aggregate \
|
aggregate \
|
||||||
jq
|
jq \
|
||||||
|
nano \
|
||||||
|
vim \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Ensure default node user has access to /usr/local/share
|
# Ensure default node user has access to /usr/local/share
|
||||||
RUN mkdir -p /usr/local/share/npm-global && \
|
RUN mkdir -p /usr/local/share/npm-global && \
|
||||||
@@ -44,10 +48,11 @@ RUN mkdir -p /workspace /home/node/.claude && \
|
|||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
ARG GIT_DELTA_VERSION=0.18.2
|
||||||
RUN ARCH=$(dpkg --print-architecture) && \
|
RUN ARCH=$(dpkg --print-architecture) && \
|
||||||
wget "https://github.com/dandavison/delta/releases/download/0.18.2/git-delta_0.18.2_${ARCH}.deb" && \
|
wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
||||||
sudo dpkg -i "git-delta_0.18.2_${ARCH}.deb" && \
|
sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
|
||||||
rm "git-delta_0.18.2_${ARCH}.deb"
|
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
|
||||||
|
|
||||||
# Set up non-root user
|
# Set up non-root user
|
||||||
USER node
|
USER node
|
||||||
@@ -59,8 +64,13 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
|||||||
# Set the default shell to zsh rather than sh
|
# Set the default shell to zsh rather than sh
|
||||||
ENV SHELL=/bin/zsh
|
ENV SHELL=/bin/zsh
|
||||||
|
|
||||||
|
# Set the default editor and visual
|
||||||
|
ENV EDITOR nano
|
||||||
|
ENV VISUAL nano
|
||||||
|
|
||||||
# Default powerline10k theme
|
# Default powerline10k theme
|
||||||
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v1.2.0/zsh-in-docker.sh)" -- \
|
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
||||||
|
RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \
|
||||||
-p git \
|
-p git \
|
||||||
-p fzf \
|
-p fzf \
|
||||||
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
|
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
"dockerfile": "Dockerfile",
|
"dockerfile": "Dockerfile",
|
||||||
"args": {
|
"args": {
|
||||||
"TZ": "${localEnv:TZ:America/Los_Angeles}",
|
"TZ": "${localEnv:TZ:America/Los_Angeles}",
|
||||||
"CLAUDE_CODE_VERSION": "latest"
|
"CLAUDE_CODE_VERSION": "latest",
|
||||||
|
"GIT_DELTA_VERSION": "0.18.2",
|
||||||
|
"ZSH_IN_DOCKER_VERSION": "1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"runArgs": [
|
"runArgs": [
|
||||||
@@ -39,8 +41,8 @@
|
|||||||
},
|
},
|
||||||
"remoteUser": "node",
|
"remoteUser": "node",
|
||||||
"mounts": [
|
"mounts": [
|
||||||
"source=claude-code-bashhistory,target=/commandhistory,type=volume",
|
"source=claude-code-bashhistory-${devcontainerId},target=/commandhistory,type=volume",
|
||||||
"source=claude-code-config,target=/home/node/.claude,type=volume"
|
"source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
|
||||||
],
|
],
|
||||||
"remoteEnv": {
|
"remoteEnv": {
|
||||||
"NODE_OPTIONS": "--max-old-space-size=4096",
|
"NODE_OPTIONS": "--max-old-space-size=4096",
|
||||||
|
|||||||
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 }}
|
|
||||||
95
.github/workflows/claude-issue-triage.yml
vendored
95
.github/workflows/claude-issue-triage.yml
vendored
@@ -1,6 +1,5 @@
|
|||||||
name: Claude Issue Triage
|
name: Claude Issue Triage
|
||||||
description: "Automatically triage GitHub issues using Claude Code"
|
description: Automatically triage GitHub issues using Claude Code
|
||||||
|
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [opened]
|
types: [opened]
|
||||||
@@ -12,12 +11,96 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
issues: write
|
issues: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Run Claude Issue Triage
|
- name: Create triage prompt
|
||||||
uses: ./.github/actions/claude-issue-triage-action
|
run: |
|
||||||
|
mkdir -p /tmp/claude-prompts
|
||||||
|
cat > /tmp/claude-prompts/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: Setup GitHub MCP Server
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/mcp-config
|
||||||
|
cat > /tmp/mcp-config/mcp-servers.json << 'EOF'
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"github": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"-i",
|
||||||
|
"--rm",
|
||||||
|
"-e",
|
||||||
|
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
||||||
|
"ghcr.io/github/github-mcp-server:sha-7aced2b"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Run Claude Code for Issue Triage
|
||||||
|
uses: anthropics/claude-code-base-action@beta
|
||||||
with:
|
with:
|
||||||
|
prompt_file: /tmp/claude-prompts/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"
|
||||||
|
timeout_minutes: "5"
|
||||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
mcp_config: /tmp/mcp-config/mcp-servers.json
|
||||||
|
claude_env: |
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
191
CHANGELOG.md
191
CHANGELOG.md
@@ -1,10 +1,201 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.0.62
|
||||||
|
|
||||||
|
- Added @-mention support with typeahead for custom agents. @<your-custom-agent> to invoke it
|
||||||
|
- Hooks: Added SessionStart hook for new session initialization
|
||||||
|
- /add-dir command now supports typeahead for directory paths
|
||||||
|
- Improved network connectivity check reliability
|
||||||
|
|
||||||
|
## 1.0.61
|
||||||
|
|
||||||
|
- Transcript mode (Ctrl+R): Changed Esc to exit transcript mode rather than interrupt
|
||||||
|
- Settings: Added `--settings` flag to load settings from a JSON file
|
||||||
|
- Settings: Fixed resolution of settings files paths that are symlinks
|
||||||
|
- OTEL: Fixed reporting of wrong organization after authentication changes
|
||||||
|
- Slash commands: Fixed permissions checking for allowed-tools with Bash
|
||||||
|
- IDE: Added support for pasting images in VSCode MacOS using ⌘+V
|
||||||
|
- IDE: Added `CLAUDE_CODE_AUTO_CONNECT_IDE=false` for disabling IDE auto-connection
|
||||||
|
- Added `CLAUDE_CODE_SHELL_PREFIX` for wrapping Claude and user-provided shell commands run by Claude Code
|
||||||
|
|
||||||
|
## 1.0.60
|
||||||
|
|
||||||
|
- You can now create custom subagents for specialized tasks! Run /agents to get started
|
||||||
|
|
||||||
|
## 1.0.59
|
||||||
|
|
||||||
|
- SDK: Added tool confirmation support with canUseTool callback
|
||||||
|
- SDK: Allow specifying env for spawned process
|
||||||
|
- Hooks: Exposed PermissionDecision to hooks (including "ask")
|
||||||
|
- Hooks: UserPromptSubmit now supports additionalContext in advanced JSON output
|
||||||
|
- Fixed issue where some Max users that specified Opus would still see fallback to Sonnet
|
||||||
|
|
||||||
|
## 1.0.58
|
||||||
|
|
||||||
|
- Added support for reading PDFs
|
||||||
|
- MCP: Improved server health status display in 'claude mcp list'
|
||||||
|
- Hooks: Added CLAUDE_PROJECT_DIR env var for hook commands
|
||||||
|
|
||||||
|
## 1.0.57
|
||||||
|
|
||||||
|
- Added support for specifying a model in slash commands
|
||||||
|
- Improved permission messages to help Claude understand allowed tools
|
||||||
|
- Fix: Remove trailing newlines from bash output in terminal wrapping
|
||||||
|
|
||||||
|
## 1.0.56
|
||||||
|
|
||||||
|
- Windows: Enabled shift+tab for mode switching on versions of Node.js that support terminal VT mode
|
||||||
|
- Fixes for WSL IDE detection
|
||||||
|
- Fix an issue causing awsRefreshHelper changes to .aws directory not to be picked up
|
||||||
|
|
||||||
|
## 1.0.55
|
||||||
|
|
||||||
|
- Clarified knowledge cutoff for Opus 4 and Sonnet 4 models
|
||||||
|
- Windows: fixed Ctrl+Z crash
|
||||||
|
- SDK: Added ability to capture error logging
|
||||||
|
- Add --system-prompt-file option to override system prompt in print mode
|
||||||
|
|
||||||
|
## 1.0.54
|
||||||
|
|
||||||
|
- Hooks: Added UserPromptSubmit hook and the current working directory to hook inputs
|
||||||
|
- Custom slash commands: Added argument-hint to frontmatter
|
||||||
|
- Windows: OAuth uses port 45454 and properly constructs browser URL
|
||||||
|
- Windows: mode switching now uses alt + m, and plan mode renders properly
|
||||||
|
- Shell: Switch to in-memory shell snapshot to fix file-related errors
|
||||||
|
|
||||||
|
## 1.0.53
|
||||||
|
|
||||||
|
- Updated @-mention file truncation from 100 lines to 2000 lines
|
||||||
|
- Add helper script settings for AWS token refresh: awsAuthRefresh (for foreground operations like aws sso login) and awsCredentialExport (for background operation with STS-like response).
|
||||||
|
|
||||||
|
## 1.0.52
|
||||||
|
|
||||||
|
- Added support for MCP server instructions
|
||||||
|
|
||||||
|
## 1.0.51
|
||||||
|
|
||||||
|
- Added support for native Windows (requires Git for Windows)
|
||||||
|
- Added support for Bedrock API keys through environment variable AWS_BEARER_TOKEN_BEDROCK
|
||||||
|
- Settings: /doctor can now help you identify and fix invalid setting files
|
||||||
|
- `--append-system-prompt` can now be used in interactive mode, not just --print/-p.
|
||||||
|
- Increased auto-compact warning threshold from 60% to 80%
|
||||||
|
- Fixed an issue with handling user directories with spaces for shell snapshots
|
||||||
|
- OTEL resource now includes os.type, os.version, host.arch, and wsl.version (if running on Windows Subsystem for Linux)
|
||||||
|
- Custom slash commands: Fixed user-level commands in subdirectories
|
||||||
|
- Plan mode: Fixed issue where rejected plan from sub-task would get discarded
|
||||||
|
|
||||||
|
## 1.0.48
|
||||||
|
|
||||||
|
- Fixed a bug in v1.0.45 where the app would sometimes freeze on launch
|
||||||
|
- Added progress messages to Bash tool based on the last 5 lines of command output
|
||||||
|
- Added expanding variables support for MCP server configuration
|
||||||
|
- Moved shell snapshots from /tmp to ~/.claude for more reliable Bash tool calls
|
||||||
|
- Improved IDE extension path handling when Claude Code runs in WSL
|
||||||
|
- Hooks: Added a PreCompact hook
|
||||||
|
- Vim mode: Added c, f/F, t/T
|
||||||
|
|
||||||
|
## 1.0.45
|
||||||
|
|
||||||
|
- Redesigned Search (Grep) tool with new tool input parameters and features
|
||||||
|
- Disabled IDE diffs for notebook files, fixing "Timeout waiting after 1000ms" error
|
||||||
|
- Fixed config file corruption issue by enforcing atomic writes
|
||||||
|
- Updated prompt input undo to Ctrl+\_ to avoid breaking existing Ctrl+U behavior, matching zsh's undo shortcut
|
||||||
|
- Stop Hooks: Fixed transcript path after /clear and fixed triggering when loop ends with tool call
|
||||||
|
- Custom slash commands: Restored namespacing in command names based on subdirectories. For example, .claude/commands/frontend/component.md is now /frontend:component, not /component.
|
||||||
|
|
||||||
|
## 1.0.44
|
||||||
|
|
||||||
|
- New /export command lets you quickly export a conversation for sharing
|
||||||
|
- MCP: resource_link tool results are now supported
|
||||||
|
- MCP: tool annotations and tool titles now display in /mcp view
|
||||||
|
- Changed Ctrl+Z to suspend Claude Code. Resume by running `fg`. Prompt input undo is now Ctrl+U.
|
||||||
|
|
||||||
|
## 1.0.43
|
||||||
|
|
||||||
|
- Fixed a bug where the theme selector was saving excessively
|
||||||
|
- Hooks: Added EPIPE system error handling
|
||||||
|
|
||||||
|
## 1.0.42
|
||||||
|
|
||||||
|
- Added tilde (`~`) expansion support to `/add-dir` command
|
||||||
|
|
||||||
|
## 1.0.41
|
||||||
|
|
||||||
|
- Hooks: Split Stop hook triggering into Stop and SubagentStop
|
||||||
|
- Hooks: Enabled optional timeout configuration for each command
|
||||||
|
- Hooks: Added "hook_event_name" to hook input
|
||||||
|
- Fixed a bug where MCP tools would display twice in tool list
|
||||||
|
- New tool parameters JSON for Bash tool in `tool_decision` event
|
||||||
|
|
||||||
|
## 1.0.40
|
||||||
|
|
||||||
|
- Fixed a bug causing API connection errors with UNABLE_TO_GET_ISSUER_CERT_LOCALLY if `NODE_EXTRA_CA_CERTS` was set
|
||||||
|
|
||||||
|
## 1.0.39
|
||||||
|
|
||||||
|
- New Active Time metric in OpenTelemetry logging
|
||||||
|
|
||||||
|
## 1.0.38
|
||||||
|
|
||||||
|
- Released hooks. Special thanks to community input in https://github.com/anthropics/claude-code/issues/712. Docs: https://docs.anthropic.com/en/docs/claude-code/hooks
|
||||||
|
|
||||||
|
## 1.0.37
|
||||||
|
|
||||||
|
- Remove ability to set `Proxy-Authorization` header via ANTHROPIC_AUTH_TOKEN or apiKeyHelper
|
||||||
|
|
||||||
|
## 1.0.36
|
||||||
|
|
||||||
|
- Web search now takes today's date into context
|
||||||
|
- Fixed a bug where stdio MCP servers were not terminating properly on exit
|
||||||
|
|
||||||
|
## 1.0.35
|
||||||
|
|
||||||
|
- Added support for MCP OAuth Authorization Server discovery
|
||||||
|
|
||||||
|
## 1.0.34
|
||||||
|
|
||||||
|
- Fixed a memory leak causing a MaxListenersExceededWarning message to appear
|
||||||
|
|
||||||
|
## 1.0.33
|
||||||
|
|
||||||
|
- Improved logging functionality with session ID support
|
||||||
|
- Added prompt input undo functionality (Ctrl+Z and vim 'u' command)
|
||||||
|
- Improvements to plan mode
|
||||||
|
|
||||||
|
## 1.0.32
|
||||||
|
|
||||||
|
- Updated loopback config for litellm
|
||||||
|
- Added forceLoginMethod setting to bypass login selection screen
|
||||||
|
|
||||||
|
## 1.0.31
|
||||||
|
|
||||||
|
- Fixed a bug where ~/.claude.json would get reset when file contained invalid JSON
|
||||||
|
|
||||||
|
## 1.0.30
|
||||||
|
|
||||||
|
- Custom slash commands: Run bash output, @-mention files, enable thinking with thinking keywords
|
||||||
|
- Improved file path autocomplete with filename matching
|
||||||
|
- Added timestamps in Ctrl-r mode and fixed Ctrl-c handling
|
||||||
|
- Enhanced jq regex support for complex filters with pipes and select
|
||||||
|
|
||||||
|
## 1.0.29
|
||||||
|
|
||||||
|
- Improved CJK character support in cursor navigation and rendering
|
||||||
|
|
||||||
|
## 1.0.28
|
||||||
|
|
||||||
|
- Slash commands: Fix selector display during history navigation
|
||||||
|
- Resizes images before upload to prevent API size limit errors
|
||||||
|
- Added XDG_CONFIG_HOME support to configuration directory
|
||||||
|
- Performance optimizations for memory usage
|
||||||
|
- New attributes (terminal.type, language) in OpenTelemetry logging
|
||||||
|
|
||||||
## 1.0.27
|
## 1.0.27
|
||||||
|
|
||||||
- Streamable HTTP MCP servers are now supported
|
- Streamable HTTP MCP servers are now supported
|
||||||
- Remote MCP servers (SSE and HTTP) now support OAuth
|
- Remote MCP servers (SSE and HTTP) now support OAuth
|
||||||
- MCP resources can now be @-mentioned
|
- MCP resources can now be @-mentioned
|
||||||
|
- /resume slash command to switch conversations within Claude Code
|
||||||
|
|
||||||
## 1.0.25
|
## 1.0.25
|
||||||
|
|
||||||
|
|||||||
148
Script/run_devcontainer_claude_code.ps1
Normal file
148
Script/run_devcontainer_claude_code.ps1
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Automates the setup and connection to a DevContainer environment using either Docker or Podman on Windows.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script automates the process of initializing, starting, and connecting to a DevContainer
|
||||||
|
using either Docker or Podman as the container backend. It must be executed from the root
|
||||||
|
directory of your project and assumes the script is located in a 'Script' subdirectory.
|
||||||
|
|
||||||
|
.PARAMETER Backend
|
||||||
|
Specifies the container backend to use. Valid values are 'docker' or 'podman'.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Script\run_devcontainer_claude_code.ps1 -Backend docker
|
||||||
|
Uses Docker as the container backend.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Script\run_devcontainer_claude_code.ps1 -Backend podman
|
||||||
|
Uses Podman as the container backend.
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
Project Structure:
|
||||||
|
Project/
|
||||||
|
├── .devcontainer/
|
||||||
|
└── Script/
|
||||||
|
└── run_devcontainer_claude_code.ps1
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[ValidateSet('docker','podman')]
|
||||||
|
[string]$Backend
|
||||||
|
)
|
||||||
|
|
||||||
|
# Notify script start
|
||||||
|
Write-Host "--- DevContainer Startup & Connection Script ---"
|
||||||
|
Write-Host "Using backend: $($Backend)"
|
||||||
|
|
||||||
|
# --- Prerequisite Check ---
|
||||||
|
Write-Host "Checking for required commands..."
|
||||||
|
try {
|
||||||
|
Get-Command $Backend -ErrorAction Stop | Out-Null
|
||||||
|
Write-Host "- $($Backend) command found."
|
||||||
|
Get-Command devcontainer -ErrorAction Stop | Out-Null
|
||||||
|
Write-Host "- devcontainer command found."
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "A required command is not installed or not in your PATH."
|
||||||
|
Write-Error "Please ensure '$($_.Exception.Message.Split(':')[0])' and 'devcontainer' are installed and accessible."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# --- Backend-Specific Initialization ---
|
||||||
|
if ($Backend -eq 'podman') {
|
||||||
|
Write-Host "--- Podman Backend Initialization ---"
|
||||||
|
|
||||||
|
# --- Step 1a: Initialize Podman machine ---
|
||||||
|
Write-Host "Initializing Podman machine 'claudeVM'..."
|
||||||
|
try {
|
||||||
|
& podman machine init claudeVM
|
||||||
|
Write-Host "Podman machine 'claudeVM' initialized or already exists."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to initialize Podman machine: $($_.Exception.Message)"
|
||||||
|
exit 1 # Exit script on error
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Step 1b: Start Podman machine ---
|
||||||
|
Write-Host "Starting Podman machine 'claudeVM'..."
|
||||||
|
try {
|
||||||
|
& podman machine start claudeVM -q
|
||||||
|
Write-Host "Podman machine started or already running."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to start Podman machine: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Step 2: Set default connection ---
|
||||||
|
Write-Host "Setting default Podman connection to 'claudeVM'..."
|
||||||
|
try {
|
||||||
|
& podman system connection default claudeVM
|
||||||
|
Write-Host "Default connection set."
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Failed to set default Podman connection (may be already set or machine issue): $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($Backend -eq 'docker') {
|
||||||
|
Write-Host "--- Docker Backend Initialization ---"
|
||||||
|
|
||||||
|
# --- Step 1 & 2: Check Docker Desktop ---
|
||||||
|
Write-Host "Checking if Docker Desktop is running and docker command is available..."
|
||||||
|
try {
|
||||||
|
docker info | Out-Null
|
||||||
|
Write-Host "Docker Desktop (daemon) is running."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Docker Desktop is not running or docker command not found."
|
||||||
|
Write-Error "Please ensure Docker Desktop is running."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Step 3: Bring up DevContainer ---
|
||||||
|
Write-Host "Bringing up DevContainer in the current folder..."
|
||||||
|
try {
|
||||||
|
$arguments = @('up', '--workspace-folder', '.')
|
||||||
|
if ($Backend -eq 'podman') {
|
||||||
|
$arguments += '--docker-path', 'podman'
|
||||||
|
}
|
||||||
|
& devcontainer @arguments
|
||||||
|
Write-Host "DevContainer startup process completed."
|
||||||
|
} catch {
|
||||||
|
Write-Error "Failed to bring up DevContainer: $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Step 4: Get DevContainer ID ---
|
||||||
|
Write-Host "Finding the DevContainer ID..."
|
||||||
|
$currentFolder = (Get-Location).Path
|
||||||
|
|
||||||
|
try {
|
||||||
|
$containerId = (& $Backend ps --filter "label=devcontainer.local_folder=$currentFolder" --format '{{.ID}}').Trim()
|
||||||
|
} catch {
|
||||||
|
$displayCommand = "$Backend ps --filter `"label=devcontainer.local_folder=$currentFolder`" --format '{{.ID}}'"
|
||||||
|
Write-Error "Failed to get container ID (Command: $displayCommand): $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $containerId) {
|
||||||
|
Write-Error "Could not find DevContainer ID for the current folder ('$currentFolder')."
|
||||||
|
Write-Error "Please check if 'devcontainer up' was successful and the container is running."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Found container ID: $containerId"
|
||||||
|
|
||||||
|
# --- Step 5 & 6: Execute command and enter interactive shell inside container ---
|
||||||
|
Write-Host "Executing 'claude' command and then starting zsh session inside container $($containerId)..."
|
||||||
|
try {
|
||||||
|
& $Backend exec -it $containerId zsh -c 'claude; exec zsh'
|
||||||
|
Write-Host "Interactive session ended."
|
||||||
|
} catch {
|
||||||
|
$displayCommand = "$Backend exec -it $containerId zsh -c 'claude; exec zsh'"
|
||||||
|
Write-Error "Failed to execute command inside container (Command: $displayCommand): $($_.Exception.Message)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Notify script completion
|
||||||
|
Write-Host "--- Script completed ---"
|
||||||
83
examples/hooks/bash_command_validator_example.py
Normal file
83
examples/hooks/bash_command_validator_example.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Claude Code Hook: Bash Command Validator
|
||||||
|
=========================================
|
||||||
|
This hook runs as a PreToolUse hook for the Bash tool.
|
||||||
|
It validates bash commands against a set of rules before execution.
|
||||||
|
In this case it changes grep calls to using rg.
|
||||||
|
|
||||||
|
Read more about hooks here: https://docs.anthropic.com/en/docs/claude-code/hooks
|
||||||
|
|
||||||
|
Make sure to change your path to your actual script.
|
||||||
|
|
||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PreToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Bash",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "python3 /path/to/claude-code/examples/hooks/bash_command_validator_example.py"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Define validation rules as a list of (regex pattern, message) tuples
|
||||||
|
_VALIDATION_RULES = [
|
||||||
|
(
|
||||||
|
r"^grep\b(?!.*\|)",
|
||||||
|
"Use 'rg' (ripgrep) instead of 'grep' for better performance and features",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r"^find\s+\S+\s+-name\b",
|
||||||
|
"Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_command(command: str) -> list[str]:
|
||||||
|
issues = []
|
||||||
|
for pattern, message in _VALIDATION_RULES:
|
||||||
|
if re.search(pattern, command):
|
||||||
|
issues.append(message)
|
||||||
|
return issues
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
input_data = json.load(sys.stdin)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||||
|
# Exit code 1 shows stderr to the user but not to Claude
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
tool_name = input_data.get("tool_name", "")
|
||||||
|
if tool_name != "Bash":
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
tool_input = input_data.get("tool_input", {})
|
||||||
|
command = tool_input.get("command", "")
|
||||||
|
|
||||||
|
if not command:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
issues = _validate_command(command)
|
||||||
|
if issues:
|
||||||
|
for message in issues:
|
||||||
|
print(f"• {message}", file=sys.stderr)
|
||||||
|
# Exit code 2 blocks tool call and shows stderr to Claude
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user