Compare commits

...

117 Commits

Author SHA1 Message Date
Boris Cherny
d820a4dbd7 Add issue close event trigger to log-issue-events workflow
Updates the GitHub workflow to also trigger when issues are closed,
expanding event tracking beyond just issue creation.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-22 18:30:52 -07:00
GitHub Actions
eb0e43457b chore: Update CHANGELOG.md 2025-08-22 01:21:59 +00:00
GitHub Actions
b417bfc532 chore: Update CHANGELOG.md 2025-08-22 00:59:57 +00:00
Dickson Tsai
239aeb55ee Merge pull request #6202 from anthropics/dickson/discord
Add Discord to README.md
2025-08-20 11:09:29 -07:00
Dickson Tsai
f4e707fdcc Add Discord to README.md 2025-08-20 11:07:32 -07:00
GitHub Actions
d2f88820c9 chore: Update CHANGELOG.md 2025-08-19 23:59:26 +00:00
ant-kurt
a3620cdd0b Merge pull request #5872 from backpaper0/remove-cname-on-domain-ip-resolution
fix: improve DNS resolution in firewall script to filter CNAME records
2025-08-19 11:23:35 -07:00
GitHub Actions
da6d2f715e chore: Update CHANGELOG.md 2025-08-18 23:43:38 +00:00
GitHub Actions
f200ab3c5c chore: Update CHANGELOG.md 2025-08-18 23:19:02 +00:00
Boris Cherny
fa29b8f9c0 Merge pull request #6047 from anthropics/boris/adbf
Re-add log-issue-events workflow with security fix
2025-08-18 13:27:03 -07:00
GitHub Actions
2558619a83 chore: Update CHANGELOG.md 2025-08-18 20:06:51 +00:00
Boris Cherny
80ceacaa78 Re-add log-issue-events workflow with security fix
Re-implements the workflow removed in #5919, but with proper security:
- All GitHub event data is now passed via environment variables
- No direct templating of values into shell commands
- Prevents remote code execution through malicious issue titles
- Still escapes quotes in JSON payload for proper formatting

This fixes the security vulnerability while maintaining the functionality
of logging issue creation events to Statsig.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-18 09:56:56 -07:00
Chris Lloyd
4e63568abd Merge pull request #5919 from anthropics/chrislloyd/8a49b1
Remove log-issue-events workflow
2025-08-16 07:32:25 -07:00
Chris Lloyd
5d0b81ae41 Remove log-issue-events workflow 2025-08-16 07:26:53 -07:00
GitHub Actions
b1751f2e86 chore: Update CHANGELOG.md 2025-08-16 00:11:04 +00:00
Uragami Taichi
eb48d5e4a8 fix: improve DNS resolution in firewall script to filter CNAME records 2025-08-16 06:38:34 +09:00
Boris Cherny
fc8c10995f Merge pull request #5858 from anthropics/boris/vreg
fix: update auto-close-duplicates workflow permissions to write
2025-08-15 10:57:02 -07:00
Boris Cherny
01fb7af5b3 fix: update auto-close-duplicates workflow permissions to write
Change issues permission from read to write to fix 403 Forbidden
errors when attempting to close duplicate issues.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 10:55:50 -07:00
Boris Cherny
afb0fc9156 Merge pull request #5802 from anthropics/boris/jymy
fix: improve duplicate issue number extraction in auto-close script
2025-08-14 16:38:49 -07:00
Boris Cherny
370a97d939 fix: improve duplicate issue number extraction in auto-close script
The extractDuplicateIssueNumber function now handles both #123 format
and full GitHub issue URLs like https://github.com/owner/repo/issues/123.
This fixes the "could not extract duplicate issue number from comment"
errors that were occurring when the script encountered URL-formatted
issue references in duplicate detection comments.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-14 16:37:46 -07:00
GitHub Actions
f54569efd2 chore: Update CHANGELOG.md 2025-08-14 20:13:16 +00:00
GitHub Actions
d8cf5a874c chore: Update CHANGELOG.md 2025-08-14 16:59:55 +00:00
GitHub Actions
e499db6e9e chore: Update CHANGELOG.md 2025-08-11 23:43:35 +00:00
Boris Cherny
5300e12135 Merge pull request #5569 from anthropics/boris/limc
Consolidate GitHub issue closure events
2025-08-11 16:07:18 -07:00
Boris Cherny
4a04589002 Use proper 'duplicate' state_reason for issue closures
- Update auto-close script to use state_reason: 'duplicate' instead of 'not_planned'
- Simplify workflow detection logic to only check for duplicate state_reason
- Remove fallback logic for backward compatibility - use modern GitHub API

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 15:44:08 -07:00
Boris Cherny
04cace9ec0 Consolidate GitHub issue closure events to prevent duplicates
- Remove duplicate Statsig logging from auto-close-duplicates.ts
- GitHub workflow now handles all issue closures uniformly
- Add 'duplicate' label to ensure proper detection by workflow
- Prevents double-logging when script closes issues

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 15:33:31 -07:00
Boris Cherny
2dbf1e97a0 Merge pull request #5564 from anthropics/boris/lptz
Fix GitHub Actions workflow to properly escape issue titles
2025-08-11 13:49:50 -07:00
Boris Cherny
0662600e93 Fix GitHub Actions workflow to properly escape issue titles
Prevents shell execution of backticks in issue titles by using single quotes and sed escaping.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 13:38:40 -07:00
Boris Cherny
27d2c6fdcf Merge pull request #5562 from anthropics/boris/zivm
Add GitHub workflow logging for issue closure events
2025-08-11 13:17:26 -07:00
GitHub Actions
dd53f86325 chore: Update CHANGELOG.md 2025-08-11 20:15:53 +00:00
Boris Cherny
c40c658e1f Add GitHub workflow logging for issue closure events
Extends the existing log-issue-events workflow to capture detailed metrics when issues are closed, including:
- Who closed the issue
- Whether it was closed automatically (by a bot)
- Whether it was closed as a duplicate
- Number of comments and reactions at closing time
- Issue state reason and timestamp

