spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

Merge pull request #5116 from anthropics/boris/fwbeBrowse files
Add auto-close functionality for duplicate issues
Boris Cherny authored on Aug 6, 2025 · GitHub committed on Aug 6, 2025 parents a9f1fef + 611956d · commit 369bd9b6d7e7
3 changed files+99 -0compared with a9f1fef
A.claude/commands/commit-push-pr.md
M.claude/commands/dedupe.md
A.github/workflows/auto-close-duplicates.yml
@@ -1,0 +1,19 @@
1+---
2+allowed-tools: Bash(git checkout --branch:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*)
3+description: Commit, push, and open a PR
4+---
5+
6+## Context
7+
8+- Current git status: !`git status`
9+- Current git diff (staged and unstaged changes): !`git diff HEAD`
10+- Current branch: !`git branch --show-current`
11+
12+## Your task
13+
14+Based on the above changes:
15+1. Create a new branch if on main
16+2. Create a single commit with an appropriate message
17+3. Push the branch to origin
18+4. Create a pull request using `gh pr create`
19+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.
@@ -30,6 +30,8 @@
3030
3131 If your issue is a duplicate, please close it and 👍 the existing issue instead.
3232
33+<sub>This issue will be automatically closed as a duplicate in 3 days if there are no additional comments. To prevent auto-closure, please 👎 this comment.</sub>
34+
3335 🤖 Generated with [Claude Code](https://claude.ai/code)
3436
3537 ---
@@ -1,0 +1,78 @@
1+name: Auto-close duplicate issues (DRY RUN)
2+description: Dry run - logs issues that would be auto-closed as duplicates after 3 days if no response
3+on:
4+ schedule:
5+ - cron: '0 9 * * *'
6+
7+jobs:
8+ auto-close-duplicates:
9+ runs-on: ubuntu-latest
10+ timeout-minutes: 10
11+ permissions:
12+ contents: read
13+ issues: write
14+
15+ steps:
16+ - name: Auto-close duplicate issues
17+ uses: actions/github-script@v7
18+ with:
19+ script: |
20+ const threeDaysAgo = new Date();
21+ threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
22+
23+ // Get all open issues
24+ const { data: issues } = await github.rest.issues.listForRepo({
25+ owner: context.repo.owner,
26+ repo: context.repo.repo,
27+ state: 'open',
28+ per_page: 100
29+ });
30+
31+ for (const issue of issues) {
32+ // Get comments for this issue
33+ const { data: comments } = await github.rest.issues.listComments({
34+ owner: context.repo.owner,
35+ repo: context.repo.repo,
36+ issue_number: issue.number
37+ });
38+
39+ // Find duplicate comments (look for "Found 1 possible duplicate" or "Found X possible duplicate")
40+ const dupeComments = comments.filter(comment =>
41+ comment.body.includes('Found') &&
42+ comment.body.includes('possible duplicate') &&
43+ comment.user.type === 'Bot'
44+ );
45+
46+ if (dupeComments.length === 0) continue;
47+
48+ // Get the most recent duplicate comment
49+ const lastDupeComment = dupeComments[dupeComments.length - 1];
50+ const dupeCommentDate = new Date(lastDupeComment.created_at);
51+
52+ // Check if the duplicate comment is 3+ days old
53+ if (dupeCommentDate > threeDaysAgo) continue;
54+
55+ // Check if there are any comments after the duplicate comment
56+ const commentsAfterDupe = comments.filter(comment =>
57+ new Date(comment.created_at) > dupeCommentDate
58+ );
59+
60+ if (commentsAfterDupe.length > 0) continue;
61+
62+ // Check if issue author reacted with thumbs down to the duplicate comment
63+ const { data: reactions } = await github.rest.reactions.listForIssueComment({
64+ owner: context.repo.owner,
65+ repo: context.repo.repo,
66+ comment_id: lastDupeComment.id
67+ });
68+
69+ const authorThumbsDown = reactions.some(reaction =>
70+ reaction.user.id === issue.user.id && reaction.content === '-1'
71+ );
72+
73+ if (authorThumbsDown) continue;
74+
75+ // DRY RUN: Log the issue that would be auto-closed
76+ const issueUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/issues/${issue.number}`;
77+ console.log(`[DRY RUN] Would auto-close issue #${issue.number} as duplicate: ${issueUrl}`);
78+ }