surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
| @@ -6,7 +6,8 @@ | ||
| 6 | 6 | ARG CLAUDE_CODE_VERSION=latest |
| 7 | 7 | |
| 8 | 8 | # Install basic development tools and iptables/ipset |
| 9 | -RUN apt update && apt install -y less \ | |
| 9 | +RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| 10 | + less \ | |
| 10 | 11 | git \ |
| 11 | 12 | procps \ |
| 12 | 13 | sudo \ |
| @@ -21,7 +22,10 @@ | ||
| 21 | 22 | iproute2 \ |
| 22 | 23 | dnsutils \ |
| 23 | 24 | aggregate \ |
| 24 | - jq | |
| 25 | + jq \ | |
| 26 | + nano \ | |
| 27 | + vim \ | |
| 28 | + && apt-get clean && rm -rf /var/lib/apt/lists/* | |
| 25 | 29 | |
| 26 | 30 | # Ensure default node user has access to /usr/local/share |
| 27 | 31 | RUN mkdir -p /usr/local/share/npm-global && \ |
| @@ -44,10 +48,11 @@ | ||
| 44 | 48 | |
| 45 | 49 | WORKDIR /workspace |
| 46 | 50 | |
| 51 | +ARG GIT_DELTA_VERSION=0.18.2 | |
| 47 | 52 | RUN ARCH=$(dpkg --print-architecture) && \ |
| 48 | - wget "https://github.com/dandavison/delta/releases/download/0.18.2/git-delta_0.18.2_${ARCH}.deb" && \ | |
| 49 | - sudo dpkg -i "git-delta_0.18.2_${ARCH}.deb" && \ | |
| 50 | - rm "git-delta_0.18.2_${ARCH}.deb" | |
| 53 | + wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ | |
| 54 | + sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ | |
| 55 | + rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" | |
| 51 | 56 | |
| 52 | 57 | # Set up non-root user |
| 53 | 58 | USER node |
| @@ -59,8 +64,13 @@ | ||
| 59 | 64 | # Set the default shell to zsh rather than sh |
| 60 | 65 | ENV SHELL=/bin/zsh |
| 61 | 66 | |
| 67 | +# Set the default editor and visual | |
| 68 | +ENV EDITOR nano | |
| 69 | +ENV VISUAL nano | |
| 70 | + | |
| 62 | 71 | # Default powerline10k theme |
| 63 | -RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v1.2.0/zsh-in-docker.sh)" -- \ | |
| 72 | +ARG ZSH_IN_DOCKER_VERSION=1.2.0 | |
| 73 | +RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \ | |
| 64 | 74 | -p git \ |
| 65 | 75 | -p fzf \ |
| 66 | 76 | -a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \ |
| @@ -4,7 +4,9 @@ | ||
| 4 | 4 | "dockerfile": "Dockerfile", |
| 5 | 5 | "args": { |
| 6 | 6 | "TZ": "${localEnv:TZ:America/Los_Angeles}", |
| 7 | - "CLAUDE_CODE_VERSION": "latest" | |
| 7 | + "CLAUDE_CODE_VERSION": "latest", | |
| 8 | + "GIT_DELTA_VERSION": "0.18.2", | |
| 9 | + "ZSH_IN_DOCKER_VERSION": "1.2.0" | |
| 8 | 10 | } |
| 9 | 11 | }, |
| 10 | 12 | "runArgs": [ |
| @@ -39,8 +41,8 @@ | ||
| 39 | 41 | }, |
| 40 | 42 | "remoteUser": "node", |
| 41 | 43 | "mounts": [ |
| 42 | - "source=claude-code-bashhistory,target=/commandhistory,type=volume", | |
| 43 | - "source=claude-code-config,target=/home/node/.claude,type=volume" | |
| 44 | + "source=claude-code-bashhistory-${devcontainerId},target=/commandhistory,type=volume", | |
| 45 | + "source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume" | |
| 44 | 46 | ], |
| 45 | 47 | "remoteEnv": { |
| 46 | 48 | "NODE_OPTIONS": "--max-old-space-size=4096", |
| @@ -1,136 +1,0 @@ | ||
| 1 | -name: "Claude Code Action" | |
| 2 | -description: "Run Claude Code in GitHub Actions workflows" | |
| 3 | - | |
| 4 | -inputs: | |
| 5 | - github_token: | |
| 6 | - description: "GitHub token with repo and issues permissions" | |
| 7 | - required: true | |
| 8 | - anthropic_api_key: | |
| 9 | - description: "Anthropic API key" | |
| 10 | - required: true | |
| 11 | - prompt: | |
| 12 | - description: "The prompt to send to Claude Code" | |
| 13 | - required: false | |
| 14 | - default: "" | |
| 15 | - prompt_file: | |
| 16 | - description: "Path to a file containing the prompt to send to Claude Code" | |
| 17 | - required: false | |
| 18 | - default: "" | |
| 19 | - allowed_tools: | |
| 20 | - description: "Comma-separated list of allowed tools for Claude Code to use" | |
| 21 | - required: false | |
| 22 | - default: "" | |
| 23 | - output_file: | |
| 24 | - description: "File to save Claude Code output to (optional)" | |
| 25 | - required: false | |
| 26 | - default: "" | |
| 27 | - timeout_minutes: | |
| 28 | - description: "Timeout in minutes for Claude Code execution" | |
| 29 | - required: false | |
| 30 | - default: "10" | |
| 31 | - install_github_mcp: | |
| 32 | - description: "Whether to install the GitHub MCP server" | |
| 33 | - required: false | |
| 34 | - default: "false" | |
| 35 | - | |
| 36 | -runs: | |
| 37 | - using: "composite" | |
| 38 | - steps: | |
| 39 | - - name: Install Claude Code | |
| 40 | - shell: bash | |
| 41 | - run: npm install -g @anthropic-ai/claude-code | |
| 42 | - | |
| 43 | - - name: Install GitHub MCP Server | |
| 44 | - if: inputs.install_github_mcp == 'true' | |
| 45 | - shell: bash | |
| 46 | - run: | | |
| 47 | - claude mcp add-json github '{ | |
| 48 | - "command": "docker", | |
| 49 | - "args": [ | |
| 50 | - "run", | |
| 51 | - "-i", | |
| 52 | - "--rm", | |
| 53 | - "-e", | |
| 54 | - "GITHUB_PERSONAL_ACCESS_TOKEN", | |
| 55 | - "ghcr.io/github/github-mcp-server:sha-ff3036d" | |
| 56 | - ], | |
| 57 | - "env": { | |
| 58 | - "GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.GITHUB_TOKEN }}" | |
| 59 | - } | |
| 60 | - }' | |
| 61 | - | |
| 62 | - - name: Prepare Prompt File | |
| 63 | - shell: bash | |
| 64 | - id: prepare_prompt | |
| 65 | - run: | | |
| 66 | - # Check if either prompt or prompt_file is provided | |
| 67 | - if [ -z "${{ inputs.prompt }}" ] && [ -z "${{ inputs.prompt_file }}" ]; then | |
| 68 | - echo "::error::Neither 'prompt' nor 'prompt_file' was provided. At least one is required." | |
| 69 | - exit 1 | |
| 70 | - fi | |
| 71 | - | |
| 72 | - # Determine which prompt source to use | |
| 73 | - if [ ! -z "${{ inputs.prompt_file }}" ]; then | |
| 74 | - # Check if the prompt file exists | |
| 75 | - if [ ! -f "${{ inputs.prompt_file }}" ]; then | |
| 76 | - echo "::error::Prompt file '${{ inputs.prompt_file }}' does not exist." | |
| 77 | - exit 1 | |
| 78 | - fi | |
| 79 | - | |
| 80 | - # Use the provided prompt file | |
| 81 | - PROMPT_PATH="${{ inputs.prompt_file }}" | |
| 82 | - else | |
| 83 | - mkdir -p /tmp/claude-action | |
| 84 | - PROMPT_PATH="/tmp/claude-action/prompt.txt" | |
| 85 | - echo "${{ inputs.prompt }}" > "$PROMPT_PATH" | |
| 86 | - fi | |
| 87 | - | |
| 88 | - # Verify the prompt file is not empty | |
| 89 | - if [ ! -s "$PROMPT_PATH" ]; then | |
| 90 | - echo "::error::Prompt is empty. Please provide a non-empty prompt." | |
| 91 | - exit 1 | |
| 92 | - fi | |
| 93 | - | |
| 94 | - # Save the prompt path for the next step | |
| 95 | - echo "PROMPT_PATH=$PROMPT_PATH" >> $GITHUB_ENV | |
| 96 | - | |
| 97 | - - name: Run Claude Code | |
| 98 | - shell: bash | |
| 99 | - id: run_claude | |
| 100 | - run: | | |
| 101 | - ALLOWED_TOOLS_ARG="" | |
| 102 | - if [ ! -z "${{ inputs.allowed_tools }}" ]; then | |
| 103 | - ALLOWED_TOOLS_ARG="--allowedTools ${{ inputs.allowed_tools }}" | |
| 104 | - fi | |
| 105 | - | |
| 106 | - # Set a timeout to ensure the command doesn't run indefinitely | |
| 107 | - timeout_seconds=$((${{ inputs.timeout_minutes }} * 60)) | |
| 108 | - | |
| 109 | - if [ -z "${{ inputs.output_file }}" ]; then | |
| 110 | - # Run Claude Code and output to console | |
| 111 | - timeout $timeout_seconds claude \ | |
| 112 | - -p \ | |
| 113 | - --verbose \ | |
| 114 | - --output-format stream-json \ | |
| 115 | - "$(cat ${{ env.PROMPT_PATH }})" \ | |
| 116 | - ${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} | |
| 117 | - else | |
| 118 | - # Run Claude Code and tee output to console and file | |
| 119 | - timeout $timeout_seconds claude \ | |
| 120 | - -p \ | |
| 121 | - --verbose \ | |
| 122 | - --output-format stream-json \ | |
| 123 | - "$(cat ${{ env.PROMPT_PATH }})" \ | |
| 124 | - ${{ inputs.allowed_tools != '' && format('--allowedTools "{0}"', inputs.allowed_tools) || '' }} | tee output.txt | |
| 125 | - | |
| 126 | - # Process output.txt into JSON in a separate step | |
| 127 | - jq -s '.' output.txt > output.json | |
| 128 | - | |
| 129 | - # Extract the result from the last item in the array (system message) | |
| 130 | - jq -r '.[-1].result' output.json > "${{ inputs.output_file }}" | |
| 131 | - | |
| 132 | - echo "Complete output saved to output.json, final response saved to ${{ inputs.output_file }}" | |
| 133 | - fi | |
| 134 | - env: | |
| 135 | - ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }} | |
| 136 | - GITHUB_TOKEN: ${{ inputs.github_token }} |
| @@ -1,87 +1,0 @@ | ||
| 1 | -name: "Claude Issue Triage Action" | |
| 2 | -description: "Automatically triage GitHub issues using Claude Code" | |
| 3 | - | |
| 4 | -inputs: | |
| 5 | - timeout_minutes: | |
| 6 | - description: "Timeout in minutes for execution" | |
| 7 | - required: false | |
| 8 | - default: "5" | |
| 9 | - anthropic_api_key: | |
| 10 | - description: "Anthropic API key" | |
| 11 | - required: true | |
| 12 | - github_token: | |
| 13 | - description: "GitHub token with repo and issues permissions" | |
| 14 | - required: true | |
| 15 | - | |
| 16 | -runs: | |
| 17 | - using: "composite" | |
| 18 | - steps: | |
| 19 | - - name: Checkout repository code | |
| 20 | - uses: actions/checkout@v4 | |
| 21 | - with: | |
| 22 | - fetch-depth: 0 | |
| 23 | - | |
| 24 | - - name: Create prompt file | |
| 25 | - shell: bash | |
| 26 | - run: | | |
| 27 | - mkdir -p /tmp/claude-prompts | |
| 28 | - cat > /tmp/claude-prompts/claude-issue-triage-prompt.txt << 'EOF' | |
| 29 | - You're an issue triage assistant for GitHub issues. Your task is to analyze the issue and select appropriate labels from the provided list. | |
| 30 | - | |
| 31 | - IMPORTANT: Don't post any comments or messages to the issue. Your only action should be to apply labels. | |
| 32 | - | |
| 33 | - Issue Information: | |
| 34 | - - REPO: ${{ github.repository }} | |
| 35 | - - ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| 36 | - | |
| 37 | - TASK OVERVIEW: | |
| 38 | - | |
| 39 | - 1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else. | |
| 40 | - | |
| 41 | - 2. Next, use the GitHub tools to get context about the issue: | |
| 42 | - - You have access to these tools: | |
| 43 | - - mcp__github__get_issue: Use this to retrieve the current issue's details including title, description, and existing labels | |
| 44 | - - mcp__github__get_issue_comments: Use this to read any discussion or additional context provided in the comments | |
| 45 | - - mcp__github__update_issue: Use this to apply labels to the issue (do not use this for commenting) | |
| 46 | - - mcp__github__search_issues: Use this to find similar issues that might provide context for proper categorization and to identify potential duplicate issues | |
| 47 | - - mcp__github__list_issues: Use this to understand patterns in how other issues are labeled | |
| 48 | - - Start by using mcp__github__get_issue to get the issue details | |
| 49 | - | |
| 50 | - 3. Analyze the issue content, considering: | |
| 51 | - - The issue title and description | |
| 52 | - - The type of issue (bug report, feature request, question, etc.) | |
| 53 | - - Technical areas mentioned | |
| 54 | - - Severity or priority indicators | |
| 55 | - - User impact | |
| 56 | - - Components affected | |
| 57 | - | |
| 58 | - 4. Select appropriate labels from the available labels list provided above: | |
| 59 | - - Choose labels that accurately reflect the issue's nature | |
| 60 | - - Be specific but comprehensive | |
| 61 | - - Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority) | |
| 62 | - - Consider platform labels (android, ios) if applicable | |
| 63 | - - 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. | |
| 64 | - | |
| 65 | - 5. Apply the selected labels: | |
| 66 | - - Use mcp__github__update_issue to apply your selected labels | |
| 67 | - - DO NOT post any comments explaining your decision | |
| 68 | - - DO NOT communicate directly with users | |
| 69 | - - If no labels are clearly applicable, do not apply any labels | |
| 70 | - | |
| 71 | - IMPORTANT GUIDELINES: | |
| 72 | - - Be thorough in your analysis | |
| 73 | - - Only select labels from the provided list above | |
| 74 | - - DO NOT post any comments to the issue | |
| 75 | - - Your ONLY action should be to apply labels using mcp__github__update_issue | |
| 76 | - - It's okay to not add any labels if none are clearly applicable | |
| 77 | - EOF | |
| 78 | - | |
| 79 | - - name: Run Claude Code | |
| 80 | - uses: ./.github/actions/claude-code-action | |
| 81 | - with: | |
| 82 | - prompt_file: /tmp/claude-prompts/claude-issue-triage-prompt.txt | |
| 83 | - 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" | |
| 84 | - install_github_mcp: "true" | |
| 85 | - timeout_minutes: ${{ inputs.timeout_minutes }} | |
| 86 | - anthropic_api_key: ${{ inputs.anthropic_api_key }} | |
| 87 | - github_token: ${{ inputs.github_token }} |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | name: Claude Issue Triage |
| 2 | -description: "Automatically triage GitHub issues using Claude Code" | |
| 3 | - | |
| 2 | +description: Automatically triage GitHub issues using Claude Code | |
| 4 | 3 | on: |
| 5 | 4 | issues: |
| 6 | 5 | types: [opened] |
| @@ -12,12 +11,96 @@ | ||
| 12 | 11 | permissions: |
| 13 | 12 | contents: read |
| 14 | 13 | issues: write |
| 14 | + | |
| 15 | 15 | steps: |
| 16 | 16 | - name: Checkout repository |
| 17 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | |
| 17 | + uses: actions/checkout@v4 | |
| 18 | 18 | |
| 19 | - - name: Run Claude Issue Triage | |
| 20 | - uses: ./.github/actions/claude-issue-triage-action | |
| 19 | + - name: Create triage prompt | |
| 20 | + run: | | |
| 21 | + mkdir -p /tmp/claude-prompts | |
| 22 | + cat > /tmp/claude-prompts/triage-prompt.txt << 'EOF' | |
| 23 | + You're an issue triage assistant for GitHub issues. Your task is to analyze the issue and select appropriate labels from the provided list. | |
| 24 | + | |
| 25 | + IMPORTANT: Don't post any comments or messages to the issue. Your only action should be to apply labels. | |
| 26 | + | |
| 27 | + Issue Information: | |
| 28 | + - REPO: ${{ github.repository }} | |
| 29 | + - ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| 30 | + | |
| 31 | + TASK OVERVIEW: | |
| 32 | + | |
| 33 | + 1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else. | |
| 34 | + | |
| 35 | + 2. Next, use the GitHub tools to get context about the issue: | |
| 36 | + - You have access to these tools: | |
| 37 | + - mcp__github__get_issue: Use this to retrieve the current issue's details including title, description, and existing labels | |
| 38 | + - mcp__github__get_issue_comments: Use this to read any discussion or additional context provided in the comments | |
| 39 | + - mcp__github__update_issue: Use this to apply labels to the issue (do not use this for commenting) | |
| 40 | + - mcp__github__search_issues: Use this to find similar issues that might provide context for proper categorization and to identify potential duplicate issues | |
| 41 | + - mcp__github__list_issues: Use this to understand patterns in how other issues are labeled | |
| 42 | + - Start by using mcp__github__get_issue to get the issue details | |
| 43 | + | |
| 44 | + 3. Analyze the issue content, considering: | |
| 45 | + - The issue title and description | |
| 46 | + - The type of issue (bug report, feature request, question, etc.) | |
| 47 | + - Technical areas mentioned | |
| 48 | + - Severity or priority indicators | |
| 49 | + - User impact | |
| 50 | + - Components affected | |
| 51 | + | |
| 52 | + 4. Select appropriate labels from the available labels list provided above: | |
| 53 | + - Choose labels that accurately reflect the issue's nature | |
| 54 | + - Be specific but comprehensive | |
| 55 | + - Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority) | |
| 56 | + - Consider platform labels (android, ios) if applicable | |
| 57 | + - 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. | |
| 58 | + | |
| 59 | + 5. Apply the selected labels: | |
| 60 | + - Use mcp__github__update_issue to apply your selected labels | |
| 61 | + - DO NOT post any comments explaining your decision | |
| 62 | + - DO NOT communicate directly with users | |
| 63 | + - If no labels are clearly applicable, do not apply any labels | |
| 64 | + | |
| 65 | + IMPORTANT GUIDELINES: | |
| 66 | + - Be thorough in your analysis | |
| 67 | + - Only select labels from the provided list above | |
| 68 | + - DO NOT post any comments to the issue | |
| 69 | + - Your ONLY action should be to apply labels using mcp__github__update_issue | |
| 70 | + - It's okay to not add any labels if none are clearly applicable | |
| 71 | + EOF | |
| 72 | + | |
| 73 | + - name: Setup GitHub MCP Server | |
| 74 | + run: | | |
| 75 | + mkdir -p /tmp/mcp-config | |
| 76 | + cat > /tmp/mcp-config/mcp-servers.json << 'EOF' | |
| 77 | + { | |
| 78 | + "mcpServers": { | |
| 79 | + "github": { | |
| 80 | + "command": "docker", | |
| 81 | + "args": [ | |
| 82 | + "run", | |
| 83 | + "-i", | |
| 84 | + "--rm", | |
| 85 | + "-e", | |
| 86 | + "GITHUB_PERSONAL_ACCESS_TOKEN", | |
| 87 | + "ghcr.io/github/github-mcp-server:sha-7aced2b" | |
| 88 | + ], | |
| 89 | + "env": { | |
| 90 | + "GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}" | |
| 91 | + } | |
| 92 | + } | |
| 93 | + } | |
| 94 | + } | |
| 95 | + EOF | |
| 96 | + | |
| 97 | + - name: Run Claude Code for Issue Triage | |
| 98 | + uses: anthropics/claude-code-base-action@beta | |
| 21 | 99 | with: |
| 100 | + prompt_file: /tmp/claude-prompts/triage-prompt.txt | |
| 101 | + 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" | |
| 102 | + timeout_minutes: "5" | |
| 22 | 103 | anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} |
| 23 | - github_token: ${{ secrets.GITHUB_TOKEN }} | |
| 104 | + mcp_config: /tmp/mcp-config/mcp-servers.json | |
| 105 | + claude_env: | | |
| 106 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| @@ -1,10 +1,201 @@ | ||
| 1 | 1 | # Changelog |
| 2 | 2 | |
| 3 | +## 1.0.62 | |
| 4 | + | |
| 5 | +- Added @-mention support with typeahead for custom agents. @<your-custom-agent> to invoke it | |
| 6 | +- Hooks: Added SessionStart hook for new session initialization | |
| 7 | +- /add-dir command now supports typeahead for directory paths | |
| 8 | +- Improved network connectivity check reliability | |
| 9 | + | |
| 10 | +## 1.0.61 | |
| 11 | + | |
| 12 | +- Transcript mode (Ctrl+R): Changed Esc to exit transcript mode rather than interrupt | |
| 13 | +- Settings: Added `--settings` flag to load settings from a JSON file | |
| 14 | +- Settings: Fixed resolution of settings files paths that are symlinks | |
| 15 | +- OTEL: Fixed reporting of wrong organization after authentication changes | |
| 16 | +- Slash commands: Fixed permissions checking for allowed-tools with Bash | |
| 17 | +- IDE: Added support for pasting images in VSCode MacOS using ⌘+V | |
| 18 | +- IDE: Added `CLAUDE_CODE_AUTO_CONNECT_IDE=false` for disabling IDE auto-connection | |
| 19 | +- Added `CLAUDE_CODE_SHELL_PREFIX` for wrapping Claude and user-provided shell commands run by Claude Code | |
| 20 | + | |
| 21 | +## 1.0.60 | |
| 22 | + | |
| 23 | +- You can now create custom subagents for specialized tasks! Run /agents to get started | |
| 24 | + | |
| 25 | +## 1.0.59 | |
| 26 | + | |
| 27 | +- SDK: Added tool confirmation support with canUseTool callback | |
| 28 | +- SDK: Allow specifying env for spawned process | |
| 29 | +- Hooks: Exposed PermissionDecision to hooks (including "ask") | |
| 30 | +- Hooks: UserPromptSubmit now supports additionalContext in advanced JSON output | |
| 31 | +- Fixed issue where some Max users that specified Opus would still see fallback to Sonnet | |
| 32 | + | |
| 33 | +## 1.0.58 | |
| 34 | + | |
| 35 | +- Added support for reading PDFs | |
| 36 | +- MCP: Improved server health status display in 'claude mcp list' | |
| 37 | +- Hooks: Added CLAUDE_PROJECT_DIR env var for hook commands | |
| 38 | + | |
| 39 | +## 1.0.57 | |
| 40 | + | |
| 41 | +- Added support for specifying a model in slash commands | |
| 42 | +- Improved permission messages to help Claude understand allowed tools | |
| 43 | +- Fix: Remove trailing newlines from bash output in terminal wrapping | |
| 44 | + | |
| 45 | +## 1.0.56 | |
| 46 | + | |
| 47 | +- Windows: Enabled shift+tab for mode switching on versions of Node.js that support terminal VT mode | |
| 48 | +- Fixes for WSL IDE detection | |
| 49 | +- Fix an issue causing awsRefreshHelper changes to .aws directory not to be picked up | |
| 50 | + | |
| 51 | +## 1.0.55 | |
| 52 | + | |
| 53 | +- Clarified knowledge cutoff for Opus 4 and Sonnet 4 models | |
| 54 | +- Windows: fixed Ctrl+Z crash | |
| 55 | +- SDK: Added ability to capture error logging | |
| 56 | +- Add --system-prompt-file option to override system prompt in print mode | |
| 57 | + | |
| 58 | +## 1.0.54 | |
| 59 | + | |
| 60 | +- Hooks: Added UserPromptSubmit hook and the current working directory to hook inputs | |
| 61 | +- Custom slash commands: Added argument-hint to frontmatter | |
| 62 | +- Windows: OAuth uses port 45454 and properly constructs browser URL | |
| 63 | +- Windows: mode switching now uses alt + m, and plan mode renders properly | |
| 64 | +- Shell: Switch to in-memory shell snapshot to fix file-related errors | |
| 65 | + | |
| 66 | +## 1.0.53 | |
| 67 | + | |
| 68 | +- Updated @-mention file truncation from 100 lines to 2000 lines | |
| 69 | +- 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). | |
| 70 | + | |
| 71 | +## 1.0.52 | |
| 72 | + | |
| 73 | +- Added support for MCP server instructions | |
| 74 | + | |
| 75 | +## 1.0.51 | |
| 76 | + | |
| 77 | +- Added support for native Windows (requires Git for Windows) | |
| 78 | +- Added support for Bedrock API keys through environment variable AWS_BEARER_TOKEN_BEDROCK | |
| 79 | +- Settings: /doctor can now help you identify and fix invalid setting files | |
| 80 | +- `--append-system-prompt` can now be used in interactive mode, not just --print/-p. | |
| 81 | +- Increased auto-compact warning threshold from 60% to 80% | |
| 82 | +- Fixed an issue with handling user directories with spaces for shell snapshots | |
| 83 | +- OTEL resource now includes os.type, os.version, host.arch, and wsl.version (if running on Windows Subsystem for Linux) | |
| 84 | +- Custom slash commands: Fixed user-level commands in subdirectories | |
| 85 | +- Plan mode: Fixed issue where rejected plan from sub-task would get discarded | |
| 86 | + | |
| 87 | +## 1.0.48 | |
| 88 | + | |
| 89 | +- Fixed a bug in v1.0.45 where the app would sometimes freeze on launch | |
| 90 | +- Added progress messages to Bash tool based on the last 5 lines of command output | |
| 91 | +- Added expanding variables support for MCP server configuration | |
| 92 | +- Moved shell snapshots from /tmp to ~/.claude for more reliable Bash tool calls | |
| 93 | +- Improved IDE extension path handling when Claude Code runs in WSL | |
| 94 | +- Hooks: Added a PreCompact hook | |
| 95 | +- Vim mode: Added c, f/F, t/T | |
| 96 | + | |
| 97 | +## 1.0.45 | |
| 98 | + | |
| 99 | +- Redesigned Search (Grep) tool with new tool input parameters and features | |
| 100 | +- Disabled IDE diffs for notebook files, fixing "Timeout waiting after 1000ms" error | |
| 101 | +- Fixed config file corruption issue by enforcing atomic writes | |
| 102 | +- Updated prompt input undo to Ctrl+\_ to avoid breaking existing Ctrl+U behavior, matching zsh's undo shortcut | |
| 103 | +- Stop Hooks: Fixed transcript path after /clear and fixed triggering when loop ends with tool call | |
| 104 | +- Custom slash commands: Restored namespacing in command names based on subdirectories. For example, .claude/commands/frontend/component.md is now /frontend:component, not /component. | |
| 105 | + | |
| 106 | +## 1.0.44 | |
| 107 | + | |
| 108 | +- New /export command lets you quickly export a conversation for sharing | |
| 109 | +- MCP: resource_link tool results are now supported | |
| 110 | +- MCP: tool annotations and tool titles now display in /mcp view | |
| 111 | +- Changed Ctrl+Z to suspend Claude Code. Resume by running `fg`. Prompt input undo is now Ctrl+U. | |
| 112 | + | |
| 113 | +## 1.0.43 | |
| 114 | + | |
| 115 | +- Fixed a bug where the theme selector was saving excessively | |
| 116 | +- Hooks: Added EPIPE system error handling | |
| 117 | + | |
| 118 | +## 1.0.42 | |
| 119 | + | |
| 120 | +- Added tilde (`~`) expansion support to `/add-dir` command | |
| 121 | + | |
| 122 | +## 1.0.41 | |
| 123 | + | |
| 124 | +- Hooks: Split Stop hook triggering into Stop and SubagentStop | |
| 125 | +- Hooks: Enabled optional timeout configuration for each command | |
| 126 | +- Hooks: Added "hook_event_name" to hook input | |
| 127 | +- Fixed a bug where MCP tools would display twice in tool list | |
| 128 | +- New tool parameters JSON for Bash tool in `tool_decision` event | |
| 129 | + | |
| 130 | +## 1.0.40 | |
| 131 | + | |
| 132 | +- Fixed a bug causing API connection errors with UNABLE_TO_GET_ISSUER_CERT_LOCALLY if `NODE_EXTRA_CA_CERTS` was set | |
| 133 | + | |
| 134 | +## 1.0.39 | |
| 135 | + | |
| 136 | +- New Active Time metric in OpenTelemetry logging | |
| 137 | + | |
| 138 | +## 1.0.38 | |
| 139 | + | |
| 140 | +- 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 | |
| 141 | + | |
| 142 | +## 1.0.37 | |
| 143 | + | |
| 144 | +- Remove ability to set `Proxy-Authorization` header via ANTHROPIC_AUTH_TOKEN or apiKeyHelper | |
| 145 | + | |
| 146 | +## 1.0.36 | |
| 147 | + | |
| 148 | +- Web search now takes today's date into context | |
| 149 | +- Fixed a bug where stdio MCP servers were not terminating properly on exit | |
| 150 | + | |
| 151 | +## 1.0.35 | |
| 152 | + | |
| 153 | +- Added support for MCP OAuth Authorization Server discovery | |
| 154 | + | |
| 155 | +## 1.0.34 | |
| 156 | + | |
| 157 | +- Fixed a memory leak causing a MaxListenersExceededWarning message to appear | |
| 158 | + | |
| 159 | +## 1.0.33 | |
| 160 | + | |
| 161 | +- Improved logging functionality with session ID support | |
| 162 | +- Added prompt input undo functionality (Ctrl+Z and vim 'u' command) | |
| 163 | +- Improvements to plan mode | |
| 164 | + | |
| 165 | +## 1.0.32 | |
| 166 | + | |
| 167 | +- Updated loopback config for litellm | |
| 168 | +- Added forceLoginMethod setting to bypass login selection screen | |
| 169 | + | |
| 170 | +## 1.0.31 | |
| 171 | + | |
| 172 | +- Fixed a bug where ~/.claude.json would get reset when file contained invalid JSON | |
| 173 | + | |
| 174 | +## 1.0.30 | |
| 175 | + | |
| 176 | +- Custom slash commands: Run bash output, @-mention files, enable thinking with thinking keywords | |
| 177 | +- Improved file path autocomplete with filename matching | |
| 178 | +- Added timestamps in Ctrl-r mode and fixed Ctrl-c handling | |
| 179 | +- Enhanced jq regex support for complex filters with pipes and select | |
| 180 | + | |
| 181 | +## 1.0.29 | |
| 182 | + | |
| 183 | +- Improved CJK character support in cursor navigation and rendering | |
| 184 | + | |
| 185 | +## 1.0.28 | |
| 186 | + | |
| 187 | +- Slash commands: Fix selector display during history navigation | |
| 188 | +- Resizes images before upload to prevent API size limit errors | |
| 189 | +- Added XDG_CONFIG_HOME support to configuration directory | |
| 190 | +- Performance optimizations for memory usage | |
| 191 | +- New attributes (terminal.type, language) in OpenTelemetry logging | |
| 192 | + | |
| 3 | 193 | ## 1.0.27 |
| 4 | 194 | |
| 5 | 195 | - Streamable HTTP MCP servers are now supported |
| 6 | 196 | - Remote MCP servers (SSE and HTTP) now support OAuth |
| 7 | 197 | - MCP resources can now be @-mentioned |
| 198 | +- /resume slash command to switch conversations within Claude Code | |
| 8 | 199 | |
| 9 | 200 | ## 1.0.25 |
| 10 | 201 |
| @@ -1,0 +1,148 @@ | ||
| 1 | +<# | |
| 2 | +.SYNOPSIS | |
| 3 | + Automates the setup and connection to a DevContainer environment using either Docker or Podman on Windows. | |
| 4 | + | |
| 5 | +.DESCRIPTION | |
| 6 | + This script automates the process of initializing, starting, and connecting to a DevContainer | |
| 7 | + using either Docker or Podman as the container backend. It must be executed from the root | |
| 8 | + directory of your project and assumes the script is located in a 'Script' subdirectory. | |
| 9 | + | |
| 10 | +.PARAMETER Backend | |
| 11 | + Specifies the container backend to use. Valid values are 'docker' or 'podman'. | |
| 12 | + | |
| 13 | +.EXAMPLE | |
| 14 | + .\Script\run_devcontainer_claude_code.ps1 -Backend docker | |
| 15 | + Uses Docker as the container backend. | |
| 16 | + | |
| 17 | +.EXAMPLE | |
| 18 | + .\Script\run_devcontainer_claude_code.ps1 -Backend podman | |
| 19 | + Uses Podman as the container backend. | |
| 20 | + | |
| 21 | +.NOTES | |
| 22 | + Project Structure: | |
| 23 | + Project/ | |
| 24 | + ├── .devcontainer/ | |
| 25 | + └── Script/ | |
| 26 | + └── run_devcontainer_claude_code.ps1 | |
| 27 | +#> | |
| 28 | + | |
| 29 | +[CmdletBinding()] | |
| 30 | +param( | |
| 31 | + [Parameter(Mandatory=$true)] | |
| 32 | + [ValidateSet('docker','podman')] | |
| 33 | + [string]$Backend | |
| 34 | +) | |
| 35 | + | |
| 36 | +# Notify script start | |
| 37 | +Write-Host "--- DevContainer Startup & Connection Script ---" | |
| 38 | +Write-Host "Using backend: $($Backend)" | |
| 39 | + | |
| 40 | +# --- Prerequisite Check --- | |
| 41 | +Write-Host "Checking for required commands..." | |
| 42 | +try { | |
| 43 | + Get-Command $Backend -ErrorAction Stop | Out-Null | |
| 44 | + Write-Host "- $($Backend) command found." | |
| 45 | + Get-Command devcontainer -ErrorAction Stop | Out-Null | |
| 46 | + Write-Host "- devcontainer command found." | |
| 47 | +} | |
| 48 | +catch { | |
| 49 | + Write-Error "A required command is not installed or not in your PATH." | |
| 50 | + Write-Error "Please ensure '$($_.Exception.Message.Split(':')[0])' and 'devcontainer' are installed and accessible." | |
| 51 | + exit 1 | |
| 52 | +} | |
| 53 | + | |
| 54 | + | |
| 55 | +# --- Backend-Specific Initialization --- | |
| 56 | +if ($Backend -eq 'podman') { | |
| 57 | + Write-Host "--- Podman Backend Initialization ---" | |
| 58 | + | |
| 59 | + # --- Step 1a: Initialize Podman machine --- | |
| 60 | + Write-Host "Initializing Podman machine 'claudeVM'..." | |
| 61 | + try { | |
| 62 | + & podman machine init claudeVM | |
| 63 | + Write-Host "Podman machine 'claudeVM' initialized or already exists." | |
| 64 | + } catch { | |
| 65 | + Write-Error "Failed to initialize Podman machine: $($_.Exception.Message)" | |
| 66 | + exit 1 # Exit script on error | |
| 67 | + } | |
| 68 | + | |
| 69 | + # --- Step 1b: Start Podman machine --- | |
| 70 | + Write-Host "Starting Podman machine 'claudeVM'..." | |
| 71 | + try { | |
| 72 | + & podman machine start claudeVM -q | |
| 73 | + Write-Host "Podman machine started or already running." | |
| 74 | + } catch { | |
| 75 | + Write-Error "Failed to start Podman machine: $($_.Exception.Message)" | |
| 76 | + exit 1 | |
| 77 | + } | |
| 78 | + | |
| 79 | + # --- Step 2: Set default connection --- | |
| 80 | + Write-Host "Setting default Podman connection to 'claudeVM'..." | |
| 81 | + try { | |
| 82 | + & podman system connection default claudeVM | |
| 83 | + Write-Host "Default connection set." | |
| 84 | + } catch { | |
| 85 | + Write-Warning "Failed to set default Podman connection (may be already set or machine issue): $($_.Exception.Message)" | |
| 86 | + } | |
| 87 | + | |
| 88 | +} elseif ($Backend -eq 'docker') { | |
| 89 | + Write-Host "--- Docker Backend Initialization ---" | |
| 90 | + | |
| 91 | + # --- Step 1 & 2: Check Docker Desktop --- | |
| 92 | + Write-Host "Checking if Docker Desktop is running and docker command is available..." | |
| 93 | + try { | |
| 94 | + docker info | Out-Null | |
| 95 | + Write-Host "Docker Desktop (daemon) is running." | |
| 96 | + } catch { | |
| 97 | + Write-Error "Docker Desktop is not running or docker command not found." | |
| 98 | + Write-Error "Please ensure Docker Desktop is running." | |
| 99 | + exit 1 | |
| 100 | + } | |
| 101 | +} | |
| 102 | + | |
| 103 | +# --- Step 3: Bring up DevContainer --- | |
| 104 | +Write-Host "Bringing up DevContainer in the current folder..." | |
| 105 | +try { | |
| 106 | + $arguments = @('up', '--workspace-folder', '.') | |
| 107 | + if ($Backend -eq 'podman') { | |
| 108 | + $arguments += '--docker-path', 'podman' | |
| 109 | + } | |
| 110 | + & devcontainer @arguments | |
| 111 | + Write-Host "DevContainer startup process completed." | |
| 112 | +} catch { | |
| 113 | + Write-Error "Failed to bring up DevContainer: $($_.Exception.Message)" | |
| 114 | + exit 1 | |
| 115 | +} | |
| 116 | + | |
| 117 | +# --- Step 4: Get DevContainer ID --- | |
| 118 | +Write-Host "Finding the DevContainer ID..." | |
| 119 | +$currentFolder = (Get-Location).Path | |
| 120 | + | |
| 121 | +try { | |
| 122 | + $containerId = (& $Backend ps --filter "label=devcontainer.local_folder=$currentFolder" --format '{{.ID}}').Trim() | |
| 123 | +} catch { | |
| 124 | + $displayCommand = "$Backend ps --filter `"label=devcontainer.local_folder=$currentFolder`" --format '{{.ID}}'" | |
| 125 | + Write-Error "Failed to get container ID (Command: $displayCommand): $($_.Exception.Message)" | |
| 126 | + exit 1 | |
| 127 | +} | |
| 128 | + | |
| 129 | +if (-not $containerId) { | |
| 130 | + Write-Error "Could not find DevContainer ID for the current folder ('$currentFolder')." | |
| 131 | + Write-Error "Please check if 'devcontainer up' was successful and the container is running." | |
| 132 | + exit 1 | |
| 133 | +} | |
| 134 | +Write-Host "Found container ID: $containerId" | |
| 135 | + | |
| 136 | +# --- Step 5 & 6: Execute command and enter interactive shell inside container --- | |
| 137 | +Write-Host "Executing 'claude' command and then starting zsh session inside container $($containerId)..." | |
| 138 | +try { | |
| 139 | + & $Backend exec -it $containerId zsh -c 'claude; exec zsh' | |
| 140 | + Write-Host "Interactive session ended." | |
| 141 | +} catch { | |
| 142 | + $displayCommand = "$Backend exec -it $containerId zsh -c 'claude; exec zsh'" | |
| 143 | + Write-Error "Failed to execute command inside container (Command: $displayCommand): $($_.Exception.Message)" | |
| 144 | + exit 1 | |
| 145 | +} | |
| 146 | + | |
| 147 | +# Notify script completion | |
| 148 | +Write-Host "--- Script completed ---" |
| @@ -1,0 +1,83 @@ | ||
| 1 | +#!/usr/bin/env python3 | |
| 2 | +""" | |
| 3 | +Claude Code Hook: Bash Command Validator | |
| 4 | +========================================= | |
| 5 | +This hook runs as a PreToolUse hook for the Bash tool. | |
| 6 | +It validates bash commands against a set of rules before execution. | |
| 7 | +In this case it changes grep calls to using rg. | |
| 8 | + | |
| 9 | +Read more about hooks here: https://docs.anthropic.com/en/docs/claude-code/hooks | |
| 10 | + | |
| 11 | +Make sure to change your path to your actual script. | |
| 12 | + | |
| 13 | +{ | |
| 14 | + "hooks": { | |
| 15 | + "PreToolUse": [ | |
| 16 | + { | |
| 17 | + "matcher": "Bash", | |
| 18 | + "hooks": [ | |
| 19 | + { | |
| 20 | + "type": "command", | |
| 21 | + "command": "python3 /path/to/claude-code/examples/hooks/bash_command_validator_example.py" | |
| 22 | + } | |
| 23 | + ] | |
| 24 | + } | |
| 25 | + ] | |
| 26 | + } | |
| 27 | +} | |
| 28 | + | |
| 29 | +""" | |
| 30 | + | |
| 31 | +import json | |
| 32 | +import re | |
| 33 | +import sys | |
| 34 | + | |
| 35 | +# Define validation rules as a list of (regex pattern, message) tuples | |
| 36 | +_VALIDATION_RULES = [ | |
| 37 | + ( | |
| 38 | + r"^grep\b(?!.*\|)", | |
| 39 | + "Use 'rg' (ripgrep) instead of 'grep' for better performance and features", | |
| 40 | + ), | |
| 41 | + ( | |
| 42 | + r"^find\s+\S+\s+-name\b", | |
| 43 | + "Use 'rg --files | rg pattern' or 'rg --files -g pattern' instead of 'find -name' for better performance", | |
| 44 | + ), | |
| 45 | +] | |
| 46 | + | |
| 47 | + | |
| 48 | +def _validate_command(command: str) -> list[str]: | |
| 49 | + issues = [] | |
| 50 | + for pattern, message in _VALIDATION_RULES: | |
| 51 | + if re.search(pattern, command): | |
| 52 | + issues.append(message) | |
| 53 | + return issues | |
| 54 | + | |
| 55 | + | |
| 56 | +def main(): | |
| 57 | + try: | |
| 58 | + input_data = json.load(sys.stdin) | |
| 59 | + except json.JSONDecodeError as e: | |
| 60 | + print(f"Error: Invalid JSON input: {e}", file=sys.stderr) | |
| 61 | + # Exit code 1 shows stderr to the user but not to Claude | |
| 62 | + sys.exit(1) | |
| 63 | + | |
| 64 | + tool_name = input_data.get("tool_name", "") | |
| 65 | + if tool_name != "Bash": | |
| 66 | + sys.exit(0) | |
| 67 | + | |
| 68 | + tool_input = input_data.get("tool_input", {}) | |
| 69 | + command = tool_input.get("command", "") | |
| 70 | + | |
| 71 | + if not command: | |
| 72 | + sys.exit(0) | |
| 73 | + | |
| 74 | + issues = _validate_command(command) | |
| 75 | + if issues: | |
| 76 | + for message in issues: | |
| 77 | + print(f"• {message}", file=sys.stderr) | |
| 78 | + # Exit code 2 blocks tool call and shows stderr to Claude | |
| 79 | + sys.exit(2) | |
| 80 | + | |
| 81 | + | |
| 82 | +if __name__ == "__main__": | |
| 83 | + main() |