Inspect GitHub Actions workflow runs, check status, analyze logs, debug failures, and identify root causes. Use when investigating CI/CD failures, checking workflow status, or debugging GitHub Actions issues.
/plugin marketplace add laurigates/claude-plugins/plugin install github-actions-plugin@lgates-claude-pluginsThis skill is limited to using the following tools:
Expert knowledge for inspecting, debugging, and troubleshooting GitHub Actions workflow runs using gh CLI and GitHub API.
Workflow Run Inspection
Log Analysis
Debugging Workflows
# List all workflow runs
gh run list
# List runs for specific workflow
gh run list --workflow=ci.yml
# List recent runs (limit results)
gh run list --limit 10
# Filter by status
gh run list --status=failure
gh run list --status=success
gh run list --status=in_progress
# Filter by branch
gh run list --branch=main
gh run list --branch=feature/new-api
# Filter by event
gh run list --event=push
gh run list --event=pull_request
gh run list --event=workflow_dispatch
# Combine filters
gh run list --workflow=ci.yml --status=failure --limit 5
# JSON output for parsing
gh run list --json databaseId,status,conclusion,name,createdAt,headBranch
# View specific run
gh run view <run-id>
# View with logs
gh run view <run-id> --log
# View failed logs only
gh run view <run-id> --log-failed
# View specific job
gh run view <run-id> --job=<job-id>
# View latest run
gh run view --workflow=ci.yml
# JSON output
gh run view <run-id> --json status,conclusion,jobs,startedAt,updatedAt
# Download logs for run
gh run download <run-id>
# Download to specific directory
gh run download <run-id> --dir ./logs
# View logs in terminal
gh run view <run-id> --log
# View failed step logs only
gh run view <run-id> --log-failed
# Extract specific job logs
gh api repos/:owner/:repo/actions/runs/<run-id>/logs | less
# Watch workflow progress
gh run watch <run-id>
# Watch with log output
gh run watch <run-id> --exit-status
# Watch latest run for workflow
gh run watch --workflow=ci.yml
# Rerun entire workflow
gh run rerun <run-id>
# Rerun only failed jobs
gh run rerun <run-id> --failed
# Rerun with debug logging
gh run rerun <run-id> --debug
# Cancel specific run
gh run cancel <run-id>
# Cancel all runs for a workflow
gh run list --workflow=ci.yml --status=in_progress --json databaseId \
| jq -r '.[].databaseId' \
| xargs -I {} gh run cancel {}
# Get last 10 failed runs
gh run list --status=failure --limit 10
# Get failures with details
gh run list --workflow=ci.yml --status=failure --limit 5 \
--json databaseId,conclusion,name,createdAt,headBranch,headSha
# Failed runs in the last day
gh run list --status=failure --json createdAt,name,databaseId \
| jq --arg date "$(date -u -v-1d +%Y-%m-%dT%H:%M:%SZ)" \
'.[] | select(.createdAt > $date)'
# Get runs for specific commit
gh run list --commit=<sha>
# Compare multiple runs
for run in $(gh run list --limit 5 --json databaseId -q '.[].databaseId'); do
echo "Run $run:"
gh run view $run --json conclusion,jobs
done
# Find tests that sometimes pass
gh run list --workflow=test.yml --limit 20 --json conclusion \
| jq 'group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})'
# View failed logs
gh run view <run-id> --log-failed
# Extract error lines
gh run view <run-id> --log-failed | grep -i "error\|failed\|exception"
# Extract stack traces
gh run view <run-id> --log-failed | grep -A 10 "Error:"
# Parse JSON for errors
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs[] | select(.conclusion == "failure") | {name, steps: [.steps[] | select(.conclusion == "failure")]}'
# Get run duration
gh run view <run-id> --json startedAt,completedAt,durationMs
# Compare run times
gh run list --workflow=ci.yml --limit 10 \
--json databaseId,createdAt,updatedAt,durationMs \
| jq '.[] | {id: .databaseId, duration_min: (.durationMs / 60000)}'
# Find slow jobs
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs | sort_by(.started_at) | .[] | {name, duration: (.completed_at - .started_at)}'
# Check current status
gh run list --status=in_progress
# Check for stuck workflows
gh run list --json databaseId,status,createdAt \
| jq --arg old "$(date -u -v-2H +%Y-%m-%dT%H:%M:%SZ)" \
'.[] | select(.status == "in_progress" and .createdAt < $old)'
# Summary of run statuses
gh run list --limit 50 --json conclusion \
| jq 'group_by(.conclusion) | map({conclusion: .[0].conclusion, count: length})'
# Step 1: Find the failing run
gh run list --workflow=ci.yml --status=failure --limit 1
# Step 2: View details
gh run view <run-id>
# Step 3: Get failed job logs
gh run view <run-id> --log-failed
# Step 4: Extract specific errors
gh run view <run-id> --log-failed | grep -E "FAIL|Error|Exception" -A 5
# Step 5: Check if rerun fixes it (flaky test)
gh run rerun <run-id>
# Get last successful run
SUCCESS=$(gh run list --workflow=ci.yml --status=success --limit 1 --json databaseId -q '.[0].databaseId')
# Get last failed run
FAILURE=$(gh run list --workflow=ci.yml --status=failure --limit 1 --json databaseId -q '.[0].databaseId')
# Compare commits
gh run view $SUCCESS --json headSha -q '.headSha'
gh run view $FAILURE --json headSha -q '.headSha'
# Compare job results
echo "Success:"
gh api repos/:owner/:repo/actions/runs/$SUCCESS/jobs | jq '.jobs[].conclusion'
echo "Failure:"
gh api repos/:owner/:repo/actions/runs/$FAILURE/jobs | jq '.jobs[].conclusion'
# Get last 20 runs of a workflow
gh run list --workflow=test.yml --limit 20 --json conclusion,createdAt,headSha
# Calculate failure rate
gh run list --workflow=test.yml --limit 50 --json conclusion \
| jq '[.[] | .conclusion] | group_by(.) | map({conclusion: .[0], count: length}) | map({conclusion, count, percent: ((.count / 50) * 100)})'
# Find which commits have failures
gh run list --workflow=test.yml --status=failure --limit 10 --json headSha,createdAt
# Watch from start
gh run watch $(gh run list --workflow=ci.yml --limit 1 --json databaseId -q '.[0].databaseId')
# Check job status during run
while true; do
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs[] | {name, status, conclusion}'
sleep 10
done
# Get step-by-step progress
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs[0].steps[] | {name, status, conclusion, number}'
# Extract test results
gh run view <run-id> --log | grep "FAIL\|PASS" | sort | uniq -c
# Find specific test failures
gh run view <run-id> --log | grep -A 10 "FAIL: test_"
# Get JUnit/TAP output
gh run download <run-id> --name test-results
# Parse test output
gh run view <run-id> --log | grep -E "✓|✗|PASS|FAIL" | wc -l
# Find dependency installation errors
gh run view <run-id> --log | grep -i "npm install\|pip install\|bundle install" -A 20
# Check for version conflicts
gh run view <run-id> --log | grep -i "conflict\|incompatible\|version"
# Compare dependency tree
gh run view <success-run-id> --log | grep "installed" > success-deps.txt
gh run view <failure-run-id> --log | grep "installed" > failure-deps.txt
diff success-deps.txt failure-deps.txt
# Check for auth errors
gh run view <run-id> --log | grep -i "authentication\|permission\|unauthorized\|403\|401"
# Symptoms: "Resource not accessible by integration", "403 Forbidden"
# Fix: Check workflow permissions, GITHUB_TOKEN scope, secrets configuration
# Find timeout errors
gh run view <run-id> --log | grep -i "timeout\|timed out"
# Check job duration
gh run view <run-id> --json jobs | jq '.jobs[] | {name, duration: (.completed_at - .started_at)}'
# Symptoms: "The job running on runner X has exceeded the maximum execution time"
# Fix: Optimize tests, increase timeout-minutes, split into parallel jobs
# Identify flaky tests by running multiple times
for i in {1..5}; do
gh workflow run test.yml
sleep 60
done
# Check failure consistency
gh run list --workflow=test.yml --limit 10 --json conclusion
# Symptoms: Same test passes/fails inconsistently
# Fix: Add delays, fix race conditions, mock external dependencies
# Find install errors
gh run view <run-id> --log | grep -B 5 -A 10 "error installing\|failed to install"
# Symptoms: "Could not find package", "Version conflict", "Network error"
# Fix: Lock versions, use cache, check package registry status
# Check environment differences
gh run view <run-id> --log | grep "runner\|environment\|os\|platform"
# Symptoms: "Command not found", "Module not found", "Path does not exist"
# Fix: Verify setup steps, check runner version, install missing tools
# Check for memory/disk issues
gh run view <run-id> --log | grep -i "out of memory\|disk space\|killed"
# Symptoms: "The runner has run out of disk space", "Process killed"
# Fix: Clean up artifacts, reduce test data, increase runner size
# Get all failed jobs with step details
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs[] | select(.conclusion == "failure") | {
job: .name,
failed_steps: [.steps[] | select(.conclusion == "failure") | .name]
}'
# Create failure summary report
gh run list --workflow=ci.yml --limit 20 --json conclusion,createdAt,headBranch \
| jq 'group_by(.headBranch) | map({
branch: .[0].headBranch,
total: length,
failures: [.[] | select(.conclusion == "failure")] | length,
success_rate: (([.[] | select(.conclusion == "success")] | length) / length * 100)
})'
# Extract error messages from API
gh api repos/:owner/:repo/actions/runs/<run-id>/jobs \
| jq '.jobs[].steps[] | select(.conclusion == "failure") | {
name,
number,
conclusion,
completed_at
}'
Efficient Debugging
gh run list to identify problematic runs--log-failed to focus on failuresPerformance
--limit to reduce API callsSystematic Investigation
Automation
# Check authentication
gh auth status
# Re-authenticate
gh auth login
# Check permissions
gh auth refresh -h github.com -s repo,workflow
# Check rate limit
gh api rate_limit
# Use personal access token
export GITHUB_TOKEN=<your-token>
# Reduce API calls with caching
gh run list --limit 100 --json databaseId,conclusion > cache.json
# Download logs instead of viewing
gh run download <run-id>
# Filter logs immediately
gh run view <run-id> --log | grep "Error" > errors.txt
# View specific sections
gh run view <run-id> --log | less +/Error
# Check workflow file exists
gh workflow list
# Verify workflow is enabled
gh workflow view ci.yml
# Check for pending runs
gh run list --status=queued
gh run list --status=waiting
gh run list - List workflow runsgh run view <id> - View run detailsgh run watch <id> - Watch run progressgh run download <id> - Download logs/artifactsgh run rerun <id> - Rerun workflowgh run cancel <id> - Cancel running workflow--workflow=<name> - Specific workflow--status=<status> - Filter by status (in_progress, completed, queued, waiting)--conclusion=<conclusion> - Filter by conclusion (success, failure, cancelled, skipped)--branch=<branch> - Specific branch--event=<event> - Specific trigger event--limit=<n> - Limit results--json <fields> - JSON outputqueued - Waiting to startin_progress - Currently runningcompleted - Finished (check conclusion)waiting - Waiting for approvalsuccess - All jobs succeededfailure - At least one job failedcancelled - Manually cancelledskipped - Skipped (conditional)neutral - Neutral resulttimed_out - Exceeded time limitThis skill complements:
Use together for complete GitHub Actions lifecycle:
This skill should be used when the user asks about libraries, frameworks, API references, or needs code examples. Activates for setup questions, code generation involving libraries, or mentions of specific frameworks like React, Vue, Next.js, Prisma, Supabase, etc.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.