DOCS // CLI

How counting works.

Public repos are counted from GitHub every night. Everything else is counted on your own computer by a small tool that reads your git history and sends only numbers. This page is the whole manual.

Setup

Needs Node.js 18+ and git. Sign in on the site first, then in a terminal:

$
  1. A browser tab opens asking you to confirm the link for this computer. Confirm.
  2. It scans your home folder for git repos and counts your commits for the last year.
  3. It prints every repo it found with totals and asks Upload? [Y/n]. Nothing is sent before you answer.
  4. It installs a background sync (macOS launchd, Windows Task Scheduler, Linux systemd user timer) that re-runs every day, also after the machine was off.

Repos outside your home folder: npx @yaroslavhaidash/gitstats-cli@latest link --root /path --root /other. Run it on every computer you commit from.

Commands

Two ways to run them. Always works: npx @yaroslavhaidash/gitstats-cli@latest <command>. Shorter: add ~/.gitstats/bin to your PATH once and use gitstats <command>.

# zsh / bash, once:
echo 'export PATH="$HOME/.gitstats/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
link
Pair this computer, scan for repos, show what it found, upload after you confirm, install the background sync. Re-running replaces the previous link. Options: --root <dir> (repeatable, default: your home folder), --yes (skip the confirmation).
sync
Recount the last year and upload now. Safe to run any time; every run replaces the previous numbers, so amends and rebases correct themselves.
status
Show server, account, machine, scanned folders, emails, and when the last sync ran.
pause
Stop the background sync. Nothing is deleted; `sync` still works by hand.
resume
Start the background sync again.
roots add <dir>
Also scan this folder (for repos outside your home directory). Syncs right away.
add <path>
Track one specific repo wherever it is. Syncs right away.
emails add <email>
Count commits made with another email (a work address, an old one). Syncs right away.
names on
Also send repo names, so your own page shows them instead of private-xxxx. Whether others see names is a separate setting on your profile.
names off
Stop sending names. Already-stored names stay until the next sync replaces them.
update
Install the latest published version now. Every sync also checks once a day on its own; config and schedule are untouched.
unlink
Revoke this computer on the server, remove the background sync and the local config. Your uploaded numbers stay on the board until you delete your account.

What leaves your computer

a keyed hash of the remote URL
HMAC-SHA256 with a secret unique to you. Same repo on two of your machines = one entry. The server cannot turn it back into a URL; it can only confirm a guess.
a language guess
From the extensions of files you changed, lockfiles ignored.
weekly numbers
For each Sunday-to-Saturday week: commits, lines added, lines deleted. Your commits only, on the default branch, merge commits excluded.
commits and lines per day
For each date: how many commits you made and how many lines you added and deleted, so private repos show on your calendar and in the daily charts.
pending work
The same numbers again for commits that only exist on a branch the default branch has not taken in yet. Counted from your pushed branches only — a remote branch whose last commit is under 30 days old — so stale local branches and squash-merged worktrees do not pile up. Shown separately under the numbers on your page — to you and to anyone allowed to see that repo's numbers — and never counted on any board.
repo name
Only if you ran `names on`. Off by default.

Never sent:

  • file contents
  • diffs
  • file or folder names
  • branch names
  • commit messages
  • other people's commits
  • anything about repos you did not commit to

No GitHub token is created and nothing gets access to your GitHub account. The tool runs as you, on your machine, like `git log` does. The source is public at github.com/yaroslavhaidash/gitstats-cli (one file, ~700 lines). Read it before you run it, or watch its traffic with any proxy.

Questions

Is my work repo safe?
Yes. Only weekly counts of your own commits leave the machine, under a keyed hash instead of the repo name. No content, names, paths, or branch names. Nothing touches your employer's GitHub org.
Which commits count?
Commits on the default branch (origin/main or whatever origin/HEAD points to) authored by one of your emails, last 365 days, merge commits excluded. Squash-merged PRs count once. Work sitting on an unmerged branch is counted separately as “pending” by a linked computer: it shows as a faint line under the numbers on your page and as hatched caps on your lines-per-week chart — visible to whoever may see those repos’ numbers, which is your crewmates when you share private repos with them — and it never counts toward a board ranking. Only branches you have pushed count, and only while their last commit is under 30 days old; branches that live on your laptop alone are ignored. On the board, WEEK means this calendar week — Monday 00:00 UTC up to today, not the last seven days — MONTH means the 1st of this month up to today, and YEAR is the last 365 days.
Some of my commits are missing.
Usually the email. Run `status` to see which emails are matched, then `emails add you@work.com`. Or the repo is outside your home folder: `roots add /path`.
Why are the line counts huge?
Lockfiles, generated code and vendored files count as lines, same as on GitHub. The language guess ignores lockfiles, the line totals do not.
I have several worktrees or clones of one repo.
Counted once. The primary clone wins; they all read the same origin/HEAD.
Two laptops?
Run `link` on both. The same repo from both machines is one entry, whichever synced last wins, and they agree because both read origin/HEAD.
How do I stop it?
`pause` keeps the link but stops the background runs. `unlink` revokes the computer, removes the schedule and the local config. You can also hit REVOKE on your settings page; the machine's next sync then fails harmlessly.
How does it update?
On its own, daily. Every sync checks the npm registry at most once a day and, when there is a newer version, installs it and finishes the sync under it — your config and the schedule are untouched. If the check fails you keep the version you have and the reason lands in ~/.gitstats/sync.log. `gitstats update` forces it now, `gitstats sync --no-update` skips the check.
Who sees what?
Your settings page has a two-column matrix: crewmates on one side, everyone else signed in on the other. Per column you pick whether they can open your page, whether private repos count in the numbers they see, and whether repo names are shown, public-only, or hidden. New accounts start open on the numbers and closed on the names: your page is open to everyone signed in, private repos count in both columns, crewmates see public repo names and everyone else sees none. On your own page each repo also has a [hide name] switch that beats the matrix, for the one client repo you would rather not name.
Can I get my data out, or delete it?
Both, on your settings page under Data. EXPORT downloads every row we hold about you as JSON — profile, crews, linked computers, weekly and daily numbers. DELETE ACCOUNT asks you to type your login, then removes all of it from the site and signs you out; a crew you started passes to whoever joined first, and an empty one is deleted. One copy is kept for 30 days, readable only by the site owner, so a delete pressed by mistake can be undone; after that the nightly job drops it. Run `unlink` on each computer to clear the local config as well.
Where does it keep things?
~/.gitstats/config.json (your link token, mode 600), ~/.gitstats/cli (the installed copy), ~/.gitstats/sync.log (background runs), plus one launchd plist / scheduled task / systemd timer.