Skip to main content

Print your current-period GitHub Copilot spend and reset date.

Project description

copilot-spend

Find out what your Copilot habit actually costs.

A small Python CLI that reads your GitHub Copilot quota and prints your current-period spend in dollars and PRUs, plus when the period resets. Works against both github.com and GitHub Enterprise hosts.

How it works

flowchart TD
    Start([copilot-spend ...]) --> Cmd{subcommand?}

    Cmd -- login --> Host[prompt: github.com or GHE host]
    Host --> DeviceCode[POST /login/device/code]
    DeviceCode --> ShowCode[show user code + verification URL]
    ShowCode --> Poll[poll /login/oauth/access_token]
    Poll -- access_denied / expired --> LoginFail[/exit 2: login failed/]
    Poll -- ghu_ token --> Verify[verify token works<br/>GET /copilot_internal/user]
    Verify -- fail --> LoginFail
    Verify -- ok --> WriteAuth[write auth.json 0o600]
    WriteAuth --> LoginDone[/exit 0/]

    Cmd -- logout --> DeleteFiles[delete auth.json]
    DeleteFiles --> LogoutDone[/exit 0/]

    Cmd -- bare --> Native{native<br/>~/.config/copilot-spend/auth.json?}
    Native -- yes --> NativeBearer[bearer = ghu_ token]
    Native -- no --> Opencode{opencode<br/>~/.local/share/opencode/auth.json?}
    Opencode -- yes --> OpencodeBearer[bearer = gho_ token]
    Opencode -- no --> NoCreds[/exit 2: run copilot-spend login/]
    NativeBearer --> Quota[GET /copilot_internal/user with Bearer]
    OpencodeBearer --> Quota
    Quota -- 200 --> Print[/print spend + reset date<br/>exit 0/]
    Quota -- 401 / 403 --> AuthErr[/exit 2: re-authenticate/]
    Quota -- 404 --> NoSub[/exit 4: no Copilot quota/]
    Quota -- 5xx / timeout --> ApiErr[/exit 3: API error/]

The bare copilot-spend invocation, expanded as numbered steps:

  1. Resolves a GitHub Copilot token from the first source that exists, in this order:
    1. Native: ~/.config/copilot-spend/auth.json, created by running copilot-spend login.
    2. Opencode fallback: ~/.local/share/opencode/auth.json (keys github-copilot.access and github-copilot.enterpriseUrl), if opencode is installed.
  2. Uses the resolved token directly as the Bearer for the next step. Both source kinds work the same way: native gives a ghu_… GitHub App user-to-server token, opencode gives a gho_… OAuth App token, and /copilot_internal/user accepts either one directly.
  3. Calls GET /api/v3/copilot_internal/user on your GHE host, or GET https://api.github.com/copilot_internal/user if no enterprise host is configured.
  4. Computes the billable overage: billable_PRUs = max(0, consumed - entitlement), then dollars_owed = billable_PRUs × $0.04. The first entitlement PRUs each period are included with your plan and cost nothing.
  5. Prints a plain-text summary on stdout.

No background daemon. No history. No session-token cache. One HTTP request per run.

Requirements

  • Python 3.10 or newer
  • macOS or Linux
  • A GitHub Copilot token, obtained by either:
    • running copilot-spend login, or
    • having opencode installed and authenticated already

Install

# Option A: pipx (persistent, isolated)
pipx install copilot-spend

# Option B: pip (into your active environment or --user)
pip install copilot-spend

# Option C: uv tool (persistent, isolated)
uv tool install copilot-spend

# Option D: one-off run, no install
uvx copilot-spend
pipx run copilot-spend

Install from source

git clone https://github.com/nkootstra/copilot-spend.git
cd copilot-spend

pipx install .
# or:
uv tool install --from . copilot-spend
# or one-off:
uvx --from . copilot-spend

Usage

copilot-spend          # print current-period quota
copilot-spend login    # authenticate via GitHub OAuth device flow
copilot-spend logout   # remove copilot-spend's stored credentials

copilot-spend login prompts for github.com or a GHE host, shows a device code with a URL to visit, then polls until you complete the flow in your browser. The new token is verified against /copilot_internal/user before anything gets persisted. Credentials land in ~/.config/copilot-spend/auth.json (mode 0o600). If you already have opencode authenticated, the bare copilot-spend command continues to work without login.

Example output (under your allowance):

