GitHub Workflows — CI/CD & Automated Operations
CI/CD & Automated Operations
15 GitHub Actions workflows handling issue triage, duplicate detection, lifecycle management, and Claude Code mentions across the repository.
⚙️ GitHub Actions🤖 AI Triage🕑 Scheduled🔔 Event-Driven
📚 What is this & why does it exist?
The .github/workflows directory defines the automated operations layer for the Claude Code repository. These 15 YAML workflow files orchestrate everything from AI-powered issue triage (using Claude Opus 4-6 with a 5-minute timeout) to twice-daily stale issue sweeps, duplicate detection pipelines, and permission checks. Together, they form a self-managing issue lifecycle system that scales across thousands of GitHub issues without human bottlenecks.
💡 Real-world analogy
Imagine a hospital’s operations center. When a patient (issue) arrives, the triage nurse (claude-issue-triage.yml) assesses severity and assigns them to the right department. The scheduling system (sweep.yml) runs twice daily to check on patients who haven’t been seen. The records department (log-issue-events.yml) keeps a log of every interaction. And the security desk (non-write-users-check.yml) verifies that only authorized staff can perform sensitive operations. Each workflow is a specialist doing one job well, but they coordinate seamlessly.
Architecture
flowchart TB
subgraph Events["GitHub Event Sources"]
ISSUE_OPEN["📄 Issue Opened"]
ISSUE_LABEL["🏷️ Issue Labeled"]
PR_COMMENT["💬 PR/Issue Comment"]
CRON_AM["⏰ Cron 10am UTC"]
CRON_PM["⏰ Cron 10pm UTC"]
DISPATCH["📤 Repository Dispatch"]
end
subgraph Core["Core Workflows"]
TRIAGE["claude-issue-triage.yml\n(Opus 4-6, 5min)"]
CLAUDE["claude.yml\n(@claude mentions)"]
SWEEP_WF["sweep.yml\n(Twice daily)"]
end
subgraph Lifecycle["Lifecycle Workflows"]
DEDUPE["claude-dedupe-issues.yml"]
AUTOCLOSE["auto-close-duplicates.yml"]
LIFECYCLE_C["issue-lifecycle-comment.yml"]
LOCK["lock-closed-issues.yml"]
REMOVE_LBL["remove-autoclose-label.yml"]
end
subgraph Support["Support Workflows"]
OPENED_DISP["issue-opened-dispatch.yml"]
LOG_EVENTS["log-issue-events.yml"]
PERM_CHECK["non-write-users-check.yml"]
BACKFILL_WF["backfill-duplicate-comments.yml"]
end
subgraph Scripts["scripts/"]
SWEEP_TS["sweep.ts"]
CLOSE_TS["auto-close-duplicates.ts"]
COMMENT_SH["comment-on-duplicates.sh"]
end
ISSUE_OPEN --> TRIAGE
ISSUE_OPEN --> OPENED_DISP
ISSUE_OPEN --> DEDUPE
ISSUE_LABEL --> LIFECYCLE_C
ISSUE_LABEL --> AUTOCLOSE
PR_COMMENT --> CLAUDE
CRON_AM --> SWEEP_WF
CRON_PM --> SWEEP_WF
DISPATCH --> BACKFILL_WF
SWEEP_WF --> SWEEP_TS
AUTOCLOSE --> CLOSE_TS
DEDUPE --> COMMENT_SH
style TRIAGE fill:#58a6ff,stroke:#58a6ff,color:#fff
style CLAUDE fill:#3fb950,stroke:#3fb950,color:#fff
style SWEEP_WF fill:#d29922,stroke:#d29922,color:#fff
Event Flow
sequenceDiagram
participant Dev as Developer
participant GH as GitHub
participant Triage as claude-issue-triage
participant Dedupe as claude-dedupe-issues
participant Sweep as sweep.yml
participant Lock as lock-closed-issues
participant Log as log-issue-events
Dev->>GH: Opens new issue
GH->>Log: Log issue_opened event
GH->>Triage: Trigger triage (Opus 4-6)
Triage->>GH: Apply labels + priority
GH->>Dedupe: Check for duplicates
Dedupe->>GH: Post duplicate matches (if any)
Note over Sweep: Scheduled: 10am + 10pm UTC
Sweep->>GH: Query all open issues
GH-->>Sweep: Issue list with activity dates
Sweep->>GH: Apply stale/autoclose labels
Note over GH: Issue closed (manual or auto)
GH->>Lock: Lock after cooling period
GH->>Log: Log issue_closed event
Workflows Reference
🤖 claude.ymlAI
Responds to @claude mentions on issues and pull requests. Uses Sonnet 4.5 for fast, contextual responses.
- Trigger:
issue_comment,pull_request_review_comment - Model: Claude Sonnet 4.5
- Filters: only activates on @claude mention
🔍 claude-issue-triage.ymlAI
Auto-triages newly opened issues using Claude Opus 4-6. Applies priority labels, categorization, and initial assessment with a 5-minute timeout.
- Trigger:
issues.opened - Model: Claude Opus 4-6
- Timeout: 5 minutes
⏰ sweep.yml
Twice-daily lifecycle sweep running at 10am and 10pm UTC. Invokes sweep.ts to mark stale issues and close expired ones.
- Trigger:
schedule(cron) - Schedule:
0 10,22 * * * - Script:
scripts/sweep.ts
🔎 claude-dedupe-issues.yml
Detects duplicate issues when new issues are opened. Uses embedding similarity to find matches and posts formatted comments.
- Trigger:
issues.opened,workflow_dispatch - Script:
comment-on-duplicates.sh
🗑️ auto-close-duplicates.yml
Closes issues confirmed as duplicates after a 3-day grace period. Runs the TypeScript closer script.
- Trigger:
schedule,workflow_dispatch - Script:
auto-close-duplicates.ts
💬 issue-lifecycle-comment.yml
Posts warning comments when lifecycle labels (stale, needs-info, etc.) are applied to issues.
- Trigger:
issues.labeled - Script:
lifecycle-comment.ts
🔒 lock-closed-issues.yml
Locks closed issues after a cooling-off period to prevent drive-by comments on resolved issues.
- Trigger:
schedule - Locks conversation thread
🏷️ remove-autoclose-label.yml
Removes the autoclose label when an issue receives new activity, resetting the closure timer.
- Trigger:
issue_comment - Checks comment author vs. bot
📤 issue-opened-dispatch.yml
Dispatches a repository_dispatch event when issues are opened, enabling downstream workflow chaining.
- Trigger:
issues.opened - Emits:
issue-openeddispatch
📋 log-issue-events.yml
Logs all issue lifecycle events for auditing and debugging the automation pipeline.
- Trigger: multiple issue events
- Outputs: structured event log
🛡️ non-write-users-check.yml
Verifies that workflow triggers come from users with appropriate repository permissions.
- Trigger:
pull_request_target - Checks: write/admin permission
🔄 backfill-duplicate-comments.yml
Retroactively processes older issues through the duplicate detection pipeline.
- Trigger:
workflow_dispatch - Script:
backfill-duplicate-comments.ts
Trigger Matrix
| Workflow | Trigger Type | Trigger Detail | Invokes Script |
|---|---|---|---|
claude.yml | Event | issue_comment with @claude | — |
claude-issue-triage.yml | Event | issues.opened | — |
sweep.yml | Cron | 0 10,22 * * * | sweep.ts |
claude-dedupe-issues.yml | Event | issues.opened | comment-on-duplicates.sh |
auto-close-duplicates.yml | Cron + Dispatch | Scheduled | auto-close-duplicates.ts |
issue-lifecycle-comment.yml | Event | issues.labeled | lifecycle-comment.ts |
lock-closed-issues.yml | Cron | Scheduled | — |
issue-opened-dispatch.yml | Event | issues.opened | — |
log-issue-events.yml | Event | Multiple issue events | — |
non-write-users-check.yml | Event | pull_request_target | — |
remove-autoclose-label.yml | Event | issue_comment | — |
backfill-duplicate-comments.yml | Dispatch | workflow_dispatch | backfill-duplicate-comments.ts |
Interactions
| Module | Interface | Data Exchanged |
|---|---|---|
| scripts/ | Direct invocation | TypeScript/shell scripts called with npx tsx or bash |
| Claude Code AI | API calls | Issue triage results, @claude responses via Anthropic API |
| GitHub API | REST / GraphQL | Issue CRUD, label management, comment posting |
| Repository secrets | Environment variables | GITHUB_TOKEN, ANTHROPIC_API_KEY, CLAUDE_CODE_* |
Directory Map
Source tree for GitHub Workflows
.github/workflows/
├── claude.yml ← @claude mention handler (Sonnet 4.5)
├── claude-issue-triage.yml ← AI issue triage (Opus 4-6, 5min)
├── sweep.yml ← Twice-daily lifecycle sweep
├── claude-dedupe-issues.yml ← Duplicate detection pipeline
├── auto-close-duplicates.yml ← Close confirmed duplicates (3d)
├── issue-opened-dispatch.yml ← Event dispatch for new issues
├── issue-lifecycle-comment.yml ← Post lifecycle warning comments
├── lock-closed-issues.yml ← Lock old closed issues
├── log-issue-events.yml ← Event logging / audit trail
├── non-write-users-check.yml ← Permission verification
├── remove-autoclose-label.yml ← Label cleanup on activity
└── backfill-duplicate-comments.yml ← Backfill duplicate comments