Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

|| true\n}\n\n# Extract an optional schedule timezone (GitHub `on.schedule[].timezone`).\nextract_timezone() {\n\tsed -nE 's/^[[:space:]]*timezone:[[:space:]]*//p' 2>/dev/null |\n\t\ttr -d \"\\\"'\" | awk '{ print $1; exit }' || true\n}\n\n# Describe a cron expression: \"HH MM daykey daylabel frequency\".\ndescribe_cron() {\n\tawk -v c=\"$1\" '\n\t\tfunction dowName(d) {\n\t\t\tif (d == 0) return \"Sunday\"\n\t\t\tif (d == 1) return \"Monday\"\n\t\t\tif (d == 2) return \"Tuesday\"\n\t\t\tif (d == 3) return \"Wednesday\"\n\t\t\tif (d == 4) return \"Thursday\"\n\t\t\tif (d == 5) return \"Friday\"\n\t\t\treturn \"Saturday\"\n\t\t}\n\t\tBEGIN {\n\t\t\tn = split(c, f, /[ \\t]+/)\n\t\t\tif (n != 5) { print \"?\\t?\\t9\\tcustom\\tcustom\"; exit }\n\t\t\tmn = f[1]; hr = f[2]; dom = f[3]; mon = f[4]; dow = f[5]\n\t\t\tif (mn !~ /^[0-9]+$/ || hr !~ /^[0-9]+$/) { print \"?\\t?\\t9\\tcustom\\tcustom\"; exit }\n\t\t\tif (dow == \"*\" && dom == \"*\") { dk = 0; lbl = \"daily\"; fr = \"daily\" }\n\t\t\telse if (dow ~ /^[0-7]$/ && dom == \"*\") { dk = (dow == 0 ? 7 : dow); lbl = dowName(dow + 0); fr = \"weekly\" }\n\t\t\telse if (dow == \"1-5\" && dom == \"*\") { dk = 1; lbl = \"weekdays\"; fr = \"weekdays\" }\n\t\t\telse if (dom ~ /^[0-9]+$/ && dow == \"*\") { dk = 0; lbl = \"monthly day \" dom; fr = \"monthly\" }\n\t\t\telse { print \"?\\t?\\t9\\tcustom\\tcustom\"; exit }\n\t\t\tprintf \"%02d\\t%02d\\t%d\\t%s\\t%s\\n\", hr + 0, mn + 0, dk, lbl, fr\n\t\t}\n\t' \u003c/dev/null\n}\n\n# Classify resource intensity from workflow content: \"high|medium|low\u003cTAB>evidence\".\n# High-intensity patterns are checked in priority order so the evidence names\n# the most meaningful resource (containers/cluster before matrix).\nclassify() {\n\tlocal content=\"$1\" evidence\n\tlocal -a high_patterns=(\n\t\t'docker[ -]?compose|compose\\.ya?ml'\n\t\t'testcontainers|withtestcontainers'\n\t\t'^[[:space:]]*services:'\n\t\t'kind-action|k3s'\n\t\t'matrix:'\n\t)\n\tlocal p\n\tfor p in \"${high_patterns[@]}\"; do\n\t\tif evidence=$(printf '%s\\n' \"$content\" | grep -oiE \"$p\" | head -1) && [[ -n \"$evidence\" ]]; then\n\t\t\tprintf 'high\\t%s\\n' \"$evidence\"\n\t\t\treturn\n\t\tfi\n\tdone\n\tif evidence=$(printf '%s\\n' \"$content\" | grep -oiE 'maven|mvn |gradle|docker build|buildx' | head -1) && [[ -n \"$evidence\" ]]; then\n\t\tprintf 'medium\\t%s\\n' \"$evidence\"\n\t\treturn\n\tfi\n\tprintf 'low\\t-\\n'\n}\n\n# ── Analyze a single workflow ──────────────────────────────────────────────\n\nanalyze() {\n\tlocal repo=\"$1\" wf=\"$2\" content=\"$3\"\n\tlocal crons\n\tcrons=\"$(printf '%s\\n' \"$content\" | extract_crons)\"\n\t[[ -n \"$crons\" ]] || return 0\n\n\tlocal intensity evidence\n\tIFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r intensity evidence \u003c \u003c(classify \"$content\")\n\n\tlocal src_tz\n\tsrc_tz=\"$(printf '%s\\n' \"$content\" | extract_timezone)\"\n\t[[ -n \"$src_tz\" ]] || src_tz=\"UTC\"\n\n\tlocal cron\n\twhile IFS= read -r cron; do\n\t\t[[ -n \"$cron\" ]] || continue\n\t\tlocal hh mm daykey daylabel freq\n\t\tIFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hh mm daykey daylabel freq \u003c \u003c(describe_cron \"$cron\")\n\t\tlocal utc_hhmm=\"?\" local_hhmm=\"?\" hour_utc=\"\"\n\t\tif [[ \"$hh\" != \"?\" ]]; then\n\t\t\tlocal epoch\n\t\t\tepoch=\"$(TZ=\"$src_tz\" date -d \"$REFDATE $hh:$mm:00\" +%s 2>/dev/null || true)\"\n\t\t\tif [[ -n \"$epoch\" ]]; then\n\t\t\t\tutc_hhmm=\"$(TZ=UTC date -d \"@$epoch\" +%H:%M)\"\n\t\t\t\tlocal_hhmm=\"$(TZ=\"$TZ_LOCAL\" date -d \"@$epoch\" +%H:%M)\"\n\t\t\t\thour_utc=\"$(TZ=UTC date -d \"@$epoch\" +%H)\"\n\t\t\tfi\n\t\tfi\n\t\tprintf '%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n' \\\n\t\t\t\"$repo\" \"$wf\" \"$cron\" \"$intensity\" \"$evidence\" \"$src_tz\" \\\n\t\t\t\"$utc_hhmm\" \"$local_hhmm\" \"$hour_utc\" \"$daylabel\" \"$freq\" >>\"$RECORDS\"\n\tdone \u003c\u003c\u003c\"$crons\"\n}\n\n# ── Collect repositories ───────────────────────────────────────────────────\n\ncollect_gh() {\n\tlocal slug=\"$1\" names name content\n\tnames=\"$(gh api \"repos/$slug/contents/.github/workflows\" --jq '.[] | select(.type==\"file\") | .name' 2>/dev/null || true)\"\n\t[[ -n \"$names\" ]] || return 0\n\twhile IFS= read -r name; do\n\t\t[[ \"$name\" == *.yml || \"$name\" == *.yaml ]] || continue\n\t\tcontent=\"$(gh api \"repos/$slug/contents/.github/workflows/$name\" -H \"Accept: application/vnd.github.raw\" 2>/dev/null || true)\"\n\t\t[[ -n \"$content\" ]] || continue\n\t\tanalyze \"$slug\" \"$name\" \"$content\"\n\tdone \u003c\u003c\u003c\"$names\"\n}\n\ncollect_local() {\n\tlocal repo_dir=\"$1\" name content\n\twhile IFS= read -r name; do\n\t\t[[ -n \"$name\" ]] || continue\n\t\tcontent=\"$(cat \"$name\")\"\n\t\tanalyze \"$(basename \"$repo_dir\")\" \"$(basename \"$name\")\" \"$content\"\n\tdone \u003c \u003c(find \"$repo_dir/.github/workflows\" -maxdepth 1 -type f \\( -name '*.yml' -o -name '*.yaml' \\) 2>/dev/null | sort)\n}\n\nif [[ -n \"$LOCAL_DIR\" ]]; then\n\t[[ -d \"$LOCAL_DIR\" ]] || {\n\t\techo \"Directory not found: $LOCAL_DIR\" >&2\n\t\texit 1\n\t}\n\techo \"Scanning local checkouts under $LOCAL_DIR ...\"\n\tfor d in \"$LOCAL_DIR\"/*/; do\n\t\t[[ -d \"$d/.github/workflows\" ]] || continue\n\t\tcollect_local \"${d%/}\"\n\t\tslug=\"$(slug_from_dir \"${d%/}\")\"\n\t\t[[ -n \"$slug\" ]] && QUEUE_REPOS+=(\"$slug\")\n\tdone\nelif [[ ${#EXPLICIT_REPOS[@]} -gt 0 ]]; then\n\techo \"Scanning ${#EXPLICIT_REPOS[@]} explicit repositories ...\"\n\tfor slug in \"${EXPLICIT_REPOS[@]}\"; do\n\t\tcollect_gh \"$slug\"\n\t\tQUEUE_REPOS+=(\"$slug\")\n\tdone\nelse\n\tOWNER=\"${OWNER:-$(gh api user --jq .login)}\"\n\techo \"Scanning repositories of owner $OWNER (limit $LIMIT) ...\"\n\tmapfile -t repos \u003c \u003c(gh repo list \"$OWNER\" --limit \"$LIMIT\" --json nameWithOwner --jq '.[].nameWithOwner')\n\tfor slug in \"${repos[@]}\"; do\n\t\tcollect_gh \"$slug\"\n\t\tQUEUE_REPOS+=(\"$slug\")\n\tdone\nfi\n\nRECORD_COUNT=\"$(wc -l \u003c\"$RECORDS\" | tr -d ' ')\"\nif [[ \"$RECORD_COUNT\" -eq 0 ]]; then\n\techo \"No scheduled workflows found.\"\n\texit 0\nfi\n\nREPO_COUNT=\"$(cut -f1 \"$RECORDS\" | sort -u | wc -l | tr -d ' ')\"\n\n# ── Optional: observed queue times ─────────────────────────────────────────\n\nQUEUE_HIST=\"\"\nif [[ \"$QUEUE_STATS\" -eq 1 && ${#QUEUE_REPOS[@]} -gt 0 ]]; then\n\techo \"Collecting queue times (last $RUNS runs per repo) ...\"\n\tfor slug in \"${QUEUE_REPOS[@]}\"; do\n\t\tgh run list -R \"$slug\" --limit \"$RUNS\" --json createdAt,startedAt 2>/dev/null |\n\t\t\tjq -r '.[] | select(.createdAt != null and .startedAt != null) | [.createdAt, .startedAt] | @tsv' 2>/dev/null |\n\t\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r created started; do\n\t\t\t\tc=\"$(date -u -d \"$created\" +%s 2>/dev/null)\" || continue\n\t\t\t\ts=\"$(date -u -d \"$started\" +%s 2>/dev/null)\" || continue\n\t\t\t\tq=$((s - c))\n\t\t\t\t[[ \"$q\" -gt 0 ]] || continue\n\t\t\t\th=\"$(date -u -d \"$created\" +%H)\"\n\t\t\t\tprintf '%s\\t%s\\n' \"$h\" \"$q\" >>\"$QUEUE_TSV\"\n\t\t\tdone\n\tdone\n\tQUEUE_HIST=\"$(awk -F'\\t' '{ n[$1]++; sum[$1] += $2; if ($2 > mx[$1]) mx[$1] = $2 } END { for (h = 0; h \u003c 24; h++) { k = sprintf(\"%02d\", h); if (n[k] > 0) printf \"%02d\\t%d\\t%.0f\\t%d\\n\", h, n[k], sum[k] / n[k], mx[k] } }' \"$QUEUE_TSV\")\"\nfi\n\n# ── Histogram / collisions / recommendations ───────────────────────────────\n\nHIST=\"$(awk -F'\\t' '$9 != \"\" { count[$9]++ } END { for (h = 0; h \u003c 24; h++) { k = sprintf(\"%02d\", h); printf \"%02d\\t%d\\n\", h, count[k] + 0 } }' \"$RECORDS\")\"\n\nWEEKDAY_HIST=\"$(awk -F'\\t' '{ count[$10]++ } END { split(\"daily Monday Tuesday Wednesday Thursday Friday Saturday Sunday weekdays monthly\", o, \" \"); for (i = 1; i \u003c= 10; i++) printf \"%s\\t%d\\n\", o[i], count[o[i]] + 0 }' \"$RECORDS\")\"\n\nCOLLISIONS=\"$(awk -F'\\t' '$9 != \"\" { c[$9]++ } END { for (h in c) if (c[h] >= 2) printf \"%02d\\t%d\\n\", h, c[h] }' \"$RECORDS\" | sort)\"\n\n# Quiet UTC hours (no scheduled runs) — candidate slots for CPU-intensive jobs.\nmapfile -t QUIET_HOURS \u003c \u003c(awk -F'\\t' '$9 != \"\" { c[$9]++ } END { for (h = 0; h \u003c 24; h++) { k = sprintf(\"%02d\", h); if ((c[k] + 0) == 0) printf \"%02d\\n\", h } }' \"$RECORDS\")\n\n# When queue data is available, prefer candidate hours with the lowest queue.\nif [[ -n \"$QUEUE_HIST\" && ${#QUIET_HOURS[@]} -gt 0 ]]; then\n\tmapfile -t QUIET_HOURS \u003c \u003c(\n\t\tfor h in \"${QUIET_HOURS[@]}\"; do\n\t\t\tavg=\"$(awk -F'\\t' -v k=\"$h\" '$1 == k { print $3; exit }' \u003c\u003c\u003c\"$QUEUE_HIST\")\"\n\t\t\tprintf '%s\\t%s\\n' \"${avg:-0}\" \"$h\"\n\t\tdone | sort -n -k1,1 | cut -f2\n\t)\nfi\n\n# Suggest moving high-intensity entries out of crowded hours.\nSUGGESTIONS=\"$(awk -F'\\t' -v top=\"$TOP\" -v quiet=\"${QUIET_HOURS[*]}\" '\n\tfunction newCron(cron, newHour, f) {\n\t\tsplit(cron, f, /[ \\t]+/)\n\t\tf[2] = newHour\n\t\treturn f[1] \" \" f[2] \" \" f[3] \" \" f[4] \" \" f[5]\n\t}\n\tBEGIN { nq = split(quiet, q, \" \") }\n\t$9 != \"\" { c[$9]++ }\n\t$4 == \"high\" && $9 != \"\" { hi[++n] = $0 }\n\tEND {\n\t\tqi = 1\n\t\tshown = 0\n\t\tfor (i = 1; i \u003c= n && shown \u003c top; i++) {\n\t\t\tsplit(hi[i], r, \"\\t\")\n\t\t\tif ((c[r[9]] + 0) \u003c 2) continue\n\t\t\tnh = \"\"\n\t\t\twhile (qi \u003c= nq) {\n\t\t\t\tcand = q[qi]; qi++\n\t\t\t\tif (cand + 0 != r[9] + 0) { nh = cand; break }\n\t\t\t}\n\t\t\tif (nh == \"\") break\n\t\t\tprintf \"%s\\t%s\\t%s\\t%s\\t%s\\t%s\\n\", r[1], r[2], r[3], r[9], nh, newCron(r[3], nh)\n\t\t\tshown++\n\t\t}\n\t}\n' \"$RECORDS\")\"\n\n# ── Console output ─────────────────────────────────────────────────────────\n\necho\necho \"Scheduled workflows by UTC hour:\"\nwhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour count; do\n\tbar=\"\"\n\tfor ((i = 0; i \u003c count; i++)); do bar+=\"▇\"; done\n\tprintf ' %s:00 %-20s %d\\n' \"$hour\" \"$bar\" \"$count\"\ndone \u003c\u003c\u003c\"$HIST\"\n\necho\necho \"Repositories: $REPO_COUNT Scheduled entries: $RECORD_COUNT\"\n\nif [[ -n \"$COLLISIONS\" ]]; then\n\techo\n\techo \"Collisions (UTC hours with 2+ scheduled runs):\"\n\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour count; do\n\t\tprintf ' %s:00 %d\\n' \"$hour\" \"$count\"\n\tdone \u003c\u003c\u003c\"$COLLISIONS\"\nfi\n\nif [[ -n \"$QUEUE_HIST\" ]]; then\n\techo\n\techo \"Observed queue time per UTC hour (avg / max seconds):\"\n\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour samples avg max; do\n\t\tprintf ' %s:00 avg %4ss max %5ss (%s runs)\\n' \"$hour\" \"$avg\" \"$max\" \"$samples\"\n\tdone \u003c\u003c\u003c\"$QUEUE_HIST\"\nfi\n\nif [[ -n \"$SUGGESTIONS\" ]]; then\n\techo\n\techo \"Redistribution suggestions (high-intensity jobs in crowded hours):\"\n\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r repo wf cron from_hour to_hour new_cron; do\n\t\tprintf ' %s/%s: %s -> %s (%s:00 -> %s:00 UTC)\\n' \"$repo\" \"$wf\" \"$cron\" \"$new_cron\" \"$from_hour\" \"$to_hour\"\n\tdone \u003c\u003c\u003c\"$SUGGESTIONS\"\nfi\n\n# ── Markdown report ────────────────────────────────────────────────────────\n\nif [[ \"$WRITE_REPORT\" -eq 1 ]]; then\n\tmkdir -p \"$(dirname \"$OUT\")\"\n\t{\n\t\techo \"# GitHub Actions Cron Schedule Overview\"\n\t\techo\n\t\techo \"- Generated: $(date '+%Y-%m-%d %H:%M:%S %z')\"\n\t\tif [[ -n \"$LOCAL_DIR\" ]]; then\n\t\t\techo \"- Source: local checkouts under \\`$LOCAL_DIR\\`\"\n\t\telif [[ ${#EXPLICIT_REPOS[@]} -gt 0 ]]; then\n\t\t\techo \"- Source: explicit repositories\"\n\t\telse\n\t\t\techo \"- Source: GitHub API (owner \\`$OWNER\\`)\"\n\t\tfi\n\t\techo \"- Local timezone: \\`$TZ_LOCAL\\` (cron is UTC)\"\n\t\techo \"- Repositories: $REPO_COUNT\"\n\t\techo \"- Scheduled entries: $RECORD_COUNT\"\n\t\tif [[ \"$QUEUE_STATS\" -eq 1 ]]; then\n\t\t\techo \"- Queue stats: last $RUNS runs per repo\"\n\t\tfi\n\t\techo\n\t\techo \"> Cron expressions are UTC. Local times use \\`$TZ_LOCAL\\` for the current date;\"\n\t\techo \"> daylight-saving transitions can shift them by one hour.\"\n\t\techo\n\t\techo \"## Scheduled workflows\"\n\t\techo\n\t\techo \"| Repo | Workflow | Cron (UTC) | UTC | Local ($TZ_LOCAL) | Frequenz | Intensität | Nutzt |\"\n\t\techo \"| ---- | -------- | ---------- | --- | ----------------- | -------- | ---------- | ----- |\"\n\t\tsort -t

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' -k9,9 -k1,1 -k2,2 \"$RECORDS\" | while IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r repo wf cron intensity evidence src_tz utc_hhmm local_hhmm hour_utc daylabel freq; do\n\t\t\techo \"| $repo | $wf | \\`$cron\\` | $utc_hhmm | $local_hhmm | $daylabel | $intensity | $evidence |\"\n\t\tdone\n\t\techo\n\t\techo \"## Runs per UTC hour\"\n\t\techo\n\t\techo \"| UTC hour | Runs | |\"\n\t\techo \"| -------- | ---- | - |\"\n\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour count; do\n\t\t\tbar=\"\"\n\t\t\tfor ((i = 0; i \u003c count; i++)); do bar+=\"▇\"; done\n\t\t\techo \"| ${hour}:00 | $count | $bar |\"\n\t\tdone \u003c\u003c\u003c\"$HIST\"\n\t\techo\n\t\techo \"## Runs per frequency / weekday\"\n\t\techo\n\t\techo \"| Slot | Runs |\"\n\t\techo \"| ---- | ---- |\"\n\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r slot count; do\n\t\t\techo \"| $slot | $count |\"\n\t\tdone \u003c\u003c\u003c\"$WEEKDAY_HIST\"\n\t\techo\n\t\tif [[ -n \"$QUEUE_HIST\" ]]; then\n\t\t\techo \"## Observed queue time per UTC hour\"\n\t\t\techo\n\t\t\techo \"| UTC hour | Samples | Avg queue | Max queue |\"\n\t\t\techo \"| -------- | ------- | --------- | --------- |\"\n\t\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour samples avg max; do\n\t\t\t\techo \"| ${hour}:00 | $samples | ${avg}s | ${max}s |\"\n\t\t\tdone \u003c\u003c\u003c\"$QUEUE_HIST\"\n\t\t\techo\n\t\tfi\n\t\techo \"## Collisions (UTC hours with 2+ scheduled runs)\"\n\t\techo\n\t\tif [[ -z \"$COLLISIONS\" ]]; then\n\t\t\techo \"_None._\"\n\t\telse\n\t\t\techo \"| UTC hour | Runs |\"\n\t\t\techo \"| -------- | ---- |\"\n\t\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r hour count; do\n\t\t\t\techo \"| ${hour}:00 | $count |\"\n\t\t\tdone \u003c\u003c\u003c\"$COLLISIONS\"\n\t\tfi\n\t\techo\n\t\techo \"## Redistribution suggestions\"\n\t\techo\n\t\tif [[ -z \"$SUGGESTIONS\" ]]; then\n\t\t\techo \"_No crowded hours with high-intensity jobs._\"\n\t\telse\n\t\t\techo \"| Repo | Workflow | Current (UTC) | Suggested (UTC) | Move |\"\n\t\t\techo \"| ---- | -------- | ------------- | --------------- | ---- |\"\n\t\t\twhile IFS=

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…

