TIER — Token Impact & Efficiency Ratio
TIER links captured AI spend to accepted software changes and reports merged work per $1,000 at list prices. This paper explains what the number means, how to read it, and how to try TIER with your team.
A white paper: accepted software changes per dollar of recorded AI usage
Paper version: 2.9 — UNRELEASED-DATE (v0.7.0 release). Describes TIER v0.7.0, an open-source tool released under the Apache License 2.0. The paper is written for two readers with no background: a skeptical engineer and a chief financial officer (CFO). It says what TIER measures, what the number is worth, which decisions it may and may not inform, how complete its inputs are, and how to try it. The mechanics behind every statement here are in the companion technical reference; Section 13 says what it covers. Where this paper and the reference disagree, the reference is correct.
Two roles. The operator is the project maintainer, who decides disputed design questions; the rulings this paper relies on are stated in full where they apply. Issue numbers (#826 and others) point to the maintainer's issue tracker, which may not be public; they are provenance only, and nothing here requires opening them. Whoever installs and runs TIER is the administrator, usually an engineer. A CFO does not install or run TIER; finance's part is posting what was paid (Section 8).
0. Summary for finance and leadership
What the number is. TIER measures merged work per $1,000 of captured AI usage, priced at list rates: an observational ratio, not a causal estimate. Its numerator is size-weighted outcome points, adjusted for quality where TIER observes CI failures and reverts. cost_per_point expresses the ratio in dollars per point. Accepted outcomes are merged pull requests, opt-in direct commits to the default branch, or API-posted outcomes. For GitHub PR ingestion, an outcome requires a recognised issue reference in the branch name or PR description; TIER does not verify that the referenced tracker record exists. The strict grammar uses the first branch slot, closing directives and explicit references; tracker keys require configuration, with OP built in (Section 2).
What a point is worth. A small change that merged with no failure afterwards is one point; the standard sizes run from 0.5 to 8. A point has no dollar value (Section 3).
What the headline can show. On the dashboard the headline is a number only when the figure clears an evidence floor. Otherwise it shows a word: "NO SCORE" (nothing accepted), "No recorded AI cost" (accepted work but no recorded cost, often a capture gap), "NOT ENOUGH SPEND TO SCORE" or "NOT ENOUGH EVIDENCE TO SCORE". A number labelled "provisional" rests mostly on spend that could not be linked to a piece of work (Section 5).
How a figure may be compared. Mainly with the same team's or organisation's own history, across closed months, with work mix reviewed, under matching frozen prices and scoring rules. Two teams in one organisation compare only weakly. Two organisations never compare (Section 6).
What it may inform. How AI is used: which model or route handles which work, whether a tool trial went with cheaper accepted work, whether a team's change in practice moved its cost per point, and whether a flat-fee plan's recorded usage is worth its fee at list prices. In v0.7.0, developers and authorized branch holders can use the same verified coaching card to discuss a practice change (Section 7).
Coaching stance. TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. The positioning is grade the work, not the worker, by policy rather than by mechanism. TIER cannot enforce an organisation's use of the figures (Section 7).
How complete the cost side is today. TIER sees only the usage it captures (Section 4). By default it reads Claude Code's session logs. The administrator can turn on capture for Codex (OpenAI's command-line coding agent), for Opencode (an open-source coding agent) when it uses the Z.ai coding plan (Z.ai sells the GLM models; the coding plan is its flat-fee subscription), for Muse Code (Meta's command-line coding agent; its token mapping was measured on one real Muse Code 1.4.0 session), and for organisation-level API usage reported by Anthropic and OpenAI. A built-in proxy records any calls a client chooses to send through it. Introduced in v0.6.2 and now supported, the collectors.copilot_billing poller can also capture GitHub Copilot organisation AI-credit gross spend. collectors.cursor_admin is supported for team costs and captures usage on a Cursor team plan with Admin API access (Teams or Enterprise; Cursor decides which plans include it). Requests using a person's own API key are left out, including the small amount Cursor itself charges on them. Individual Copilot Pro and individual Cursor accounts are not covered by these pollers; ChatGPT Team is still not captured. Usage TIER does not capture looks free, so TIER reads high (when any cost is recorded at all). Claude costs are derived from deduplicated Claude Code usage logs. Their completeness against independent provider accounting remains unvalidated, including for subscriptions such as Claude Max seats. Missing usage would understate those costs. Codex costs use logged cumulative counters; those counters do not independently establish complete capture. If a Codex log undercount understates its priced cost while other spending and positive outcome points stay fixed, the TIER ratio reads high when recorded total cost remains positive, and Codex looks relatively cheaper than Claude in that cross-vendor cost comparison. The size of any missing usage remains unknown; issue #837 tracks validation.
Spend Leverage is the list-price value of recorded usage divided by what finance posted as paid (Section 8). Above 1, the organisation paid less than list; near 1 is metered billing at list; below 1, it paid more than list, for example for an under-used flat plan. It is not a saving, and it never changes TIER.
1. The problem
AI bills report spending, not the software changes that spending produced. Two teams can spend the same amount and merge very different amounts of work, and some spend goes to work that never merges.
The common engineering frameworks do not cover this. DORA (DevOps Research and Assessment) measures delivery speed and stability; SPACE (satisfaction, performance, activity, communication, efficiency) and DX Core 4 (speed, effectiveness, quality, impact) are frameworks for developer productivity and experience. As the project reads their published definitions, none uses dollars of AI spend as a denominator. TIER adds a measure in dollars of AI spend, for use alongside them.
A useful measure has to deal with four things. Tokens are not comparable across models: the same token count costs very different amounts on an expensive and a cheap model. Invoices are not comparable across organisations: discounts, credits and subscriptions make identical workloads bill differently. Merged work is not comparable by count: a one-line typo fix and a multi-week subsystem are both one pull request (PR). And a number tied to a person's incentives can be gamed. Sections 2 to 6 deal with the first three; Sections 7 and 10 with the fourth.
2. What TIER measures
2.1 The formula
TIER = Σ(outcome_weight × quality_multiplier) / (total_AI_cost_USD / 1000)
Unit: weighted outcome points per $1,000 of list-price AI cost. A TIER of 100 means 100 weighted points for each $1,000 of AI usage. When the window has no recorded cost the formula would divide by zero, so TIER reports 0 instead (Section 2.4).
-
Accepted outcomes. The numerator counts three kinds: a merged pull request; a direct commit to the repository's default branch, when the administrator turns on push capture; and an outcome posted through TIER's outcomes API, where the caller asserts the merge. Each merged PR is its own outcome, even when several share an issue. An otherwise eligible merged PR can earn points regardless of its file paths, including documentation, operational notes and agent-memory changes. A point does not establish that the change improved deployed software. A PR that is closed without merging, abandoned or still open adds nothing to the numerator, but its AI cost stays in the denominator. A merged PR counts only if its branch name or description names an issue (for example a branch
feature/42-login, orcloses #42orrefs #42in the description). Tracker keys require configuration (OP is built in); later branch numbers, bare#Nand unconfigured tracker-shaped tokens do not count. One with no recognised issue records no outcome at all, while its captured cost remains in the denominator and can lower the pooled ratio. A direct commit needs a close directive or configured tracker key in its commit subject and always weighs 0.5. Holding captured spend and all other outcomes fixed, omitting an otherwise eligible PR cannot increase the numeric ratio; it can reduce it. -
Weight is the change's size: 0.5, 1, 3, 5 or 8, from a size label on the PR (
size/xsorxs, throughsize/xlorxl; Section 3) or, with no label, from the number of lines and files changed. An outcome posted through the API may instead carry any weight above 0 up to 8. -
Quality multiplier starts at 1.0 and is lowered by what happens after merge: to 0.7 when continuous integration (CI) fails on the merge commit within 48 hours (a later successful attempt of the same workflow on that commit, within 30 minutes of the failure and the same 48-hour cutoff, can cancel it if the failure is already recorded), to 0.8 when the change is reverted within 60 days for a business reason, and to 0.1 when it is reverted within 60 days for a defect. TIER tells the two kinds of revert apart by keywords in the revert commit's message ("no longer needed" reads as business; "broke" or "bug" as defect, and a message with neither counts as a defect). When several apply, the lowest wins. These signals come only from GitHub, so outside GitHub an outcome keeps the quality it was posted with (1.0 unless the caller sent another value).
The floor values (0.7, 0.8, 0.1) are scoring conventions chosen by the project, not measured fractions of correctness, business value or value lost; no calibration study is published. TIER considers completed CI results only for the repository's default branch and a commit already recorded as an outcome; it does not separately verify that the run came from a merged pull request. In v0.6.1 (#1230), only push-triggered runs on the default branch change quality; matched scheduled and dispatched runs are audit-only, and
merge_groupruns are dropped. The matcher still sets no lower bound on the failure's timestamp relative to the outcome and does not check workflow scope; a matching push-triggered failure can reflect runner or deployment problems, rather than a defect caused by the merge. -
Cost is eligible captured usage in the window, priced from the reference table, except caller-supplied dollars through the manual cost API (Section 4.1). It covers accepted work, abandoned work and unlinked spend. Group reports cover identified developers' captured spend and exclude pseudo-developer spend, including poller remainders; a repository scope excludes unqualified spend.
-
Team and organisation figures are summed points over summed cost, never an average of individual ratios. If A has 10 points on $10 (TIER 1,000) and B has 1 point on $100 (TIER 10), the average of the two ratios is 505, while the pooled figure is 11 ÷ $110 × 1,000 = 100.
The weights, quality values and time limits are the project's rubric choices; it publishes no study behind them. The rubric version, reported with every score, changes when the canonical weight scale, the work-type categories or the quality multiplier floors change; it does not detect differences in how generously teams label work or local remapping of size labels.
2.2 A worked example (illustration)
Suppose a developer merges three pull requests in a window, and $35.00 of list-price AI spend is recorded under that developer in the same window.
| PR | Size label | Weight | What happened after merge | Quality | weight × quality |
|---|---|---|---|---|---|
| A | size/m |
3 | nothing | 1.0 | 3.0 |
| B | size/s |
1 | CI failed on the merge commit within 48 h | 0.7 | 0.7 |
| C | size/l |
5 | reverted 20 days later because the feature was "no longer needed" | 0.8 | 4.0 |
Weighted points = 3.0 + 0.7 + 4.0 = 7.7. TIER = 7.7 / (35.00 / 1000) = 7.7 / 0.035 = 220 points per $1,000. cost_per_point = 35.00 / 7.7 = $4.55 per point (and 1,000 / 220 = 4.55, the same figure from the other direction).
2.3 How the pieces fit together
- Capture. TIER reads the token counts that AI coding tools already record (Section 4.1): model, tokens by kind, the time, the git branch and the working directory. It never reads the text of prompts or responses from those logs.
- Price. Each call's tokens are multiplied by the list rates for that model and summed to one dollar figure per call, rounded once to the millionth of a dollar.
- Link. The call is linked to a piece of work through the issue number in its git branch (for example
feature/42-logingives issue 42), or recorded as unlinked. - Record outcomes. Merged PRs arrive from GitHub as they merge, or from a one-time backfill of history, or from any other system through the API, each with its issue number, size and later quality.
- Score. For a window, TIER adds up points and cost per developer, per team and overall, and divides.
2.4 The companion figures
cost_per_point= cost ÷ points, in dollars per weighted point. With zero points it is empty (null), so "nothing accepted" never reads as the most efficient score. With points but zero recorded cost, TIER is 0 andcost_per_pointis 0. Those two zeros mean "no recorded cost", not the least or the most efficient result; the dashboard shows the case as "No recorded AI cost", often a capture gap rather than free work, and neither number should be read as efficiency.- Spend Leverage = list-price cost ÷ what was actually paid (Section 8).
2.5 Which figure a decision uses
TIER reports a pooled closed-month figure: points divided by captured cost, including abandoned work and unlinked spend. Compare the same population across closed UTC months, inspect published work-category context and frozen capture disclosures, and account for changing task mix. The monthly publication decision can withhold panels or groups.
Synthetic/offline raw windows additionally report outcome-linked per-type segments and segment_reconciliation. Those segments exclude no-outcome and unattributed spend and can overlap; they do not describe the real monthly API contract. Do not compare one work kind with another: nothing establishes equivalent points across categories.
3. What a point is and is not worth
A weighted point is a unit of accepted change, sized by a label or by the size of the diff and reduced by a CI failure or a revert. "Clean" here means that no failure was recorded, not that success was verified.
Points are the project's size conventions, derived from labels or changed lines and files. They are not validated measures of difficulty, maintainability, customer value, engineering time or the contribution made by AI. The preserved 152-outcome snapshot averaged 4.7599 points per PR; all stored weights have weight_source=git-heuristic. These facts have not yet been established for the exact published window.
A point has no dollar value. TIER does not measure revenue, customer value or engineering hours. It does not separate what the AI contributed from what the developer did: a change written entirely by hand still counts as a point. There is no good or bad level, and no benchmark: a TIER of 40 is neither good nor bad on its own. What the number can say is how many points of accepted work went with each $1,000 of recorded AI spend, and how that changed over time for the same people doing the same kind of work.
The size labels mean:
| Label | Weight | Meaning |
|---|---|---|
size/xs |
0.5 | trivial: a one-line fix, a typo, a config flag, a dependency bump |
size/s |
1 | small: a localised change to one function or file |
size/m |
3 | medium: a self-contained feature or fix across a few files |
size/l |
5 | large: a feature touching several components, or a refactor with migration |
size/xl |
8 | extra-large: a subsystem or multi-day effort landed as one PR |
With no label, TIER computes effort = lines added + lines deleted + 10 × files changed, and maps it to 0.5 (up to 15), 1 (up to 60), 3 (up to 200), 5 (up to 1,000) or 8. A 50-line change across 3 files has effort 80 and weight 3. The diff heuristic cannot tell generated or vendored files from written code. A reviewed label can account for context the heuristic lacks, but it remains a judgment rather than a validated measurement. TIER creates no labels; the team adds them in GitHub.
Because the weight comes from labels, a team that labels generously scores the same work higher than one that labels strictly, and nothing in the software can see the difference. A review of a sample of labels against the size meanings is the only check.
Generous labels or caller-supplied values can raise points without a change in delivered work. The same holds for weight and quality posted through the API, recorded with source set to api-outcome. A matching rubric version does not prove two teams apply the rubric equally.
Changes in merge, review or labelling policy can move TIER even when the underlying work does not change. Deterministic scoring does not establish independent acceptance.
4. Where the cost comes from, and how complete it is
4.1 What is captured
TIER prices tokens with a reference price table built into the program: recorded token classes at the rates and selected billing mechanics encoded in that table, including supported cache and long-context rules. This is not complete provider accounting; the technical reference, Section 3.2, lists unsupported billing features. Discounts and subscription fees are recorded separately, as paid spend (Section 8). TIER v0.6.0 ships version 14 of the table, effective 2026-10-12, with 93 models. A model the table does not list is priced at a rough rate the project chose ($0.10 to $2.00 per million tokens, by apparent model size), with a warning in the server's log.
Cost reaches TIER by these paths:
| Path | Default | What it sees |
|---|---|---|
| Claude Code session logs | on | Claude Code usage on the machine it runs on, for the repository being watched |
| Codex CLI logs | off | Codex usage, when the administrator turns it on |
| Opencode database | off | Opencode usage on the Z.ai coding plan only, when turned on |
| Muse Code session logs | off | Muse Code usage, when turned on; some subagent spend is left out, with a warning |
| Reverse proxy | listening | only the calls a client is configured to send through it; it stores usage counts, not request or response text |
| Organisation pollers | off | daily API usage from Anthropic's and OpenAI's organisation reports, for the part the paths above did not record |
| GitHub Copilot billing (introduced in v0.6.2, supported) | off | GitHub's gross amount (before included credits and discounts) for organisation AI-credit usage per mapped developer and model, plus an unattributed organisation remainder; requires an installed GitHub App with Administration: Read-only for spend (preferred), or an org-admin token; organization GitHub Copilot Business: read is needed only for counting through root mappings |
| Cursor Admin (introduced v0.6.2, supported for team costs) | off | Usage events from a Cursor team plan with Admin API access (Teams or Enterprise; Cursor decides which plans include it) with a team Admin API key; token-based calls on models with an audited TIER rate valued at list rate, whether included-plan or usage-based; any other event uses Cursor's reported cents; own-API-key requests and Cursor's small fee on them left out |
| Manual cost API | available | whatever a script posts, at the dollar figure it gives |
A priced call, as an illustration using version 14's rates shipped in v0.6.0. claude-sonnet-5 is listed at $2.00 per million input tokens and $10.00 per million output tokens; Anthropic charges cache reads at 0.10× the input rate and five-minute cache writes at 1.25×. A call with 200,000 input tokens, 1,500,000 cache-read tokens, 50,000 cache-write tokens and 5,000 output tokens costs 0.2 × $2.00 + 1.5 × $2.00 × 0.10 + 0.05 × $2.00 × 1.25 + 0.005 × $10.00 = $0.400 + $0.300 + $0.125 + $0.050 = $0.875. Cache reuse therefore matters: for the same tokens on the same model, less reuse costs more and scores lower, which is why the API reports the share of tokens that were cache reads beside the score.
A developer's laptop sends its captured cost to a central server with tierd ship. Cost is recorded under a developer id: the laptop's operating-system user name, unless --developer names another. Outcomes are recorded under the PR author's GitHub login. When the two differ, an alias joins them (Section 11), and every figure is then reported under the GitHub login.
4.2 What is missing, and in which direction it moves the number
- Accounts and tools outside capture. Individual Copilot Pro accounts have no organisation billing API; individual Cursor accounts are outside the team Admin poller. ChatGPT Team is not captured, nor is any other tool not listed above. Their usage looks free, so TIER reads high. If a window has no recorded cost at all, TIER is 0 instead.
- Cursor limits. Events whose kind contains
api key(case-insensitive; observed BYO kind:User API Key) are skipped: the provider spend is captured byanthropic_adminoropenai_usageonly when the matching poller is configured for the billed organisation. Cursor's per-request fee on those events is not counted. If a chargeable event falls back to Cursor's reported cents and the resulting cost is zero, it is uncosted; this covers non-token calls on any model and token-based calls without an audited TIER rate. An unresolved day becomes a lost span and is disclosed in monthly close evidence. For a token call without an audited rate, adding the model's price before the day leaveslookback_dayscan resolve it on a clean re-read before a loss is recorded; late discoveries can record a loss immediately. See the source requirements. - Tools not turned on. Codex, Opencode or Muse Code work done on a laptop whose
shipdoes not include those tools records outcomes with no cost, so it too reads high.
Bot- and agent-produced changes can earn points even when their AI usage is not captured. Account type does not establish whether a change used AI, and missing usage can make the ratio read high.
TIER reports captured spending by model and associates merged outcome points with models in proportion to their attributable cost. Task mix and other practices can explain differences. Same-task comparisons appear in the separate Model Report, which measures model-and-tool combinations on declared tasks. Its benchmark points are not repository TIER.
- Capture validation (issue #837). Claude costs are derived from deduplicated Claude Code usage logs. Their completeness against independent provider accounting remains unvalidated, including for subscriptions such as Claude Max seats. Missing usage would understate those costs. Codex costs use logged cumulative counters; those counters do not independently establish complete capture. If a Codex log undercount understates its priced cost while other spending and positive outcome points stay fixed, the TIER ratio reads high when recorded total cost remains positive, and Codex looks relatively cheaper than Claude in that cross-vendor cost comparison. Independent reconciliation must match engines, routes, versions and the reporting window; a subscription bill without token-class accounting cannot validate the captured counts. TIER applies no assumed multiplier to history.
- Subscriptions. A flat-fee plan's bill has no token counts, so it cannot be used to check TIER's token-based cost. Its fee is recorded as paid spend for Spend Leverage and never enters TIER.
- Fast mode. Anthropic's faster, dearer "fast mode" is not detected, so it is priced at the normal rate: cost reads low, TIER high.
- Muse Code web search. Meta charges for web searches per query, not per token, and TIER does not price them, so Muse Code cost reads low for sessions that searched.
- Old logs. Tools delete old session logs. The project's reading is that Claude Code keeps about 30 days by default, so a first run of TIER usually recovers about a month of cost. Work merged before that has outcomes but no recorded cost.
- Scope. The log readers take only sessions run inside the watched repository (or a git worktree of it). AI spend on planning or research in other folders is not captured by them; the proxy, pollers and manual API are not limited this way.
4.3 How to check before relying on a dollar figure
Confirm by hand that every AI tool the team uses is captured by some path. For API-billed usage, compare one month of TIER's cost with what the provider billed for the same usage. For subscription usage no such check exists. Prefer decisions that rest on a change over time within one capture path over decisions that rest on the absolute dollar level.
5. Reading a figure
5.1 The evidence floor
A figure clears the evidence floor when it has at least 3 outcomes, at least $5.00 of recorded cost, and no zero-token outcome. An outcome is zero-token when its developer recorded fewer than 1,000 AI tokens on that issue in the 14 days up to the issue's latest merge in the window. That catches, without being able to tell them apart, AI work TIER never captured, cost and outcomes under two unjoined names, AI work done more than 14 days before the merge, work whose session logs are gone, and work written without AI. If Claude Code's logs undercount (Section 4.2), AI work that was done can also fall under the threshold. A team's figure applies the same test to its summed numbers, so one zero-token outcome from any member takes the whole team's figure below the floor. The thresholds are fixed in the code and are the project's judgement, with no published study behind them.
The evidence floor can reject some suspicious readings, but passing it does not verify the inputs or establish statistical adequacy.
Below the floor the number is still computed and returned by the API; the floor changes what the number may claim, not the number. With the v0.6.1 interval rule (#1233), a developer figure that clears it gets bootstrap bounds only when its own attributed-cost share is at least 50%: the 2.5th and 97.5th percentiles of the stated bootstrap resampling procedure, found by resampling that developer's outcomes 1,000 times (in a rare case where every resample has zero cost, the interval reads 0 to 0). The API field that marks the floor is called ranked, a name kept for compatibility: nothing in TIER ranks anyone, and every list is shown in alphabetical order (a team view's other row last), never by TIER. Nominal 95% bounds. Coverage is unvalidated: in constructed tests where several outcomes share one issue, they covered the true value less often than 95%. They exclude uncertainty from uncaptured usage, incorrect attribution and unattributed spend. Below 50%, the interval and cost-per-point interval are withheld; exactly 50% passes. When shown, the interval is labelled "excludes uncertainty from unattributed spend". The share uses this row's cost paired with resampled outcomes; the remainder stays fixed. Team and division rows carry none and disclose no floor status. v0.6.0 itself did not apply this withholding rule.
5.2 The words on the dashboard
The dashboard headline shows a word instead of a number in four cases, checked in this order (the first that applies wins):
| Word | Meaning |
|---|---|
| NO SCORE | the window has no accepted points; nothing accepted is the absence of a score, not a score of zero |
| No recorded AI cost | accepted points but zero recorded cost; often a capture gap rather than free work |
| NOT ENOUGH SPEND TO SCORE | below the floor, with under $5.00 of recorded cost |
| NOT ENOUGH EVIDENCE TO SCORE | below the floor for any other reason |
Separately, when less than half of the window's cost could be linked to an issue, the headline is dimmed and labelled "provisional — N% attribution coverage", where N is linked cost as a percentage of the window's cost. Team and division reports do not publish that share, so their headline reads "provisional — coverage not shown". Provisional and the evidence floor are independent: a figure can have either, both or neither.
5.3 Linked and unlinked spend
TIER links spend to a piece of work through the issue number in the git branch the session ran on. Claude Code records the branch a session started on, so work started in the main checkout and done in a git worktree (a second checkout of the repository, on its own branch) is booked as unlinked. An opt-in switch, --worktree-attribution, off by default, links that spend through the worktree the session's tool calls worked in. It was released in v0.5.2 as a preview because its measured accuracy fell short, and there is no supported correction of an already assigned issue. TIER v0.6.0 can fill previously unlinked rows by recorded PR or branch evidence, without overwriting an assigned issue; read the reference, Section 5.1, and docs/how-it-works.md, section "Measured accuracy: read this before turning it on", before turning it on. Parents no longer carry (#1016); only subagent groups labelled isSidechain:true may carry. The feature remains off by default, and activation requires the recorded gates, operator security rulings and an explicit operator decision; no new accuracy figures have been measured. Spend it cannot link is kept in the denominator as unattributed spend. Linking does not move the pooled figure by itself, because the denominator includes linked and unlinked cost alike. The figure reads low in one linking case: accepted work whose PR named no issue, which records no outcome while its cost stays in. That case often shares a cause with a low linked share, branch names without issue numbers, so a provisional label is a reason to check how many merged PRs recorded no outcome (tierd backfill reports the count). A merged PR that did name its issue is counted even if its spend was not linked; what is lost then is the pairing, which weakens the per-kind segments and can trip the zero-token test.
5.4 Windows
A figure covers a half-open window [since, until) in Coordinated Universal Time (UTC). Real monthly /scores reads select a closed UTC calendar month with period=YYYY-MM. The synthetic demo retains rolling windows: its API defaults to 90 days from the start of that UTC day, its dashboard to 30 days, both with no end. Cost is timestamped when it is spent (for log-captured cost, the time in the tool's log) and outcomes when they merge, so:
- Recent, open-ended windows tend to read low: work in progress has cost but no outcome yet.
- Windows that start before TIER began recording cost read high (when some cost is recorded): they count outcomes whose cost was never captured. Monthly
GET /api/v1/scores?period=YYYY-MMreads reportdisclosures.horizon.window_predates_cost_captureanddisclosures.horizon.cost_coverage_safe_since, the earliest UTC date that clears the captured horizon. If the flag is true, select a later closed month beginning on or after that date; monthly reads rejectsinceanduntilwith HTTP 400. Unknown or unrecorded horizon status does not establish complete capture. Clearing the global horizon cannot show a developer or tool whose capture started later. The technical reference, Section 5.5, shows where to read it.
Live windows can still move with a late ship, backfill, quality event or administrator correction. Monthly reports freeze activity, costs and census at close; later uploads do not revise them. Compare two closed months and inspect each frozen disclosure (Section 9).
5.5 Did it change?
TIER has not established inference from a before/after difference. The legacy API significant field remains a raw, unvalidated interval non-overlap result for compatibility; neither value establishes an effect or a noise threshold. The dashboard withdraws significance verdicts and their colours and shows “inference not established”. Nominal 95% bounds. Coverage is unvalidated: in constructed tests where several outcomes share one issue, they covered the true value less often than 95%. They are descriptive resampling bounds and exclude uncertainty from unattributed spend, incorrect attribution and uncaptured usage. Team figures carry no bounds. A small difference is no evidence either way, and a large difference is a prompt to investigate, not a measured effect. Developer work-type segments carry their own descriptive bounds, but the comparison cannot filter by type.
6. The comparison rule
- The main comparison is with your own past: the same population across closed UTC months, with changes in work mix documented.
- Same prices, scoring rules and release. For a single-origin monthly projection, compare
disclosures.pricesentries (versionandhash),disclosures.used_price_versions,disclosures.unregistered_price_versionsandclose.policy(includingrubric_version). Multi-origin projections carry these disclosures and policy per entry inorigin_evidence[]. Unknown price identities do not establish comparable pricing; matching stamps cannot establish matching task mix, labelling habits or capture completeness. Use the same TIER release. Real/scoresreads a closedperiod=YYYY-MM;/scores/compareaccepts onlyperiod_aandperiod_b. The rawprice_table.table_hash,rubric.versionanddata_quality.mixed_price_versionsfields belong to synthetic/offline reports. - Two teams in one organisation compare weakly: only across comparable closed months after a review of size labels and task mix. Treat the difference as a question to ask, not a finding.
- Two organisations never compare, even on the same price table. List prices put their cost on one price basis, but their labelling, task mix and capture coverage differ.
- One kind of work never compares with another.
7. Coaching and interpretation limits
7.1 Coaching, not evaluation
TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. A manager may discuss model choice, context and cache reuse, and issue-linked spending with a developer. The figures do not establish which model caused an outcome, and TIER cannot enforce the coaching stance. Access limits are described below.
Two reasons support the coaching stance. The first is the project's reading of the law, not legal advice: in Germany, per-developer measurement is subject to works-council co-determination; in France and the Netherlands it requires the works council's consultation or consent; the project reads most of the European Union and European Economic Area (EU/EEA) as similar; and using the output alone to drive a human-resources decision would likely engage Article 22 of the General Data Protection Regulation (GDPR). The project expects a data protection impact assessment (DPIA) for any per-developer deployment, and for measured employees in the EU/EEA recommends team-only reporting plus advance consultation. The second reason is method: a per-developer figure moves with task mix, seniority, pairing and review load, and a number tied to a person's evaluation invites gaming.
Current access and retention: Real servers always require an issued key. Root reads everyone, node keys read their dated branch and personal keys read their holder. Named cards audit before construction and need no declaration or positive verified spend. Shared/static credentials and server reporting modes are retired. Team, division and company reports expand to their people; name-free monthly comparisons retain the k floor. Writable servers run raw retention at startup and daily (90 days by default, 60–365 days); pruning is permanent. Read-only servers and the synthetic demo do not initiate pruning. See identity access for current setup and trust limits.
Named bars on a shared scale are removed on real data; named administrator reads and compliance exports are audited. Immutable spend provenance distinguishes counted identity evidence from historical shared uploads and manual root-posted costs. Only personal and upload keys can post /events; root can name a developer through /costs.
7.2 Decisions it can inform
- Model or routing choice. Treat a move to a cheaper model as a hypothesis to investigate. Compare similar work over finished periods, record other changes (task mix, acceptance criteria, pricing and capture), and inspect acceptance and repair evidence beside cost. A before/after change in TIER cannot show that the model change caused the difference. TIER associates merged outcome points with models by cost, with an equal-share allowance for zero-cost attributable models; this is association, not causal credit, so it cannot say whether the cheaper model did the work as well.
- A tool trial. Give a group a new AI tool for a window and compare its cost per point with its own previous window. This works only if the new tool is captured; if it is not, its spend reads as zero and the trial looks free.
- A team's trend. Whether one team's cost per point moves after a change in practice, such as linking branches to issues or reusing context.
- Whether a flat plan's usage is worth its fee. Spend Leverage below 1 for several months means the fee was more than the list-price value of the usage TIER recorded. It does not say what metered billing would have cost, because usage might have differed under it. This is the decision most exposed to TIER's blind spots. On a subscription, TIER has no bill to check its token counts against (Section 4.2), and if the Claude Code undercount doubt (#837) holds, the recorded usage, and so leverage, is too low: a plan could look under-used when it is not. Do not cancel or downgrade a plan on this figure alone; set it beside the provider's own usage reports.
Before reading a change as an efficiency gain, rule out four ordinary causes: a shift in the mix of work, a change in how generously labels are applied, a change in which tools are captured, and a window edge.
7.3 Limits on interpretation
TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. Comparisons between organisations or between kinds of work remain unsupported (Section 6). TIER measures no human effort, and points have no dollar value, so it supplies no headcount, hours-saved or dollar-return estimate.
8. Spend Leverage
Spend Leverage = list-price cost ÷ actual paid. Finance's input is what was paid: a US-dollar amount per calendar month, posted either per developer (POST /api/v1/actual_spend) or for the whole organisation (POST /api/v1/org_actual_spend), with a root key. An organisation-level amount, less any per-developer amounts for the same month, is split equally among the other developers enrolled with that organisation in TIER's team map (Section 9). The interface, credits and corrections are in the reference, Section 8.1.
A real monthly report uses that closed month's frozen billing basis and records later billing revisions separately. In synthetic/offline raw reports, a window takes the full paid amount of each month from the month containing its start up to, but not including, the month containing its end; with no end, every month from the start onward. So only windows aligned to whole months line up the two halves; a window inside a single month has no paid amount at all, and the dashboard's default 30-day window, which has no end, does not line up.
- Above 1: the organisation paid less than list for the recorded usage (a discount, a commitment, a subscription). Synthetic example for the same developer and one complete calendar month: $600 of captured list-price usage divided by $300 paid for that usage gives $600 / $300 = 2×. Both amounts are invented to show the method; they use no private input and describe no observed deployment.
- Near 1: metered billing at list; discounts, capture gaps and how seats are counted can each move it.
- Below 1: the organisation paid more than list, for example for an under-used flat plan.
- Shown as "—": no payment posted, or a net of exactly zero; when credits exceed payments the dashboard tile reads "(credit)".
A high figure on a flat plan says what the plan bought at list prices; it does not say what metered billing would have cost, so it is not a saving. Leverage also inherits every capture gap: unrecorded usage lowers it, and a bill that covers tools TIER does not capture lowers it too. It never changes TIER.
9. Privacy and reporting
Server reporting modes are retired. serve takes no aggregation setting;
--aggregation, nonempty TIER_AGGREGATION, and the YAML aggregation key
are rejected. Root keys read everyone, node keys read their dated branch, and
personal keys read their holder. Organization, Team, Person and Models views
remain available, including group-to-person expansion. Name-free monthly
comparisons retain the k floor (default 5, minimum 3), complementary
suppression. Archived raw-manifest verification retains its original pinned
arithmetic; that pin cannot select a server access policy.
Monthly reports. A writable server closes UTC months automatically 24 hours
after each month ends, checking at startup and every minute. Source coverage and
known loss remain frozen evidence; there is no arming, preview or skip command.
Reports read month_person; late raw input does not revise a closed month.
Named branch views expand to people, and name-free comparisons retain the k
floor. The synthetic demo also supports live windows.
Anyone who can read the database file can see individual rows. The API confines named reads to holder scopes and logs each card open before building it.
TIER's log readers read only metadata and token counts, never prompt or response text. Two paths differ: the proxy forwards complete requests and responses to the provider but stores only usage counts, and the GitHub webhook stores each raw delivery, which can include commit messages and author names and emails. Those deliveries are cut to the last 90 days when the database is opened and every 24 hours while the server runs. On every real writable server, retention permanently prunes aged cost and outcome detail at startup and daily, with a default 90-day window (configurable from 60 to 365 days). Read-only serving and the synthetic demo do not initiate age-pruning. Name-free rollups remain, but widening the window cannot restore deleted detail (Section 7.1). An erasure endpoint removes one developer's records, with limits the reference lists (Section 6.4). TIER sends no telemetry to the project or anyone else. It is built for one organisation per installation and must not be run as a shared multi-organisation service.
One known defect remains in what the k-anonymity floor protects (Section 10). The floor also cannot protect against a reader who already knows the other members' figures.
10. Known limits
Known limits, and whether each is filed for a fix:
- The Claude Code undercount doubt (#837). Direction known, size unknown, unsettled (Section 4.2).
- Integration branches count twice. A PR merged into an integration branch that is merged again later records two outcomes, one per merge. (A squash merge that push capture counted twice before v0.5.2, #849, stays counted twice; from v0.5.2 it counts once.)
- Administrators remain trusted. Root controls the roster and prospective vendor mappings; node managers can create people within their branch. Counting still requires qualified captured cost and merged outcomes. A manager able to generate that evidence can pad a census; k does not protect against that manager or the database owner.
- Manual cost and the pollers (#854). A server running an organisation poller refuses a manual cost row for that provider's models unless the caller declares it billed elsewhere. The declaration is trusted, and rows posted before v0.5.2 that a poller also counts stay counted twice.
- Labels and partitioning are trusted. Nothing detects a generously sized PR. With no labels, one 1,000-line PR across 10 files earns 8 points; the same lines as five 200-line PRs earn 25. Only a weight that grows in exact proportion to lines changed would be unaffected by splitting, and that weight would be a line count. Points depend on how work is divided into PRs, including across different issues, so compare trends only with a stable splitting practice. Read TIER as its two parts: points per PR and merged PRs per $1,000.
- Repeated calls keep their original pricing basis. A coherent larger observation can promote token counts and token-derived cost together at the original rates. Caller-authoritative costs, unavailable rates, frozen input bands and incompatible observations prevent promotion. Historical count/cost mismatches require explicit
tierd doctor cost-consistencyrepair. - One flagged outcome takes a whole team below the floor. The more outcomes a team has, the likelier one of them is flagged, so a large team's headline can stay a word for long periods.
- Quality is partial. TIER does not measure the fraction reversed. A partial reversal that matches its supported revert rule receives the same message-selected floor as a full reversal—0.1 or 0.8. Other partial reversals can remain unobserved. Footer matching identifies recorded merge or squash SHAs, not constituent-commit ancestry. Incidents, hotfix detection and downstream-CI penalties are not enforced in v0.6.0. Its backfill does not reconstruct quality history. Corrective-work accounting (Event 3) ships in v0.6.0 (see
CHANGELOG.md, 0.6.0), and is off by default; it affects live scores when the operator enables it on their installation. See enabled operation. - Holder-scoped access protects API reads (Section 7.1); host and database owners remain trusted. The project publishes no tested deployment size for the single-file database.
- Gaming. If TIER becomes a target, people can raise the number without improving the work: by inflating labels, splitting PRs, avoiding hard problems, doing AI work on tools TIER cannot see, or posting named manual cost with a root key. The reference lists each route (Section 11).
11. Quick install and first run, for one person
Solo users can read their own local Claude Code, Codex CLI, Opencode (Z.ai coding plan) and Muse Code cost table and issue-attributed spend share with tierd score. tierd score --outcomes joins that spend to only the GitHub token owner's merged PRs for a personal TIER; it persists no report data and shows no team band. tierd demo provides the dashboard on invented data.
This trial is for an engineer: it runs on one laptop, with Claude Code as the AI tool and a GitHub repository. The v0.7.0 trial needs Go 1.27.3 (Go 1.27.3 or newer for source builds at this revision or later, raised for GO-2026-6809; plus git and make only to build from a clone), or a downloaded release (the download and checksum steps are in the repository's docs/quickstart.md). Everything below uses TIER's default database file, ~/.tier/tier.db, and its default address, 127.0.0.1:8080, which only this computer can reach.
1. Install.
go install github.com/tiermetric/tier/cmd/tierd@v0.7.0
tierd version
go install puts tierd in Go's binary directory ($(go env GOPATH)/bin unless GOBIN is set); add that to PATH if tierd version is not found.
2. See it with invented data.
tierd demo # then open http://127.0.0.1:8080
The demo keeps running in that terminal and uses its own throwaway database. Stop it with Ctrl-C before step 5, because the server in step 5 uses the same address.
3. See where your own Claude Code spend went (no server, no outcomes). It prints the price-table version, cost per developer id, and cost per issue, including an unattributed row:
tierd score --repo ~/src/your-repo # --repo here is a folder on this computer
4. Create a read-only GitHub token so TIER can read your merged PRs. On GitHub: Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token. Give it access to that one repository and "Pull requests: Read-only". Copy the value, run the line below, paste the value (nothing is shown) and press Enter:
mkdir -m 700 -p ~/.tier && chmod 700 ~/.tier && read -rs T && (umask 077; printf '%s' "$T" > ~/.tier/github-token) && chmod 600 ~/.tier/github-token; unset T
5. Load outcomes, start the server, load cost.
First complete issued-key bootstrap
and the upload-key setup.
The commands assume the issued root secret is in ~/.tier/api-token and your
YOUR_LOGIN upload secret is in ~/.tier/upload-key. Stop that server before
backfilling, then restart it with the same database below.
Start in the current UTC month with a fresh database. Both commands below start
at that month so startup cannot freeze older outcomes before their matching
spend and roster arrive. The first serve closes every elapsed due month at once; ship's back catalog cannot enter those closes. Writable serve closes due months at startup and every
minute, 24 hours after month end. Import the roster and finish shipping and
identity mapping before then; later uploads cannot revise frozen costs or census.
This sequence cannot bootstrap complete historical reports: use offline
score --outcomes for past work. For branch reports, use the first full month
after the roster takes effect.
export TIER_GITHUB_TOKEN=@$HOME/.tier/github-token # "@path" means: read the value from this file
tierd backfill --repo your-org/your-repo --since "$(date -u +%Y-%m-01)" # --repo here is the GitHub owner/name
mkdir -p ~/.tier && chmod 700 ~/.tier
tierd serve
# import the roster with root, then in a second terminal:
tierd ship --server http://127.0.0.1:8080 --repo ~/src/your-repo \
--developer YOUR_LOGIN --bound-token @"$HOME/.tier/upload-key" \
--since "$(date -u +%Y-%m-01)"
- Why backfill first.
backfillandservewrite the same database file, and SQLite lets one writer in at a time; a backfill while the server is busy can fail with "database is busy". To load new merges later, stopserve, runbackfillagain with the current-month bound above, and restart. Later shipping cannot repair a month already closed at startup. - Repeat shipping before close. This walkthrough starts no watcher.
shiploads this month's retained session logs; repeat it with the same bound and tool flags for new activity before close. See bound watcher setup for separate live capture. - Authentication is required even on loopback. Use issued root keys for administration and holder upload keys for
ship;serveresolves them from its credential table (the reference, Section 9.5).
Open http://127.0.0.1:8080. If your computer's user name differs from your GitHub login, join them:
printf 'Authorization: Bearer %s\n' "$(cat ~/.tier/api-token)" |
curl -f -X POST http://127.0.0.1:8080/api/v1/developer_alias \
-H @- -H "Content-Type: application/json" -d '{"alias":"<your-os-user>","canonical":"<your-github-login>"}'
6. Check coverage and report readiness.
tierd doctor --repo ~/src/your-repo --server http://127.0.0.1:8080 --api-token @"$HOME/.tier/api-token"
The doctor reports actual monthly close time. A writable server closes UTC months automatically after 24 hours; Team provides live branch views before close. Name-free comparisons retain the k floor.
What to expect. A one-person trial can read its holder-scoped card and live branch. Name-free monthly aggregates remain withheld below the configurable k floor (default 5, minimum 3). Monthly comparisons require a close (reference, Section 6.2).
Use tierd score --repo ~/src/your-repo for your own Claude Code cost table
and the issue-attributed share of that spend, and
tierd demo to preview a populated synthetic dashboard. Neither evaluates
this laptop's real server TIER: plain score reports costs; score --outcomes joins the GitHub token owner's merged PRs locally, and demo data is
invented.
Backfill loads 90 days of PRs while the logs may cover about 30. Older PRs can therefore be flagged zero-token; the doctor in step 6 identifies this coverage mismatch. With no GitHub webhook in this setup, no CI or revert signal arrives, so every outcome keeps quality 1.0. Deploying for a team (a central server, laptops sending cost on a schedule, the webhook, encryption in transit, tokens) is for the administrator and is in the reference, Section 9.5.
12. Glossary
- Accepted outcome: a merged PR, an opt-in direct commit to the default branch, or an outcome posted through the API (§2.1).
- Weighted point: one outcome's weight × quality (§2.1).
- TIER: weighted points per $1,000 of list-price AI cost (§2.1).
- cost_per_point: dollars of list-price AI cost per weighted point (§2.4).
- List price: the provider's published per-token rate, from TIER's built-in price table (§4.1).
- Unattributed (unlinked) spend: cost that could not be linked to an issue; it stays in the denominator (§5.3).
- Evidence floor (
ranked): 3 outcomes, $5.00 of cost, no zero-token outcome (§5.1). - Zero-token outcome: an outcome whose developer recorded under 1,000 tokens on its issue in the 14 days to the issue's latest merge (§5.1).
- Provisional: the dashboard's label when less than half of the cost was linked to an issue (§5.2).
- Window: the time span a figure covers,
[since, until)in UTC (§5.4). - Cost horizon: the earliest cost TIER has recorded; windows starting before it read high (§5.4).
- Segment: the figure for one kind of work, using only that kind's linked cost (§2.5).
- Spend Leverage: list-price cost ÷ actual paid (§8).
- Developer id: the name cost and outcomes are recorded under; an operating-system user name or a GitHub login, joined by an alias (§4.1).
- Team map: the administrator's table giving each developer id a team, a division (a group of teams) and an organisation (§9).
- Rubric version: the number that changes when the canonical weight scale, the work-type categories or the quality multiplier floors change (§2.1).
- Reporting scope: issued keys determine whose retained figures a real server serves; server reporting modes are retired (§9).
- k-anonymity: a group is named only when at least k people count toward it (§9).
- Closed month: frozen monthly contributions captured after the UTC month and its 24-hour grace (§9).
- Operator / administrator: the project maintainer who rules on design questions / whoever runs an installation (front matter).
- Codex, Opencode, Muse Code, Z.ai: OpenAI's command-line coding agent; an open-source coding agent; Meta's command-line coding agent; the company selling the GLM models and a flat-fee coding plan for them (§0).
13. Where the detail lives
The technical reference covers, in more detail:
| Reference section | What it covers |
|---|---|
| 2 | the formula's edge cases, the comparison rule's price-version check, which figure a decision uses |
| 3 | every capture path, what each reads, identity, double counting, the organisation pollers, pricing and cache arithmetic, unknown-model guesses, price-table versions and overrides |
| 4 | the outcome producers, size labels and the size heuristic, kinds of work, quality floors and revert rules, push capture, the outcomes API, backfill |
| 5 | issue linking, opt-in worktree attribution, identity aliases, unattributed buckets, the two clocks, the cost horizon |
| 6 | holder scopes, k-anonymity and suppression, closed monthly reports, the coaching position, what is stored, erasure and retention |
| 7 | the evidence floor, unvalidated descriptive bounds, legacy significant |
| 8 | Spend Leverage accounting (months, seats, credits, subscription fees) and how to use TIER for a spending decision |
| 9 | install, demo, the full single-user score, team deployment, the other commands, upgrades |
| 10 | the API: routes, token scopes, response fields |
| 11 | known limits and gaming routes |
| 12, Appendix A | glossary and a machine-readable summary |
Administration procedures that neither document reproduces (full schemas, configuration keys, restore, hardening) are named in the reference with the repository file that holds each.
Monthly close metadata. Closed reports show their actual UTC closed_at,
frozen policy and capture-loss disclosure. Late evidence does not change closed
figures. Scores, comparisons and manifests no longer serve legacy seal timing
headers or outcome-dependent revert-window observations. See the
monthly metadata contract.