Skip to content

Claude Auto Tasks

Claude Auto Tasks #273

# Autonomous Claude Code Task Processing
#
# This workflow runs daily at 5am EST to pick up Linear issues labeled for Claude
# and process them autonomously. It queries Linear for issues, generates a matrix,
# and dispatches parallel jobs to process each task.
#
# SETUP:
# 1. Create a "claude" label in your Linear team (or configure a different label)
# 2. Add LINEAR_API_KEY secret to your repository
# 3. Ensure ANTHROPIC_API_KEY secret is configured
# 4. Add issues with the "claude" label in "Backlog" or "Todo" status
#
# USAGE:
# - Automatic: Runs daily at 5am EST
# - Manual: Use workflow_dispatch with optional inputs
#
# LINEAR REQUIREMENTS:
# - Issues must have the configured label (default: "claude")
# - Issues must be in "Backlog" or "Todo" status
# - Issues are sorted by priority (Urgent > High > Normal > Low > No Priority)
name: Claude Auto Tasks
on:
# Run daily at 5am EST (10:00 UTC)
schedule:
- cron: "0 10 * * *"
# Manual trigger with inputs
workflow_dispatch:
inputs:
linear_team:
description: "Linear team name to query"
required: false
type: string
default: "Developer AI"
linear_label:
description: "Label to filter issues by"
required: false
type: string
default: "claude"
max_issues:
description: "Maximum number of issues to process"
required: false
type: string
default: "3"
model:
description: "Claude model to use"
required: false
type: choice
options:
- "claude-sonnet-5"
- "claude-opus-5"
- "claude-haiku-4-5"
default: "claude-opus-5"
target_branch:
description: "Branch to create PRs against"
required: false
type: string
default: "next"
linear_task_utils_tag:
description: "npm tag for @uniswap/ai-toolkit-linear-task-utils"
required: false
type: choice
options:
- "latest"
- "next"
default: "next"
debug_mode:
description: "Enable full Claude Code output for debugging"
required: false
type: boolean
default: true
# Prevent concurrent runs
permissions: {}
concurrency:
group: claude-auto-tasks
cancel-in-progress: false
jobs:
# Job 1: Query Linear and prepare the task matrix
prepare:
permissions:
contents: read
uses: ./.github/workflows/_claude-task-prepare.yml
with:
linear_team: ${{ inputs.linear_team || 'Developer AI' }}
linear_label: ${{ inputs.linear_label || 'claude' }}
max_issues: ${{ inputs.max_issues || '3' }}
linear_task_utils_tag: ${{ inputs.linear_task_utils_tag || 'next' }}
target_branch: ${{ inputs.target_branch || 'next' }}
secrets:
LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
# Job 2: Process each task in parallel
process-task:
needs: prepare
if: needs.prepare.outputs.has_tasks == 'true'
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
actions: read
strategy:
fail-fast: false
max-parallel: 3
matrix: ${{ fromJson(needs.prepare.outputs.matrix_json) }}
uses: ./.github/workflows/_claude-task-worker.yml
with:
issue_id: ${{ matrix.issue_id }}
issue_identifier: ${{ matrix.issue_identifier }}
issue_title: ${{ matrix.issue_title }}
issue_description: ${{ matrix.issue_description }}
issue_url: ${{ matrix.issue_url }}
branch_name: ${{ matrix.branch_name }}
target_branch: ${{ inputs.target_branch || 'next' }}
model: ${{ inputs.model || 'claude-opus-5' }}
timeout_minutes: 60
linear_task_utils_tag: ${{ needs.prepare.outputs.linear_task_utils_tag }}
debug_mode: ${{ inputs.debug_mode != '' && inputs.debug_mode || true }}
secrets:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }}
# Job 3: Summary (always runs)
summary:
needs: [prepare, process-task]
if: always()
runs-on: ubuntu-latest
permissions: {}
steps:
# Security scanning
- name: Security scanning
uses: bullfrogsec/bullfrog@1831f79cce8ad602eef14d2163873f27081ebfb3 # v0.8.4
with:
egress-policy: audit
- name: Generate final summary
env:
RUN_NUMBER: ${{ github.run_number }}
SERVER_URL: ${{ github.server_url }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
HAS_TASKS: ${{ needs.prepare.outputs.has_tasks }}
QUERY_RESULT: ${{ needs.prepare.outputs.result }}
TASK_RESULT: ${{ needs.process-task.result }}
INPUT_LINEAR_TEAM: ${{ inputs.linear_team }}
INPUT_LINEAR_LABEL: ${{ inputs.linear_label }}
run: |
echo "# Claude Auto Tasks Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Workflow Run:** [#${RUN_NUMBER}](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$HAS_TASKS" == "true" ]; then
TASK_COUNT=$(echo "$QUERY_RESULT" | jq -r '.count')
echo "**Tasks Found:** $TASK_COUNT" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
case "$TASK_RESULT" in
"success")
echo "**Result:** All tasks completed successfully" >> $GITHUB_STEP_SUMMARY
;;
"failure")
echo "**Result:** Some tasks failed - check individual job logs" >> $GITHUB_STEP_SUMMARY
;;
"cancelled")
echo "**Result:** Workflow was cancelled" >> $GITHUB_STEP_SUMMARY
;;
*)
echo "**Result:** $TASK_RESULT" >> $GITHUB_STEP_SUMMARY
;;
esac
else
echo "**Result:** No tasks found matching criteria" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "To add tasks for Claude to process:" >> $GITHUB_STEP_SUMMARY
echo "1. Create issues in the **$INPUT_LINEAR_TEAM** team" >> $GITHUB_STEP_SUMMARY
echo "2. Add the **$INPUT_LINEAR_LABEL** label" >> $GITHUB_STEP_SUMMARY
echo "3. Set status to **Backlog** or **Todo**" >> $GITHUB_STEP_SUMMARY
fi