Files
ghstats/README.md
T
tiennm99 ff4975fae2 feat: implement profile summary cards with GraphQL fetch and Action wrapper
- 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.
2026-04-18 18:39:51 +07:00

5.4 KiB
Raw Blame History

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)

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:

![profile](./output/dracula/0-profile-details.svg)
![languages](./output/dracula/1-languages.svg)
![stats](./output/dracula/2-stats.svg)
![productive-time](./output/dracula/3-productive-time.svg)

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

License

Apache-2.0 — see LICENSE.