Skip to content

Repository files navigation

GitHub Profiler

A Go CLI that analyzes a GitHub account via the GitHub REST API and produces a JSON evidence document describing the authenticated user's engineering activity. It is useful for building an engineering CV, portfolio, or profile: for every repository the user has contributed to, it records commit activity, programming languages, permissions, and links back to the actual commits.

Features

  • Authenticates against GitHub and scans every repository the token can access (owned, collaborated, and organization membership).
  • Per repository, captures:
    • Metadata: URL, visibility, description, default branch, fork/archived flags
    • Your permissions (admin, maintain, push, triage, pull)
    • Activity: total commit count, first and last contribution dates
    • Language breakdown with byte counts and percentages
    • The 20 most recent commits (SHA, message, author, date, URL)
    • A human-readable safe_summary line suitable for a CV
  • Aggregate totals across all scanned repositories.
  • Concurrent scanning (worker pool) for speed.
  • Skips forked repositories by default; optionally includes them.
  • Optional -since filter to count only commits after a given date.

Requirements

  • Go 1.25 or newer (go.mod declares go 1.25.0)
  • A GitHub personal access token (classic or fine-grained) with read access to the repositories you want to scan. A classic token with the repo scope works for private repositories; a public-only token covers public contributions.

Installation

go build -o github-profiler .

Create a GitHub token

The CLI requires a token in GITHUB_TOKEN. Keep it private: do not commit it, add it to a source file, or share it in screenshots.

Option 1: GitHub CLI (recommended)

Install GitHub CLI, then authenticate in your browser:

gh auth login

Choose GitHub.com, HTTPS, then Login with a web browser. Confirm the authorization, then use the token GitHub CLI stores securely for the current shell:

export GITHUB_TOKEN="$(gh auth token)"
./github-profiler

Verify the account at any time with:

gh auth status

Option 2: GitHub website

Open GitHub SettingsDeveloper settingsPersonal access tokensFine-grained tokensGenerate new token. Give it a descriptive name, short expiration, and access to the repositories you want to scan. Grant repository Contents: Read-only, generate the token, copy it immediately, then run:

export GITHUB_TOKEN='github_pat_...'
./github-profiler

For private repositories across multiple organizations, a fine-grained token may not cover every resource owner. If your organization allows it, create a classic token with the repo scope instead. See GitHub's official personal access token guide for current permission and organization-approval requirements.

Usage

The token is read from the GITHUB_TOKEN environment variable; it is required.

export GITHUB_TOKEN=ghp_xxx
./github-profiler

The tool logs its progress to stderr and writes the evidence document to a timestamped filename by default, such as evidence-20260806T120000.123456789Z.json. Set -file-name-with-timestamp=false to write to the exact -output path.

Flags

Flag Default Description Token permission when enabled
-output evidence.json Output JSON file path.
-file-name-with-timestamp true Append a UTC timestamp to the output filename.
-with-toon false Write TOON output with a .toon extension.
-since (none) Only count commits since this date.
-concurrency 4 Number of repositories scanned concurrently.
-max-recent-commits 20 Maximum recent commits recorded per repository.
-max-repositories 0 Maximum contributed repositories in final output.
-max-repository-scans 0 Maximum eligible repositories to scan.
-include-forks false Include forked repositories in the scan.
-exclude-private false Exclude private repositories from the scan.
-include-pull-requests false Include pull requests authored by you. Classic: repo; fine-grained: Pull requests: Read-only
-include-reviews false Include pull request reviews submitted by you. Classic: repo; fine-grained: Pull requests: Read-only
-include-issues false Include issues authored by you. Classic: repo; fine-grained: Issues: Read-only
-include-discussions false Include discussions created by you. Classic: repo; fine-grained: Discussions: Read-only
-exclude-repo (none) Exclude an owner/name repository; may be repeated.
-exclude-org (none) Exclude repositories owned by an organization; may be repeated.
-sort-repo-by last-contribution-date-desc Repository sort criterion; may be repeated.

For example, to skip a private repository and a fork:

./github-profiler \
  -max-repository-scans 50 \
  -max-repositories 20 \
  -max-recent-commits 10 \
  -exclude-repo your-account/private-project \
  -exclude-repo upstream/example-fork \
  -exclude-org example-organization

Exclusions are applied before -max-repository-scans, so it caps the number of repositories actually scanned. Repositories are considered in GitHub's full-name sort order. -max-repositories is applied afterwards: it limits the final sorted contributed-repository results and recalculates their totals.

Optional contribution evidence

Commits are always included. The following flags add opt-in evidence and allow a repository to appear when it contains one of these contributions but no attributed commit:

./github-profiler \
  -include-pull-requests \
  -include-reviews \
  -include-issues \
  -include-discussions

For a fine-grained token, grant read access to Pull requests, Issues, and Discussions for the selected repositories. Reviews can generate substantially more API requests because GitHub exposes them per pull request.

A classic token with repo covers all private-repository features above. For public repositories, GitHub permits many endpoints without those private-repository scopes.

Repository sorting

