- Add GraphQL client fetching profile, stats, language aggregation, and per-repo commit histograms for the productive-time heatmap. - Render real SVG cards (profile details, top languages, stats grid, weekday×hour heatmap) with XML escaping and thousands-formatted numbers. - Expand theme palette to 30 built-ins ported from github-readme-stats; add -list-themes, multi-theme rendering, and 'all' shortcut. - Package as Docker-based GitHub Action (action.yml, Dockerfile, entrypoint.sh) with optional auto-commit of generated cards. - Release workflow publishes GHCR image and cross-platform binaries on v* tags. - Unit tests cover rendering, XML escape, number formatting, language sort.
5.4 KiB
ghstats
Generate SVG cards summarizing a GitHub user's profile — written in Go.
ghstats is a single-binary CLI (and a GitHub Action wrapping it) that fetches
public data for a GitHub user and writes a themed set of SVGs you can embed in
your profile README:
- Profile details
- Top languages
- Stats (stars, commits, PRs, issues, PR reviews, contributed-to)
- Productive time heatmap (weekday × hour)
Use as a GitHub Action (recommended)
Drop this in .github/workflows/ghstats.yml in your profile repo (the one
named after your username):
name: ghstats
on:
schedule:
- cron: "0 0 * * *" # daily
workflow_dispatch:
permissions:
contents: write
jobs:
cards:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: tiennm99/ghstats@v1
with:
user: ${{ github.repository_owner }}
token: ${{ secrets.GHSTATS_TOKEN }} # classic PAT with read:user + repo
themes: dracula,github-dark,tokyonight
tz: Asia/Saigon
commit_changes: "true"
Then embed the cards in your README.md:




Action inputs
| Input | Default | Description |
|---|---|---|
user |
— | GitHub username (required) |
token |
${{ github.token }} |
PAT with read:user + repo for private repo stats |
out |
output |
Output directory |
themes |
dracula |
Comma-separated theme ids, or all |
tz |
UTC |
IANA tz for the productive-time card (e.g. Asia/Saigon) |
top_repos |
10 |
Owned repos sampled for commit heatmap (0 to skip) |
commits_per_repo |
100 |
Max commits sampled per repo |
commit_changes |
false |
Commit generated cards back to the repo |
commit_message |
chore: update ghstats cards |
Commit message |
commit_branch |
(current ref) | Target branch for auto-commit |
author_name |
github-actions[bot] |
Commit author |
author_email |
…@users.noreply.github.com |
Commit email |
Use as a CLI
go install github.com/tiennm99/ghstats@latest
Or build from source:
git clone https://github.com/tiennm99/ghstats
cd ghstats
go build -o ghstats .
Then:
export GITHUB_TOKEN=ghp_xxx
ghstats -user tiennm99 -themes dracula,github-dark -tz Asia/Saigon -out output
| Flag | Default | Description |
|---|---|---|
-user |
(required) | GitHub username |
-token |
$GITHUB_TOKEN |
Personal access token |
-out |
output |
Output directory (<out>/<theme>/…svg) |
-themes |
dracula |
Comma-separated theme ids, or all |
-tz |
Local |
IANA timezone for productive-time heatmap |
-top-repos |
10 |
Owned repos sampled for heatmap (0 to skip) |
-commits-per-repo |
100 |
Max commits sampled per repo |
-list-themes |
Print available theme ids and exit |
Themes
Run ghstats -list-themes for the full list. Built-ins include default,
dark, dracula, github, github-dark, tokyonight, onedark, nord,
gruvbox, radical, synthwave, monokai, solarized-dark,
solarized-light, transparent, and more.
Output
output/
dracula/
0-profile-details.svg
1-languages.svg
2-stats.svg
3-productive-time.svg
Tokens & permissions
The default ${{ github.token }} can read public user data but will not see
your private-repo commits. For accurate stats, create a classic personal
access token with read:user and repo, save it as a repo secret (e.g.
GHSTATS_TOKEN), and pass it via the token input.
Credits & inspiration
- github-profile-summary-cards by @vn7n24fzkq — card layout, theme set, and output structure.
- profile-summary-for-github by @tipsy — the original profile-summary generator.
- github-readme-stats by @anuraghazra — theme palette reference.
License
Apache-2.0 — see LICENSE.