
Finops Workflows
- 59 installs
- 49 repo stars
- Updated August 4, 2026
- laurigates/claude-plugins
Helps with automation & workflows tasks.
About
finops-workflows is a Claude Code skill for automation & workflows. It helps solo builders move faster with AI-assisted development.
- finops-workflows
- Automation & Workflows
- AI-coding skill
Finops Workflows by the numbers
- 59 all-time installs (skills.sh)
- Ranked #1,005 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/laurigates/claude-plugins --skill finops-workflowsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 59 |
|---|---|
| repo stars | ★ 49 |
| Last updated | August 4, 2026 |
| Repository | laurigates/claude-plugins ↗ |
What it does
Helps with automation & workflows tasks.
Files
/finops:workflows
Analyze GitHub Actions workflow runs for a repository - frequency, duration, success rates, and efficiency metrics.
When to Use
| Scenario | Use this skill | Alternative |
|---|---|---|
| Analyze workflow run frequency and duration | /finops:workflows | - |
| Investigate high failure rates | /finops:workflows | - |
| Understand trigger type distribution | /finops:workflows | - |
| Org-wide workflow analysis | /finops:workflows org <name> | - |
| Quick overall health snapshot | /finops:overview | Use overview for high-level summary |
| Fix workflow configuration issues | /finops:waste | Use waste for actionable config fixes |
| Compare workflow metrics across repos | /finops:compare | Use compare for multi-repo view |
Context
- Current repo URL: !
git remote get-url origin
Parameters
| Parameter | Description | Default |
|---|---|---|
repo | Repository in owner/name format | Current repository |
--created | Date range filter (e.g., >=2026-03-01) | None (last 100 runs) |
org <name> | Org-wide analysis (use instead of repo) | - |
Execution
Per-repo analysis (default)
bash "${SKILL_DIR}/scripts/workflow-runs.sh" $ARGSOrg-wide analysis
When the user requests org-wide analysis, use the org script:
bash "${SKILL_DIR}/scripts/workflow-runs-org.sh" $ARGSOutput Format
Analyzing workflows for: org/repo
=== Active Workflows ===
CI (id: 12345)
Deploy (id: 12346)
CodeQL (id: 12347)
=== Run Summary ===
CI:
Total: 156 | Success: 140 | Failure: 10 | Cancelled: 4 | Skipped: 2
Success rate: 89%
Deploy:
Total: 45 | Success: 44 | Failure: 1 | Cancelled: 0 | Skipped: 0
Success rate: 97%
=== Duration Analysis ===
CI:
Runs: 50 | Avg: 4m32s | Max: 12m15s | Total: 226min
Deploy:
Runs: 20 | Avg: 2m10s | Max: 3m45s | Total: 43min
=== Trigger Types ===
push: 89 runs
pull_request: 67 runs
schedule: 30 runs
workflow_dispatch: 5 runs
=== Recent Failures (last 10) ===
#234 CI - 2025-01-28 - https://github.com/org/repo/actions/runs/...
#231 CI - 2025-01-27 - https://github.com/org/repo/actions/runs/...
=== High Frequency Workflows ===
CI: 156 runs (~5.2/day) - consider path filtersAgentic Optimizations
| Context | Command |
|---|---|
| Workflow list (JSON) | gh workflow list --json name,id,state |
| Recent runs (compact) | gh run list --workflow <name> --limit 20 --json status,conclusion,createdAt |
| Failed runs only | gh run list --status failure --limit 10 --json name,createdAt,url |
| Run timing (JSON) | `gh api "/repos/{owner}/{repo}/actions/runs?per_page=50" --jq '.workflow_runs[] |
| Compact per-repo analysis | bash "${SKILL_DIR}/scripts/workflow-runs.sh" $ARGS |
| Org-wide analysis | bash "${SKILL_DIR}/scripts/workflow-runs-org.sh" $ARGS |
Post-actions
Based on findings, suggest:
- High failure rate -> Investigate recent failures, check logs with
gh run view --log-failed - High frequency -> Review trigger conditions, add path filters
- Long durations -> Review caching, parallelization, step optimization
- Many skipped -> Run
/finops:wastefor detailed analysis
#!/usr/bin/env bash
# Org-Wide Workflow Runs Analysis
# Aggregates workflow run data across all repositories in an organization.
# Usage: bash workflow-runs-org.sh [org] [--created RANGE] [--limit N]
#
# Args:
# org GitHub organization name (default: current repo's org)
# --created Date range filter (e.g., ">=2026-03-01", "2026-02-01..2026-03-01")
# --limit Max repos to scan (default: 100)
#
# Output: Per-repo run counts, org-wide totals, top consumers, failure hotspots.
# shellcheck disable=SC2016 # jq expressions use $ for variable references, not shell expansion
set -euo pipefail
ORG=""
CREATED=""
LIMIT=100
while [[ $# -gt 0 ]]; do
case $1 in
--created)
CREATED="$2"
shift 2
;;
--limit)
LIMIT="$2"
shift 2
;;
*)
ORG="$1"
shift
;;
esac
done
ORG="${ORG:-$(gh repo view --json owner --jq '.owner.login')}"
echo "=== Org-Wide Workflow Analysis: $ORG ==="
QUERY="per_page=100"
if [[ -n "$CREATED" ]]; then
QUERY="${QUERY}&created=${CREATED}"
echo "Date filter: $CREATED"
fi
echo ""
# Collect repos
REPOS=$(gh repo list "$ORG" --json nameWithOwner --limit "$LIMIT" --jq '.[].nameWithOwner')
REPO_COUNT=$(echo "$REPOS" | wc -l | tr -d ' ')
echo "Scanning $REPO_COUNT repositories..."
echo ""
# Temporary file for aggregation
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
ORG_TOTAL=0
ORG_SUCCESS=0
ORG_FAILURE=0
ORG_SKIPPED=0
ORG_CANCELLED=0
echo "=== Per-Repository Summary ==="
printf "%-45s %6s %6s %6s %6s %6s\n" "Repository" "Total" "OK" "Fail" "Skip" "Cancel"
printf "%-45s %6s %6s %6s %6s %6s\n" "---------" "-----" "----" "----" "----" "------"
while IFS= read -r repo; do
result=$(gh api "/repos/$repo/actions/runs?${QUERY}" 2>/dev/null || echo '{"workflow_runs":[]}')
stats=$(echo "$result" | jq -r '
.workflow_runs |
{
total: length,
success: ([.[] | select(.conclusion == "success")] | length),
failure: ([.[] | select(.conclusion == "failure")] | length),
skipped: ([.[] | select(.conclusion == "skipped")] | length),
cancelled: ([.[] | select(.conclusion == "cancelled")] | length)
} |
"\(.total)\t\(.success)\t\(.failure)\t\(.skipped)\t\(.cancelled)"
')
IFS=$'\t' read -r total success failure skipped cancelled <<< "$stats"
total=${total:-0}
success=${success:-0}
failure=${failure:-0}
skipped=${skipped:-0}
cancelled=${cancelled:-0}
if [[ "$total" -gt 0 ]]; then
short_name="${repo#*/}"
printf "%-45s %6d %6d %6d %6d %6d\n" "$short_name" "$total" "$success" "$failure" "$skipped" "$cancelled"
echo "$repo $total $success $failure $skipped $cancelled" >> "$TMPFILE"
fi
ORG_TOTAL=$((ORG_TOTAL + total))
ORG_SUCCESS=$((ORG_SUCCESS + success))
ORG_FAILURE=$((ORG_FAILURE + failure))
ORG_SKIPPED=$((ORG_SKIPPED + skipped))
ORG_CANCELLED=$((ORG_CANCELLED + cancelled))
done <<< "$REPOS"
echo ""
echo "=== Org-Wide Totals ==="
echo " Total runs: $ORG_TOTAL"
echo " Success: $ORG_SUCCESS"
echo " Failure: $ORG_FAILURE"
echo " Skipped: $ORG_SKIPPED"
echo " Cancelled: $ORG_CANCELLED"
if [[ "$ORG_TOTAL" -gt 0 ]]; then
SUCCESS_RATE=$((ORG_SUCCESS * 100 / ORG_TOTAL))
WASTE_RATE=$(((ORG_SKIPPED + ORG_CANCELLED) * 100 / ORG_TOTAL))
echo " Success rate: ${SUCCESS_RATE}%"
echo " Waste rate (skipped+cancelled): ${WASTE_RATE}%"
fi
echo ""
echo "=== Top 10 by Run Count ==="
# shellcheck disable=SC2034 # Positional fields — not all used in every loop
sort -k2 -n -r "$TMPFILE" | head -10 | while read -r repo total success failure skipped cancelled; do
short="${repo#*/}"
printf " %-40s %d runs\n" "$short" "$total"
done
echo ""
echo "=== Failure Hotspots ==="
# shellcheck disable=SC2034 # Positional fields — not all used in every loop
sort -k4 -n -r "$TMPFILE" | head -10 | while read -r repo total success failure skipped cancelled; do
if [[ "$failure" -gt 0 ]]; then
short="${repo#*/}"
rate=$((failure * 100 / total))
printf " %-40s %d failures (%d%%)\n" "$short" "$failure" "$rate"
fi
done
echo ""
echo "=== Waste Hotspots (skipped + cancelled) ==="
# shellcheck disable=SC2034 # Positional fields — not all used in every loop
while read -r repo total success failure skipped cancelled; do
waste=$((skipped + cancelled))
if [[ "$waste" -gt 5 ]]; then
short="${repo#*/}"
rate=$((waste * 100 / total))
printf " %-40s %d wasted (%d%%)\n" "$short" "$waste" "$rate"
fi
done < <(sort -k2 -n -r "$TMPFILE")
#!/usr/bin/env bash
# Workflow Runs Analysis
# Analyzes GitHub Actions workflow runs for a repository.
# Usage: bash workflow-runs.sh [repo] [--created RANGE]
#
# Args:
# repo Repository in owner/name format (default: current repo)
# --created Date range filter for gh api (e.g., ">=2026-03-01", "2026-02-01..2026-03-01")
#
# Output: Active workflows, run summary, duration analysis, triggers, failures,
# and high-frequency detection.
# shellcheck disable=SC2016 # jq expressions use $ for variable references, not shell expansion
set -euo pipefail
REPO=""
CREATED=""
while [[ $# -gt 0 ]]; do
case $1 in
--created)
CREATED="$2"
shift 2
;;
*)
REPO="$1"
shift
;;
esac
done
REPO="${REPO:-$(gh repo view --json nameWithOwner --jq '.nameWithOwner')}"
echo "Analyzing workflows for: $REPO"
# Build query params
QUERY="per_page=100"
if [[ -n "$CREATED" ]]; then
QUERY="${QUERY}&created=${CREATED}"
echo "Date filter: $CREATED"
fi
echo ""
echo "=== Active Workflows ==="
gh workflow list --repo "$REPO" --json id,name,state \
--jq '.[] | select(.state == "active") | " \(.name) (id: \(.id))"'
echo ""
echo "=== Run Summary ==="
gh api "/repos/$REPO/actions/runs?${QUERY}" \
--jq '.workflow_runs | group_by(.name) |
map({
name: .[0].name,
total: length,
success: ([.[] | select(.conclusion == "success")] | length),
failure: ([.[] | select(.conclusion == "failure")] | length),
cancelled: ([.[] | select(.conclusion == "cancelled")] | length),
skipped: ([.[] | select(.conclusion == "skipped")] | length)
}) |
sort_by(-.total)[] |
"\(.name):\n Total: \(.total) | Success: \(.success) | Failure: \(.failure) | Cancelled: \(.cancelled) | Skipped: \(.skipped)\n Success rate: \(if .total > 0 then ((.success / .total * 100) | floor) else 0 end)%"'
echo ""
echo "=== Duration Analysis ==="
DURATION_QUERY="per_page=50&status=completed"
if [[ -n "$CREATED" ]]; then
DURATION_QUERY="${DURATION_QUERY}&created=${CREATED}"
fi
gh api "/repos/$REPO/actions/runs?${DURATION_QUERY}" \
--jq '.workflow_runs | group_by(.name) |
map({
name: .[0].name,
count: length,
durations: [.[] | (.run_started_at as $start | .updated_at as $end |
(($end | fromdateiso8601) - ($start | fromdateiso8601)))],
}) |
map({
name: .name,
count: .count,
avg_seconds: (if .count > 0 then (.durations | add / length | floor) else 0 end),
max_seconds: (if .count > 0 then (.durations | max) else 0 end),
total_seconds: (.durations | add)
}) |
sort_by(-.total_seconds)[] |
"\(.name):\n Runs: \(.count) | Avg: \(.avg_seconds / 60 | floor)m\(.avg_seconds % 60)s | Max: \(.max_seconds / 60 | floor)m\(.max_seconds % 60)s | Total: \(.total_seconds / 60 | floor)min"'
echo ""
echo "=== Trigger Types ==="
gh api "/repos/$REPO/actions/runs?${QUERY}" \
--jq '.workflow_runs | group_by(.event) |
map({event: .[0].event, count: length}) |
sort_by(-.count)[] |
" \(.event): \(.count) runs"'
echo ""
echo "=== Recent Failures (last 10) ==="
FAIL_QUERY="per_page=100&status=completed"
if [[ -n "$CREATED" ]]; then
FAIL_QUERY="${FAIL_QUERY}&created=${CREATED}"
fi
gh api "/repos/$REPO/actions/runs?${FAIL_QUERY}" \
--jq '[.workflow_runs[] | select(.conclusion == "failure")] | .[0:10][] |
" #\(.run_number) \(.name) - \(.created_at | split("T")[0]) - \(.html_url)"'
echo ""
echo "=== High Frequency Workflows ==="
gh api "/repos/$REPO/actions/runs?${QUERY}" \
--jq '.workflow_runs | group_by(.name) |
map(select(length > 60)) |
map({name: .[0].name, runs: length, per_day: (length / 30 | . * 10 | floor / 10)}) |
sort_by(-.runs)[] |
" \(.name): \(.runs) runs (~\(.per_day)/day) - consider path filters"'
Related skills
Automation & Workflowsworkflow