docs(readme): refresh for 9-card layout, seed sampling, visibility flags

This commit is contained in:
2026-04-18 22:10:00 +07:00
parent ed7ff1b7cd
commit 0168fd1f56
+71 -32
View File
@@ -3,14 +3,22 @@
> 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:
data for a GitHub user and writes a themed set of SVGs you can embed in your
profile README:
- Profile details
- Repos per language (how many owned repos use each language as primary)
- Most commit language (last year's commits attributed to each repo's primary language)
- Stats (stars, commits, PRs, issues, PR reviews, contributed-to)
- Productive time heatmap (weekday × hour)
| # | Card | What it shows |
| --- | --- | --- |
| 0 | Profile details | Login (Name) title + Octicon-labelled rows for company, location, link, join date (with age), followers/following, public repos |
| 1 | Repos per language | Donut + legend: how many owned non-fork repos use each language as primary |
| 2 | Most commit language (last year) | Donut + legend: last-year commits byte-weighted across each repo's language breakdown |
| 3 | Stats | Star, commit (lifetime + last-year), PR, issue, PR-review, contributed-to totals |
| 4 | Productive time (last year) | 24-hour bar chart with axes, title includes `UTC±N.NN` |
| 5 | Contributions (last year) | Smooth monthly area chart, Y-axis mirrored both sides, `mm/yy` labels |
| 6 | **Most commit language (all time)** | Same as #2 but over lifetime commits |
| 7 | **Productive time (all time)** | Same as #4 but over lifetime commits |
| 8 | **Contributions (all time)** | Area chart across every active year, auto-thinned x-axis labels |
Live dracula sample ships in [`output/dracula/`](./output/dracula).
## Use as a GitHub Action (recommended)
@@ -39,6 +47,8 @@ jobs:
token: ${{ secrets.GHSTATS_TOKEN }} # classic PAT with read:user + repo
themes: dracula,github_dark,tokyonight
tz: Asia/Saigon
include_forks: "false"
include_private: "false"
commit_changes: "true"
```
@@ -50,24 +60,30 @@ Then embed the cards in your `README.md`:
![most-commit-language](./output/dracula/2-most-commit-language.svg)
![stats](./output/dracula/3-stats.svg)
![productive-time](./output/dracula/4-productive-time.svg)
![contributions](./output/dracula/5-contributions.svg)
![most-commit-language-all-time](./output/dracula/6-most-commit-language-all-time.svg)
![productive-time-all-time](./output/dracula/7-productive-time-all-time.svg)
![contributions-all-time](./output/dracula/8-contributions-all-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 |
| 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` | `0` | Optional cap on seed repos probed for commit history (`0` = unlimited) |
| `commits_per_repo` | `500` | Max commits sampled per repo (covers last-year and all-time aggregates) |
| `include_forks` | `false` | Include forked repos in stats and commit probing |
| `include_private` | `false` | Include private repos (requires PAT with `repo` scope) |
| `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
@@ -90,16 +106,31 @@ 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 |
| 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 cards |
| `-top-repos` | `0` | Optional cap on seed repos probed (`0` = unlimited) |
| `-commits-per-repo` | `500` | Max commits sampled per repo |
| `-include-forks` | `false` | Include forked repos in the stats |
| `-include-private` | `false` | Include private repos (requires `repo` PAT scope) |
| `-list-themes` | | Print available theme ids and exit |
## How attribution works
**Repo sampling** uses a seed list built from `contributionsCollection.commitContributionsByRepository`, unioned across every active contribution year. This catches every repo you've committed in — not just your top-starred ones.
**Commit-to-language** is byte-weighted: each commit credits every language in the repo, proportional to linguist's byte share. A commit to a 60% Go / 40% Python repo adds 0.6 to Go and 0.4 to Python, regardless of which file was touched. Caveats:
- Linguist excludes prose (Markdown, AsciiDoc, reST) from byte counts, so heavily-Markdown repos skew toward whatever small code fraction linguist did detect.
- For per-file accuracy, a future `-accurate-languages` mode is planned (per-commit REST + go-enry).
**Cost per run** (current defaults, typical user):
- ~1 profile query + ~1 query per active year + ~50 commit-history pages ≈ **50-70 GraphQL calls**.
- Zero REST calls. Well under the 5000 points/hr budget.
## Themes
@@ -119,14 +150,22 @@ output/
2-most-commit-language.svg
3-stats.svg
4-productive-time.svg
5-contributions.svg
6-most-commit-language-all-time.svg
7-productive-time-all-time.svg
8-contributions-all-time.svg
```
Only the `dracula` theme is tracked in git as a reference sample; other
themes are rebuilt on each run and gitignored.
## 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.
`GHSTATS_TOKEN`), and pass it via the `token` input. Then pair with
`include_private: "true"` to have those commits actually counted.
## Credits & inspiration