This provides comprehensive analytics for issue lifecycle tracking alongside the existing issue creation logging.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 13:13:52 -07:00
Ashwin Bhat
e05411140d Remove timeout-minutes from lock-closed-issues workflow (#5455)
The 10-minute timeout is unnecessary for this workflow as it typically
completes quickly. Removing it allows the workflow to use the default
GitHub Actions timeout (6 hours for public repos, 72 hours for private),
providing more flexibility if the workflow needs to process a large
number of issues.

Also fixed trailing whitespace inconsistencies in the script.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-09 10:58:52 -07:00
Boris Cherny
ce5b9164fa Merge pull request #5429 from anthropics/boris/bzxy
Add Statsig event logging to GitHub issue workflows
2025-08-08 18:46:52 -07:00
Boris Cherny
5af0b38a92 Add Statsig event logging to GitHub issue workflows
- Log events when issues are closed as duplicates in auto-close script
- Log events when duplicate comments are added via dedupe workflow
- Log events when new issues are created
- Follow existing pattern from code review reactions workflow

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 18:26:48 -07:00
Boris Cherny
22946869b2 Merge pull request #5423 from anthropics/boris/uqbo
Rename auto-close duplicate issues workflow to remove "dry run"
2025-08-08 17:28:36 -07:00
Boris Cherny
1579216fc7 Enable auto-close duplicate issues workflow
Remove DRY RUN from workflow name and description to activate the automatic closing of duplicate issues after the testing period.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 14:03:43 -07:00
Ashwin Bhat
f0042afb3b Replace lock-threads action with GitHub Script (#5330)
Replaces the dessant/lock-threads action with a direct GitHub Script
implementation to avoid the deprecated search/issues API endpoint warning.
The new implementation:
- Uses github.rest.issues.listForRepo() instead of the deprecated search API
- Maintains the same 7-day inactivity threshold
- Adds the same comment before locking
- Uses 'resolved' as the lock reason
- Handles pagination properly for large repositories

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-08 13:02:20 -07:00
Boris Cherny
6059607354 Merge pull request #5420 from anthropics/boris/cmyy
Fix workflow failure by adding workflow_dispatch trigger
2025-08-08 12:57:16 -07:00
Boris Cherny
478f63be73 Fix workflow failure by adding workflow_dispatch trigger
The backfill-duplicate-comments script was failing because it tried to trigger
claude-dedupe-issues.yml via workflow_dispatch, but that workflow only had an
issues trigger. Added workflow_dispatch with issue_number input and updated the
prompt to use either event or input issue number.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 12:55:48 -07:00
Boris Cherny
a7edbdc9e7 Merge pull request #5414 from anthropics/boris/aier
Add workflow to backfill duplicate comments
2025-08-08 12:13:19 -07:00
Boris Cherny
399a7dcf2f Add workflow to backfill duplicate comments
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 12:11:08 -07:00
Boris Cherny
9ced2a3470 Merge pull request #5413 from anthropics/boris/bktr
Add script to backfill duplicate comments for old issues
2025-08-08 12:08:17 -07:00
Boris Cherny
d7aa61e6f1 Add script to backfill duplicate comments for old issues
Creates a script that identifies old issues without duplicate detection comments and triggers the existing claude-dedupe-issues workflow for each one. This helps ensure historical issues get proper duplicate detection coverage.

Features:
- Scans issues from configurable time period (default 30 days)
- Skips issues that already have duplicate detection comments
- Triggers existing workflow instead of duplicating logic
- Includes dry-run mode and rate limiting for safety

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 12:06:36 -07:00
Boris Cherny
072856dd5b Merge pull request #5411 from anthropics/boris/gity
Update auto-close-duplicates script to actually close issues
2025-08-08 11:54:07 -07:00
Boris Cherny
1cc90e9b78 Update auto-close-duplicates script to actually close issues
- Remove dry run mode and implement actual issue closing
- Extract duplicate issue number from bot comments
- Close issues via GitHub API with proper state and comments
- Add error handling for API failures
- Use Claude Code comment format with reopening instructions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 11:52:34 -07:00
Boris Cherny
483e0e892f Merge pull request #5409 from anthropics/boris/cuxg
Improve auto-close duplicates script pagination and filtering
2025-08-08 11:31:03 -07:00
GitHub Actions
5248fa06bc chore: Update CHANGELOG.md 2025-08-08 18:22:13 +00:00
Boris Cherny
eb48a37a48 Improve auto-close duplicates script pagination and filtering
- Add pagination to fetch more than 100 issues (up to 20 pages/2000 issues)
- Filter to only process issues created more than 3 days ago
- Add created_at field to GitHubIssue interface

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 11:21:27 -07:00
Boris Cherny
fdb7efe6f1 Merge pull request #5358 from anthropics/boris/eyda
Extract auto-close duplicates script to TypeScript with Bun
2025-08-08 11:13:27 -07:00
Boris Cherny
7060992aa5 Update .github/workflows/auto-close-duplicates.yml
Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
2025-08-08 11:13:05 -07:00
Boris Cherny
b7116c78d8 Extract auto-close duplicates script to TypeScript with Bun
- Move GitHub workflow script logic to scripts/auto-close-duplicates.ts
- Convert from inline JavaScript to standalone TypeScript module
- Update workflow to use Bun instead of Node.js for better performance
- Add proper TypeScript types and ES module syntax

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-08 11:11:41 -07:00
GitHub Actions
3fd750e3cb chore: Update CHANGELOG.md 2025-08-07 22:22:12 +00:00
GitHub Actions
3262b673c3 chore: Update CHANGELOG.md 2025-08-07 05:48:29 +00:00
Boris Cherny
369bd9b6d7 Merge pull request #5116 from anthropics/boris/fwbe
Add auto-close functionality for duplicate issues
2025-08-05 17:18:29 -07:00
Boris Cherny
611956def4 Convert auto-close duplicates workflow to dry run mode
Instead of automatically closing duplicate issues, the workflow now:
- Logs URLs of issues that would have been closed
- Runs in dry run mode for safety
- Preserves all detection logic but skips actual closing actions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-05 17:17:51 -07:00
GitHub Actions
a9f1fefbe9 chore: Update CHANGELOG.md 2025-08-05 16:50:00 +00:00
Boris Cherny
3d5ef4e8c0 Add auto-close functionality for duplicate issues
- Update dedupe command to include auto-close warning
- Add commit-push-pr command for streamlined workflow
- Add GitHub workflow to automatically close duplicates

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 17:09:09 -07:00
GitHub Actions
d967bbbe30 chore: Update CHANGELOG.md 2025-08-04 23:29:26 +00:00
GitHub Actions
5faa082d6e chore: Update CHANGELOG.md 2025-07-31 23:39:25 +00:00
Boris Cherny
60124df21f Merge pull request #4817 from anthropics/bcherny-patch-4
Update dedupe.md
2025-07-30 19:30:06 -07:00
Boris Cherny
1aaffa4e6d Update dedupe.md 2025-07-30 19:29:10 -07:00
Boris Cherny
f5b24d5480 Merge pull request #4816 from anthropics/bcherny-patch-3
Update claude-dedupe-issues.yml
2025-07-30 19:16:36 -07:00
Boris Cherny
07e6bec5ff Update claude-dedupe-issues.yml 2025-07-30 19:09:48 -07:00
GitHub Actions
cf8c6fdf2d chore: Update CHANGELOG.md 2025-07-30 21:49:14 +00:00
ant-kurt
d720bf7aba Merge pull request #4644 from shota-0129/shota-0129/feat-docker-dns-protection
feat: Add Docker DNS protection to firewall script
2025-07-30 10:56:41 -07:00
Kurt Carpenter
dde41f6225 fix: Handle missing Docker DNS rules gracefully in firewall script
Add error handling for grep when no Docker DNS rules exist, preventing
script failure on default Docker networks while still preserving DNS
functionality on custom networks.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-30 10:54:05 -07:00
shota-0129
78e0785950 simplify Docker DNS restoration using grep and xargs approach 2025-07-30 14:22:15 +09:00
GitHub Actions
b3658880e5 chore: Update CHANGELOG.md 2025-07-29 21:43:06 +00:00
Boris Cherny
9be8e07e92 Merge pull request #4710 from anthropics/boris/nvko
Add GitHub workflow to deduplicate issues
2025-07-29 11:36:52 -07:00
Boris Cherny
c904f0f409 Update .claude/commands/dedupe.md 2025-07-29 11:36:28 -07:00
Boris Cherny
6418cacb0b Add GitHub workflow to deduplicate issues and Claude configuration
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-29 11:05:36 -07:00
Ashwin Bhat
4fd2c49e8b Enable log output for lock stale issues workflow (#4698)
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 09:31:05 -07:00
Ashwin Bhat
48ed55b459 Add GitHub workflow to lock stale issues (#4602)
* Add GitHub workflow to lock stale issues

- Locks issues closed for 7+ days without activity
- Runs daily at 7am Pacific (2pm UTC)
- Includes manual workflow dispatch trigger
- Posts helpful comment before locking with guidance for new issues

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* PR feedback

* adjust params

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 09:11:39 -07:00
shota-0129
8b2cbe3f86 feat: Add Docker DNS protection to firewall script
- Extract Docker DNS NAT ports before iptables cleanup
- Restore Docker DNS NAT rules after iptables reset
- Maintains Docker container DNS functionality in network isolation
- Fixes connection refused errors to 127.0.0.11 in Docker environments

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-29 13:54:29 +09:00
ant-kurt
40251280cc Merge pull request #3938 from toshitanaa/fix-devcontainer-env-vars
fix: Use containerEnv for environment variables in devcontainer.json
2025-07-28 18:02:07 -07:00
ant-kurt
8f0379c698 Merge pull request #2448 from kowsik11/fix/pin-claude-version
Fix: Allow overriding Claude Code version in Dockerfile
2025-07-28 17:48:33 -07:00
ant-kurt
10c1ec5391 Merge branch 'main' into fix/pin-claude-version 2025-07-28 17:44:49 -07:00
Kurt Carpenter
6c7836e02f feat: Add CLAUDE_CODE_VERSION build arg to devcontainer.json
- Add CLAUDE_CODE_VERSION with default value of "latest" as a build argument
- Allows overriding Claude Code version during devcontainer build

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-28 17:42:35 -07:00
ant-kurt
6f6fc43c73 Merge pull request #3342 from toms74209200/main
Improve devcontainer Dockerfile following best practices
2025-07-28 16:44:23 -07:00
ant-kurt
944eb4eff6 Merge branch 'main' into main 2025-07-28 16:43:21 -07:00
ant-kurt
21df74bb49 Merge pull request #3678 from suwakei/fix/script
fix: Add check to run_devcontainer_claude_code.ps1 for the presence of required command
2025-07-28 16:20:19 -07:00
Kurt Carpenter
66ce673883 feat: Add CLAUDE_CODE_VERSION arg to devcontainer Dockerfile
- Add ARG CLAUDE_CODE_VERSION with default value of "latest"
- Update npm install command to use the version variable
- Allows overriding Claude Code version during build

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-28 16:09:53 -07:00
ant-kurt
07b198b9de Merge pull request #2101 from Masa1984a/fix/add-nano-to-devcontainer
fix: Add nano and vim editors to devcontainer with default editor config
2025-07-28 15:51:14 -07:00
GitHub Actions
8ad36c459c chore: Update CHANGELOG.md 2025-07-28 22:35:41 +00:00
GitHub Actions
b48dfb8e87 chore: Update CHANGELOG.md 2025-07-28 18:35:03 +00:00
GitHub Actions
55219b8b4e chore: Update CHANGELOG.md 2025-07-25 21:06:44 +00:00
GitHub Actions
812c27b8b3 chore: Update CHANGELOG.md 2025-07-24 21:01:31 +00:00
GitHub Actions
e0d79c3571 chore: Update CHANGELOG.md 2025-07-23 21:21:28 +00:00
GitHub Actions
c8207b4f68 chore: Update CHANGELOG.md 2025-07-23 21:17:14 +00:00
GitHub Actions
4c056f7a09 chore: Update CHANGELOG.md 2025-07-19 00:06:08 +00:00
GitHub Actions
b328530abd chore: Update CHANGELOG.md 2025-07-18 20:30:50 +00:00
GitHub Actions
486b305708 chore: Update CHANGELOG.md 2025-07-18 16:41:25 +00:00
Toshiyuki Tanaka
8e23e7d791 fix: Use containerEnv for environment variables in devcontainer.json
When launching dev containers via scripts (not through VS Code), remoteEnv
does not properly set environment variables. This causes NODE_OPTIONS,
CLAUDE_CONFIG_DIR, and POWERLEVEL9K_DISABLE_GITSTATUS to be undefined.

Changed remoteEnv to containerEnv to ensure environment variables are
correctly set regardless of how the container is launched.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 09:21:12 -07:00
GitHub Actions
68d43db2a0 chore: Update CHANGELOG.md 2025-07-17 22:39:14 +00:00
keitosuwahara
9285dfbf2f Addition of check for presence of required commands 2025-07-17 13:05:39 +09:00
GitHub Actions
90c26533d1 chore: Update CHANGELOG.md 2025-07-16 23:50:28 +00:00
GitHub Actions
d45bce242d chore: Update CHANGELOG.md 2025-07-11 22:54:23 +00:00
toms74209200
f91aed5440 Improve devcontainer Dockerfile following best practices
- Use apt-get instead of apt for better script compatibility
- Add --no-install-recommends to reduce image size
- Add cleanup to remove apt cache
- Parameterize external tool versions with build args
2025-07-11 22:51:14 +09:00
Robert Boyce
54a4ed0f5e Merge pull request #3310 from ddworken/main
Isolate devcontainer mounts using ${devcontainerId}
2025-07-10 15:26:42 -07:00
David Dworken
33e37bd828 Fix devcontainer volume security vulnerability
Use ${devcontainerId} variable to create project-specific volumes,
preventing cross-container data access. This addresses the security
issue where multiple containers could share sensitive data through
named volumes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-10 15:13:18 -07:00
GitHub Actions
ff15c6f147 chore: Update CHANGELOG.md 2025-07-10 16:17:34 +00:00
GitHub Actions
0cbe1dcac5 chore: Update CHANGELOG.md 2025-07-08 23:54:58 +00:00
GitHub Actions
a705bca81c chore: Update CHANGELOG.md 2025-07-08 23:08:40 +00:00
GitHub Actions
ecaf0d818a chore: Update CHANGELOG.md 2025-07-07 22:48:22 +00:00
GitHub Actions
397442ddf5 chore: Update CHANGELOG.md 2025-07-03 21:09:58 +00:00
GitHub Actions
5def9264e5 chore: Update CHANGELOG.md 2025-07-03 03:54:12 +00:00
ant-kurt
0149827a77 Merge pull request #951 from Masa1984a/feat/Add-PowerShell-script-for-Windows-DevContainer-setup
Add PowerShell script for Windows DevContainer setup (Docker/Podman)
2025-07-02 18:09:19 -07:00
Kurt Carpenter
c93c724eeb PowerShell parameter improvements 2025-07-02 18:06:00 -07:00
Masa1984a
545d78c331 Apply review suggestions: Add ValidateSet and improve documentation 2025-07-03 06:29:38 +09:00
GitHub Actions
e16c9857ef chore: Update CHANGELOG.md 2025-07-02 18:25:23 +00:00
Thariq Shihipar
a39ae004aa Merge pull request #2871 from anthropics/examples/hook
Example Hook
2025-07-02 11:01:12 -07:00
Dickson Tsai
74ba615503 Script polish 2025-07-02 11:00:03 -07:00
Thariq Shihipar
3d2166eec9 proper hook file 2025-07-02 09:32:33 -07:00
Ashwin Bhat
beacb95320 Add checkout step to issue triage workflow (#2867)
Added a checkout step to the GitHub Actions workflow for issue triage
to ensure the repository is available during the triage process.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-02 09:01:44 -07:00
Kowsik Perumalla
46ca39c463 fix: pin Claude version in Dockerfile to avoid stale builds 2025-06-22 21:32:37 +05:30
Masa1984a
a6091b65c0 fix: Add nano and vim editors to devcontainer with default editor config
Fixes #2098

- Add nano and vim to provide editor choices for users
- Set EDITOR and VISUAL environment variables to nano as default
- This ensures /memory command and other tools work out of the box

Users can still change their preferred editor by setting these environment variables in their shell configuration.
2025-06-15 11:34:23 +09:00
Massan
11cfc055af Add PowerShell script for Windows DevContainer setup (Docker/Podman) 2025-05-04 22:05:27 +09:00
17 changed files with 1344 additions and 14 deletions

View File

@@ -0,0 +1,19 @@
---
allowed-tools: Bash(git checkout --branch:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*)
description: Commit, push, and open a PR
---
## Context
- Current git status: !`git status`
- Current git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
## Your task
Based on the above changes:
1. Create a new branch if on main
2. Create a single commit with an appropriate message
3. Push the branch to origin
4. Create a pull request using `gh pr create`
5. You have the capability to call multiple tools in a single response. You MUST do all of the above in a single message. Do not use any other tools or do anything else. Do not send any other text or messages besides these tool calls.

View File

@@ -0,0 +1,38 @@
---
allowed-tools: Bash(gh issue view:*), Bash(gh search:*), Bash(gh issue list:*), Bash(gh api:*), Bash(gh issue comment:*)
description: Find duplicate GitHub issues
---
Find up to 3 likely duplicate issues for a given GitHub issue.
To do this, follow these steps precisely:
1. Use an agent to check if the Github issue (a) is closed, (b) does not need to be deduped (eg. because it is broad product feedback without a specific solution, or positive feedback), or (c) already has a duplicates comment that you made earlier. If so, do not proceed.
2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue
3. Then, launch 5 parallel agents to search Github for duplicates of this issue, using diverse keywords and search approaches, using the summary from #1
4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed.
5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates)
Notes (be sure to tell this to your agents, too):
- Use `gh` to interact with Github, rather than web fetch
- Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.)
- Make a todo list first
- For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates):
---
Found 3 possible duplicate issues:
1. <link to issue>
2. <link to issue>
3. <link to issue>
This issue will be automatically closed as a duplicate in 3 days.
- If your issue is a duplicate, please close it and 👍 the existing issue instead
- To prevent auto-closure, add a comment or 👎 this comment
🤖 Generated with [Claude Code](https://claude.ai/code)
---

View File

@@ -3,8 +3,11 @@ FROM node:20
ARG TZ
ENV TZ="$TZ"
ARG CLAUDE_CODE_VERSION=latest
# 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 \
procps \
sudo \
@@ -19,7 +22,10 @@ RUN apt update && apt install -y less \
iproute2 \
dnsutils \
aggregate \
jq
jq \
nano \
vim \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Ensure default node user has access to /usr/local/share
RUN mkdir -p /usr/local/share/npm-global && \
@@ -42,10 +48,11 @@ RUN mkdir -p /workspace /home/node/.claude && \
WORKDIR /workspace
ARG GIT_DELTA_VERSION=0.18.2
RUN ARCH=$(dpkg --print-architecture) && \
wget "https://github.com/dandavison/delta/releases/download/0.18.2/git-delta_0.18.2_${ARCH}.deb" && \
sudo dpkg -i "git-delta_0.18.2_${ARCH}.deb" && \
rm "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_${GIT_DELTA_VERSION}_${ARCH}.deb" && \
rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
# Set up non-root user
USER node
@@ -57,8 +64,13 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
# Set the default shell to zsh rather than sh
ENV SHELL=/bin/zsh
# Set the default editor and visual
ENV EDITOR nano
ENV VISUAL nano
# 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 fzf \
-a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \
@@ -67,7 +79,8 @@ RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/
-x
# Install Claude
RUN npm install -g @anthropic-ai/claude-code
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
# Copy and set up firewall script
COPY init-firewall.sh /usr/local/bin/

View File

@@ -3,7 +3,10 @@
"build": {
"dockerfile": "Dockerfile",
"args": {
"TZ": "${localEnv:TZ:America/Los_Angeles}"
"TZ": "${localEnv:TZ:America/Los_Angeles}",
"CLAUDE_CODE_VERSION": "latest",
"GIT_DELTA_VERSION": "0.18.2",
"ZSH_IN_DOCKER_VERSION": "1.2.0"
}
},
"runArgs": [
@@ -38,10 +41,10 @@
},
"remoteUser": "node",
"mounts": [
"source=claude-code-bashhistory,target=/commandhistory,type=volume",
"source=claude-code-config,target=/home/node/.claude,type=volume"
"source=claude-code-bashhistory-${devcontainerId},target=/commandhistory,type=volume",
"source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"
],
"remoteEnv": {
"containerEnv": {
"NODE_OPTIONS": "--max-old-space-size=4096",
"CLAUDE_CONFIG_DIR": "/home/node/.claude",
"POWERLEVEL9K_DISABLE_GITSTATUS": "true"

View File

@@ -2,6 +2,9 @@
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
IFS=$'\n\t' # Stricter word splitting
# 1. Extract Docker DNS info BEFORE any flushing
DOCKER_DNS_RULES=$(iptables-save -t nat | grep "127\.0\.0\.11" || true)
# Flush existing rules and delete existing ipsets
iptables -F
iptables -X
@@ -11,6 +14,16 @@ iptables -t mangle -F
iptables -t mangle -X
ipset destroy allowed-domains 2>/dev/null || true
# 2. Selectively restore ONLY internal Docker DNS resolution
if [ -n "$DOCKER_DNS_RULES" ]; then
echo "Restoring Docker DNS rules..."
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
echo "$DOCKER_DNS_RULES" | xargs -L 1 iptables -t nat
else
echo "No Docker DNS rules to restore"
fi
# First allow DNS and localhost before any restrictions
# Allow outbound DNS
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
@@ -58,7 +71,7 @@ for domain in \
"statsig.anthropic.com" \
"statsig.com"; do
echo "Resolving $domain..."
ips=$(dig +short A "$domain")
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
if [ -z "$ips" ]; then
echo "ERROR: Failed to resolve $domain"
exit 1

View File

@@ -0,0 +1,31 @@
name: Auto-close duplicate issues
description: Auto-closes issues that are duplicates of existing issues
on:
schedule:
- cron: "0 9 * * *"
workflow_dispatch:
jobs:
auto-close-duplicates:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Auto-close duplicate issues
run: bun run scripts/auto-close-duplicates.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}

View File

@@ -0,0 +1,44 @@
name: Backfill Duplicate Comments
description: Triggers duplicate detection for old issues that don't have duplicate comments
on:
workflow_dispatch:
inputs:
days_back:
description: 'How many days back to look for old issues'
required: false
default: '90'
type: string
dry_run:
description: 'Dry run mode (true to only log what would be done)'
required: false
default: 'true'
type: choice
options:
- 'true'
- 'false'
jobs:
backfill-duplicate-comments:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
issues: read
actions: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Backfill duplicate comments
run: bun run scripts/backfill-duplicate-comments.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DAYS_BACK: ${{ inputs.days_back }}
DRY_RUN: ${{ inputs.dry_run }}

View File

@@ -0,0 +1,80 @@
name: Claude Issue Dedupe
description: Automatically dedupe GitHub issues using Claude Code
on:
issues:
types: [opened]
workflow_dispatch:
inputs:
issue_number:
description: 'Issue number to process for duplicate detection'
required: true
type: string
jobs:
claude-dedupe-issues:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Claude Code slash command
uses: anthropics/claude-code-base-action@beta
with:
prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
claude_env: |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Log duplicate comment event to Statsig
if: always()
env:
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
run: |
ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}
REPO=${{ github.repository }}
if [ -z "$STATSIG_API_KEY" ]; then
echo "STATSIG_API_KEY not found, skipping Statsig logging"
exit 0
fi
# Prepare the event payload
EVENT_PAYLOAD=$(jq -n \
--arg issue_number "$ISSUE_NUMBER" \
--arg repo "$REPO" \
--arg triggered_by "${{ github.event_name }}" \
'{
events: [{
eventName: "github_duplicate_comment_added",
value: 1,
metadata: {
repository: $repo,
issue_number: ($issue_number | tonumber),
triggered_by: $triggered_by,
workflow_run_id: "${{ github.run_id }}"
},
time: (now | floor | tostring)
}]
}')
# Send to Statsig API
echo "Logging duplicate comment event to Statsig for issue #${ISSUE_NUMBER}"
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
-H "Content-Type: application/json" \
-H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
-d "$EVENT_PAYLOAD")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | head -n-1)
if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
echo "Successfully logged duplicate comment event for issue #${ISSUE_NUMBER}"
else
echo "Failed to log duplicate comment event for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
fi

View File

@@ -13,6 +13,9 @@ jobs:
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create triage prompt
run: |
mkdir -p /tmp/claude-prompts

View File

@@ -0,0 +1,92 @@
name: "Lock Stale Issues"
on:
schedule:
# 8am Pacific = 1pm UTC (2pm UTC during DST)
- cron: "0 14 * * *"
workflow_dispatch:
permissions:
issues: write
concurrency:
group: lock-threads
jobs:
lock-closed-issues:
runs-on: ubuntu-latest
steps:
- name: Lock closed issues after 7 days of inactivity
uses: actions/github-script@v7
with:
script: |
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const lockComment = `This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.`;
let page = 1;
let hasMore = true;
let totalLocked = 0;
while (hasMore) {
// Get closed issues (pagination)
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
sort: 'updated',
direction: 'asc',
per_page: 100,
page: page
});
if (issues.length === 0) {
hasMore = false;
break;
}
for (const issue of issues) {
// Skip if already locked
if (issue.locked) continue;
// Skip pull requests
if (issue.pull_request) continue;
// Check if updated more than 7 days ago
const updatedAt = new Date(issue.updated_at);
if (updatedAt > sevenDaysAgo) {
// Since issues are sorted by updated_at ascending,
// once we hit a recent issue, all remaining will be recent too
hasMore = false;
break;
}
try {
// Add comment before locking
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: lockComment
});
// Lock the issue
await github.rest.issues.lock({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
lock_reason: 'resolved'
});
totalLocked++;
console.log(`Locked issue #${issue.number}: ${issue.title}`);
} catch (error) {
console.error(`Failed to lock issue #${issue.number}: ${error.message}`);
}
}
page++;
}
console.log(`Total issues locked: ${totalLocked}`);

