Skip to content

Actions budget

node ~/.claude/scripts/fleet/actions-budget.js probe tells you how much of an account’s GitHub Actions minutes are spent before the spending limit stops every job. When the limit is reached, each job dies at startup and nothing says why (todo #1648). This probe turns that into a figure you see in advance (#1695, cap #1690).

A run that has already died at startup is reported by the CI locus resolver as “jobs never started” (CI Locus, #1731). This page covers the forward-looking half: how close the account is.

One record per repo owner (bob-actions-budget/1):

Key Meaning
owner The account, lower-cased.
kind user or org, whichever endpoint answered; null when neither did.
verdict ok, warn, over, unknown or unavailable (below).
used_minutes Actions minutes used this billing cycle (billing endpoint) or this calendar month (usage report).
included_minutes The plan’s included minutes; from the billing endpoint, else BOB_ACTIONS_INCLUDED_MINUTES, else null.
paid_minutes / net_amount Minutes or charges past the included quota this period.
pct used_minutes ÷ included_minutes, one decimal; null without a quota.
warn_pct The warn threshold applied.
source billing-actions or usage-report.
reason, fix Why the verdict is not ok/warn, and the command or setting that fixes it.
checked_at When the API was read (a cached answer keeps its time and adds cached: true).
Verdict Meaning
ok Below the warn threshold.
warn At or above BOB_ACTIONS_WARN_PCT (default 80) of the included minutes.
over The included minutes are spent (pct ≥ 100, or paid minutes or a net charge this period). Jobs now run against the spending limit and die at startup when it is reached.
unknown Minutes are measured but the quota is not known. The usage report does not carry it, so set BOB_ACTIONS_INCLUDED_MINUTES.
unavailable Not measured. The token cannot read billing, or the API failed. The caller never fails because of it, and it is never treated as ok.

For each owner it tries the users/ endpoints and then the orgs/ endpoints:

  1. GET /{users|orgs}/<owner>/settings/billing/actions returns the included minutes and the minutes used this cycle.
  2. GET /{users|orgs}/<owner>/settings/billing/usage?year=&month=, the enhanced-billing usage report. Only rows with product actions and unit minutes are summed.

Scope. A user’s billing needs a token with the user scope. A default gh auth login token does not have it, so the verdict is unavailable with the fix gh auth refresh -h github.com -s user. A scope refusal settles the answer for that owner after one call, because the other endpoint needs the same scope. An organization’s billing needs an owner or billing-manager token.

Cache. Each answer is kept in $BOB_HOME/.actions-budget.json for BOB_ACTIONS_BUDGET_TTL_MIN minutes (default 360), and that includes an unavailable answer. A snapshot therefore costs at most two gh calls per owner a few times a day. A cached figure is re-graded on every read, so a new warn threshold takes effect at once. --fresh bypasses the cache.

  • Fleet snapshot. summary.actions_budget is {verdict, warn_pct, owners[]}, one record per distinct owner of this machine’s projects, taken from each project’s repo. verdict is the worst one. It is null when no project has a GitHub origin, or when BOB_FLEET_ACTIONS_PROBE=0. See Fleet Snapshot Timer.
  • audit.js view. An Actions budget table has one row per owner across the fleet: OWNER VERDICT USED% USED INCLUDED NOTE. Where several machines report an owner, the newest measured answer wins. An unreadable owner shows its fix in NOTE.
  • /what-next --report. The line under the health line comes from actions-budget.js line --cwd <project>. A warn does not change the health verdict. The catch-up names it as a risk.
Terminal window
node ~/.claude/scripts/fleet/actions-budget.js probe [--owner O]... [--repo O/R] [--cwd DIR] [--fresh] [--json]
node ~/.claude/scripts/fleet/actions-budget.js line [--repo O/R] [--cwd DIR] [--fresh]

probe defaults to the owner of the checkout’s origin. Its exit codes: 0 when every owner is ok, unknown or unavailable, 1 when any is warn or over, 2 on a usage error. line always exits 0:

Actions: paulirv: 84% of 3000 included minutes used (2520 min) WARN (≥80%)
Actions: paulirv: usage unavailable — the gh token cannot read billing (no `user` scope) (fix: gh auth refresh -h github.com -s user)
Actions: not measured — no GitHub origin
Variable Default Effect
BOB_ACTIONS_WARN_PCT 80 The warn threshold, in percent of the included minutes.
BOB_ACTIONS_INCLUDED_MINUTES unset The quota for an owner whose answer does not carry one.
BOB_ACTIONS_BUDGET_TTL_MIN 360 How long a cached answer is reused.
BOB_FLEET_ACTIONS_PROBE unset 0 leaves summary.actions_budget null and makes no billing call.

tests/test-actions-budget.sh drives the CLI, the snapshot and the view against a stub gh. The owners it covers are ok, warn, an org over quota, a scope refusal and a usage-report-only owner. It also tests the cache, --fresh and the opt-out.