Skip to content

Instantly share code, notes, and snippets.

@vasi
Last active September 7, 2026 01:04
Show Gist options
  • Select an option

  • Save vasi/a826f4d88eaefb79b2efd016a9ba19d6 to your computer and use it in GitHub Desktop.

Select an option

Save vasi/a826f4d88eaefb79b2efd016a9ba19d6 to your computer and use it in GitHub Desktop.
Github release downloader
#!/bin/bash
set -euo pipefail
api_base='https://api.github.com'
usage() {
cat <<'EOF'
Usage:
ghr search QUERY...
ghr releases OWNER/REPO
ghr assets OWNER/REPO [TAG]
ghr download OWNER/REPO TAG ASSET
Examples:
ghr search powerpc browser
ghr releases dillo-browser/dillo
ghr assets owner/repo
ghr assets owner/repo v1.2.3
ghr download owner/repo v1.2.3 foo-powerpc.tar.gz
ghr download owner/repo latest foo-powerpc.tar.gz
EOF
}
api_get() {
curl -fsSL \
-H 'Accept: application/vnd.github+json' \
"$@"
}
release_url() {
local repo=$1
local tag=$2
if [[ $tag == latest ]]; then
printf '%s/repos/%s/releases/latest\n' "$api_base" "$repo"
else
printf '%s/repos/%s/releases/tags/%s\n' "$api_base" "$repo" "$tag"
fi
}
cmd_search() {
(($# > 0)) || {
echo 'usage: ghr search QUERY...' >&2
exit 2
}
curl -fsSLG \
-H 'Accept: application/vnd.github+json' \
--data-urlencode "q=$*" \
--data-urlencode 'per_page=30' \
"$api_base/search/repositories" |
jq -r '.items[].full_name'
}
cmd_releases() {
(($# == 1)) || {
echo 'usage: ghr releases OWNER/REPO' >&2
exit 2
}
api_get "$api_base/repos/$1/releases?per_page=100" |
jq -r '.[] | [.tag_name, .name] | @tsv'
}
cmd_assets() {
(($# >= 1 && $# <= 2)) || {
echo 'usage: ghr assets OWNER/REPO [TAG]' >&2
exit 2
}
local repo=$1
local tag=${2:-latest}
api_get "$(release_url "$repo" "$tag")" |
jq -r '.assets[] |
[.name, .size, .browser_download_url] |
@tsv'
}
cmd_download() {
(($# == 3)) || {
echo 'usage: ghr download OWNER/REPO TAG ASSET' >&2
exit 2
}
local repo=$1
local tag=$2
local asset=$3
local url
url=$(
api_get "$(release_url "$repo" "$tag")" |
jq -r --arg asset "$asset" '
.assets[] |
select(.name == $asset) |
.browser_download_url
'
)
if [[ -z $url ]]; then
echo "ghr: asset not found: $asset" >&2
exit 1
fi
curl -fL -O "$url"
}
main() {
(($# > 0)) || {
usage >&2
exit 2
}
local command=$1
shift
case $command in
search)
cmd_search "$@"
;;
releases)
cmd_releases "$@"
;;
assets)
cmd_assets "$@"
;;
download)
cmd_download "$@"
;;
-h|--help|help)
usage
;;
*)
echo "ghr: unknown command: $command" >&2
usage >&2
exit 2
;;
esac
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment