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

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

Download GitHub Actions Artefacts Safely with gh run download

You will finish with a repeatable way to extract GitHub Actions artefacts into a directory you control, 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.

Allow 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 when 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 does not provide an output-file option or an option for renaming an extracted artefact.

Checkpoint: if gh --version reports an older executable than the one expected by your team, stop and resolve that path or package mismatch first. Option details can vary between CLI releases.

2. Choose the repository and run

When your current directory is a checkout of the target repository, gh can infer the repository. 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, then record the numeric value. If you already have a run ID from CI output, you can 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 modify 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 directory 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 are meaningful 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 artefact 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 in this output 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 additional artifact-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. 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 artefact. 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 can be useful for an occasional manual download, but it is a poor fit for a script because it requires a person to make the selection. Scripts should pass the run ID and explicit --name or --pattern values.

7. Diagnose failures without guessing

First 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 interpreting 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

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

  • You confirmed the installed gh version and local subcommand help.
  • You selected the intended repository and, for reproducible work, a specific run ID.
  • You downloaded into a fresh directory and inspected the extracted paths.
  • You used --name for exact names and quoted --pattern for globs.
  • You understand that omitting the run ID selects a changing latest artefact.
  • You kept authentication data out of commands and treated downloaded files as untrusted.