spacehub

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

Merge branch 'main' into fix/pin-claude-versionBrowse files
ant-kurt authored on Jul 29, 2025 · GitHub committed on Jul 29, 2025 parents 6c7836e + 6f6fc43 · commit 10c1ec539135
8 changed files+532 -238compared with 6c7836e
M.devcontainer/Dockerfile
M.devcontainer/devcontainer.json
D.github/actions/claude-code-action/action.yml
D.github/actions/claude-issue-triage-action/action.yml
M.github/workflows/claude-issue-triage.yml
MCHANGELOG.md
AScript/run_devcontainer_claude_code.ps1
Aexamples/hooks/bash_command_validator_example.py
@@ -6,7 +6,8 @@
66 ARG CLAUDE_CODE_VERSION=latest
77
88 # 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 \
1011 git \
1112 procps \
1213 sudo \
@@ -21,7 +22,10 @@
2122 iproute2 \
2223 dnsutils \
2324 aggregate \
24- jq
25+ jq \
26+ nano \
27+ vim \
28+ && apt-get clean && rm -rf /var/lib/apt/lists/*
2529
2630 # Ensure default node user has access to /usr/local/share
2731 RUN mkdir -p /usr/local/share/npm-global && \
@@ -44,10 +48,11 @@
4448
4549 WORKDIR /workspace
4650
51+ARG GIT_DELTA_VERSION=0.18.2
4752 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"
5156
5257 # Set up non-root user
5358 USER node
@@ -59,8 +64,13 @@
5964 # Set the default shell to zsh rather than sh
6065 ENV SHELL=/bin/zsh
6166
67+# Set the default editor and visual
68+ENV EDITOR nano
69+ENV VISUAL nano
70+
6271 # 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)" -- \
6474 -p git \
6575 -p fzf \
6676 -a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
@@ -4,7 +4,9 @@
44 "dockerfile": "Dockerfile",
55 "args": {
66 "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"
810 }
911 },
1012 "runArgs": [
@@ -39,8 +41,8 @@
3941 },
4042 "remoteUser": "node",
4143 "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"
4446 ],
4547 "remoteEnv": {
4648 "NODE_OPTIONS": "--max-old-space-size=4096",
D.github/actions/claude-code-action/action.yml+0 -136
@@ -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 }}
D.github/actions/claude-issue-triage-action/action.yml+0 -87
@@ -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 @@
11 name: Claude Issue Triage
2-description: "Automatically triage GitHub issues using Claude Code"
3-
2+description: Automatically triage GitHub issues using Claude Code
43 on:
54 issues:
65 types: [opened]
@@ -12,12 +11,96 @@
1211 permissions:
1312 contents: read
1413 issues: write
14+
1515 steps:
1616 - name: Checkout repository
17- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
17+ uses: actions/checkout@v4
1818
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
2199 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"
22103 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 }}
MCHANGELOG.md+191 -0
@@ -1,10 +1,201 @@
11 # Changelog
22
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+
3193 ## 1.0.27
4194
5195 - Streamable HTTP MCP servers are now supported
6196 - Remote MCP servers (SSE and HTTP) now support OAuth
7197 - MCP resources can now be @-mentioned
198+- /resume slash command to switch conversations within Claude Code
8199
9200 ## 1.0.25
10201
@@ -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()