A fast, simple command-line tool for fetching and downloading GitHub release assets. Perfect for CI/CD pipelines, automation scripts, and development workflows.
- 🚀 Fast and lightweight - Single binary written in Rust
- 🔐 Multiple authentication methods - Token, token file, or
.netrcsupport - 🔒 Private repository support - Works seamlessly with private repos using proper authentication
- 🎯 Advanced asset filtering - Glob patterns, regex, and exclusion filters
- 📦 Latest release shorthand - Use
-d latestto always get the newest release - 📁 Custom output directory - Save downloads to any directory
- 📊 Release information - View detailed info about releases before downloading
- 🔄 Cross-platform - Works on Linux, macOS, and Windows
- 🏢 GitHub Enterprise support - Custom API base URLs for enterprise instances
- 💾 Response caching - Optional caching to reduce API calls
- 🎭 Dry-run mode - Preview operations without executing them
- 📋 JSON output - Machine-readable output for scripting
git clone https://github.com/saimizi/gh_release.git
cd gh_release
cargo build --release
sudo cp target/release/ghr /usr/local/bin/cargo install --path .ghr [OPTIONS] --repo <REPO>-r, --repo <REPO>- GitHub repository in format "owner/repo"
| Option | Short | Long | Description |
|---|---|---|---|
| Token | -t |
--token <TOKEN> |
GitHub API token for authentication |
| Token File | -T |
--token-file <PATH> |
Path to file containing GitHub token |
| Clone | -c |
--clone <URL[:REF]> |
Clone repository with optional branch/tag/commit |
| Download | -d |
--download <VERSION> |
Download specific version (or "latest") |
| Filter | -f |
--filter <FILTERS> |
Filter assets by patterns (glob/regex/exclude) |
| Info | -i |
--info <VERSIONS> |
Show info about specific versions (comma-separated) |
| Search | -s |
--search <PATTERN> |
Search for repositories |
| Number | -n |
--num <NUM> |
Number of releases to list (default: 10) |
| Concurrency | -j |
--concurrency <NUM> |
Maximum number of concurrent downloads (default: 5) |
| Dry-run | --dry-run |
Preview operations without executing them | |
| Format | --format <FORMAT> |
Output format: table (default) or json | |
| API URL | --api-url <URL> |
GitHub API base URL (for GitHub Enterprise) | |
| Cache | --cache |
Enable response caching (24 hour TTL) | |
| Verbose | -v |
--verbose |
Increase verbosity (-v, -vv for more detail) |
| Argument | Description |
|---|---|
[DIRECTORY] |
Directory for downloads or clone destination |
ghr -r owner/repoghr -r owner/repo -n 5# Download all assets from latest release to current directory
ghr -r owner/repo -d latest
# Download to specific directory
ghr -r owner/repo -d latest ./downloads# Download to current directory
ghr -r owner/repo -d v1.2.3
# Download to specific directory
ghr -r owner/repo -d v1.2.3 ./releasesThe filter system supports multiple pattern types:
# Download assets containing "linux" AND "amd64"
ghr -r owner/repo -d latest -f "linux,amd64"# Download only .deb files
ghr -r owner/repo -d latest -f "*.deb"
# Download .tar.gz files
ghr -r owner/repo -d latest -f "*.tar.gz"
# Download files starting with "app-"
ghr -r owner/repo -d latest -f "app-*"# Download linux packages for amd64 architecture
ghr -r owner/repo -d latest -f "linux-.*-amd64"
# Download versioned releases
ghr -r owner/repo -d latest -f "app-v[0-9]+\\..*"# Download everything except Windows binaries
ghr -r owner/repo -d latest -f "!windows"
# Download .deb files but not test packages
ghr -r owner/repo -d latest -f "*.deb,!test"# Multiple filters work with AND logic
ghr -r owner/repo -d latest -f "*.deb,!test,linux"
# Downloads: .deb files, excluding test packages, containing "linux"Clone a GitHub repository with optional branch, tag, or commit checkout:
# Clone repository to default directory (repository name)
ghr -c owner/repo
# Clone to specific directory
ghr -c owner/repo my-directory
# Clone specific branch
ghr -c owner/repo:main my-directory
# Clone specific tag
ghr -c owner/repo:v1.0.0 my-directory
# Clone specific commit
ghr -c owner/repo:abc1234 my-directory
# Clone with HTTPS URL
ghr -c https://github.com/owner/repo
# Clone private repository (requires authentication)
ghr -t YOUR_TOKEN -c owner/private-repo my-directorySupported URL formats:
owner/repo(short format)https://github.com/owner/repohttps://github.com/owner/repo.gitgit@github.com:owner/repo.git
Optional ref specification:
Append :ref to specify branch, tag, or commit SHA to checkout after cloning (e.g., owner/repo:main).
Prerequisites:
- Git must be installed and available in PATH
# Show info about specific version
ghr -r owner/repo -i v1.2.3
# Show info about multiple versions
ghr -r owner/repo -i "v1.2.3,v1.2.2,v1.2.1"Search for GitHub repositories using flexible patterns:
# List all repositories owned by a user
ghr -s "torvalds/"
# Search user's repositories containing keyword
ghr -s "rust-lang/compiler"
# Search top N repositories globally
ghr -s "/kubernetes" -n 10| Pattern | Description | Example |
|---|---|---|
username/ |
List all repos owned by user/org | ghr -s "microsoft/" |
username/keyword |
Search user's repos with keyword | ghr -s "google/tensorflow" |
/keyword |
Search top repos globally | ghr -s "/docker" |
Note: Use -n flag to control number of results (default: 10)
Preview what will be downloaded or cloned without executing:
# Preview download without downloading
ghr -r owner/repo -d latest --dry-run
# Output shows:
# - List of assets that would be downloaded
# - Size of each asset
# - Total download size
# - Destination directory
# Preview clone operation
ghr -c owner/repo:main --dry-run
# Output shows:
# - Repository to be cloned
# - Branch/tag/commit to checkout
# - Target directoryGet machine-readable output for scripting and automation:
# List releases in JSON format
ghr -r owner/repo --format json
# Search repositories in JSON format (includes latest tags)
ghr -s "rust-lang/" --format json -n 5
# The -n flag controls both:
# - Number of repositories to return
# - Number of latest tags to fetch for each repository
ghr -s "microsoft/" --format json -n 10
# Parse with jq
ghr -r owner/repo --format json | jq '.[0].tag_name'
ghr -r owner/repo --format json | jq -r '.[] | .assets[].name'
# Extract repository names and their latest tags
ghr -s "rust-lang/" --format json | jq -r '.[] | "\(.full_name): \(.latest_tags | join(", "))"'JSON Output for Search Mode:
When using --format json with search (-s), each repository includes:
- All standard repository fields (name, description, stars, etc.)
latest_tags: Array of the latest N tag names (where N is specified by-n)
Example output:
[
{
"name": "rust",
"full_name": "rust-lang/rust",
"description": "Empowering everyone to build reliable and efficient software.",
"stargazers_count": 95000,
"html_url": "https://github.com/rust-lang/rust",
"owner": {
"login": "rust-lang"
},
"private": false,
"latest_tags": [
"1.75.0",
"1.74.1",
"1.74.0"
]
}
]Enable caching to reduce API calls and improve performance:
# Enable caching (24 hour TTL)
ghr -r owner/repo --cache
# Subsequent calls use cached data
ghr -r owner/repo --cache # Fast! Uses cache
# Works with all API operations
ghr -s "microsoft/" --cache -n 10
ghr -r owner/repo -i v1.0.0 --cacheBenefits:
- Reduces API rate limit usage
- Faster response times for repeated queries
- Cache stored in
~/.cache/ghr/(or platform equivalent) - Automatic expiration after 24 hours
Use with GitHub Enterprise instances:
# Specify custom API URL
ghr --api-url https://github.enterprise.com/api -r owner/repo -d latest
# Works with all operations
ghr --api-url https://ghe.company.com/api -s "team/" -n 10
ghr --api-url https://ghe.company.com/api -c owner/repo# Using token directly
ghr -r owner/private-repo -d latest -t ghp_xxxxxxxxxxxx
# Using token from file
echo "ghp_xxxxxxxxxxxx" > ~/.github_token
ghr -r owner/private-repo -d latest -T ~/.github_token
# Using .netrc (automatic)
# Add to ~/.netrc:
# machine github.com
# login your-username
# password ghp_xxxxxxxxxxxx
ghr -r owner/private-repo -d latest- name: Download release asset
run: |
# Use advanced filtering and caching
ghr -r owner/repo -d latest -f "*.deb,!test" --cache ./bin
- name: Check for new releases
run: |
# Use JSON output for scripting
LATEST=$(ghr -r owner/repo --format json | jq -r '.[0].tag_name')
echo "Latest version: $LATEST"download_release:
script:
# Use dry-run first, then download
- ghr -r owner/repo -d v1.0.0 -t $GITHUB_TOKEN --dry-run
- ghr -r owner/repo -d v1.0.0 -t $GITHUB_TOKEN -f "linux-.*-amd64" ./artifacts// Use GitHub Enterprise and caching
sh 'ghr --api-url https://ghe.company.com/api -r owner/repo -d latest --cache -T /var/jenkins/.github_token ./bin'ghr supports three authentication methods (in priority order):
ghr -r owner/repo -t ghp_xxxxxxxxxxxx -d latestghr -r owner/repo -T ~/.github_token -d latestThe token file should contain only the token string, with optional whitespace.
Create or edit ~/.netrc:
machine github.com
login your-username
password ghp_xxxxxxxxxxxx
Then run without explicit authentication:
ghr -r owner/repo -d latestFor public repositories, you can run without authentication:
ghr -r owner/public-repo -d latestNote: Unauthenticated requests have lower rate limits (60 requests/hour).
- Go to GitHub Settings → Developer settings → Personal access tokens
- Click "Generate new token (classic)"
- Give it a descriptive name (e.g., "ghr CLI")
- Select scopes:
repo(for private repositories)public_repo(for public repositories only)
- Click "Generate token"
- Copy the token immediately (it won't be shown again)
Control output detail with the -v flag:
# Normal (INFO level)
ghr -r owner/repo -d latest
# Debug output
ghr -r owner/repo -d latest -v
# Trace output (very detailed)
ghr -r owner/repo -d latest -vv#!/bin/bash
# Preview first with dry-run
ghr -r mycompany/app -d latest -f "*.deb,!test" --dry-run
# Then download with advanced filtering
ghr -r mycompany/app -d latest -f "*.deb,!test,linux" /tmp
sudo dpkg -i /tmp/app_*_amd64.deb#!/bin/bash
for platform in linux darwin windows; do
ghr -r owner/repo -d v1.0.0 -f "$platform" "./dist/$platform"
done#!/bin/bash
current_version="v1.2.3"
# Use JSON output with caching for efficiency
latest=$(ghr -r owner/repo --format json --cache | jq -r '.[0].tag_name')
if [ "$latest" != "$current_version" ]; then
echo "New version available: $latest"
# Preview before downloading
ghr -r owner/repo -d latest --dry-run
# Then download
ghr -r owner/repo -d latest -f "linux-.*-amd64" ./updates
fighr provides clear error messages:
# Release not found
$ ghr -r owner/repo -d v99.99.99
Error: Release with tag 'v99.99.99' not found
# Repository not found or access denied
$ ghr -r owner/nonexistent
Error: GitHub API request failed with status: 404
# Network error
$ ghr -r owner/repo -d latest
Error: Failed to send request: connection timeout- Rust 1.70 or later
- Cargo
git clone https://github.com/yourusername/gh_release.git
cd gh_release
cargo build --releaseThe binary will be at target/release/ghr.
cargo testContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Clone your fork:
git clone https://github.com/yourname/gh_release.git - Create a feature branch:
git checkout -b feature/my-feature - Make your changes and add tests
- Run tests:
cargo test - Run formatter:
cargo fmt - Run linter:
cargo clippy - Commit your changes:
git commit -am 'Add new feature' - Push to the branch:
git push origin feature/my-feature - Submit a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built with:
- clap - Command line argument parsing
- reqwest - HTTP client
- tokio - Async runtime
- serde - Serialization framework
- regex - Regular expressions
- globset - Glob pattern matching
- thiserror - Error handling
If you encounter any issues or have questions:
- Open an issue on GitHub Issues
- Check existing issues for solutions