Trace and Manage GitHub Actions Runs with gh run

gh run finds a GitHub Actions run, shows you the failing job, and lets you watch, download, rerun, cancel or delete it from one shell. The examples use GitHub CLI 2.87.3, installed on this machine in March 2026. Most commands here take a few minutes; downloading or diagnosing a large run takes as long as the logs and artefacts require.

Before you start

Install and authenticate GitHub CLI, then work from a directory where downloaded artefacts can safely live. You need access to the repository and the Actions permissions the operation requires. The commands below use OWNER/REPO as a placeholder: replace it with a real repository such as octo-org/example-app, and replace RUN_ID with the numeric run ID returned by the list command.

gh --version
gh auth status
mkdir -p ~/tmp/gh-run-work
cd ~/tmp/gh-run-work

Checkpoint: authentication should report the account and host you intend to use. No command in this guide needs sudo; repository permissions are checked by GitHub instead.

1. Find the run

Start with a small list so an old run does not distract you. By default, gh run list fetches at most 20 runs. Filter by workflow, branch, event, status, commit, or triggering user when the repository is busy.

gh run list --repo OWNER/REPO --limit 10
gh run list --repo OWNER/REPO --workflow build.yml --branch main --status failure

The table includes a run status, conclusion, workflow, branch, event, and run ID. A run can be in_progress while its conclusion is not yet final. --workflow takes a workflow name or file, but a disabled workflow needs --all as well when you filter by name.

For scripts, request named JSON fields rather than parsing the display table.

gh run list --repo OWNER/REPO --limit 5   --json databaseId,workflowName,status,conclusion,headBranch,url   --jq '.[] | [.databaseId, .workflowName, .status, (.conclusion // "-"), .headBranch, .url] | @tsv'

Checkpoint: save one numeric databaseId as RUN_ID. If the list is empty, check the repository, branch, workflow filter, and whether your account can see Actions runs at all.

2. Inspect the run and its logs

View a summary first. With no run ID, gh run view selects one interactively, which is handy at a terminal but awkward in automation.

gh run view RUN_ID --repo OWNER/REPO
gh run view RUN_ID --repo OWNER/REPO --verbose
gh run view RUN_ID --repo OWNER/REPO --log-failed

For a machine-readable summary, request only the fields you need. If a run has multiple attempts, specify the attempt number.

gh run view RUN_ID --repo OWNER/REPO   --json name,number,status,conclusion,jobs,url
gh run view RUN_ID --repo OWNER/REPO --attempt 3
gh run view RUN_ID --repo OWNER/REPO --log --job JOB_ID

The job ID is not necessarily the number shown in a browser URL. Pull the correct database ID from the JSON response instead:

gh run view RUN_ID --repo OWNER/REPO   --json jobs --jq '.jobs[] | {name, databaseId}'

Checkpoint: identify the failed job and the first meaningful error, not just the final summary line. If the failure looks external, rerunning it may produce a different result, so record the evidence first.

3. Watch an active run

When a run is still moving, watch it rather than repeatedly running list. The default refresh interval is three seconds, and compact mode reduces noise by showing only relevant or failed steps.

gh run watch RUN_ID --repo OWNER/REPO
gh run watch RUN_ID --repo OWNER/REPO --compact --interval 10

By default, watch returns successfully when the run finishes, even if the workflow itself failed. Add --exit-status when a shell script must stop on a failed run.

if gh run watch RUN_ID --repo OWNER/REPO --compact --exit-status; then
  echo "workflow passed"
else
  echo "workflow failed; inspect it with gh run view" >&2
  exit 1
fi

Checkpoint: the command has only completed once the run reaches a terminal state. A non-zero exit here is a useful signal, not proof that the CLI itself is broken.

4. Download artefacts into a controlled directory

Without a run ID, gh run download chooses the latest artefact. That is fine for a quick look but unsafe for reproducible troubleshooting, since workflows can delete or overwrite artefacts. Use the run ID whenever the artefact must match the run you inspected.

mkdir -p ./artifacts/RUN_ID
gh run download RUN_ID --repo OWNER/REPO --dir ./artifacts/RUN_ID
gh run download RUN_ID --repo OWNER/REPO --name test-report --dir ./artifacts/RUN_ID

Each artefact is extracted into its own directory unless you select a single one. To see what arrived:

find ./artifacts/RUN_ID -maxdepth 3 -type f -print

Warning: do not extract untrusted files into a source tree, deployment directory, or home-directory configuration location. The command only changes the destination you provide, so recovery is simply removing that dedicated directory once you have checked its contents.

5. Change a run only after checking the boundary

Rerunning, cancelling, and deleting are state-changing operations. Confirm the repository and run ID immediately before using any of them; rerunning can consume Actions minutes and repeat deployment or release steps.

gh run rerun RUN_ID --repo OWNER/REPO --failed
gh run rerun RUN_ID --repo OWNER/REPO --job JOB_ID

The first command reruns failed jobs and their dependencies. The second targets one job and its dependencies. If you only need more evidence, do not rerun yet.

Cancel a run that should no longer continue. The normal cancellation is preferable; --force is an explicit escalation.

gh run cancel RUN_ID --repo OWNER/REPO
gh run cancel RUN_ID --repo OWNER/REPO --force

Warning: deletion is irreversible from the CLI. There is no undo command in gh run, and deleting a run removes its run record and available artefacts. Use it only after confirming your retention or audit requirements.

gh run delete RUN_ID --repo OWNER/REPO

Checkpoint: after a rerun, list the repository again and use the new run or attempt details. After a cancellation, view the run to confirm its terminal conclusion. Treat a deletion as final.

Done means