Home / Alt manpages / gh-run-download(1)

  • gh-run-download(1)
  • User command
  • linux

Download GitHub Actions Artefacts Safely with gh run download

gh run download pulls GitHub Actions artefacts into a directory you choose, instead of you hunting through a web UI for a zip file. It works either from one workflow run or by name across runs. The examples use GitHub CLI 2.87.3, which is the version reported by the installed gh executable.

Budget about ten minutes. You need GitHub CLI, access to the repository, and an authenticated account with permission to read its workflow artefacts. This is an ordinary user command: it does not need sudo. Keep a specific run ID whenever the files must be reproducible, because the default selection can change as workflows upload, replace or delete artefacts.

1. Check the installed command

Confirm the executable and read its local help before choosing a command line:

$ command -v gh
/home/linuxbrew/.linuxbrew/bin/gh
$ gh --version
gh version 2.87.3 (2026-02-23)
$ gh run download --help

The subcommand accepts an optional run ID, a destination directory, one or more artefact names, a glob pattern, and the inherited repository selector. It has no output-file option and no option for renaming an extracted artefact.

Checkpoint

If gh --version reports an older executable than your team expects, stop and resolve that path or package mismatch first. Option details vary between CLI releases.

2. Choose the repository and run

When your current directory is a checkout of the target repository, gh can infer it. Otherwise pass it explicitly with --repo:

$ gh run list --repo OWNER/REPOSITORY --limit 10

Replace OWNER/REPOSITORY with the real repository. Find the workflow run ID in the list and record the numeric value. If you already have a run ID from CI output, use it directly: a run ID is more precise than relying on whichever artefact was uploaded most recently.

Authentication failures are separate from an empty artefact result. GitHub CLI documents exit status 4 as authentication required, while status 1 means an error. Check the current login state without downloading anything:

$ gh auth status --hostname github.com
github.com
  Logged in to github.com as ACCOUNT

The account name and status lines are host-specific. If the command says authentication is required, use your organisation's approved gh auth login process. Do not put a token directly into a shell command or paste it into a guide, terminal transcript or issue.

3. Create an isolated destination

Use a fresh directory so extracted files cannot be confused with files left by an earlier download. This changes local state by creating a directory, but it does not touch the repository or the GitHub run:

$ mkdir -p "$HOME/tmp/gh-artifacts/run-123456789"
$ find "$HOME/tmp/gh-artifacts/run-123456789" -mindepth 1 -maxdepth 1 -print

An empty result from find is the useful checkpoint. Replace 123456789 with the real run ID. If the directory is not empty, choose another one or inspect it before proceeding. Do not download into a source tree merely because the default destination is .; an artefact may contain files with names that matter to your project.

4. Download every artefact from one run

Pass the run ID and destination directory together:

$ gh run download 123456789 \
    --repo OWNER/REPOSITORY \
    --dir "$HOME/tmp/gh-artifacts/run-123456789"

For more than one artefact, the command extracts each one below a separate directory named for the artefact. Verify what arrived rather than assuming a particular file layout:

$ find "$HOME/tmp/gh-artifacts/run-123456789" -maxdepth 3 -type f -print | sort
/home/ACCOUNT/tmp/gh-artifacts/run-123456789/linux-amd64/release.tar.gz
/home/ACCOUNT/tmp/gh-artifacts/run-123456789/test-results/results.xml

The names and depth above are examples; the actual paths depend on the artefact names and contents. If you selected one artefact with --name, its contents are extracted directly into the selected directory rather than into an extra artefact-name directory.

5. Select one or more artefacts by name

Use --name when you know the exact artefact name. Repeat the option for multiple names:

$ gh run download 123456789 \
    --repo OWNER/REPOSITORY \
    --name linux-amd64 \
    --name test-results \
    --dir "$HOME/tmp/gh-artifacts/run-123456789-selected"

Create that destination first, as in the previous step, and check it afterwards:

$ find "$HOME/tmp/gh-artifacts/run-123456789-selected" -maxdepth 3 -type f -print | sort

Names are not shell globs. If you need pattern matching, use --pattern instead, and quote patterns so the local shell does not expand them against files in your current directory:

$ gh run download 123456789 \
    --repo OWNER/REPOSITORY \
    --pattern 'linux-*' \
    --dir "$HOME/tmp/gh-artifacts/run-123456789-linux"

The pattern is evaluated by GitHub CLI against artefact names. Keep the run ID when you need a consistent set; omitting it changes the search to artefacts available across runs.

6. Understand the no-run-ID default

This command can be run without a run ID:

$ gh run download --repo OWNER/REPOSITORY --name test-results \
    --dir "$HOME/tmp/gh-artifacts/latest-test-results"

Without a run ID, GitHub CLI downloads the latest artefact created and uploaded through GitHub Actions. That is a moving target: a newer workflow may upload an artefact with the same name, or a workflow may delete or overwrite an earlier one. Use this form for an intentionally current result, not for a build record that must be audited or reproduced.

If you omit both the run ID and an artefact selector, the command selects interactively. That is fine for an occasional manual download, but it is a poor fit for a script because it requires a person to choose. Scripts should pass the run ID and explicit --name or --pattern values.

7. Diagnose failures without guessing

Rerun the exact command with the destination and repository visible in your shell history, then classify the result:

  • A message about authentication means the account or token needs attention. Check gh auth status; do not retry with sudo, which uses a different environment and does not grant GitHub access.
  • A missing run or artefact usually means the ID, repository, name or pattern is wrong, or the artefact has expired or been deleted. Use gh run list and inspect the run in the correct repository.
  • A non-empty destination may contain files from a previous attempt. Stop before treating them as a successful download; use a new empty directory.
  • A successful command means the download and extraction completed. It does not prove that an archive or report inside the artefact is trustworthy: treat downloaded files as untrusted input before executing programs or unpacking nested archives.

To remove a disposable download after inspection, delete only its explicitly named directory:

$ rm -rf -- "$HOME/tmp/gh-artifacts/run-123456789"
$ test ! -e "$HOME/tmp/gh-artifacts/run-123456789" && echo 'temporary artifacts removed'
temporary artifacts removed

Warning

This removal is irreversible for the local copy. It does not delete the GitHub Actions artefact, cancel a workflow or alter repository history. Before running it, verify the path is a disposable download directory and not a source checkout.

Done means

  • Confirmed the install. You checked the installed gh version and local subcommand help.
  • Chose the right target. You selected the intended repository and, for reproducible work, a specific run ID.
  • Downloaded somewhere clean. You used a fresh directory and inspected the extracted paths.
  • Selected precisely. You used --name for exact names and quoted --pattern for globs.
  • Know the default moves. You understand that omitting the run ID selects a changing latest artefact.
  • Stayed safe. You kept authentication data out of commands and treated downloaded files as untrusted.