40
.github/workflows/log-issue-events.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Log Issue Events to Statsig
on:
issues:
types: [opened, closed]
jobs:
log-to-statsig:
runs-on: ubuntu-latest
permissions:
issues: read
steps:
- name: Log issue creation to Statsig
env:
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
REPO: ${{ github.repository }}
ISSUE_TITLE: ${{ github.event.issue.title }}
AUTHOR: ${{ github.event.issue.user.login }}
CREATED_AT: ${{ github.event.issue.created_at }}
run: |
# All values are now safely passed via environment variables
# No direct templating in the shell script to prevent injection attacks
curl -X POST "https://events.statsigapi.net/v1/log_event" \
-H "Content-Type: application/json" \
-H "statsig-api-key: $STATSIG_API_KEY" \
-d '{
"events": [{
"eventName": "github_issue_created",
"metadata": {
"issue_number": "'"$ISSUE_NUMBER"'",
"repository": "'"$REPO"'",
"title": "'"$(echo "$ISSUE_TITLE" | sed "s/\"/\\\\\"/g")"'",
"author": "'"$AUTHOR"'",
"created_at": "'"$CREATED_AT"'"
},
"time": '"$(date +%s)000"'
}]
}'

View File

@@ -1,8 +1,252 @@
# Changelog
## 1.0.88
- Fixed issue causing "OAuth authentication is currently not supported"
- Status line input now includes `exceeds_200k_tokens`
- Fixed incorrect usage tracking in /cost.
- Introduced `ANTHROPIC_DEFAULT_SONNET_MODEL` and `ANTHROPIC_DEFAULT_OPUS_MODEL` for controlling model aliases opusplan, opus, and sonnet.
- Bedrock: Updated default Sonnet model to Sonnet 4
## 1.0.86
- Added /context to help users self-serve debug context issues
- SDK: Added UUID support for all SDK messages
- SDK: Added `--replay-user-messages` to replay user messages back to stdout
## 1.0.85
- Status line input now includes session cost info
- Hooks: Introduced SessionEnd hook
## 1.0.84
- Fix tool_use/tool_result id mismatch error when network is unstable
- Fix Claude sometimes ignoring real-time steering when wrapping up a task
- @-mention: Add ~/.claude/\* files to suggestions for easier agent, output style, and slash command editing
- Use built-in ripgrep by default; to opt out of this behavior, set USE_BUILTIN_RIPGREP=0
## 1.0.83
- @-mention: Support files with spaces in path
- New shimmering spinner
## 1.0.82
- SDK: Add request cancellation support
- SDK: New additionalDirectories option to search custom paths, improved slash command processing
- Settings: Validation prevents invalid fields in .claude/settings.json files
- MCP: Improve tool name consistency
- Bash: Fix crash when Claude tries to automatically read large files
## 1.0.81
- Released output styles, including new built-in educational output styles "Explanatory" and "Learning". Docs: https://docs.anthropic.com/en/docs/claude-code/output-styles
- Agents: Fix custom agent loading when agent files are unparsable
## 1.0.80
- UI improvements: Fix text contrast for custom subagent colors and spinner rendering issues
## 1.0.77
- Bash tool: Fix heredoc and multiline string escaping, improve stderr redirection handling
- SDK: Add session support and permission denial tracking
- Fix token limit errors in conversation summarization
- Opus Plan Mode: New setting in `/model` to run Opus only in plan mode, Sonnet otherwise
## 1.0.73
- MCP: Support multiple config files with `--mcp-config file1.json file2.json`
- MCP: Press Esc to cancel OAuth authentication flows
- Bash: Improved command validation and reduced false security warnings
- UI: Enhanced spinner animations and status line visual hierarchy
- Linux: Added support for Alpine and musl-based distributions (requires separate ripgrep installation)
## 1.0.72
- Ask permissions: have Claude Code always ask for confirmation to use specific tools with /permissions
## 1.0.71
- Background commands: (Ctrl-b) to run any Bash command in the background so Claude can keep working (great for dev servers, tailing logs, etc.)
- Customizable status line: add your terminal prompt to Claude Code with /statusline
## 1.0.70
- Performance: Optimized message rendering for better performance with large contexts
- Windows: Fixed native file search, ripgrep, and subagent functionality
- Added support for @-mentions in slash command arguments
## 1.0.69
- Upgraded Opus to version 4.1
## 1.0.68
- Fix incorrect model names being used for certain commands like `/pr-comments`
- Windows: improve permissions checks for allow / deny tools and project trust. This may create a new project entry in `.claude.json` - manually merge the history field if desired.
- Windows: improve sub-process spawning to eliminate "No such file or directory" when running commands like pnpm
- Enhanced /doctor command with CLAUDE.md and MCP tool context for self-serve debugging
- SDK: Added canUseTool callback support for tool confirmation
- Added `disableAllHooks` setting
- Improved file suggestions performance in large repos
## 1.0.65
- IDE: Fixed connection stability issues and error handling for diagnostics
- Windows: Fixed shell environment setup for users without .bashrc files
## 1.0.64
- Agents: Added model customization support - you can now specify which model an agent should use
- Agents: Fixed unintended access to the recursive agent tool
- Hooks: Added systemMessage field to hook JSON output for displaying warnings and context
- SDK: Fixed user input tracking across multi-turn conversations
- Added hidden files to file search and @-mention suggestions
## 1.0.63
- Windows: Fixed file search, @agent mentions, and custom slash commands functionality
## 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](https://docs.anthropic.com/en/docs/claude-code/hooks). Special thanks to community input in [Github Issues](https://github.com/anthropics/claude-code/issues/712)
- 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
@@ -24,7 +268,7 @@
## 1.0.33
- Improved logging functionality with session ID support
- Added undo functionality (Ctrl+Z and vim 'u' command)
- Added prompt input undo functionality (Ctrl+Z and vim 'u' command)
- Improvements to plan mode
## 1.0.32

