mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Compare commits
41 Commits
ashwin/tas
...
inigo/clea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d81efef324 | ||
|
|
c3a32e4ccf | ||
|
|
2511feadf3 | ||
|
|
bdba4a874d | ||
|
|
cd043128fe | ||
|
|
8fba17cb99 | ||
|
|
2b3a504f85 | ||
|
|
1bcc5cf5bd | ||
|
|
3e00a44590 | ||
|
|
702c601369 | ||
|
|
542b57b9a4 | ||
|
|
5c2a1e1d2e | ||
|
|
156d9e9e3f | ||
|
|
3404b075ec | ||
|
|
72042e95fb | ||
|
|
1feaffa747 | ||
|
|
7127181c79 | ||
|
|
e66b150c0e | ||
|
|
dbff8bea24 | ||
|
|
5a2442227a | ||
|
|
f5dd15ac7e | ||
|
|
c0a28eede9 | ||
|
|
81f65bea8a | ||
|
|
dc8f77c7ef | ||
|
|
786259a00c | ||
|
|
8e679e75f7 | ||
|
|
87560460bc | ||
|
|
07e13937b2 | ||
|
|
55988caadf | ||
|
|
8beb9b0c76 | ||
|
|
4607d83fa8 | ||
|
|
70d5361861 | ||
|
|
c792b7d4c7 | ||
|
|
5f52517c0b | ||
|
|
cc09d58e8e | ||
|
|
d820a4dbd7 | ||
|
|
2b46e47360 | ||
|
|
c58a7da257 | ||
|
|
6d79459b16 | ||
|
|
20ba9a34a5 | ||
|
|
10a1f7dab9 |
@@ -65,8 +65,8 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
||||
ENV SHELL=/bin/zsh
|
||||
|
||||
# Set the default editor and visual
|
||||
ENV EDITOR nano
|
||||
ENV VISUAL nano
|
||||
ENV EDITOR=nano
|
||||
ENV VISUAL=nano
|
||||
|
||||
# Default powerline10k theme
|
||||
ARG ZSH_IN_DOCKER_VERSION=1.2.0
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"anthropic.claude-code",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"eamodio.gitlens"
|
||||
@@ -51,5 +52,6 @@
|
||||
},
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
|
||||
"workspaceFolder": "/workspace",
|
||||
"postCreateCommand": "sudo /usr/local/bin/init-firewall.sh"
|
||||
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
|
||||
"waitFor": "postStartCommand"
|
||||
}
|
||||
|
||||
@@ -69,7 +69,10 @@ for domain in \
|
||||
"api.anthropic.com" \
|
||||
"sentry.io" \
|
||||
"statsig.anthropic.com" \
|
||||
"statsig.com"; do
|
||||
"statsig.com" \
|
||||
"marketplace.visualstudio.com" \
|
||||
"vscode.blob.core.windows.net" \
|
||||
"update.code.visualstudio.com"; do
|
||||
echo "Resolving $domain..."
|
||||
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
|
||||
if [ -z "$ips" ]; then
|
||||
@@ -113,6 +116,9 @@ iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
# Then allow only specific outbound traffic to allowed domains
|
||||
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
||||
|
||||
# Explicitly REJECT all other outbound traffic for immediate feedback
|
||||
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
|
||||
|
||||
echo "Firewall configuration complete"
|
||||
echo "Verifying firewall rules..."
|
||||
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
||||
|
||||
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,34 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: '[BUG] '
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Environment
|
||||
- Platform (select one):
|
||||
- [ ] Anthropic API
|
||||
- [ ] AWS Bedrock
|
||||
- [ ] Google Vertex AI
|
||||
- [ ] Other: <!-- specify -->
|
||||
- Claude CLI version: <!-- output of `claude --version` -->
|
||||
- Operating System: <!-- e.g. macOS 14.3, Windows 11, Ubuntu 22.04 -->
|
||||
- Terminal: <!-- e.g. iTerm2, Terminal App -->
|
||||
|
||||
## Bug Description
|
||||
<!-- A clear and concise description of the bug -->
|
||||
|
||||
## Steps to Reproduce
|
||||
1. <!-- First step -->
|
||||
2. <!-- Second step -->
|
||||
3. <!-- And so on... -->
|
||||
|
||||
## Expected Behavior
|
||||
<!-- What you expected to happen -->
|
||||
|
||||
## Actual Behavior
|
||||
<!-- What actually happened -->
|
||||
|
||||
## Additional Context
|
||||
<!-- Add any other context about the problem here, such as screenshots, logs, etc. -->
|
||||
188
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
188
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior in Claude Code
|
||||
title: "[BUG] "
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report this bug! Please fill out the sections below to help us understand and fix the issue.
|
||||
|
||||
Before submitting, please check:
|
||||
- You're using the [latest version](https://www.npmjs.com/package/@anthropic-ai/claude-code?activeTab=versions) of Claude Code (`claude --version`)
|
||||
- This issue hasn't already been reported by searching [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug).
|
||||
- This is a bug, not a feature request or support question
|
||||
|
||||
- type: checkboxes
|
||||
id: preflight
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
description: Please confirm before submitting
|
||||
options:
|
||||
- label: I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
|
||||
required: true
|
||||
- label: This is a single bug report (please file separate reports for different bugs)
|
||||
required: true
|
||||
- label: I am using the latest version of Claude Code
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: What's Wrong?
|
||||
description: Describe what's happening that shouldn't be
|
||||
placeholder: |
|
||||
When I try to create a Python file, Claude shows an error "EACCES: permission denied" and the file isn't created.
|
||||
|
||||
The command fails immediately after accepting the file write permission...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What Should Happen?
|
||||
description: Describe the expected behavior
|
||||
placeholder: Claude should create a Python script file successfully without errors
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error_output
|
||||
attributes:
|
||||
label: Error Messages/Logs
|
||||
description: If you see any error messages, paste them here
|
||||
placeholder: |
|
||||
Paste any error output, stack traces, or relevant logs here.
|
||||
This will be automatically formatted as code.
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: |
|
||||
Please provide clear, numbered steps that anyone can follow to reproduce the issue.
|
||||
**Important**: Include any necessary code, file contents, or context needed to reproduce the bug.
|
||||
If the issue involves specific files or code, please create a minimal example.
|
||||
placeholder: |
|
||||
1. Create a file `test.py` with this content:
|
||||
```python
|
||||
def hello():
|
||||
print("test")
|
||||
```
|
||||
2. Run `claude "add type hints to test.py"`
|
||||
3. When prompted for file access, accept
|
||||
4. Error appears: "Unable to parse..."
|
||||
|
||||
Note: The bug only happens with Python files containing...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: model
|
||||
attributes:
|
||||
label: Claude Model
|
||||
description: Which model were you using? (Run `/model` to check)
|
||||
options:
|
||||
- Sonnet (default)
|
||||
- Opus
|
||||
- Not sure / Multiple models
|
||||
- Other
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: regression
|
||||
attributes:
|
||||
label: Is this a regression?
|
||||
description: Did this work in a previous version?
|
||||
options:
|
||||
- "Yes, this worked in a previous version"
|
||||
- "No, this never worked"
|
||||
- "I don't know"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: working_version
|
||||
attributes:
|
||||
label: Last Working Version
|
||||
description: If this is a regression, which version last worked? This helps expedite a fix.
|
||||
placeholder: "e.g., 1.0.100"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Claude Code Version
|
||||
description: Run `claude --version` and paste the output
|
||||
placeholder: "e.g., 1.0.123 (Claude Code)"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Which API platform are you using?
|
||||
options:
|
||||
- Anthropic API
|
||||
- AWS Bedrock
|
||||
- Google Vertex AI
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
options:
|
||||
- macOS
|
||||
- Windows
|
||||
- Ubuntu/Debian Linux
|
||||
- Other Linux
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: terminal
|
||||
attributes:
|
||||
label: Terminal/Shell
|
||||
description: Which terminal are you using?
|
||||
options:
|
||||
- Terminal.app (macOS)
|
||||
- Warp
|
||||
- Cursor
|
||||
- iTerm2
|
||||
- IntelliJ IDEA terminal
|
||||
- VS Code integrated terminal
|
||||
- PyCharm terminal
|
||||
- Windows Terminal
|
||||
- PowerShell
|
||||
- WSL (Windows Subsystem for Linux)
|
||||
- Xterm
|
||||
- Non-interactive/CI environment
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
Anything else that might help us understand the issue?
|
||||
- Screenshots (drag and drop images here)
|
||||
- Configuration files
|
||||
- Related files or code
|
||||
- Links to repositories demonstrating the issue
|
||||
placeholder: Any additional context, screenshots, or information...
|
||||
validations:
|
||||
required: false
|
||||
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Discord Community
|
||||
url: https://anthropic.com/discord
|
||||
about: Get help, ask questions, and chat with other Claude Code users
|
||||
- name: 📖 Documentation
|
||||
url: https://docs.anthropic.com/en/docs/claude-code
|
||||
about: Read the official documentation and guides
|
||||
- name: 🎓 Getting Started Guide
|
||||
url: https://docs.anthropic.com/en/docs/claude-code/getting-started
|
||||
about: New to Claude Code? Start here
|
||||
- name: 🔧 Troubleshooting Guide
|
||||
url: https://docs.anthropic.com/en/docs/claude-code/troubleshooting
|
||||
about: Common issues and how to fix them
|
||||
- name: 💡 Discussions
|
||||
url: https://github.com/anthropics/claude-code/discussions
|
||||
about: Share ideas, tips, and chat with maintainers
|
||||
117
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
117
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
name: 📚 Documentation Issue
|
||||
description: Report missing, unclear, or incorrect documentation
|
||||
title: "[DOCS] "
|
||||
labels:
|
||||
- documentation
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Help us improve our documentation!
|
||||
|
||||
Good documentation is crucial for a great developer experience. Please let us know what's missing or confusing.
|
||||
|
||||
- type: dropdown
|
||||
id: doc_type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What kind of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation (feature not documented)
|
||||
- Unclear/confusing documentation
|
||||
- Incorrect/outdated documentation
|
||||
- Typo or formatting issue
|
||||
- Missing code examples
|
||||
- Broken links
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where did you encounter this issue? Provide a URL if possible
|
||||
placeholder: "e.g., https://docs.anthropic.com/en/docs/claude-code/getting-started"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: input
|
||||
id: section
|
||||
attributes:
|
||||
label: Section/Topic
|
||||
description: Which specific section or topic needs improvement?
|
||||
placeholder: "e.g., MCP Server Configuration section"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: current
|
||||
attributes:
|
||||
label: Current Documentation
|
||||
description: |
|
||||
What does the documentation currently say?
|
||||
Quote the specific text if applicable.
|
||||
placeholder: |
|
||||
The docs currently say:
|
||||
"To configure MCP servers, add them to your configuration..."
|
||||
|
||||
But it doesn't explain...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: What's Wrong or Missing?
|
||||
description: Explain what's incorrect, unclear, or missing
|
||||
placeholder: |
|
||||
The documentation doesn't explain how to:
|
||||
- Configure multiple MCP servers
|
||||
- Handle authentication
|
||||
- Debug connection issues
|
||||
|
||||
The example code doesn't work because...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggested
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved? Provide suggested text if possible
|
||||
placeholder: |
|
||||
The documentation should include:
|
||||
|
||||
1. A complete example showing...
|
||||
2. Explanation of common errors like...
|
||||
3. Step-by-step guide for...
|
||||
|
||||
Suggested text:
|
||||
"To configure multiple MCP servers, create an array in your settings..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: impact
|
||||
attributes:
|
||||
label: Impact
|
||||
description: How much does this documentation issue affect users?
|
||||
options:
|
||||
- High - Prevents users from using a feature
|
||||
- Medium - Makes feature difficult to understand
|
||||
- Low - Minor confusion or inconvenience
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: |
|
||||
- Screenshots showing the issue
|
||||
- Links to related documentation
|
||||
- Examples from other projects that do this well
|
||||
placeholder: Any additional information that would help...
|
||||
validations:
|
||||
required: false
|
||||
132
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
132
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
name: ✨ Feature Request
|
||||
description: Suggest a new feature or enhancement for Claude Code
|
||||
title: "[FEATURE] "
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Thanks for suggesting a feature!
|
||||
|
||||
We love hearing ideas from our community. Please help us understand your use case by filling out the sections below.
|
||||
Before submitting, please check if this feature has already been requested.
|
||||
|
||||
- type: checkboxes
|
||||
id: preflight
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
options:
|
||||
- label: I have searched [existing requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
|
||||
required: true
|
||||
- label: This is a single feature request (not multiple features)
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: |
|
||||
What problem are you trying to solve? Why do you need this feature?
|
||||
Focus on the problem, not the solution. Help us understand your workflow.
|
||||
placeholder: |
|
||||
I often need to work with multiple projects simultaneously, but Claude Code doesn't support...
|
||||
|
||||
When I'm debugging code, I find it difficult to...
|
||||
|
||||
The current workflow requires me to manually...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: |
|
||||
How would you like this to work? Describe the ideal user experience.
|
||||
Be specific about how you'd interact with this feature.
|
||||
placeholder: |
|
||||
I'd like to be able to run `claude --workspace project1,project2` to...
|
||||
|
||||
There should be a command or setting that allows...
|
||||
|
||||
The interface should show...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternative Solutions
|
||||
description: |
|
||||
What alternatives have you considered or tried?
|
||||
Are there workarounds you're currently using?
|
||||
placeholder: |
|
||||
I've tried using multiple terminal windows but...
|
||||
|
||||
Currently I work around this by...
|
||||
|
||||
Other tools solve this by...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to your workflow?
|
||||
options:
|
||||
- Critical - Blocking my work
|
||||
- High - Significant impact on productivity
|
||||
- Medium - Would be very helpful
|
||||
- Low - Nice to have
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: category
|
||||
attributes:
|
||||
label: Feature Category
|
||||
description: What area does this feature relate to?
|
||||
options:
|
||||
- CLI commands and flags
|
||||
- Interactive mode (TUI)
|
||||
- File operations
|
||||
- API and model interactions
|
||||
- MCP server integration
|
||||
- Performance and speed
|
||||
- Configuration and settings
|
||||
- Developer tools/SDK
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use_case
|
||||
attributes:
|
||||
label: Use Case Example
|
||||
description: |
|
||||
Provide a concrete, real-world example of when you'd use this feature.
|
||||
Walk us through a scenario step-by-step.
|
||||
placeholder: |
|
||||
Example scenario:
|
||||
1. I'm working on a React app with a Node.js backend
|
||||
2. I need to make changes to both frontend and backend
|
||||
3. With this feature, I could...
|
||||
4. This would save me time because...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: |
|
||||
- Screenshots or mockups of the proposed feature
|
||||
- Links to similar features in other tools
|
||||
- Technical considerations or constraints
|
||||
- Any other relevant information
|
||||
placeholder: Add any other context, mockups, or examples here...
|
||||
validations:
|
||||
required: false
|
||||
220
.github/ISSUE_TEMPLATE/model_behavior.yml
vendored
Normal file
220
.github/ISSUE_TEMPLATE/model_behavior.yml
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
name: 🤖 Model Behavior Issue
|
||||
description: Report unexpected Claude model behavior, incorrect actions, or permission violations
|
||||
title: "[MODEL] "
|
||||
labels:
|
||||
- model
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Report Unexpected Model Behavior
|
||||
|
||||
Use this template when Claude does something unexpected, makes unwanted changes, or behaves inconsistently with your instructions.
|
||||
|
||||
**This is for:** Unexpected actions, file modifications outside scope, ignoring instructions, making assumptions
|
||||
**NOT for:** Crashes, API errors, or installation issues (use Bug Report instead)
|
||||
|
||||
- type: checkboxes
|
||||
id: preflight
|
||||
attributes:
|
||||
label: Preflight Checklist
|
||||
description: Please confirm before submitting
|
||||
options:
|
||||
- label: I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Amodel) for similar behavior reports
|
||||
required: true
|
||||
- label: This report does NOT contain sensitive information (API keys, passwords, etc.)
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: behavior_type
|
||||
attributes:
|
||||
label: Type of Behavior Issue
|
||||
description: What category best describes the unexpected behavior?
|
||||
options:
|
||||
- Claude modified files I didn't ask it to modify
|
||||
- Claude accessed files outside the working directory
|
||||
- Claude ignored my instructions or configuration
|
||||
- Claude reverted/undid previous changes without asking
|
||||
- Claude made incorrect assumptions about my project
|
||||
- Claude refused a reasonable request
|
||||
- Claude's behavior changed between sessions
|
||||
- Subagent behaved unexpectedly
|
||||
- Other unexpected behavior
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what_you_asked
|
||||
attributes:
|
||||
label: What You Asked Claude to Do
|
||||
description: Provide the exact prompt or command you gave
|
||||
placeholder: |
|
||||
I asked: "Update the README.md file to add installation instructions"
|
||||
|
||||
Or I ran: `claude "fix the bug in auth.js"`
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: what_claude_did
|
||||
attributes:
|
||||
label: What Claude Actually Did
|
||||
description: Describe step-by-step what Claude did instead
|
||||
placeholder: |
|
||||
1. Claude read README.md
|
||||
2. Instead of updating it, Claude deleted the entire file
|
||||
3. Created a new README from scratch with different content
|
||||
4. Also modified package.json without being asked
|
||||
5. Changed .gitignore file
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected_behavior
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What should Claude have done?
|
||||
placeholder: |
|
||||
Claude should have:
|
||||
1. Read the existing README.md
|
||||
2. Added an "Installation" section
|
||||
3. Only modified that single file
|
||||
4. Not touched any other files
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: files_affected
|
||||
attributes:
|
||||
label: Files Affected
|
||||
description: |
|
||||
List all files that were accessed or modified (even if you didn't expect them to be)
|
||||
placeholder: |
|
||||
Modified:
|
||||
- README.md (deleted and recreated)
|
||||
- package.json (version bumped - not requested)
|
||||
- .gitignore (added entries - not requested)
|
||||
|
||||
Read (unexpectedly):
|
||||
- /Users/me/.ssh/config
|
||||
- ../../../parent-directory/secrets.env
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: permission_mode
|
||||
attributes:
|
||||
label: Permission Mode
|
||||
description: What permission settings were active?
|
||||
options:
|
||||
- Accept Edits was ON (auto-accepting changes)
|
||||
- Accept Edits was OFF (manual approval required)
|
||||
- I don't know / Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: reproducible
|
||||
attributes:
|
||||
label: Can You Reproduce This?
|
||||
description: Does this happen consistently?
|
||||
options:
|
||||
- Yes, every time with the same prompt
|
||||
- Sometimes (intermittent)
|
||||
- No, only happened once
|
||||
- Haven't tried to reproduce
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction_steps
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: If reproducible, provide minimal steps
|
||||
placeholder: |
|
||||
1. Create a new directory with a simple README.md
|
||||
2. Ask Claude Code to "improve the README"
|
||||
3. Claude will delete and recreate the file instead of editing
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: model
|
||||
attributes:
|
||||
label: Claude Model
|
||||
description: Which model were you using? (Run `/model` to check)
|
||||
options:
|
||||
- Sonnet
|
||||
- Opus
|
||||
- Haiku
|
||||
- Not sure
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: conversation_log
|
||||
attributes:
|
||||
label: Relevant Conversation
|
||||
description: |
|
||||
Include relevant parts of Claude's responses, especially where it explains what it's doing
|
||||
placeholder: |
|
||||
Claude said: "I'll help you update the README. Let me first delete the old one and create a fresh version..."
|
||||
|
||||
[Then proceeded to delete without asking for confirmation]
|
||||
render: markdown
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: impact
|
||||
attributes:
|
||||
label: Impact
|
||||
description: How severe was the impact of this behavior?
|
||||
options:
|
||||
- Critical - Data loss or corrupted project
|
||||
- High - Significant unwanted changes
|
||||
- Medium - Extra work to undo changes
|
||||
- Low - Minor inconvenience
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Claude Code Version
|
||||
description: Run `claude --version` and paste the output
|
||||
placeholder: "e.g., 1.0.123 (Claude Code)"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Which API platform are you using?
|
||||
options:
|
||||
- Anthropic API
|
||||
- AWS Bedrock
|
||||
- Google Vertex AI
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: |
|
||||
- Any patterns you've noticed
|
||||
- Similar behavior in other sessions
|
||||
- Specific file types or project structures that trigger this
|
||||
- Screenshots if relevant
|
||||
placeholder: |
|
||||
This seems to happen more often with:
|
||||
- Python projects
|
||||
- When there are multiple similar files
|
||||
- After long conversations
|
||||
validations:
|
||||
required: false
|
||||
31
.github/workflows/auto-close-duplicates.yml
vendored
31
.github/workflows/auto-close-duplicates.yml
vendored
@@ -1,31 +0,0 @@
|
||||
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 }}
|
||||
@@ -1,44 +0,0 @@
|
||||
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 }}
|
||||
80
.github/workflows/claude-dedupe-issues.yml
vendored
80
.github/workflows/claude-dedupe-issues.yml
vendored
@@ -1,80 +0,0 @@
|
||||
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
|
||||
28
.github/workflows/issue-opened-dispatch.yml
vendored
Normal file
28
.github/workflows/issue-opened-dispatch.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Issue Opened Dispatch
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: read
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 1
|
||||
steps:
|
||||
- name: Process new issue
|
||||
env:
|
||||
ISSUE_URL: ${{ github.event.issue.html_url }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
ISSUE_TITLE: ${{ github.event.issue.title }}
|
||||
TARGET_REPO: ${{ secrets.ISSUE_OPENED_DISPATCH_TARGET_REPO }}
|
||||
GH_TOKEN: ${{ secrets.ISSUE_OPENED_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
gh api repos/${TARGET_REPO}/dispatches \
|
||||
-f event_type=issue_opened \
|
||||
-f client_payload[issue_url]="${ISSUE_URL}" || {
|
||||
exit 0
|
||||
}
|
||||
2
.github/workflows/log-issue-events.yml
vendored
2
.github/workflows/log-issue-events.yml
vendored
@@ -2,7 +2,7 @@ name: Log Issue Events to Statsig
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
types: [opened, closed]
|
||||
|
||||
jobs:
|
||||
log-to-statsig:
|
||||
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,5 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## 1.0.106
|
||||
|
||||
- Windows: Fixed path permission matching to consistently use POSIX format (e.g., `Read(//c/Users/...)`)
|
||||
|
||||
## 1.0.97
|
||||
|
||||
- Settings: /doctor now validates permission rule syntax and suggests corrections
|
||||
|
||||
## 1.0.94
|
||||
|
||||
- Vertex: add support for global endpoints for supported models
|
||||
- /memory command now allows direct editing of all imported memory files
|
||||
- SDK: Add custom tools as callbacks
|
||||
- Added /todos command to list current todo items
|
||||
|
||||
## 1.0.93
|
||||
|
||||
- Windows: Add alt + v shortcut for pasting images from clipboard
|
||||
- Support NO_PROXY environment variable to bypass proxy for specified hostnames and IPs
|
||||
|
||||
## 1.0.90
|
||||
|
||||
- Settings file changes take effect immediately - no restart required
|
||||
|
||||
## 1.0.88
|
||||
|
||||
- Fixed issue causing "OAuth authentication is currently not supported"
|
||||
|
||||
@@ -34,9 +34,7 @@ When you use Claude Code, we collect feedback, which includes usage data (such a
|
||||
|
||||
### How we use your data
|
||||
|
||||
We may use feedback to improve our products and services, but we will not train generative models using your feedback from Claude Code. Given their potentially sensitive nature, we store user feedback transcripts for only 30 days.
|
||||
|
||||
If you choose to send us feedback about Claude Code, such as transcripts of your usage, Anthropic may use that feedback to debug related issues and improve Claude Code's functionality (e.g., to reduce the risk of similar bugs occurring in the future).
|
||||
See our [data usage policies](https://docs.anthropic.com/en/docs/claude-code/data-usage).
|
||||
|
||||
### Privacy safeguards
|
||||
|
||||
|
||||
@@ -40,14 +40,18 @@ Write-Host "Using backend: $($Backend)"
|
||||
# --- Prerequisite Check ---
|
||||
Write-Host "Checking for required commands..."
|
||||
try {
|
||||
Get-Command $Backend -ErrorAction Stop | Out-Null
|
||||
if (-not (Get-Command $Backend -ErrorAction SilentlyContinue)) {
|
||||
throw "Required command '$($Backend)' not found."
|
||||
}
|
||||
Write-Host "- $($Backend) command found."
|
||||
Get-Command devcontainer -ErrorAction Stop | Out-Null
|
||||
if (-not (Get-Command devcontainer -ErrorAction SilentlyContinue)) {
|
||||
throw "Required command 'devcontainer' not found."
|
||||
}
|
||||
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."
|
||||
Write-Error "A required command is not installed or not in your PATH. $($_.Exception.Message)"
|
||||
Write-Error "Please ensure both '$Backend' and 'devcontainer' are installed and accessible in your system's PATH."
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
#!/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 {};
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/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 {};
|
||||
Reference in New Issue
Block a user