\\t' read -r repo wf cron from_hour to_hour new_cron; do\n\t\t\t\techo \"| $repo | $wf | \\`$cron\\` | \\`$new_cron\\` | ${from_hour}:00 → ${to_hour}:00 |\"\n\t\t\tdone \u003c\u003c\u003c\"$SUGGESTIONS\"\n\t\t\techo\n\t\t\techo \"Suggestions only move high-intensity jobs out of crowded hours into empty\"\n\t\t\techo \"ones; review before applying and adjust for DST.\"\n\t\tfi\n\t} >\"$OUT\"\n\techo\n\techo \"Report written to $OUT\"\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":16560,"content_sha256":"45cf0bd5698685b2fefccf8c742a6a26768d6bae0f2962d1ef07bf1038c0be4e"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Cron Schedule Planner","type":"text"}]},{"type":"paragraph","content":[{"text":"Collects GitHub Actions ","type":"text"},{"text":"on.schedule","type":"text","marks":[{"type":"code_inline"}]},{"text":" cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions.","type":"text"}]},{"type":"paragraph","content":[{"text":"Read-only: the script never edits workflows. Suggestions are applied only after the user confirms.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Instructions","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Decide the repository scope","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Default: all repositories of the authenticated ","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]},{"text":" user (no local checkouts needed).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--owner \u003cowner>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to scan a different owner.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--repo \u003cowner/repo>","type":"text","marks":[{"type":"code_inline"}]},{"text":" (repeatable) for an explicit list.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"--local \u003cdir>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to scan local checkouts instead of the GitHub API.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Run the script","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"bash scripts/cron-schedule-planner.sh","type":"text"}]},{"type":"paragraph","content":[{"text":"Common variants:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Specific owner, Swiss local time, report in target/\nbash scripts/cron-schedule-planner.sh --owner dboeckli --tz Europe/Zurich\n\n# Local checkouts (no GitHub API)\nbash scripts/cron-schedule-planner.sh --local ~/projects/referenzen\n\n# A few explicit repos\nbash scripts/cron-schedule-planner.sh --repo dboeckli/ai-agent-skills --repo dboeckli/camel-first","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Present the results","type":"text"}]},{"type":"paragraph","content":[{"text":"The script prints the hourly histogram, collisions and suggestions, and writes ","type":"text"},{"text":"target/cron-schedule-overview.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Summarise:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"how many repos / scheduled entries were found,","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"the most crowded UTC hours (collisions),","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"which high-intensity jobs sit in crowded hours.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Apply suggestions only after confirmation","type":"text"}]},{"type":"paragraph","content":[{"text":"The redistribution suggestions are heuristic (they move high-intensity jobs out of crowded hours into empty ones, keeping the minute and day fields). Present them as a diff and change workflow files ","type":"text"},{"text":"only after explicit confirmation","type":"text","marks":[{"type":"strong"}]},{"text":". Never edit automatically.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Options","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Option","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Meaning","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--owner \u003cowner>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"GitHub owner to scan (default: authenticated user)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--repo \u003cowner/repo>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"explicit repo (repeatable); disables owner scan","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--local \u003cdir>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scan local checkouts under ","type":"text"},{"text":"\u003cdir>","type":"text","marks":[{"type":"code_inline"}]},{"text":" instead of GitHub","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--tz \u003czone>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"local timezone for the ","type":"text"},{"text":"Local","type":"text","marks":[{"type":"code_inline"}]},{"text":" column (default ","type":"text"},{"text":"Europe/Zurich","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--limit \u003cn>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max repos for the owner scan (default 200)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--out \u003cfile>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Markdown report (default ","type":"text"},{"text":"target/cron-schedule-overview.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--no-report","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"console only, no report file","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--top \u003cn>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max redistribution suggestions (default 5)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--queue-stats","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"add observed queue time per UTC hour (via ","type":"text"},{"text":"gh run list","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--runs \u003cn>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max runs per repo for queue stats (default 50)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Output","type":"text"}]},{"type":"paragraph","content":[{"text":"target/cron-schedule-overview.md","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scheduled workflows","type":"text","marks":[{"type":"strong"}]},{"text":" table: repo, workflow, cron (UTC), UTC time, local time, frequency, intensity, evidence.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Runs per UTC hour","type":"text","marks":[{"type":"strong"}]},{"text":" histogram (bars).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Runs per frequency / weekday","type":"text","marks":[{"type":"strong"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Collisions","type":"text","marks":[{"type":"strong"}]},{"text":" — UTC hours with two or more scheduled runs.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Observed queue time per UTC hour","type":"text","marks":[{"type":"strong"}]},{"text":" (with ","type":"text"},{"text":"--queue-stats","type":"text","marks":[{"type":"code_inline"}]},{"text":") — average and max wait between ","type":"text"},{"text":"createdAt","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"startedAt","type":"text","marks":[{"type":"code_inline"}]},{"text":" across recent runs, as an empirical contention signal.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Redistribution suggestions","type":"text","marks":[{"type":"strong"}]},{"text":" — high-intensity jobs in crowded hours moved to empty ones; with ","type":"text"},{"text":"--queue-stats","type":"text","marks":[{"type":"code_inline"}]},{"text":" the empty hours with the lowest observed queue are preferred.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Classification","type":"text"}]},{"type":"paragraph","content":[{"text":"Intensity is derived heuristically from the workflow content. See ","type":"text"},{"text":"references/classification-and-timezones.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the exact patterns and the UTC/timezone rules.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"high","type":"text","marks":[{"type":"strong"}]},{"text":" — Docker Compose, Testcontainers, service containers (","type":"text"},{"text":"services:","type":"text","marks":[{"type":"code_inline"}]},{"text":"), Kind/k3s cluster, matrix builds.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"medium","type":"text","marks":[{"type":"strong"}]},{"text":" — Maven/Gradle full builds, Docker image builds.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"low","type":"text","marks":[{"type":"strong"}]},{"text":" — lint/format/validate and other meta workflows.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 1: Are my scheduled builds colliding?","type":"text"}]},{"type":"paragraph","content":[{"text":"User says: \"Do my scheduled GitHub Actions builds collide?\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Actions:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"bash scripts/cron-schedule-planner.sh --owner \u003cowner>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Report the crowded UTC hours and the high-intensity jobs in them","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Point to ","type":"text"},{"text":"target/cron-schedule-overview.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"paragraph","content":[{"text":"Result: Collision overview across all repos with concrete evidence.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 2: When should the Testcontainers build run?","type":"text"}]},{"type":"paragraph","content":[{"text":"User says: \"When should I schedule the Testcontainers build?\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Actions:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run the planner and locate the crowded hours (collisions)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Recommend one of the empty hours from the suggestions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Offer the concrete cron diff, apply only after confirmation","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Result: A low-contention slot and a ready-to-apply cron change.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Troubleshooting","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"gh: not found","type":"text","marks":[{"type":"code_inline"}]},{"text":" or authentication error","type":"text"}]},{"type":"paragraph","content":[{"text":"The script needs an authenticated ","type":"text"},{"text":"gh","type":"text","marks":[{"type":"code_inline"}]},{"text":". Run ","type":"text"},{"text":"gh auth status","type":"text","marks":[{"type":"code_inline"}]},{"text":"; if that fails, the user must authenticate. Alternatively use ","type":"text"},{"text":"--local \u003cdir>","type":"text","marks":[{"type":"code_inline"}]},{"text":" with local checkouts.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Empty report","type":"text"}]},{"type":"paragraph","content":[{"text":"No workflow in scope has an ","type":"text"},{"text":"on.schedule","type":"text","marks":[{"type":"code_inline"}]},{"text":" entry. Check the repo scope (","type":"text"},{"text":"--owner","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--repo","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--local","type":"text","marks":[{"type":"code_inline"}]},{"text":") and that the workflows actually define ","type":"text"},{"text":"schedule:","type":"text","marks":[{"type":"code_inline"}]},{"text":" crons.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Times look off by one hour","type":"text"}]},{"type":"paragraph","content":[{"text":"Cron is always UTC. Local times are computed for the current date, so daylight-saving transitions can shift them by one hour. Re-run after a DST change or adjust manually.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"--queue-stats","type":"text","marks":[{"type":"code_inline"}]},{"text":" shows little or no data","type":"text"}]},{"type":"paragraph","content":[{"text":"GitHub reports ","type":"text"},{"text":"startedAt","type":"text","marks":[{"type":"code_inline"}]},{"text":" equal to ","type":"text"},{"text":"createdAt","type":"text","marks":[{"type":"code_inline"}]},{"text":" for most runs (no recorded queue), so the signal is sparse. Increase ","type":"text"},{"text":"--runs","type":"text","marks":[{"type":"code_inline"}]},{"text":" to include older runs. Treat large gaps with care: they can come from approval gates, concurrency limits or manual runs, not only runner contention.","type":"text"}]}]},"metadata":{"date":"2026-11-02","name":"cron-schedule-planner","author":"@skillopedia","source":{"stars":0,"repo_name":"ai-agent-skills","origin_url":"https://github.com/dboeckli/ai-agent-skills/blob/HEAD/.claude/skills/cron-schedule-planner/SKILL.md","repo_owner":"dboeckli","body_sha256":"46991916be9feef0981243287ecc62f2192c7be351d343585f8fa8f0a3151831","cluster_key":"5e6f393f5a71bf7be025aed685b547c03d5e3ad18787324149be9af545ee8def","clean_bundle":{"format":"clean-skill-bundle-v1","source":"dboeckli/ai-agent-skills/.claude/skills/cron-schedule-planner/SKILL.md","text_bytes":19978,"source_commit":"ab99d0c7b12ebf0a63c76c82ff3337d9b5af1199","skills_sh_rank":7633,"attachment_count":2,"text_attachments":2,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":".claude/skills/cron-schedule-planner/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","import_tag":"skills-sh-top20k-2026-11","description":"Builds an overview of GitHub Actions `schedule` cron expressions across multiple repositories and helps spread CPU-intensive jobs (Docker Compose, Testcontainers, Kind/k3s, matrix builds) into less contended slots. Use when the user asks 'when do my cron actions run?', 'do my scheduled builds collide?', 'when should the Testcontainers build run?', or wants a cron schedule overview/distribution report across repos. Scans via `gh` (no local checkouts required) or local checkouts, converts UTC to a local timezone, classifies job intensity, and writes a Markdown report with an hourly histogram, collisions and concrete cron redistribution suggestions."}},"renderedAt":1793671662971}

Cron Schedule Planner Collects GitHub Actions cron expressions across repositories, classifies how resource-intensive each workflow is, converts the UTC cron times to a local timezone, and produces a Markdown report with an hourly histogram, collisions and concrete redistribution suggestions. Read-only: the script never edits workflows. Suggestions are applied only after the user confirms. Instructions Step 1: Decide the repository scope - Default: all repositories of the authenticated user (no local checkouts needed). - to scan a different owner. - (repeatable) for an explicit list. - to sca…