Compare commits

..

2 Commits

Author SHA1 Message Date
Boris Cherny
5792e3c43f Update .github/workflows/claude-dedupe-issues.yml 2025-07-30 19:51:21 -07:00
Boris Cherny
5bff800d8b Update claude-dedupe-issues.yml 2025-07-30 19:31:02 -07:00
22 changed files with 60 additions and 1679 deletions

View File

@@ -1,19 +0,0 @@
---
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

@@ -28,10 +28,7 @@ Found 3 possible duplicate issues:
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
If your issue is a duplicate, please close it and 👍 the existing issue instead.
🤖 Generated with [Claude Code](https://claude.ai/code)

View File

@@ -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

View File

@@ -16,7 +16,6 @@
"customizations": {
"vscode": {
"extensions": [
"anthropic.claude-code",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"eamodio.gitlens"
@@ -52,6 +51,5 @@
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
"waitFor": "postStartCommand"
"postCreateCommand": "sudo /usr/local/bin/init-firewall.sh"
}

View File

@@ -69,12 +69,9 @@ for domain in \
"api.anthropic.com" \
"sentry.io" \
"statsig.anthropic.com" \
"statsig.com" \
"marketplace.visualstudio.com" \
"vscode.blob.core.windows.net" \
"update.code.visualstudio.com"; do
"statsig.com"; do
echo "Resolving $domain..."
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
ips=$(dig +short A "$domain")
if [ -z "$ips" ]; then
echo "ERROR: Failed to resolve $domain"
exit 1
@@ -116,9 +113,6 @@ 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 Normal file
View File

@@ -0,0 +1,34 @@
---
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. -->

View File

@@ -1,188 +0,0 @@
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

View File

@@ -1,17 +0,0 @@
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

View File

@@ -1,117 +0,0 @@
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

View File

@@ -1,132 +0,0 @@
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

View File

@@ -1,220 +0,0 @@
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

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -3,12 +3,6 @@ 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:
@@ -23,58 +17,9 @@ jobs:
uses: actions/checkout@v4
- name: Run Claude Code slash command
uses: anthropics/claude-code-base-action@beta
uses: anthropics/claude-code-action@beta
with:
prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
override_prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.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

@@ -1,28 +0,0 @@
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
}

View File

@@ -13,80 +13,16 @@ concurrency:
group: lock-threads
jobs:
lock-closed-issues:
lock-threads:
runs-on: ubuntu-latest
steps:
- name: Lock closed issues after 7 days of inactivity
uses: actions/github-script@v7
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
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}`);
issue-inactive-days: "7"
process-only: "issues"
log-output: true
issue-comment: >
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.

View File

@@ -1,40 +0,0 @@
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,196 +1,5 @@
# Changelog
## 1.0.123
- Bash permission rules now support output redirections when matching (e.g., `Bash(python:*)` matches `python script.py > output.txt`)
- Fixed thinking mode triggering on negation phrases like "don't think"
- Fixed rendering performance degradation during token streaming
- Added SlashCommand tool, which enables Claude to invoke your slash commands. https://docs.claude.com/en/docs/claude-code/slash-commands#SlashCommand-tool
- Enhanced BashTool environment snapshot logging
- Fixed a bug where resuming a conversation in headless mode would sometimes enable thinking unnecessarily
- Migrated --debug logging to a file, to enable easy tailing & filtering
## 1.0.120
- Fix input lag during typing, especially noticeable with large prompts
- Improved VSCode extension command registry and sessions dialog user experience
- Enhanced sessions dialog responsiveness and visual feedback
- Fixed IDE compatibility issue by removing worktree support check
- Fixed security vulnerability where Bash tool permission checks could be bypassed using prefix matching
## 1.0.119
- Fix Windows issue where process visually freezes on entering interactive mode
- Support dynamic headers for MCP servers via headersHelper configuration
- Fix thinking mode not working in headless sessions
- Fix slash commands now properly update allowed tools instead of replacing them
## 1.0.117
- Add Ctrl-R history search to recall previous commands like bash/zsh
- Fix input lag while typing, especially on Windows
- Add sed command to auto-allowed commands in acceptEdits mode
- Fix Windows PATH comparison to be case-insensitive for drive letters
- Add permissions management hint to /add-dir output
## 1.0.115
- Improve thinking mode display with enhanced visual effects
- Type /t to temporarily disable thinking mode in your prompt
- Improve path validation for glob and grep tools
- Show condensed output for post-tool hooks to reduce visual clutter
- Fix visual feedback when loading state completes
- Improve UI consistency for permission request dialogs
## 1.0.113
- Deprecated piped input in interactive mode
- Move Ctrl+R keybinding for toggling transcript to Ctrl+O
## 1.0.112
- Transcript mode (Ctrl+R): Added the model used to generate each assistant message
- Addressed issue where some Claude Max users were incorrectly recognized as Claude Pro users
- Hooks: Added systemMessage support for SessionEnd hooks
- Added `spinnerTipsEnabled` setting to disable spinner tips
- IDE: Various improvements and bug fixes
## 1.0.111
- /model now validates provided model names
- Fixed Bash tool crashes caused by malformed shell syntax parsing
## 1.0.110
- /terminal-setup command now supports WezTerm
- MCP: OAuth tokens now proactively refresh before expiration
- Fixed reliability issues with background Bash processes
## 1.0.109
- SDK: Added partial message streaming support via `--include-partial-messages` CLI flag
## 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"
- 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.claude.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
@@ -340,7 +149,7 @@
## 1.0.38
- Released hooks. Special thanks to community input in https://github.com/anthropics/claude-code/issues/712. Docs: https://docs.claude.com/en/docs/claude-code/hooks
- 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

View File

@@ -24,17 +24,15 @@ 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.
### How we use your data
See our [data usage policies](https://docs.anthropic.com/en/docs/claude-code/data-usage).
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).
### Privacy safeguards

View File

@@ -40,18 +40,14 @@ Write-Host "Using backend: $($Backend)"
# --- Prerequisite Check ---
Write-Host "Checking for required commands..."
try {
if (-not (Get-Command $Backend -ErrorAction SilentlyContinue)) {
throw "Required command '$($Backend)' not found."
}
Get-Command $Backend -ErrorAction Stop | Out-Null
Write-Host "- $($Backend) command found."
if (-not (Get-Command devcontainer -ErrorAction SilentlyContinue)) {
throw "Required command 'devcontainer' not 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. $($_.Exception.Message)"
Write-Error "Please ensure both '$Backend' and 'devcontainer' are installed and accessible in your system's PATH."
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
}

View File

@@ -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 {};

View File

@@ -1,213 +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)
MAX_ISSUE_NUMBER - Only process issues with numbers less than this value (default: 4050)`);
}
console.log("[DEBUG] GitHub token found");
const owner = "anthropics";
const repo = "claude-code";
const dryRun = process.env.DRY_RUN !== "false";
const maxIssueNumber = parseInt(process.env.MAX_ISSUE_NUMBER || "4050", 10);
const minIssueNumber = parseInt(process.env.MIN_ISSUE_NUMBER || "1", 10);
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
console.log(`[DEBUG] Dry run mode: ${dryRun}`);
console.log(`[DEBUG] Looking at issues between #${minIssueNumber} and #${maxIssueNumber}`);
console.log(`[DEBUG] Fetching issues between #${minIssueNumber} and #${maxIssueNumber}...`);
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}&sort=created&direction=desc`,
token
);
if (pageIssues.length === 0) break;
// Filter to only include issues within the specified range
const filteredIssues = pageIssues.filter(issue =>
issue.number >= minIssueNumber && issue.number < maxIssueNumber
);
allIssues.push(...filteredIssues);
// If the oldest issue in this page is still above our minimum, we need to continue
// but if the oldest issue is below our minimum, we can stop
const oldestIssueInPage = pageIssues[pageIssues.length - 1];
if (oldestIssueInPage && oldestIssueInPage.number >= maxIssueNumber) {
console.log(`[DEBUG] Oldest issue in page #${page} is #${oldestIssueInPage.number}, continuing...`);
} else if (oldestIssueInPage && oldestIssueInPage.number < minIssueNumber) {
console.log(`[DEBUG] Oldest issue in page #${page} is #${oldestIssueInPage.number}, below minimum, stopping`);
break;
} else if (filteredIssues.length === 0 && pageIssues.length > 0) {
console.log(`[DEBUG] No issues in page #${page} are in range #${minIssueNumber}-#${maxIssueNumber}, continuing...`);
}
page++;
// Safety limit to avoid infinite loops
if (page > 200) {
console.log("[DEBUG] Reached page limit, stopping pagination");
break;
}
}
console.log(`[DEBUG] Found ${allIssues.length} issues between #${minIssueNumber} and #${maxIssueNumber}`);
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 {};