Use -sort-repo-by once or multiple times. Criteria are evaluated in the order provided: the first is the primary sort and each later criterion breaks ties.

./github-profiler \
  -sort-repo-by=star-count-desc \
  -sort-repo-by=project-size-desc

Available criteria:

  • creation-date-desc, creation-date-asc
  • first-contribution-date-desc, first-contribution-date-asc
  • last-contribution-date-desc, last-contribution-date-asc
  • star-count-desc, star-count-asc
  • fork-count-desc, fork-count-asc
  • commit-count-desc, commit-count-asc
  • project-size-desc, project-size-asc

Without this flag, repositories remain sorted by latest contribution first. project-size uses the repository size reported by GitHub, in KB. Each repository also includes its star_count, fork_count, and project_size_kb in the output JSON.

Environment variables

Variable Required Default Description
GITHUB_TOKEN yes Personal access token used for API calls.
GITHUB_API_URL no https://api.github.com Override for GitHub Enterprise API base URL.

Output format

The output is a pretty-printed JSON document with the following top-level structure:

{
  "profile": {
    "github": "octocat",
    "name": "The Octocat",
    "email": "octocat@example.com",
    "generated_at": "2026-08-06T12:00:00Z"
  },
  "totals": {
    "accessible_repositories": 12,
    "contributed_repositories": 8,
    "public_repositories": 5,
    "private_repositories": 3,
    "commits": 342
  },
  "repositories": [
    {
      "repository": "octocat/hello-world",
      "owner": "octocat",
      "name": "hello-world",
      "url": "https://github.com/octocat/hello-world",
      "visibility": "public",
      "description": "My first repository",
      "default_branch": "main",
      "fork": false,
      "archived": false,
      "star_count": 80,
      "fork_count": 9,
      "project_size_kb": 108,
      "permissions": {
        "admin": true,
        "maintain": true,
        "push": true,
        "triage": true,
        "pull": true
      },
      "activity": {
        "commit_count": 42,
        "first_contribution": "2023-01-15T10:00:00Z",
        "last_contribution": "2026-07-30T09:30:00Z"
      },
      "languages": [
        { "name": "Go", "bytes": 20480, "percentage": 80.0 },
        { "name": "Markdown", "bytes": 5120, "percentage": 20.0 }
      ],
      "recent_commits": [
        {
          "sha": "abc123",
          "message": "Fix flaky test",
          "author": "octocat",
          "email": "octocat@example.com",
          "date": "2026-07-30T09:30:00Z",
          "url": "https://github.com/octocat/hello-world/commit/abc123"
        }
      ],
      "safe_summary": "Contributed to My first repository, using primarily Go, Markdown."
    }
  ],
  "warnings": [
    "Only repositories accessible to the supplied token were scanned.",
    "Commit attribution depends on GitHub associating commits with the authenticated username.",
    "Squashed commits, alternate unverified emails, reviews, issues, discussions, and pair-programming activity may be missing.",
    "Private repository names and commit messages must be reviewed before publishing."
  ]
}

Details worth knowing:

  • Repositories with no commits attributed to the authenticated user are omitted.
  • Repositories are sorted by most recent contribution (descending).
  • Languages are sorted by byte count (descending), with percentages rounded to two decimals.
  • Only the first line of each commit message is included in recent_commits.
  • The output file is written with 0600 permissions to keep private data safe.

How it works

  1. GET /user — identifies the authenticated user.
  2. GET /user/repos (paginated, 100 per page) — lists all accessible repositories, covering owner, collaborator, and organization_member affiliations.
  3. For each repository, concurrently:
    • GET /repos/{owner}/{repo}/commits?author={username} (paginated, optional since)
    • GET /repos/{owner}/{repo}/languages
  4. Results are aggregated into the evidence document and written to the output file.

Project structure

The project stays as a single main package because it is a small, self-contained CLI. Files are separated by responsibility so the application flow and GitHub integration are easy to navigate:

.
├── main.go           # CLI orchestration: fetch, analyze, sort, and write
├── config.go         # Flags, environment variables, and validation
├── models.go         # GitHub API and evidence-document data structures
├── github_client.go  # GitHub REST requests, pagination, and API errors
├── analyzer.go       # Concurrent repository analysis and commit evidence
├── evidence.go       # Evidence-document creation and aggregate totals
├── output.go         # JSON serialization and secure file writing
└── helpers.go        # Date, repository-name, summary, and rounding helpers

If the CLI gains more commands or integrations, the next step would be to move these concerns into internal/ packages (for example internal/github and internal/evidence) while keeping main.go as the command entry point.

Caveats

  • The scan only sees repositories the supplied token can access. Totals reflect what the token can see, not necessarily the entire account.
  • Commit counts depend on GitHub's author association. Squashed commits, commits made under unverified or alternate emails, reviews, issues, discussions, and pair-programming work are not counted.
  • The output contains private repository names and commit messages — review the JSON before sharing or publishing it.

About

A Go CLI that analyzes a GitHub account via the GitHub REST API and produces a JSON describing the authenticated user's engineering activity. It is useful for building an engineering CV, portfolio, or profile.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages