How to Delete All GitHub Actions Workflow Runs with the GitHub CLI (gh)
GitHub’s Actions UI is great for day-to-day viewing, but it’s not designed for bulk cleanup. If you’ve just enabled Actions on an older repository, migrated from Bitbucket, or iterated on workflows in a test-heavy phase, your run history can become cluttered fast.
This guide shows how to delete workflow runs using gh api (GitHub CLI), explains what’s happening under the hood, and then adds safer patterns you’ll actually want in production (dry-run, completed-only, keep-last-N).

What you’re deleting (and how GitHub exposes it)
A workflow run is a single execution of a workflow file (for example, one push to main might create one run). GitHub exposes workflow runs via the REST API, including endpoints to list runs and delete runs.
Prerequisites (don’t skip these)
You’ll need:
- GitHub CLI installed and authenticated (interactive login or a token)
- Repository access
- Listing runs requires read access; deleting runs requires write-level Actions permission
- If you’re using a token:
- Classic PATs typically need
reposcope for private repos - Fine-grained PATs need Actions: write to delete runs
- Classic PATs typically need
Also worth knowing: gh api is a thin wrapper over the GitHub REST API; --paginate tells it to keep following pages automatically
The Delete Everything Command
Warning: USE WITH CAUTION!
Remember to update the ORG and REPO values with your own values.
REPO="ORG/REPO"
# Optional: count runs first
gh api --paginate "/repos/$REPO/actions/runs?per_page=100" --jq '.workflow_runs[].id' | wc -l
# Delete everything
gh api --paginate "/repos/$REPO/actions/runs?per_page=100" --jq '.workflow_runs[].id' \
| while read -r RUN_ID; do
echo "Deleting run $RUN_ID"
gh api -X DELETE "/repos/$REPO/actions/runs/$RUN_ID" >/dev/null
done
What each line is doing
GET /repos/{owner}/{repo}/actions/runsreturns a list of runs for the repository. GitHub Docs--jq '.workflow_runs[].id'extracts the run IDs from the API response.- The loop calls
DELETE /repos/{owner}/{repo}/actions/runs/{run_id}for each ID to remove the run. GitHub Docs --paginateensures you don’t stop at the first page of results. GitHub CLI+1
⚠️ Permanent action: Deleting runs is not a “hide” operation. Treat it like data deletion and apply your org’s retention/audit expectations first.
A safer TurboGeek version (recommended for real repos)
In practice, “delete everything” is rarely what you want. Most teams want one of these:
- Confirm what will be deleted (dry-run)
- Delete only completed runs (avoid nuking in-progress executions)
- Keep the most recent N runs for quick troubleshooting
1) Dry-run: list what you’re about to delete
Remember to update the ORG and REPO values with your own values.
REPO="ORG/REPO"
gh api --paginate "/repos/$REPO/actions/runs?per_page=100" \
--jq '.workflow_runs[] | "\(.id) \(.status) \(.created_at) \(.name)"' \
| head -n 50
This prints the first 50 items so you can sanity-check repo, workflow names, and timestamps before deletion.
2) Delete completed runs only (and keep the newest 20)
Remember to update the ORG and REPO values with your own values.
REPO="ORG/REPO"
KEEP=20
gh api --paginate "/repos/$REPO/actions/runs?per_page=100" \
--jq '.workflow_runs[] | select(.status=="completed") | .id' \
| tail -n +$((KEEP+1)) \
| while read -r RUN_ID; do
echo "Deleting run $RUN_ID"
gh api -X DELETE "/repos/$REPO/actions/runs/$RUN_ID" >/dev/null
done
This pattern reduces the chance you delete something still executing, while leaving a “recent history” window.
Alternative: delete logs but keep the run record
Sometimes you want to keep the run entry (who ran what, when) while deleting the stored logs.
GitHub provides a dedicated endpoint for that: DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs. GitHub Docs
Here’s the log-cleaner equivalent:
Remember to update the ORG and REPO values with your own values.
REPO="ORG/REPO"
gh api --paginate "/repos/$REPO/actions/runs?per_page=100" --jq '.workflow_runs[].id' \
| while read -r RUN_ID; do
echo "Deleting logs for run $RUN_ID"
gh api -X DELETE "/repos/$REPO/actions/runs/$RUN_ID/logs" >/dev/null
doneTroubleshooting checklist
403 Forbidden
Your token/user doesn’t have permission to delete workflow runs. Deleting runs requires Actions write permission.
Only deletes some runs
Pagination matters. --paginate is the correct fix, because GitHub paginates large result sets.
If you’re still seeing odd behaviour, dump IDs to a file first, then delete from the file (two-phase deletion avoids “moving target” issues while paging).
500 Internal Error when deleting logs
GitHub documents 500 as a possible response for deleting workflow logs. If you hit it intermittently, retry logic is sensible.
FAQ
Does deleting runs delete workflow YAML files?
No. You are deleting run history objects, not the workflow definitions. Workflow definitions live in .github/workflows/*.yml.
What’s the difference between deleting runs and deleting logs?
Deleting runs removes the run records entirely (DELETE .../actions/runs/{run_id}).
Deleting logs removes the stored logs for a run but leaves the run record (DELETE .../actions/runs/{run_id}/logs)

Recent Comments