View File

@@ -24,6 +24,10 @@ npm install -g @anthropic-ai/claude-code
We welcome your feedback. Use the `/bug` command to report issues directly within Claude Code, or file a [GitHub issue](https://github.com/anthropics/claude-code/issues).
## Connect on Discord
Join the [Claude Developers Discord](https://anthropic.com/discord) to connect with other developers using Claude Code. Get help, share feedback, and discuss your projects with the community.
## Data collection, usage, and retention
When you use Claude Code, we collect feedback, which includes usage data (such as code acceptance or rejections), associated conversation data, and user feedback submitted via the `/bug` command.

View 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 ---"

View 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()

View File

@@ -0,0 +1,277 @@
#!/usr/bin/env bun
declare global {
var process: {
env: Record<string, string | undefined>;
};
}
interface GitHubIssue {
number: number;
title: string;
user: { id: number };
created_at: string;
}
interface GitHubComment {
id: number;
body: string;
created_at: string;
user: { type: string; id: number };
}
interface GitHubReaction {
user: { id: number };
content: string;
}
async function githubRequest<T>(endpoint: string, token: string, method: string = 'GET', body?: any): Promise<T> {
const response = await fetch(`https://api.github.com${endpoint}`, {
method,
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/vnd.github.v3+json",
"User-Agent": "auto-close-duplicates-script",
...(body && { "Content-Type": "application/json" }),
},
...(body && { body: JSON.stringify(body) }),
});
if (!response.ok) {
throw new Error(
`GitHub API request failed: ${response.status} ${response.statusText}`
);
}
return response.json();
}
function extractDuplicateIssueNumber(commentBody: string): number | null {
// Try to match #123 format first
let match = commentBody.match(/#(\d+)/);
if (match) {
return parseInt(match[1], 10);
}
// Try to match GitHub issue URL format: https://github.com/owner/repo/issues/123
match = commentBody.match(/github\.com\/[^\/]+\/[^\/]+\/issues\/(\d+)/);
if (match) {
return parseInt(match[1], 10);
}
return null;
}
async function closeIssueAsDuplicate(
owner: string,
repo: string,
issueNumber: number,
duplicateOfNumber: number,
token: string
): Promise<void> {
await githubRequest(
`/repos/${owner}/${repo}/issues/${issueNumber}`,
token,
'PATCH',
{
state: 'closed',
state_reason: 'duplicate',
labels: ['duplicate']
}
);
await githubRequest(
`/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
token,
'POST',
{
body: `This issue has been automatically closed as a duplicate of #${duplicateOfNumber}.
If this is incorrect, please re-open this issue or create a new one.
🤖 Generated with [Claude Code](https://claude.ai/code)`
}
);
}
async function autoCloseDuplicates(): Promise<void> {
console.log("[DEBUG] Starting auto-close duplicates script");
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error("GITHUB_TOKEN environment variable is required");
}
console.log("[DEBUG] GitHub token found");
const owner = process.env.GITHUB_REPOSITORY_OWNER || "anthropics";
const repo = process.env.GITHUB_REPOSITORY_NAME || "claude-code";
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
const threeDaysAgo = new Date();
threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
console.log(
`[DEBUG] Checking for duplicate comments older than: ${threeDaysAgo.toISOString()}`
);
console.log("[DEBUG] Fetching open issues created more than 3 days ago...");
const allIssues: GitHubIssue[] = [];
let page = 1;
const perPage = 100;
while (true) {
const pageIssues: GitHubIssue[] = await githubRequest(
`/repos/${owner}/${repo}/issues?state=open&per_page=${perPage}&page=${page}`,
token
);
if (pageIssues.length === 0) break;
// Filter for issues created more than 3 days ago
const oldEnoughIssues = pageIssues.filter(issue =>
new Date(issue.created_at) <= threeDaysAgo
);
allIssues.push(...oldEnoughIssues);
page++;
// Safety limit to avoid infinite loops
if (page > 20) break;
}
const issues = allIssues;
console.log(`[DEBUG] Found ${issues.length} open issues`);
let processedCount = 0;
let candidateCount = 0;
for (const issue of issues) {
processedCount++;
console.log(
`[DEBUG] Processing issue #${issue.number} (${processedCount}/${issues.length}): ${issue.title}`
);
console.log(`[DEBUG] Fetching comments for issue #${issue.number}...`);
const comments: GitHubComment[] = await githubRequest(
`/repos/${owner}/${repo}/issues/${issue.number}/comments`,
token
);
console.log(
`[DEBUG] Issue #${issue.number} has ${comments.length} comments`
);
const dupeComments = comments.filter(
(comment) =>
comment.body.includes("Found") &&
comment.body.includes("possible duplicate") &&
comment.user.type === "Bot"
);
console.log(
`[DEBUG] Issue #${issue.number} has ${dupeComments.length} duplicate detection comments`
);
if (dupeComments.length === 0) {
console.log(
`[DEBUG] Issue #${issue.number} - no duplicate comments found, skipping`
);
continue;
}
const lastDupeComment = dupeComments[dupeComments.length - 1];
const dupeCommentDate = new Date(lastDupeComment.created_at);
console.log(
`[DEBUG] Issue #${
issue.number
} - most recent duplicate comment from: ${dupeCommentDate.toISOString()}`
);
if (dupeCommentDate > threeDaysAgo) {
console.log(
`[DEBUG] Issue #${issue.number} - duplicate comment is too recent, skipping`
);
continue;
}
console.log(
`[DEBUG] Issue #${
issue.number
} - duplicate comment is old enough (${Math.floor(
(Date.now() - dupeCommentDate.getTime()) / (1000 * 60 * 60 * 24)
)} days)`
);
const commentsAfterDupe = comments.filter(
(comment) => new Date(comment.created_at) > dupeCommentDate
);
console.log(
`[DEBUG] Issue #${issue.number} - ${commentsAfterDupe.length} comments after duplicate detection`
);
if (commentsAfterDupe.length > 0) {
console.log(
`[DEBUG] Issue #${issue.number} - has activity after duplicate comment, skipping`
);
continue;
}
console.log(
`[DEBUG] Issue #${issue.number} - checking reactions on duplicate comment...`
);
const reactions: GitHubReaction[] = await githubRequest(
`/repos/${owner}/${repo}/issues/comments/${lastDupeComment.id}/reactions`,
token
);
console.log(
`[DEBUG] Issue #${issue.number} - duplicate comment has ${reactions.length} reactions`
);
const authorThumbsDown = reactions.some(
(reaction) =>
reaction.user.id === issue.user.id && reaction.content === "-1"
);
console.log(
`[DEBUG] Issue #${issue.number} - author thumbs down reaction: ${authorThumbsDown}`
);
if (authorThumbsDown) {
console.log(
`[DEBUG] Issue #${issue.number} - author disagreed with duplicate detection, skipping`
);
continue;
}
const duplicateIssueNumber = extractDuplicateIssueNumber(lastDupeComment.body);
if (!duplicateIssueNumber) {
console.log(
`[DEBUG] Issue #${issue.number} - could not extract duplicate issue number from comment, skipping`
);
continue;
}
candidateCount++;
const issueUrl = `https://github.com/${owner}/${repo}/issues/${issue.number}`;
try {
console.log(
`[INFO] Auto-closing issue #${issue.number} as duplicate of #${duplicateIssueNumber}: ${issueUrl}`
);
await closeIssueAsDuplicate(owner, repo, issue.number, duplicateIssueNumber, token);
console.log(
`[SUCCESS] Successfully closed issue #${issue.number} as duplicate of #${duplicateIssueNumber}`
);
} catch (error) {
console.error(
`[ERROR] Failed to close issue #${issue.number} as duplicate: ${error}`
);
}
}
console.log(
`[DEBUG] Script completed. Processed ${processedCount} issues, found ${candidateCount} candidates for auto-close`
);
}
autoCloseDuplicates().catch(console.error);
// Make it a module
export {};

View File

@@ -0,0 +1,198 @@
#!/usr/bin/env bun
declare global {
var process: {
env: Record<string, string | undefined>;
};
}
interface GitHubIssue {
number: number;
title: string;
state: string;
state_reason?: string;
user: { id: number };
created_at: string;
closed_at?: string;
}
interface GitHubComment {
id: number;
body: string;
created_at: string;
user: { type: string; id: number };
}
async function githubRequest<T>(endpoint: string, token: string, method: string = 'GET', body?: any): Promise<T> {
const response = await fetch(`https://api.github.com${endpoint}`, {
method,
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/vnd.github.v3+json",
"User-Agent": "backfill-duplicate-comments-script",
...(body && { "Content-Type": "application/json" }),
},
...(body && { body: JSON.stringify(body) }),
});
if (!response.ok) {
throw new Error(
`GitHub API request failed: ${response.status} ${response.statusText}`
);
}
return response.json();
}
async function triggerDedupeWorkflow(
owner: string,
repo: string,
issueNumber: number,
token: string,
dryRun: boolean = true
): Promise<void> {
if (dryRun) {
console.log(`[DRY RUN] Would trigger dedupe workflow for issue #${issueNumber}`);
return;
}
await githubRequest(
`/repos/${owner}/${repo}/actions/workflows/claude-dedupe-issues.yml/dispatches`,
token,
'POST',
{
ref: 'main',
inputs: {
issue_number: issueNumber.toString()
}
}
);
}
async function backfillDuplicateComments(): Promise<void> {
console.log("[DEBUG] Starting backfill duplicate comments script");
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error(`GITHUB_TOKEN environment variable is required
Usage:
GITHUB_TOKEN=your_token bun run scripts/backfill-duplicate-comments.ts
Environment Variables:
GITHUB_TOKEN - GitHub personal access token with repo and actions permissions (required)
DRY_RUN - Set to "false" to actually trigger workflows (default: true for safety)
DAYS_BACK - How many days back to look for old issues (default: 90)`);
}
console.log("[DEBUG] GitHub token found");
const owner = "anthropics";
const repo = "claude-code";
const dryRun = process.env.DRY_RUN !== "false";
const daysBack = parseInt(process.env.DAYS_BACK || "90", 10);
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
console.log(`[DEBUG] Dry run mode: ${dryRun}`);
console.log(`[DEBUG] Looking back ${daysBack} days`);
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - daysBack);
console.log(`[DEBUG] Fetching issues created since ${cutoffDate.toISOString()}...`);
const allIssues: GitHubIssue[] = [];
let page = 1;
const perPage = 100;
while (true) {
const pageIssues: GitHubIssue[] = await githubRequest(
`/repos/${owner}/${repo}/issues?state=all&per_page=${perPage}&page=${page}&since=${cutoffDate.toISOString()}`,
token
);
if (pageIssues.length === 0) break;
allIssues.push(...pageIssues);
page++;
// Safety limit to avoid infinite loops
if (page > 100) {
console.log("[DEBUG] Reached page limit, stopping pagination");
break;
}
}
console.log(`[DEBUG] Found ${allIssues.length} issues from the last ${daysBack} days`);
let processedCount = 0;
let candidateCount = 0;
let triggeredCount = 0;
for (const issue of allIssues) {
processedCount++;
console.log(
`[DEBUG] Processing issue #${issue.number} (${processedCount}/${allIssues.length}): ${issue.title}`
);
console.log(`[DEBUG] Fetching comments for issue #${issue.number}...`);
const comments: GitHubComment[] = await githubRequest(
`/repos/${owner}/${repo}/issues/${issue.number}/comments`,
token
);
console.log(
`[DEBUG] Issue #${issue.number} has ${comments.length} comments`
);
// Look for existing duplicate detection comments (from the dedupe bot)
const dupeDetectionComments = comments.filter(
(comment) =>
comment.body.includes("Found") &&
comment.body.includes("possible duplicate") &&
comment.user.type === "Bot"
);
console.log(
`[DEBUG] Issue #${issue.number} has ${dupeDetectionComments.length} duplicate detection comments`
);
// Skip if there's already a duplicate detection comment
if (dupeDetectionComments.length > 0) {
console.log(
`[DEBUG] Issue #${issue.number} already has duplicate detection comment, skipping`
);
continue;
}
candidateCount++;
const issueUrl = `https://github.com/${owner}/${repo}/issues/${issue.number}`;
try {
console.log(
`[INFO] ${dryRun ? '[DRY RUN] ' : ''}Triggering dedupe workflow for issue #${issue.number}: ${issueUrl}`
);
await triggerDedupeWorkflow(owner, repo, issue.number, token, dryRun);
if (!dryRun) {
console.log(
`[SUCCESS] Successfully triggered dedupe workflow for issue #${issue.number}`
);
}
triggeredCount++;
} catch (error) {
console.error(
`[ERROR] Failed to trigger workflow for issue #${issue.number}: ${error}`
);
}
// Add a delay between workflow triggers to avoid overwhelming the system
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log(
`[DEBUG] Script completed. Processed ${processedCount} issues, found ${candidateCount} candidates without duplicate comments, ${dryRun ? 'would trigger' : 'triggered'} ${triggeredCount} workflows`
);
}
backfillDuplicateComments().catch(console.error);
// Make it a module
export {};