GitHub Copilot - your-login (business)
  Used:      221 PRUs
  Allowance: $12.00  (300 PRUs included)
  Remaining: $3.16  (79 PRUs of free allowance left)
  Resets:    May 31, 2026 (in 15 days)

Example output (over your allowance — billable overage):

GitHub Copilot - your-login (business)
  Used:      4073 PRUs
  Allowance: $12.00  (300 PRUs included)
  Billable:  $150.92  (3773 PRUs over allowance at $0.04/PRU)
  Resets:    Jun 01, 2026 (in 16 days)

Flags: --help, --version. Subcommands: login, logout.

Exit codes

Code Meaning
0 Success
1 Unexpected error
2 Auth error (missing/invalid auth.json or token)
3 API error (network, timeout, 4xx/5xx)
4 No Copilot quota on the account

Switch to your own GitHub App

copilot-spend login runs the GitHub OAuth device flow against Microsoft's well-known VS Code Copilot GitHub App (Iv1.b507a08c87ecfe98). This is the same client ID used by every working third-party Copilot tool — copilot.vim, avante.nvim, LiteLLM, and others — because GitHub's session-token exchange endpoint (/copilot_internal/v2/token) only accepts tokens issued by a GitHub App, not by an OAuth App.

The trade-off: the GitHub consent screen during login says "GitHub for VS Code" rather than "copilot-spend", and you depend on Microsoft not rotating that app. To remove both, register your own GitHub App and swap the constant:

  1. Visit https://github.com/settings/apps and click New GitHub App. This must be a GitHub App, not an OAuth App — OAuth Apps issue gho_… tokens that the Copilot exchange endpoint rejects with 404.
  2. Set Homepage URL and Callback URL to anything (the device flow does not use them).
  3. Enable Device flow under "Identifying and authorizing users".
  4. Account permissions: none required beyond user identification. The read:user OAuth scope is enough.
  5. Note the resulting Client ID (starts with Iv23 or Iv1.).
  6. Replace the CLIENT_ID constant in src/copilot_spend/login.py with your new client ID.
  7. Rebuild/reinstall (pipx install --force . or uv tool install --force --from . copilot-spend).

After the swap, the consent screen shows your app's name and your copilot-spend install no longer breaks if Microsoft rotates Iv1.b507a08c87ecfe98.

Caveats

  • The PRU price is hardcoded at $0.04 (correct as of 2026-05). Update the constant in src/copilot_spend/quota.py if GitHub changes it.
  • v1 ships with VS Code's GitHub App ID Iv1.b507a08c87ecfe98 for the device flow. See "Switch to your own GitHub App" above to remove the dependency.
  • The billing model assumed: the first entitlement PRUs each period are included with your plan, and anything beyond that is billable at $0.04 per PRU. This matches observed behavior on a business plan. Org-level caps or contracts may change what you actually pay — treat the Billable figure as a personal estimate, not an invoice.
  • The reset-date field name in the Copilot API response is best-effort: copilot-spend tries the field names observed on a real response, plus a few defensive fallbacks, and prints next reset: unknown if none match. Adjust RESET_FIELD_CANDIDATES in quota.py if your response uses a different name.
  • The /copilot_internal/user endpoint is not a public, documented API. GitHub may change its shape at any time.

Development

python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

copilot_spend-0.1.0.tar.gz (26.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

copilot_spend-0.1.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file copilot_spend-0.1.0.tar.gz.

File metadata

  • Download URL: copilot_spend-0.1.0.tar.gz
  • Upload date:
  • Size: 26.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for copilot_spend-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0bc7d5b36af01b4571a47e23697d4931f0f3b6f325a226a6d4b270fea468ac88
MD5 64c232dc4c65016ae0313385ce38b8db
BLAKE2b-256 a7669914a65af1b076beaad715c50b7cda699113c093946910f1ba5d4ec3b9ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for copilot_spend-0.1.0.tar.gz:

Publisher: release.yml on nkootstra/copilot-spend

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file copilot_spend-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: copilot_spend-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for copilot_spend-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 51f244c8b39cc017e2087f5208d217ffaa652167d2aed8492c7dffb8a9aa0f42
MD5 a60cf019b51ed9fbc2993548ae16dd4c
BLAKE2b-256 55f991065c5b67b39e12cba63e3c7d76262cd25d39b191f5f3d8110708515b84

See more details on using hashes here.

Provenance

The following attestation bundles were made for copilot_spend-0.1.0-py3-none-any.whl:

Publisher: release.yml on nkootstra/copilot-spend

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page