See download counts for your GitHub releases across all your repos
By Flavio
Updated
The release page lists each file without a download count. Read download_count with gh, then see every repo you ship in Releases Manager.
You shipped a release, attached a zip, and you want to know how many people downloaded it. Open the release on GitHub and each file row shows its name, size and date, but no count. The count is in the API. Each file you uploaded is a release asset, and each asset has download_count. The GitHub CLI prints it for the repo you are standing in. Releases Manager is the place I use when that same question covers every app I ship, because GitHub still shows one repository at a time.
How to add automatic updates to a Mac app reads this same releases response to see whether a new version exists. A developer’s introduction to GitHub is the short tour of what a release is, if the tag and the asset list are still fuzzy.
What you need
You need gh. On a Mac, install it with Homebrew:
brew install gh
On Omarchy:
omarchy pkg add github-cli
The gh commands below need a GitHub login or token, even for public repositories. Signed in, you get 5,000 requests an hour (see GitHub’s REST API rate limits). Sign in before running the examples:
gh auth login
Releases Manager runs on macOS 14 or later, on Apple silicon and on Intel. After purchasing it, download the app from your Polar receipt, unzip it, and drag Releases Manager to your Applications folder. It is signed with an Apple Developer ID and notarized. The first time you open it, enter the license key from the receipt.
The window is enough for the counts. There is no Releases Manager account. It signs its GitHub requests with the GitHub CLI token after gh auth login, or with GH_TOKEN or GITHUB_TOKEN from its environment, and with a token private repos work too. Without a token it still works for public repos, within GitHub’s limit of 60 unauthenticated requests an hour. The token stays in memory and is not written to disk.
The releases command is optional. With Xcode 26 or a Swift 6.2 toolchain, build it from the purchased source:
./Scripts/install-cli.sh
That puts releases in ~/.local/bin, which needs to be on your PATH.
Read the count for one release
Open Terminal in the repository and name the tag. Here it’s the 1.5.0 release of Tranquillity Maker:
gh release view v1.5.0 --json assets --jq '.assets[] | {name, downloadCount}'
Leave the tag off and gh release view uses the latest release. downloadCount is the CLI’s name for the API field download_count. One line is one uploaded file.
The output has this shape (the count here is made up):
{"name":"Tranquillity-Maker-1.5.0.zip","downloadCount":128}
A release with a zip and a dmg has two numbers. Add them yourself when you want one total for that tag. The release object has no download_count of its own.
The Source code (zip) and Source code (tar.gz) links at the bottom of the release page are not uploaded assets. On the release object they are zipball_url and tarball_url, and those fields have no download_count. GitHub’s releases API is where the asset count lives. The about releases page points at that API for “the number of times people download a release asset.”
Add up the releases in that repo
The latest tag is one release, and people keep downloading the previous one. List every release and the assets on it:
gh api --paginate "repos/{owner}/{repo}/releases" --jq '.[] | {tag: .tag_name, assets: [.assets[] | {name, download_count}]}'
{owner} and {repo} are filled in from the checkout you are in. This endpoint uses the underscore name, download_count. gh release view --json uses downloadCount. Same number, two spellings.
A single request returns one page of releases. --paginate follows the rest, and each page is its own JSON array. The number on each asset is the total since that file was uploaded.
There is no GitHub call that sums this across every repository you own. You repeat the command in each checkout, and a long list of repositories uses multiple API requests, especially when each one has several pages of releases.
Calculate a total you can explain
Say a release has a zip with 128 downloads, a DMG with 42, and checksums.txt with 17. Adding every asset gives 187, and the app packages alone give 170. These are downloads, not installs: one person can download twice, and an updater or build script can fetch an asset too.
Use a filename filter that matches the packages you actually distribute. This example needs jq and includes only ZIP and DMG assets from published, non-prerelease releases:
releases=$(gh api --paginate --slurp 'repos/{owner}/{repo}/releases') &&
printf '%s\n' "$releases" | jq '[.[][]
| select(.draft == false and .prerelease == false)
| .assets[]
| select(.name | test("\\.(zip|dmg)$"; "i"))
| .download_count] | add // 0'
The assignment must succeed before jq runs. If GitHub returns an error partway through pagination, this command fails instead of printing a partial total.
--paginate fetches all pages. --slurp wraps those page arrays in another array, which is why .[][] appears twice. The final // 0 gives an empty repository a useful result. These flags are documented in the GitHub CLI API command.
For a daily comparison, save the asset IDs alongside their counts. If an asset goes from 128 to 146, that’s 18 downloads between the two readings. If you deleted the old asset and uploaded a new zip, the new asset has a different ID and its counter starts again, so treat it as a replacement, not a negative day. GitHub exposes those fields in its release asset API.
See every repo on one timeline
Open Releases Manager. Drop a project folder on the window, press ⌘O, or click Add More… and then Choose Folder…. It reads the git remote and fetches that project’s GitHub releases.
Latest Releases puts every tracked project on one timeline, grouped by day. Each row shows what changed and how many downloads its assets have. The changes come from the project’s CHANGELOG.md, or from the “What’s new” part of the release notes on GitHub. The release that launched an app has a green background.
Downloads shows totals and trends. GitHub only reports the cumulative total, so Releases Manager stores an observation each day and draws the history from those saved points. A project you added today does not arrive with months of daily measurements. The total is whatever GitHub has now. The trend starts the day the project was added.
Open a project for its version, the file that version comes from, the branch, the commits since the last release, and every release with its downloads. ⌘R refreshes immediately. The app also refreshes on its own, and again when you switch back to it.
Ask for the same numbers from the terminal
From a machine where releases is installed, pass the folder name of a project you added, not a GitHub login:
releases show tranquillity-maker --json
releases recent is the timeline. Every command accepts --json, and releases help --json lists the rest. The app watches the project list, so a project added from the terminal shows up in the window.
If something looks wrong
If downloadCount is 0, or the asset list is empty, people may have taken the automatic source archive from the bottom of the release page. That link is not an asset, so it has no count. Upload the file you want counted and attach it to the release.
If the list stops after the newest releases, you saw one page. Run the same gh api command with --paginate.
If Releases Manager runs without a token and public repos stop updating after a burst of refreshes, it hit the limit of 60 unauthenticated requests an hour. A 403 or 429 with x-ratelimit-remaining: 0 is that limit. Run gh auth login, or wait for the window to reset.
If Releases Manager shows no releases for a private project, sign in with gh auth login using an account that can read that repo, or set GH_TOKEN or GITHUB_TOKEN in the app’s environment.
If the Downloads trend is only a day long, the chart has the days since you added the project. GitHub’s number on the row is still the cumulative download_count.
If your shell says releases: command not found, run ./Scripts/install-cli.sh from the source checkout and confirm ~/.local/bin is on your PATH. That build needs Xcode 26 or Swift 6.2. The app window works without it.
Get Releases Manager
See every app release on one timeline, find projects waiting to ship, and prepare your next release from your Mac.
See Releases Manager → · Read the docs · $20 including tax, with full source code.
Want me to talk about your product? You can sponsor this site.