Generate GitHub language stats as JSON or SVG charts with multiple themes.
- Node.js 18+ (for built-in
fetch) - pnpm 10 (see
packageManagerinpackage.json) - A GitHub token with access to private repositories if needed
pnpm install
pnpm run buildGITHUB_TOKEN=your_token npx @saadjs/gh-stats --svg --out stats.svgnpx @saadjs/gh-stats --svg --theme phosphor --in data.json --out stats.svgBuild first, then link globally or install from the local path.
pnpm run build
pnpm link --globalOr:
pnpm run build
pnpm add -g .GITHUB_TOKEN=your_token gh-statsJSON schema (for custom inputs)
{
"type": "object",
"required": [
"totalBytes",
"languages",
"generatedAt",
"repositoryCount",
"includedForks",
"includedArchived",
"includedMarkdown"
],
"properties": {
"totalBytes": { "type": "number" },
"languages": {
"type": "array",
"items": {
"type": "object",
"required": ["language", "bytes", "percent"],
"properties": {
"language": { "type": "string" },
"bytes": { "type": "number" },
"percent": { "type": "number" }
},
"additionalProperties": false
}
},
"generatedAt": { "type": "string", "format": "date-time" },
"repositoryCount": { "type": "number" },
"includedForks": { "type": "boolean" },
"includedArchived": { "type": "boolean" },
"includedMarkdown": { "type": "boolean" }
},
"additionalProperties": false
}GITHUB_TOKEN=your_token gh-stats --svg --out stats.svgGenerate the JSON once, then re-render SVGs with different themes without hitting the GitHub API.
GITHUB_TOKEN=your_token gh-stats --json --out data.jsongh-stats --svg --theme phosphor --in data.json --out stats.svg
gh-stats --svg --theme infrared --in data.json --out stats.svg
gh-stats --svg --theme pie --in data.json --out stats.svgUse a scheduled GitHub Actions workflow to regenerate stats.svg and commit it back to the
profile README repo (<username>/<username>).
Example workflow setup
Create .github/workflows/update-stats.yml in the profile repo:
name: Update GH Stats
on:
schedule:
- cron: "0 6 * * *" # daily at 06:00 UTC
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install
- run: pnpm run build
- run: GITHUB_TOKEN=${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} gh-stats --svg --out stats.svg
- run: |
if [[ -n "$(git status --porcelain)" ]]; then
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add stats.svg
git commit -m "chore: update language stats"
git push
fiNotes:
- For public-only stats,
GITHUB_TOKENis enough. - For private repos, add a PAT as
GH_TOKENin repo secrets (withreposcope). - Embed the SVG in your profile
README.mdwith.
--token <token>GitHub access token (or useGITHUB_TOKEN)--format <json|svg>choose output format--jsonoutput JSON--svgoutput SVG--theme <name>choose SVG theme: default, phosphor, infrared, outline, pie--in <path>read precomputed stats JSON (skips GitHub API)--include-forksinclude forked repositories (default: excluded)--exclude-archivedexclude archived repositories (default: included)--include-markdowninclude Markdown/MDX in language stats (default: excluded)--top <n>limit to top N languages (default: 10)--allinclude all languages (overrides--top)--out <path>write output to a file--help/-hshow help
For private repos, use a token with repo scope. For public-only, public_repo is enough.
pnpm testGitHub’s API reports language byte totals per repository, not per-user LOC. Per-user attribution requires cloning and analyzing repositories locally.