{{prov}} {{vendorStatus(prov).text}} {{visibleAccounts(prov).length}} of {{(ov.providers[prov]||[]).length}} account(s) · pool free {{cw.label}} {{cw.avail}}%
authpool-agent reauth.
| account | status | Quota usage | Activity and clients | actions | |
|---|---|---|---|---|---|
|
{{a.name}}
{{a.identity}}Login not yet known
Scheduled removal: {{removalTime(a.remove_at)}}
reserves: 5h {{a.max_5h_pct||'—'}} · 7d {{a.max_7d_pct||'—'}}
{{freeLabel(a)}}
|
{{statusText(a)}}
{{providerErrorLabel(a)}}
{{a.provider_error.message}}
{{a.provider_error.source==='cli'?'Reported by Claude Code':'Claude '+a.provider_error.source}} · {{ago(a.provider_error.observed_at*1000)}} · HTTP {{a.provider_error.http_status}}
Provider end time: {{dateTimeShort(a.provider_error.restricted_until)}}
Claude did not provide an end time. Check this account on claude.ai.
Re-authenticate to return this account to rotation.
No credentials stored. Add credentials to use this account.
Duplicate of {{(a.duplicate_of||[]).join(', ')}} · check the login.
Token expired · quota reading is out of date.
Grant has not refreshed in over {{ov.grant_stale_hours}}h.
Temporarily blocked
{{autoUnblockIn(a)}}
{{resetIn(a.blocked_until)}} · {{hasGauge(a)?'a healthy probe can clear it early':'manual unblock available'}}
Client reported a rate or quota limit.
|
Quota usage
Cached · {{ago(dataAsOf(a))}}
{{dataAsOf(a)?'Updated '+ago(dataAsOf(a)):'Awaiting reading'}}
{{w.label}} CLI hit
{{w.stale?'reset':w.pct+'%'}}
{{gaugeEmpty(a)}}
Model quotas {{cardWindows(a,true).length}} windowsNear limit{{w.label}} CLI hit
{{w.stale?'reset':w.pct+'%'}}
|
{{burnChip(a).text}}
· as of {{ago(a.burn.as_of)}}
· projected {{a.projected_pct}}%
⚠ no tenant
preempted
Connected clients {{a.client_count}}×{{c.label||c.key_prefix}} · Fable{{fableSuffix(c)}} ({{idleTenant(c)}})still on {{clientDrift(c,a)}}No clients assigned 📌 forced: , {{c.label||c.key_prefix}}
|
||
|
Credentials: {{a.has_creds?'stored':'missing'}} · token {{ago(a.token_expires_at,true)}}
usage credits {{a.extra_usage.is_enabled?'(on)':'(off)'}}
{{a.extra_usage.utilization_pct}}%
used {{a.extra_usage.used_credits}} / {{a.extra_usage.monthly_limit}}
monthly tools (web search / reader)
{{a.mcp_uses.utilization_pct}}% · {{resetIn(a.mcp_uses.resets_at)}}
used {{fmt(a.mcp_uses.used)}} / {{fmt(a.mcp_uses.limit)}} · never blocks the account (separate tools budget)
plan: {{planOf(a)}}
billing:
Expires {{billingDateTime(a.subscription.expires_at)}}
Renews {{billingDateTime(a.subscription.renewal_at)}}
Paid until {{billingDateTime(a.subscription.period_ends_at)}}
day {{a.subscription.billing_day}} · renews {{renewIn(a)}}
{{a.subscription.status}}
· set by hand
{{a.provider==='claude'||a.provider==='codex'?'Connect billing or select a billing parent':'Not set · edit in caps'}}
usage resets banked: {{a.reset_credits}}
Reset count unavailable
limit resets: {{lr(a,'promo').resets_left}}
· use by {{dateTimeShort(lr(a,'promo').deadline)}} ({{ago(lr(a,'promo').deadline,true)}})
· {{lr(a,'promo').why_not}}
session reset (weekly):
available
used{{lr(a,'session').next_available_at?' · next '+dateTimeShort(lr(a,'session').next_available_at):''}}
· {{lr(a,'session').why_not}}
reserves: 5h {{a.max_5h_pct||'—'}} · 7d {{a.max_7d_pct||'—'}}
grant:
{{a.last_refresh?'refreshed '+ago(a.last_refresh):'not yet'}}
stale >{{ov.grant_stale_hours}}h
reclaimed {{ago(a.last_reclaim_at)}}
drift {{ago(a.last_drift_at)}}
login: {{a.identity||((a.provider==='z.ai'||a.provider==='kimi'||a.provider==='muse')?'— (unknown — set the account email via caps; API keys carry no identity to learn)':a.provider==='claude'?'— (unknown — learns automatically on the next poll/re-auth, or set it via caps)':'— (unknown — learns automatically from the stored credentials on the next poll, or hit ⟳ refresh)')}}
· id {{a.cred_fingerprint}}
⚠ duplicate: {{dupWhy(a)}} as {{(a.duplicate_of||[]).join(', ')}} — both rows are ONE underlying account (identical usage); re-auth one of them into the correct login
models: main {{(a.models||{}).ANTHROPIC_MODEL||'—'}} · opus {{modelOf(a,'OPUS')}} · sonnet {{modelOf(a,'SONNET')}} · haiku {{modelOf(a,'HAIKU')}} · forced
| |||||
| no accounts — add one below | |||||
Global GLM model mapping (Claude Code; overrides per-account)
Global Kimi model mapping (Claude Code; overrides per-account)
Add / replace account credentials
Paste the whole .credentials.json (claude), auth.json (codex), oauth_creds.json (gemini), or the raw API key (z.ai / kimi — sk-kimi-… from kimi.com/code/console, NOT a platform.kimi.ai key; muse — a Meta API key from dev.meta.ai):
Clients {{visibleClients().length}} of {{(ov.clients||[]).length}} match "{{q}}"
| label | status | os / host | ver | installed |
|---|---|---|---|---|
| {{c.label||c.key_prefix}} Fable{{fableSuffix(c)}} | {{c.online?'online':'offline'}} | {{c.os||'?'}} / {{c.hostname||'?'}} | {{c.client_version||'?'}}old | {{installedStr(c)}} |
| no client matches "{{q}}" | ||||
Capacity & cost planning loading…
Measured {{dateTimeShort(cap.since)}} – {{dateTimeShort(cap.now)}} · quota history retained {{cap.retention_days}} days. Longer windows need a complete cycle before release advice is available.
{{g.provider}} · {{g.plan}}
{{g.usable_accounts}} usable / {{g.current_accounts}} enabled · {{g.required_accounts==null?'—':g.required_accounts}} estimated needed
Binding limit: {{g.binding_window||'unknown'}} · monthly spend {{money(g.current_monthly_usd)}} → {{money(g.recommended_monthly_usd)}}
| window | peak / average % | coverage | needed |
|---|---|---|---|
| {{w.window}} | {{w.peak_pct.toFixed(1)}} / {{w.average_cycle_pct.toFixed(1)}} | {{w.coverage_pct}}% | {{w.accounts_needed}} |
{{reason}}
Add accounts and collect quota history to estimate demand.
Claude Code via proxy: Claude ↔ Codex subscription scenarios
{{cap.optimization.assumption}}
{{cap.optimization.reason}} Set account prices in Analysis → Flat-rate costs.
Planning target: {{fmt(cap.optimization.target_output_tokens_per_day)}} output tokens/day, based on observed peak demand and your safety margin. Current Claude/Codex spend: {{money(cap.optimization.current_monthly_usd)}}/month.
| Run transferable work on | accounts | buy | release same plan / others | monthly USD | monthly savings |
|---|---|---|---|---|---|
| {{s.provider}} · {{s.plan}} lowest cost at chosen Claude sharebelow chosen Claude sharecheck model caps | {{s.accounts}} ({{s.claude_accounts}} Claude + {{s.codex_accounts}} Codex) | {{s.buy}} | {{s.release_same_plan}} / {{s.release_other_accounts}} | {{money(s.monthly_usd)}} | {{money(s.savings_usd)}} |
{{cap.note}}
Realtime model usage
moving-average depletion forecast · auto-refreshes every {{predEvery}}sNo gauge readings yet — add accounts with a usage gauge (Claude / Codex / z.ai) and let them poll.
Usage est. cost, last {{usageData.days}}d
{{tokDesc}} — applies to the charts and tables below (the activity heatmap always shows total tokens). It changes which component is shown, never which data: the range above still decides that.
Daily {{tokPhrase}} ({{tokDesc}})
By provider ({{tokSum}}, last {{usageData.days}}d)
a doughnut has one dimension and it is spent on the provider — showing the total; hover a slice for the four components
Model usage ({{msSubtitle}} — the model "market share" over time)
the tokens control above does not apply while the y-axis is {{msAxisLabel}}
the stack is already spent on the model — showing total tokens ({{tokSumText}}); pick a single component above to chart it per model
no per-model usage recorded in this range / filter yet
Activity heatmap ({{heatMetricLbl}} per day × hour, {{heatTzLabel}} local time — live data)
Subscription utilization (daily peak % per account · red = limit hit)
No utilization recorded yet — it accumulates as the server polls each account's gauge (Claude / Codex / z.ai). Build up over a few days.
What 1% actually costs (measured across all accounts — not vendor documentation) ⚠ {{calErr}}
Over a window epoch that ran from A% to B% we attributed T tokens, so 1% = T/(B−A). Interior rounding telescopes away, so a 90-point run carries one ±1-point error rather than ninety. Nothing here is read from vendor documentation — the gauge is measured, not described.
The price of a percent (every completed run, every account — judge the fit before you read the number)
No completed run yet. A run is a stretch of polls inside one window epoch; the first one lands as soon as an account burns measurable gauge inside a single window.
Points above the line = movement we could not attribute (someone else was on this account). Points below = tokens with no movement (a CLI serving on another identity — env-var shadowing). A tight cloud on one slope is a real measurement; two slopes means two plan tiers; a fan means the relationship is not stable over your workload and the headline is a local average, not a constant. The fit passes through the origin because tokens-per-point is a ratio — an intercept would be a different claim. Showing the {{(cal.runs||[]).length}} largest-movement runs.
Every component is at zero. An empty basket buys nothing, so no figure is quoted at it — drag one back up, or press "back to the measured mix".
This basket has zero weight under {{calScaleShort(calVec.from)}}, so a point would buy unboundedly many of these tokens — no figure is quoted. Pick a scaling that charges for them, or mix some back in.
Under {{calScaleShort(calVec.from)}} every token weighs exactly the same, so re-mixing cannot change the answer and these sliders will not move it. Switch to a weighted scaling to watch the mix bite.
"1% = {{calPrec(cal.headline.raw_tokens_per_pct,cal.headline.raw_ci)}} tokens" is false as a bare sentence. Drag cache-read down and watch it collapse: the weighted cost of a point is what holds still, so the same point buys an order of magnitude fewer tokens once you stop buying cache reads. Priced through the {{calScaleShort(calVec.from)}} vector (borrowed — the selected scaling has no four-component vector to price a mix with).
A {{fmt(cal.headline.session_equivalent.raw_tokens)}}-token session costs about {{calH.sess.toFixed(2)}}% — roughly {{Math.floor(100/calH.sess)}} such sessions fill one window. Pooled and median disagree by {{calPctS(cal.headline.pooled_vs_median_gap)}} — one or two runs dominate this estimate. One run is {{calPctS(cal.headline.top_run_share)}} of all movement: this is that run's figure. One account is {{calPctS(cal.headline.top_account_share)}} of all movement. Dropping each run's first and last poll moves the answer by more than 15% — gauge lag is biting, and it is not resolvable finer than one poll interval ({{Math.round(cal.cadence_sec)}}s here).
Your own readings have already refuted the premise
{{calPremise}}
The whole method assumes a run's movement IS consumption against a fixed denominator. That is checked against this pool's existing gauge readings before anything is built on it, and here the check failed — so no price is published, and no amount of further collection would change that. The diagnostics below carry the counts.
Not enough measured movement yet
{{cal.headline_reason}}
At {{cal.eta.runs_per_day}} run(s)/day over the last week, expect a first number around {{tshort(cal.eta.first_number_at).slice(0,10)}}. No date is guessed here: {{cal.eta.basis}}. Collecting since {{tshort(cal.collecting_since).slice(0,10)}}; the gauge side cannot be backfilled, so this measurement genuinely starts when the server that records it does. The gauge side has recorded nothing yet — it starts at this server version, and says so rather than implying older data exists.
We can measure the movement — but not who caused it
{{cal.headline_reason}}
This is not a sample-size problem and waiting will not fix it. {{calPctS(cal.floors.gauge_without_tokens)}} of the {{fmt(Math.round(cal.floors.movement_total_pct))}} points that moved had no attributed tokens behind them, so any price computed from them would be a price for someone else's traffic. Named causes, counted where this system can count them:
A count of not measurable from inside means real and unbounded, never zero. Remedy: get every machine onto the agent, check for a second login on the account, and look for a CLI still serving on a credential it was moved off.
What a token costs, per model family (relative to {{calFamRef||'the most-used family'}} — measured, not assumed by the headline's vector)
{{calPurityBroken}} — the per-model weights below rest on a premise that just failed, and are not trustworthy.
No family has cleared its gate yet — every one of them is listed below with the reason.
Is it requests, tokens, or effort — and how are they combined? (seven frozen candidate scalings, scored on your own runs)
{{cal.unit.reason}} — no candidate is named a winner on this much data.
Inconclusive. Neither {{calScaleShort(calUnitBest)}} (spread {{calPctS(calUnitMad(calUnitBest))}}) nor {{calScaleShort(cal.unit.runner_up)}} (spread {{calPctS(calUnitMad(cal.unit.runner_up))}}) can be named the winner — {{cal.unit.reason}}.
Over your traffic the gauge behaves most like {{calScaleShort(cal.unit.verdict)}} — spread {{calPctS(calUnitMad(cal.unit.verdict))}}, better than {{calScaleShort(cal.unit.runner_up)}} ({{calPctS(calUnitMad(cal.unit.runner_up))}}) with {{calPctS(cal.unit.p_beats_runner_up)}} confidence on a paired bootstrap over your {{cal.unit.runs}} runs. That is how the gauge behaves on this workload, never what it counts. Scored as: {{(cal.scales[cal.unit.verdict]||{}).label}}.
{{cal.unit.separable_question}}. {{cal.unit.note}}.
{{calScaleShort(c.id)}} is drawn but kept out of the ranking — {{c.reason}}.
effort — not identified: {{cal.unit.effort.reason}}. within {{cal.unit.effort.family}} only: {{cal.unit.effort.status==='no_effect'?'no detectable effect':'the two levels differ'}} — · {{e}} {{calNum(g.per_pct,1)}} tok/pt ({{g.runs}} runs) IQR {{calNum(g.iqr[0],1)}}–{{calNum(g.iqr[1],1)}} · IQRs {{cal.unit.effort.iqr_overlap?'overlap, so no effect is detectable':'do not overlap'}}. {{cal.unit.effort.aliasing_note}}.
Per account (a scale belongs to one account on one plan tier — it does not transfer)
| account | plan | raw tok/1% | turns/1% | interval | runs | movement | wide | no tokens | no movement | silent | enriched | weeklies |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {{a.name}} | {{a.plan||'—'}} | — premise refuted {{calPrec(a.raw_tokens_per_pct,a.raw_ci||a.iqr)}} — {{a.status==='floor_too_high'?'unattributable':'not yet'}} | {{(calPremise||a.requests_per_pct==null)?'—':'≈'+a.requests_per_pct.toFixed(2)}} | {{calPremise?'—':(a.raw_ci?calPrec(a.raw_ci[0],a.raw_ci)+'–'+calPrec(a.raw_ci[1],a.raw_ci) :(a.iqr?'IQR '+calPrec(a.iqr[0],a.iqr)+'–'+calPrec(a.iqr[1],a.iqr):'—'))}} | {{a.runs}} | {{Math.round(a.movement_pct)}} pt | {{a.movement_pct?calPctS(a.movement_wide_pct/a.movement_pct):'—'}} | {{calPctS(a.floor_gauge_without_tokens)}} | {{calPctS(a.floor_tokens_without_gauge)}} | {{a.silent_client_intervals||0}} | {{a.runs?calPctS(a.enriched_run_share):'—'}} | {{(a.scoped_weeklies||[]).length?a.scoped_weeklies.join(', '):'none published'}} |
| pool | movement-weighted | {{calPrec(cal.headline.raw_tokens_per_pct,cal.headline.raw_ci)}} | ≈{{(cal.headline.requests_per_pct||0).toFixed(2)}} | {{cal.headline.raw_ci?calPrec(cal.headline.raw_ci[0],cal.headline.raw_ci)+'–'+calPrec(cal.headline.raw_ci[1],cal.headline.raw_ci):'—'}} | {{cal.headline.runs}} | {{Math.round(cal.headline.movement_pct_total)}} pt | — | {{calPctS(cal.floors.gauge_without_tokens)}} | {{calPctS(cal.floors.tokens_without_gauge)}} | — | — | — |
| no accounts in this lane | ||||||||||||
Every price column is blank: {{calPremise}} The run and movement counts beside them are still facts — what cannot be published is what a point COST.
The per-account figures span {{(cal.pool_spread||0).toFixed(1)}}×. Accounts on different plan tiers have different window sizes, so that spread is expected, not an error — and it is exactly why the scatter above shows more than one slope.
What this measurement cannot account for
No gauge movement has been recorded yet, so there is nothing to explain or fail to explain — these two floors stay blank rather than reporting 100% of zero.
(of {{fmt(Math.round(cal.floors.movement_total_pct||0))}} points)
({{fmt(Math.round(cal.floors.movement_blind_pct||0))}} points — a second login, an unmanaged machine, the web app)
(env-var shadowing — served on another identity)
These are two different denominators with opposite causes and they are never summed, differenced or shown as one "unexplained" number. The first is a hard lower bound on what no model of these data can explain; above {{calPctS(0.25)}} it suppresses the headline outright.
Checked where the answer is known
No lane in this range publishes its own used/limit counter, so the estimator cannot be checked against a known answer here. That is a missing check, not a passed one.
This is the honest answer to "what generalizes": the method generalizes and is validated above; the Claude unit finding does not. Codex publishes a percent like Claude, so the method transfers and the number does not. Gemini publishes no gauge at all.
does the payload simply state the denominator? yes — a captured payload carries limit_dollars {{cal.dollar_denominator.limit_dollars}} on {{calWinLbl(cal.dollar_denominator.window)}}, which implies {{calNum(cal.dollar_denominator.implied_raw_tokens_per_pct,1)}} raw tokens per point — that sits {{calPctS(cal.dollar_denominator.agreement)}} away from the measured figure, and a large gap means the pricing table, not the gauge, is what disagrees — but no implied figure yet: {{cal.dollar_denominator.reason}}. no — {{cal.dollar_denominator.reason}} ({{cal.dollar_denominator.captures}} capture(s) inspected). "We looked and it was absent" is a different state from "we never looked".
What this measurement refuses to claim ({{(cal.refusals||[]).length}} refusals, printed verbatim — including the ones that undercut the headline)
Provenance: {{cal.days}}d · {{calWinLbl(cal.window)}} · {{(cal.scales[cal.scale]||{}).label}} ·
{{(cal.runs||[]).length}} run(s) plotted · {{fmt(Math.round(cal.floors.movement_total_pct||0))}} points of movement ·
poll cadence {{Math.round(cal.cadence_sec||0)}}s · {{calWinLbl(cal.window)}} gauge tick
{{calStep==null?'not yet observed on this window':calStep.toFixed(2)+' pt'}} ·
server {{cal.server_version||'?'}} · generated {{ago(cal.generated_at)}}.
Enriched columns are NULL, not zero, on events ingested before client 1.0.33 —
authpool-agent resync-usage re-reads local transcripts and heals them.
Machine → account (current assignments)
| machine | status | claude | codex | gemini |
|---|---|---|---|---|
| {{m.machine}} | {{m.online?'online':'offline'}} | {{(m.accounts||{}).claude||'—'}} | {{(m.accounts||{}).codex||'—'}} | {{(m.accounts||{}).gemini||'—'}} |
| no active assignments | ||||
By machine
| machine | provider | requests | {{tokSum}} | est. cost |
|---|---|---|---|---|
| {{r.machine}} | {{r.provider}} | {{fmt(r.requests)}} | {{fmt(tokVal(r))}} | ${{(r.cost||0).toFixed(2)}} |
| no usage yet | ||||
By provider
| provider | requests | input | output | cache write | cache read | est. cost |
|---|---|---|---|---|---|---|
| {{r.provider}} | {{fmt(r.requests)}} | {{fmt(r.input)}} | {{fmt(r.output)}} | {{fmt(r.cache_write)}} | {{fmt(r.cache_read)}} | ${{(r.cost||0).toFixed(2)}} |
By CLI × vendor
| CLI | vendor | requests | {{tokSum}} | est. cost |
|---|---|---|---|---|
| {{r.cli||'?'}} | {{r.provider}} | {{fmt(r.requests)}} | {{fmt(tokVal(r))}} | ${{(r.cost||0).toFixed(2)}} |
By day
| day | requests | {{tokSum}} | est. cost | vs. busiest day |
|---|---|---|---|---|
| {{r.day}} | {{fmt(r.req)}} | {{fmt(r.tok)}} | ${{r.cost.toFixed(2)}} |
By model
| provider | model | requests | input | output | cache write | cache read | est. cost |
|---|---|---|---|---|---|---|---|
| {{r.provider}} | {{r.model||'?'}} | {{fmt(r.requests)}} | {{fmt(r.input)}} | {{fmt(r.output)}} | {{fmt(r.cache_write)}} | {{fmt(r.cache_read)}} | ${{(r.cost||0).toFixed(2)}} |
Cost is an estimate from the pricing table; the real budget on subscriptions is the % gauges on Overview.
Historic usage (ccusage backfill — all time; no per-account; not summed with the live figures above)
By model (all time)
| provider | model | input | output | cache write | cache read | est. cost |
|---|---|---|---|---|---|---|
| {{r.provider}} | {{r.model||'?'}} | {{fmt(r.input)}} | {{fmt(r.output)}} | {{fmt(r.cache_write)}} | {{fmt(r.cache_read)}} | ${{(r.cost||0).toFixed(2)}} |
By day (all time)
| day | provider | {{tokSum}} | est. cost |
|---|---|---|---|
| {{r.day}} | {{r.provider}} | {{fmt(tokVal(r))}} | ${{(r.cost||0).toFixed(2)}} |
No historic data yet — it's backfilled from ccusage hourly by each agent (client ≥1.0.24) and on client install/update (needs Node + ccusage on that machine). Today's row keeps growing through the day.
Clients / API keys
Client installer
Give each user this download + a per-computer API key (mint one below).
Then on their machine: extract, pip install ".[client]", and
{{enrollCmd}}
{{newKey}}
| label | prefix | OS / host | version | last seen | status | |
|---|---|---|---|---|---|---|
| {{c.label||'—'}} Fable{{fableSuffix(c)}} | {{c.key_prefix}}… | {{c.os_version||c.os||'?'}} · {{c.hostname}} | {{c.client_version||'?'}} update failed ⟳ {{updPhase(c)}} outdated | {{c.online?'online':'offline'}}{{c.last_seen?ago(c.last_seen):'never'}} | {{c.revoked?'revoked':(c.enabled?'enabled':'disabled')}} |
{{routeStatus(c)}}
⟳ updating…
|
Admin users
| user | status | role | last login | |
|---|---|---|---|---|
| {{u.username}} (you) | {{u.disabled?'disabled':'active'}} | super admin admin | {{u.last_login||'—'}} |
Super admins can see the Analysis tab: which enrolled computer spent tokens on which
project, and they manage projects and permanent exclusions there. The admin user is always a super admin.
Flat-rate costs loading…
{{econ.since}} – {{econ.until}} · USD · {{econProvider||'all providers'}}
{{econTotal.unpriced_accounts}} account(s) have missing prices for part or all of the range. These costs are unknown; the multiplier covers priced usage only.
| {{econGroup==='accounts'?'Account':'Provider'}} | API equivalent | subscription spend | API / actual | actual / 1M tokens | price coverage | monthly USD | |
|---|---|---|---|---|---|---|---|
| {{econGroup==='accounts'?r.name:r.provider}} · {{r.provider}} · disabled | {{money(r.api_usd)}} | {{money(r.subscription_usd)}} | {{multiple(r.api_to_actual)}} | {{money(r.effective_usd_per_million)}} | {{r.usage_price_coverage_pct==null?'—':r.usage_price_coverage_pct+'%'}} · {{r.priced_days}}/{{econ.days}} days | {{money(r.monthly_usd)}} | price history{{p.effective_from}}: {{money(p.monthly_usd)}}/month |
| No accounts or tracked usage. | |||||||
{{econ.note}}
Choose “account” to record paid prices. Enter annual or discounted subscriptions as monthly USD equivalents. Use the subscription start date for initial pricing; add later effective dates for price changes and $0 after cancellation. Editing an existing effective date corrects that entry.
Project analysis {{anScopeTitle}} · {{anRangeLbl}} ⚠ {{anErr}}
{{an.coverage.historic_note||'ccusage day totals carry no folder and are not part of this view'}} — the analysis covers the live per-message rows (which include the backfilled transcript history), so its totals are lower than the Usage tab's all-time figures by exactly that. Excluded rows are left out.
Project share ({{anShSub}}) ⚠ {{anShErr}}
no {{anShMeta.phrase}} in this period — pick another metric for the strip
|
{{r.name}} |
{{fmt(r.users)}} | {{r.folders==null?'—':fmt(r.folders)}} | {{anShCell(r,c.k)}}
|
| total {{anShVirt==='1'?'(all traffic)':'(named projects only)'}} | {{anShTotCell(c.k)}} |
all of this period's traffic{{anClient?' for this user':''}} is Unassigned / No folder info, which the “incl. unassigned / no folder” toggle leaves out
nothing recorded in this period{{anClient?' for this user':''}}
loading…
{{anProjTitle}} ({{anMetricMeta.phrase}} per {{anBucketKind}} · grey = no folder info / unassigned)
nothing recorded in this range / filter
{{anUserTitle}} ({{anMetricMeta.phrase}} per {{anBucketKind}})
nothing recorded in this range / filter
Who worked on what (one row per user · colour = that {{anBucketKind}}'s dominant project · brightness = volume, square-root scale · hover for the split)
nothing recorded in this range / filter
Project × user ({{anMetricMeta.phrase}} · % = share of that project)
| project | total | {{c.lbl}} |
|---|---|---|
| {{p.name}} | {{anFmt(p.total)}} | {{anFmt(c.v)}} {{c.pct}}% · |
nothing recorded in this range / filter
Accounts per project (which subscription paid for it)
nothing recorded in this range / filter
Model mix per project
nothing recorded in this range / filter
{{anClientLbl(anClient)}}'s working hours ({{anMetricMeta.phrase}} per weekday × hour, {{anHeatTzLbl}})
no activity in this range
{{anClient?anClientLbl(anClient)+'\'s recent sessions':'Recent sessions'}} (most recent {{an.sessions.length}} with a session id)
| start | duration | user | project | folder | branch | models | {{anMetricMeta.lbl}} |
|---|---|---|---|---|---|---|---|
| {{dateTimeShort(s.start)}} | {{anDur(s)}} | {{anClientLbl(s.client_id)}} |
{{anProjName(s.project_id)}} |
{{anDir(s.folder)}}{{anBase(s.folder)}} |
{{s.git_branch||'—'}} | {{s.cli||s.provider}} {{m}} | {{anFmt(anVal(s))}} |
| no sessions with a session id in this range — they appear as clients on 1.0.39+ report them | |||||||
Folders (every working folder seen, all time · the project each one resolves to)
|
{{anDir(f.folder)}}{{anBase(f.folder)}} |
{{f.ul.join(', ')||'—'}} |
unassigned
{{anProjName(f.project_id)}}
|
{{f.range?anFmt(anVal(f.range)):'—'}} | {{anShort(f.turns)}} turns · {{anUsd(f.cost)}} | {{f.last_day||'—'}} | {{f.br.join(', ')||'—'}} | ||
| {{anFolders.length?'no folder matches this filter':'no folder recorded yet — clients report them from 1.0.39 (and backfill their transcript history once after updating)'}} | ||||||||
Projects (a project collects working folders through rules — several users can reach it from different local paths)
{{anPatHelp}}
No projects yet — create one above, or use new project on a folder row.
{{p.name}}
| pattern | kind | user | matches | |
|---|---|---|---|---|
|
{{s}} {{r.exact?'this folder only':'+ subfolders'}} |
{{anPatKind(r.pattern)}} | {{r.client_id?anClientLbl(r.client_id):'any user'}} | {{(anRuleHits[r.id]||[]).length}} folder(s) | |
| no rules yet — nothing maps to this project | ||||
Analysis exclusions (permanent — for folders or users that must never show up here)
An exclusion keeps a folder — that folder and all its subfolders — for one user or for every user, or a whole user, out of the analysis for good. Matching rows lose their folder, session and branch data immediately and forever, and future traffic that matches is stored without it. The rows themselves stay: token counts, costs and every chart of the Usage tab are not affected.
| folder pattern | user | added | by | rows redacted | |
|---|---|---|---|---|---|
| {{x.pattern||'(every folder)'}} | {{x.client_id?anClientLbl(x.client_id):'every user'}} | {{dateTimeShort(x.created_at)}} | {{x.created_by||'—'}} | {{fmt(x.redacted_rows)}} | |
| no exclusions | |||||
Audit log
| time | actor | event | provider | detail |
|---|---|---|---|---|
| {{tshort(r.ts)}} | {{r.actor}} | {{r.event}} | {{r.provider||''}} | {{r.detail?JSON.stringify(r.detail):''}} |