claude-attribution 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,37 +1,45 @@
1
1
  # claude-attribution
2
2
 
3
- > **Hey team** we've built a tool that automatically tracks and documents AI contribution in your PRs so you don't have to do it manually.
4
- >
5
- > **One-time setup:**
6
- > ```bash
7
- > npm install -g claude-attribution
8
- > claude-attribution install ~/Code/your-repo
9
- > claude-attribution init --ai # repo built with Claude Codeor --human if human/mixed
10
- > git add .claude/settings.json .gitignore && git commit -m "chore: install claude-attribution hooks"
11
- > ```
12
- > From then on, just work normally. After each `git commit` you'll see a one-line attribution summary in your terminal. When you're ready to open a PR, run `/pr` in Claude Code (or `claude-attribution pr "feat: your title"`) — it fills in the metrics automatically, no copy-paste needed.
13
- >
14
- > **Using Copilot or @claude (claude-code-action)?** Commits made by AI bots (Copilot coding agent, `@claude` via claude-code-action) are automatically detected and attributed as 100% AI in metrics — no extra steps needed. See [AI Actor Attribution](#ai-actor-attribution-copilot-bot-claude-gha) for details. For Copilot-specific org-level stats, use the GitHub Copilot usage dashboard. Both tools' data flows into the VP Datadog dashboard automatically on every PR merge.
15
- >
16
- > **Requirements:** [Bun](https://bun.sh) (preferred) or Node 18+, and `gh` (GitHub CLI) authenticated for the `/pr` command.
3
+ AI code attribution for Claude Code. After every `git commit`, a one-line summary appears in your terminal:
4
+
5
+ ```
6
+ [claude-attribution] a3f1b2c — 142 AI / 38 human / 4 mixed lines (77% AI)
7
+ ```
8
+
9
+ When a PR is opened, full metrics model usage, token counts, tool calls, and attribution percentages are injected automatically into the PR body. No copy-paste, no manual tracking.
10
+
11
+ **Quick start:**
12
+
13
+ ```bash
14
+ npm install -g claude-attribution
15
+ claude-attribution install ~/Code/your-repo
16
+ claude-attribution init --ai # if repo was built with Claude Code; use --human otherwise
17
+ git add .claude/settings.json .github/workflows/claude-attribution-pr.yml .gitignore
18
+ git commit -m "chore: install claude-attribution hooks"
19
+ git push
20
+ ```
21
+
22
+ **Using Copilot or `@claude` (claude-code-action)?** Bot commits are auto-detected and attributed as 100% AI — no extra steps needed. See [AI Actor Attribution](#ai-actor-attribution-copilot-bot-claude-gha).
23
+
24
+ **Requirements:** [Bun](https://bun.sh) (preferred) or Node 18+, and `gh` (GitHub CLI) authenticated for the `/pr` command.
17
25
 
18
26
  ---
19
27
 
20
- AI code attribution tracking for Claude Code. Measures which lines in a commit were written by Claude vs. a human — using checkpoint snapshots and line-level SHA-256 comparison, not gross write-operation counts.
28
+ Measures which lines in a commit were written by Claude vs. a human — using checkpoint snapshots and line-level SHA-256 comparison, not gross write-operation counts.
21
29
 
22
30
  ---
23
31
 
24
32
  ## GitHub Actions Requirements
25
33
 
26
- Three workflows are installed into repos that use this tool. Each requires specific GitHub Actions to be allowed in your org. If your org enforces an action allowlist, you must approve the third-party action before the workflows will run.
34
+ Up to three workflows are installed into repos that use this tool — one always, two optionally. Each requires specific GitHub Actions to be allowed in your org. If your org enforces an action allowlist, you must approve the third-party action before the workflows will run.
27
35
 
28
36
  ### Workflows and the actions they use
29
37
 
30
- | Workflow file | Trigger | GitHub-owned actions | Third-party actions |
31
- |---|---|---|---|
32
- | `claude-attribution-pr.yml` | PR opened / pushed | `actions/checkout@v4`, `actions/github-script@v7` | `oven-sh/setup-bun@v2` |
33
- | `claude-attribution.yml` | PR merged | `actions/checkout@v4` | `oven-sh/setup-bun@v2` |
34
- | `claude-attribution-gha.yml` | Every push (optional) | `actions/checkout@v4` | `oven-sh/setup-bun@v2` |
38
+ | Workflow file | Trigger | Install | GitHub-owned actions | Third-party actions |
39
+ |---|---|---|---|---|
40
+ | `claude-attribution-pr.yml` | PR opened / pushed | Always | `actions/checkout@v4`, `actions/github-script@v7` | `oven-sh/setup-bun@v2` |
41
+ | `claude-attribution-export.yml` | PR merged | Optional (prompted) | `actions/checkout@v4` | `oven-sh/setup-bun@v2` |
42
+ | `claude-attribution-gha.yml` | Every push | Optional (claude-code-action detected) | `actions/checkout@v4` | `oven-sh/setup-bun@v2` |
35
43
 
36
44
  **GitHub-owned actions** (`actions/*`) are pre-approved in all orgs by default.
37
45
 
@@ -44,7 +52,7 @@ Three workflows are installed into repos that use this tool. Each requires speci
44
52
  | Workflow | `contents` | `pull-requests` | Why |
45
53
  |---|---|---|---|
46
54
  | `claude-attribution-pr.yml` | read | write | Reads git history; writes metrics into the PR body |
47
- | `claude-attribution.yml` | read | — | Reads git notes and pushes Datadog metrics |
55
+ | `claude-attribution-export.yml` | read | — | Reads git notes and exports metrics via OTLP/webhook |
48
56
  | `claude-attribution-gha.yml` | write | — | Pushes attribution git notes back to origin |
49
57
 
50
58
  ### Required secrets
@@ -52,8 +60,11 @@ Three workflows are installed into repos that use this tool. Each requires speci
52
60
  | Secret / Variable | Workflow | Required | Notes |
53
61
  |---|---|---|---|
54
62
  | `GITHUB_TOKEN` | All | Automatic | Provided by GitHub Actions; no setup needed |
55
- | `DATADOG_API_KEY` | `claude-attribution.yml` | Yes | Org-level secret; needed to push metrics to Datadog |
56
- | `DATADOG_SITE` | `claude-attribution.yml` | No | Org-level variable; defaults to `datadoghq.com` |
63
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | `claude-attribution-export.yml` | One of these | OTLP/HTTP base URL (e.g. `https://otlp.datadoghq.com`, `https://otlp-gateway-<zone>.grafana.net/otlp`, `http://localhost:4318`). Unset = dry-run mode. |
64
+ | `OTEL_EXPORTER_OTLP_HEADERS` | `claude-attribution-export.yml` | Depends on backend | Comma-separated `key=value` auth headers (e.g. `DD-Api-Key=xxx` for Datadog, `x-honeycomb-team=xxx` for Honeycomb) |
65
+ | `DATADOG_API_KEY` | `claude-attribution-export.yml` | Datadog shortcut | Org-level secret; auto-configures the Datadog OTLP endpoint without needing `OTEL_EXPORTER_OTLP_ENDPOINT`. |
66
+ | `DATADOG_SITE` | `claude-attribution-export.yml` | No | Org-level variable; used with `DATADOG_API_KEY`. Defaults to `datadoghq.com`. |
67
+ | `METRICS_WEBHOOK_URL` | `claude-attribution-export.yml` | No | Posts a flat JSON payload to any HTTP endpoint on each PR merge. Can be used alongside OTLP. |
57
68
 
58
69
  ---
59
70
 
@@ -67,30 +78,16 @@ Three workflows are installed into repos that use this tool. Each requires speci
67
78
 
68
79
  ### One-time setup (per developer machine)
69
80
 
70
- **Option A — npm (recommended):**
71
-
72
81
  ```bash
73
82
  npm install -g claude-attribution
74
83
  ```
75
84
 
76
- **Option B — clone (if npm isn't available):**
77
-
78
- ```bash
79
- git clone git@github.com:DTS-Productivity-Engineering/claude-attribution.git ~/Code/claude-attribution
80
- cd ~/Code/claude-attribution
81
- bun install
82
- ```
83
-
84
85
  ### Install into a repo (per repo, per developer)
85
86
 
86
87
  **Step 1 — Run the installer:**
87
88
 
88
89
  ```bash
89
- # npm install:
90
90
  claude-attribution install ~/Code/your-repo
91
-
92
- # clone install:
93
- bun ~/Code/claude-attribution/src/setup/install.ts ~/Code/your-repo
94
91
  ```
95
92
 
96
93
  **Step 2 — Declare your attribution baseline (`init`):**
@@ -106,6 +103,9 @@ claude-attribution init --human
106
103
 
107
104
  # Not sure? Run with no flag — same as --human, prints a confirmation:
108
105
  claude-attribution init
106
+
107
+ # Repo has mixed history — mark commits after a specific date as AI-written:
108
+ claude-attribution init --ai-since 2025-01-01
109
109
  ```
110
110
 
111
111
  > **Why this matters:** Without `init`, the codebase-wide AI% starts at 0% and grows only from new commits. If your repo is all Claude Code, run `init --ai` now or the metrics will be misleading until the entire codebase has been re-committed line by line.
@@ -139,11 +139,14 @@ The installer makes the following changes to the target repo:
139
139
 
140
140
  **`.github/workflows/claude-attribution-pr.yml`** — GitHub Actions workflow that fires on every PR open and push. Injects metrics into the PR body automatically for PRs created outside Claude (Copilot, manual `gh pr create`, GitHub UI). Skips injection if the local `post-bash` hook already injected metrics on `opened`; always updates on `synchronize` (new commits).
141
141
 
142
+ **`.github/workflows/claude-attribution-export.yml`** — fires on every PR merge. Exports AI attribution metrics via OTLP/HTTP or a generic webhook. Supports Datadog, Grafana Cloud, Splunk Observability, New Relic, Honeycomb, and any OpenTelemetry Collector. Runs in dry-run mode (prints payload to stdout, exits 0) when no export destination is configured. See [Metrics Export](#metrics-export).
143
+
142
144
  **`.github/workflows/claude-attribution-gha.yml`** *(optional — installed when claude-code-action is detected)* — fires on every push. Writes a 100% AI git note for commits made by known AI actors (e.g. `@claude` via claude-code-action, Copilot coding agent). Silent no-op for human commits. See [AI Actor Attribution](#ai-actor-attribution-copilot-bot-claude-gha).
143
145
 
144
- **`.claude/commands/`** — installs two slash commands:
146
+ **`.claude/commands/`** — installs three slash commands:
145
147
  - `/metrics` — generate a PR metrics report
146
- - `/start` — mark the start of a new Jira ticket session
148
+ - `/start` — mark the start of a new ticket session
149
+ - `/pr` — create a PR with metrics embedded
147
150
 
148
151
  **`.gitignore`** — adds `.claude/logs/` so tool usage logs don't end up in version control.
149
152
 
@@ -177,16 +180,12 @@ claude-attribution init --ai # only if repo was built 100% with Claude Code
177
180
  git push origin refs/notes/claude-attribution-map
178
181
  ```
179
182
 
180
- ### Re-installing after moving this directory
183
+ ### Re-installing
181
184
 
182
- If you move `~/Code/claude-attribution` to a different path, re-run the installer — it updates the absolute paths in `settings.json` and the git hook:
185
+ If you reinstall `claude-attribution` globally (e.g. after upgrading), re-run the installer — it updates the absolute paths in `settings.json` and the git hook:
183
186
 
184
187
  ```bash
185
- # npm install:
186
188
  claude-attribution install ~/Code/your-repo
187
-
188
- # clone install:
189
- bun src/setup/install.ts ~/Code/your-repo
190
189
  ```
191
190
 
192
191
  ### Uninstalling
@@ -194,14 +193,10 @@ bun src/setup/install.ts ~/Code/your-repo
194
193
  To remove claude-attribution from a repo:
195
194
 
196
195
  ```bash
197
- # npm install:
198
196
  claude-attribution uninstall ~/Code/your-repo
199
-
200
- # clone install:
201
- bun ~/Code/claude-attribution/src/setup/uninstall.ts ~/Code/your-repo
202
197
  ```
203
198
 
204
- This removes hooks from `.claude/settings.json`, removes `.git/hooks/post-commit`, removes the slash commands, removes `.github/workflows/claude-attribution-pr.yml`, and removes any legacy `pre-push` hooks (for example `.husky/pre-push` or `.git/hooks/pre-push`) if present. Attribution state (`.claude/attribution-state/`) and logs (`.claude/logs/`) are left in place. The `remote.origin.push` refspec is also removed from git config.
199
+ This removes hooks from `.claude/settings.json`, removes `.git/hooks/post-commit`, removes the slash commands, removes `.github/workflows/claude-attribution-pr.yml`, `.github/workflows/claude-attribution-export.yml`, and `.github/workflows/claude-attribution-gha.yml` (if present), and removes any legacy `pre-push` hooks (for example `.husky/pre-push` or `.git/hooks/pre-push`) if present. Attribution state (`.claude/attribution-state/`) and logs (`.claude/logs/`) are left in place. The `remote.origin.push` refspec is also removed from git config.
205
200
 
206
201
  ---
207
202
 
@@ -237,33 +232,36 @@ Metrics are injected automatically — no command needed.
237
232
 
238
233
  **On every new push to an open PR**: the workflow fires on `synchronize` and updates the attribution percentages to reflect new commits.
239
234
 
240
- The metrics block looks like (when the cumulative minimap exists):
241
-
242
- ```markdown
243
- ## Claude Code Metrics
235
+ The metrics block injected into the PR body looks like (when the cumulative minimap exists):
244
236
 
245
- **Codebase: ~77% AI** (3200 / 4150 lines)
246
- **This PR:** 184 lines changed (4% of codebase) · 77% Claude edits · 142 AI lines · Active: 8m
237
+ > ## Claude Code Metrics
238
+ >
239
+ > **Codebase: ~77% AI** (3200 / 4150 lines)
240
+ > **This PR:** 184 lines changed (4% of codebase) · 77% Claude edits · 142 AI lines · Active: 8m
241
+ >
242
+ > | Model | Calls | Input | Output | Cache |
243
+ > |-------|-------|-------|--------|-------|
244
+ > | Sonnet | 45 | 120K | 35K | 10K |
245
+ > | **Total** | 45 | 120K | 35K | 10K |
246
+ >
247
+ > **Human prompts (steering effort):** 12
248
+ >
249
+ > <details><summary>Tools · Agents · Files</summary>
250
+ >
251
+ > **Tools:** Edit ×47, Read ×31, Bash ×12
252
+ >
253
+ > </details>
247
254
 
248
- | Model | Calls | Input | Output | Cache |
249
- |-------|-------|-------|--------|-------|
250
- | Sonnet | 45 | 120K | 35K | 10K |
251
- | **Total** | 45 | 120K | 35K | 10K |
255
+ Before running `init --ai` (or on a fresh install with no minimap), the headline falls back to the session-only view:
252
256
 
253
- **Human prompts (steering effort):** 12
257
+ > **AI contribution: ~77%** (142 of 184 committed lines) · Active: 8m
254
258
 
255
- <details>
256
- <summary>Tools · Agents · Files</summary>
259
+ The block is wrapped in HTML comments for idempotent updates — re-running replaces the existing block rather than appending:
257
260
 
258
- **Tools:** Edit ×47, Read ×31, Bash ×12
259
- ...
260
- </details>
261
261
  ```
262
-
263
- Before running `init --ai` (or on a fresh install with no minimap), the headline falls back to the session-only view:
264
-
265
- ```markdown
266
- **AI contribution: ~77%** (142 of 184 committed lines) · Active: 8m
262
+ <!-- claude-attribution metrics -->
263
+ ...metrics content...
264
+ <!-- /claude-attribution metrics -->
267
265
  ```
268
266
 
269
267
  #### Manual option
@@ -271,7 +269,7 @@ Before running `init --ai` (or on a fresh install with no minimap), the headline
271
269
  If you need to create a PR with metrics outside of Claude, use the `/pr` slash command or CLI directly:
272
270
 
273
271
  ```bash
274
- claude-attribution pr "feat: COMM-1234 add user authentication"
272
+ claude-attribution pr "feat: PROJ-1234 add user authentication"
275
273
  claude-attribution pr "feat: my feature" --draft
276
274
  claude-attribution pr "feat: my feature" --base develop
277
275
  ```
@@ -284,7 +282,6 @@ To see the metrics output without creating a PR, use `/metrics` or run directly:
284
282
 
285
283
  ```bash
286
284
  claude-attribution metrics
287
- # or: bun ~/Code/claude-attribution/src/metrics/calculate.ts
288
285
  ```
289
286
 
290
287
  The output is markdown you paste into your PR description:
@@ -351,7 +348,7 @@ Example output:
351
348
  {
352
349
  "commit": "a3f1b2c",
353
350
  "session": "abc-123-...",
354
- "branch": "feature/COMM-1234",
351
+ "branch": "feature/PROJ-1234",
355
352
  "timestamp": "2026-03-26T15:32:00.000Z",
356
353
  "files": [
357
354
  { "path": "src/components/Foo.tsx", "ai": 82, "human": 10, "mixed": 2, "total": 94, "pctAi": 87 }
@@ -466,36 +463,60 @@ To force re-detection of the TypeScript runtime (e.g., after installing Bun): `r
466
463
 
467
464
  ---
468
465
 
469
- ## VP Dashboard (Datadog)
466
+ ## Metrics Export
470
467
 
471
- Attribution data is pushed to Datadog automatically on every PR merge via GitHub Actions (`.github/workflows/claude-attribution.yml`). No developer holds the API key it lives in an org-level GHA secret.
468
+ Attribution metrics are exported automatically on every PR merge via GitHub Actions (`.github/workflows/claude-attribution-export.yml`). The workflow uses the OpenTelemetry OTLP/HTTP JSON format and supports any OTel-compliant backend.
472
469
 
473
- **Metrics pushed on each merged PR:**
470
+ **Metrics exported on each merged PR:**
474
471
 
475
- | Metric | Description |
476
- |--------|-------------|
477
- | `claude_attribution.ai_lines` | Lines written by Claude and committed unchanged |
478
- | `claude_attribution.human_lines` | Lines written or left unchanged by the developer |
479
- | `claude_attribution.total_lines` | Total committed lines in the PR |
480
- | `claude_attribution.pct_ai` | Percentage of lines attributed to Claude (this PR) |
481
- | `claude_attribution.codebase_pct_ai` | Cumulative codebase-wide AI% at PR merge time (requires minimap) |
482
- | `claude_attribution.codebase_total_lines` | Total codebase lines tracked in the minimap |
483
- | `github_copilot.acceptance_rate` | Org-level Copilot suggestion acceptance rate |
484
- | `github_copilot.lines_accepted` | Copilot lines accepted org-wide |
485
- | `github_copilot.lines_suggested` | Copilot lines suggested org-wide |
472
+ | Metric | Unit | Description |
473
+ |--------|------|-------------|
474
+ | `claude_attribution.ai_lines` | lines | Lines written by Claude and committed unchanged |
475
+ | `claude_attribution.human_lines` | lines | Lines written or left unchanged by the developer |
476
+ | `claude_attribution.total_lines` | lines | Total committed lines in the PR |
477
+ | `claude_attribution.pct_ai` | % | Percentage of lines attributed to Claude (this PR) |
478
+ | `claude_attribution.codebase_pct_ai` | % | Cumulative codebase-wide AI% at PR merge time (requires minimap) |
479
+ | `claude_attribution.codebase_total_lines` | lines | Total codebase lines tracked in the minimap |
480
+ | `claude_attribution.cost_usd` | $ | Estimated Claude API cost for this PR (requires v1.5.0+ notes) |
481
+ | `claude_attribution.input_tokens` | tokens | Total input tokens consumed by Claude in this PR |
482
+ | `claude_attribution.output_tokens` | tokens | Total output tokens generated by Claude in this PR |
483
+ | `claude_attribution.cache_read_tokens` | tokens | Cache read tokens in this PR |
484
+ | `claude_attribution.cache_creation_tokens` | tokens | Cache creation tokens in this PR |
486
485
 
487
- All metrics are tagged `repo:`, `pr:`, `branch:`, `author:`, `tool:` — enabling side-by-side Claude vs. Copilot comparison on a single dashboard.
486
+ Token and cost metrics are only emitted when the git notes contain token data (written by v1.5.0+ hooks). All metrics carry attributes `pr`, `branch`, `author`, `tool` — enabling per-PR trend analysis.
488
487
 
489
- > **Important limitation — Copilot metrics are org-level aggregates, not per-PR or per-developer:**
490
- > GitHub's Copilot usage API returns org-wide daily totals (suggestions shown, lines accepted, acceptance rate). These are the same numbers regardless of which PR triggered the push. The Copilot rows in Datadog reflect organization-wide Copilot activity at the time of the push — they cannot be scoped to a specific PR, branch, or developer. In contrast, `claude_attribution.*` metrics are per-PR and per-file, derived from git notes written at commit time.
491
- >
492
- > If you need per-seat or per-repo Copilot breakdowns, use the GitHub Copilot usage dashboard directly. The org-level Copilot numbers here are useful as a trend signal alongside Claude attribution data.
488
+ **Supported backends:**
489
+
490
+ | Backend | Configuration |
491
+ |---------|---------------|
492
+ | **Datadog** (shortcut) | Set `DATADOG_API_KEY` secret (and optionally `DATADOG_SITE` org variable, defaults to `datadoghq.com`). Endpoint is auto-configured. |
493
+ | **Datadog** (explicit) | `OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.datadoghq.com`, `OTEL_EXPORTER_OTLP_HEADERS=DD-Api-Key=<key>` |
494
+ | **Grafana Cloud** | `OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-<zone>.grafana.net/otlp`, `OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic <base64(user:token)>` |
495
+ | **Splunk Observability** | `OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.<realm>.signalfx.com/v2/datapoint/otlp`, `OTEL_EXPORTER_OTLP_HEADERS=X-SF-Token=<token>` |
496
+ | **New Relic** | `OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net`, `OTEL_EXPORTER_OTLP_HEADERS=api-key=<key>` |
497
+ | **Honeycomb** | `OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io`, `OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=<key>` |
498
+ | **OTel Collector** | `OTEL_EXPORTER_OTLP_ENDPOINT=http://your-collector:4318` |
499
+ | **Generic webhook** | `METRICS_WEBHOOK_URL=https://...` — POSTs a flat JSON payload with `pr`, `repo`, `author`, `branch`, `ai_lines`, `human_lines`, `total_lines`, `pct_ai`, and optionally `codebase_pct_ai` / `codebase_total_lines` / `cost_usd` / `input_tokens` / `output_tokens` |
500
+
501
+ When no destination is configured, the workflow runs in **dry-run mode** — it prints the OTLP payload to stdout and exits 0. This makes it safe to install and test before secrets are set.
502
+
503
+ Set secrets at the org level so they apply to all repos that use this tool. Multiple export destinations can be active simultaneously (e.g. both `OTEL_EXPORTER_OTLP_ENDPOINT` and `METRICS_WEBHOOK_URL`).
504
+
505
+ **Model pricing (org variables — update when Anthropic changes pricing):**
506
+
507
+ | Variable | Default | Description |
508
+ |----------|---------|-------------|
509
+ | `CLAUDE_PRICE_OPUS_INPUT` | `15.00` | $ per 1M input tokens (Claude Opus) |
510
+ | `CLAUDE_PRICE_OPUS_OUTPUT` | `75.00` | $ per 1M output tokens (Claude Opus) |
511
+ | `CLAUDE_PRICE_SONNET_INPUT` | `3.00` | $ per 1M input tokens (Claude Sonnet) |
512
+ | `CLAUDE_PRICE_SONNET_OUTPUT` | `15.00` | $ per 1M output tokens (Claude Sonnet) |
513
+ | `CLAUDE_PRICE_HAIKU_INPUT` | `0.80` | $ per 1M input tokens (Claude Haiku) |
514
+ | `CLAUDE_PRICE_HAIKU_OUTPUT` | `4.00` | $ per 1M output tokens (Claude Haiku) |
515
+ | `CLAUDE_PRICE_CACHE_READ_MULT` | `0.1` | Fraction of input price for cache reads |
516
+ | `CLAUDE_PRICE_CACHE_WRITE_MULT` | `1.25` | Fraction of input price for cache writes |
493
517
 
494
- **Required secrets (set once at org level):**
495
- - `DATADOG_API_KEY` — Datadog API key
496
- - `DATADOG_SITE` variable — e.g. `datadoghq.com`
518
+ Unrecognized model names (new Claude releases) fall back to Opus pricing. Set these as org-level **variables** (not secrets) — they're not sensitive.
497
519
 
498
- **Future:** When Faros is purchased, ADMPLAT-9609 will provide a Faros pipeline. Switching destinations is a one-line change to `src/export/pr-summary.ts` — the data collection, notes format, and GHA trigger all stay the same.
499
520
 
500
521
  ---
501
522
 
@@ -553,7 +574,7 @@ permissions:
553
574
  jobs:
554
575
  note-ai-commit:
555
576
  name: Record AI actor commit attribution
556
- runs-on: ubuntu-latest
577
+ runs-on: ubuntu-latest # replace with your self-hosted runner label if needed
557
578
  steps:
558
579
  - uses: actions/checkout@v4
559
580
  with:
@@ -621,7 +642,7 @@ Each hook invocation is a short-lived process that exits immediately. The trace
621
642
 
622
643
  The post-commit hook may not have run. Check:
623
644
  1. Is `bun` (or `tsx`) on your PATH in a git hook context? Run `which bun` from your shell, then check if that path is in `.git/hooks/post-commit`.
624
- 2. Did you run `bun src/setup/install.ts <repo>` for this specific repo?
645
+ 2. Did you run `claude-attribution install <repo>` for this specific repo?
625
646
  3. Check `.claude/logs/attribution.jsonl` — if it's empty, the hook isn't firing.
626
647
 
627
648
  **Attribution is 0% AI even though Claude wrote everything**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-attribution",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "AI code attribution tracking for Claude Code sessions — checkpoint-based line diff approach",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,6 +34,7 @@ import {
34
34
  type LineAttribution,
35
35
  hashLine,
36
36
  } from "./differ.ts";
37
+ import { parseTranscript } from "../metrics/transcript.ts";
37
38
  import {
38
39
  writeNote,
39
40
  headSha,
@@ -146,6 +147,21 @@ async function main() {
146
147
  totals: aggregateTotals(fileResults),
147
148
  };
148
149
 
150
+ // Attach token usage from the Claude session transcript (non-fatal if unavailable)
151
+ if (sessionId) {
152
+ const tx = await parseTranscript(sessionId, repoRoot).catch(() => null);
153
+ if (tx && tx.byModel.length > 0) {
154
+ result.modelUsage = tx.byModel.map((m) => ({
155
+ modelFull: m.modelFull,
156
+ modelShort: m.modelShort,
157
+ inputTokens: m.inputTokens,
158
+ outputTokens: m.outputTokens,
159
+ cacheCreationTokens: m.cacheCreationTokens,
160
+ cacheReadTokens: m.cacheReadTokens,
161
+ }));
162
+ }
163
+ }
164
+
149
165
  // Write git note
150
166
  await writeNote(result, repoRoot);
151
167
 
@@ -21,6 +21,16 @@ export interface FileAttribution {
21
21
  pctAi: number;
22
22
  }
23
23
 
24
+ /** Token usage captured from the Claude session transcript at commit time. */
25
+ export interface CommitModelUsage {
26
+ modelFull: string;
27
+ modelShort: "Opus" | "Sonnet" | "Haiku" | "Unknown";
28
+ inputTokens: number;
29
+ outputTokens: number;
30
+ cacheCreationTokens: number;
31
+ cacheReadTokens: number;
32
+ }
33
+
24
34
  export interface AttributionResult {
25
35
  commit: string;
26
36
  /** Session ID from .claude/attribution-state/current-session, or null if committed outside a Claude session. */
@@ -30,6 +40,8 @@ export interface AttributionResult {
30
40
  timestamp: string;
31
41
  files: FileAttribution[];
32
42
  totals: Omit<FileAttribution, "path">;
43
+ /** Token usage from the Claude session that produced this commit. Absent for commits outside a Claude session or pre-v1.5.0 notes. */
44
+ modelUsage?: CommitModelUsage[];
33
45
  }
34
46
 
35
47
  /**
package/src/cli.ts CHANGED
@@ -33,6 +33,9 @@ switch (cmd) {
33
33
  case "note-ai-commit":
34
34
  await import("./commands/note-ai-commit.ts");
35
35
  break;
36
+ case "pr-summary":
37
+ await import("./export/pr-summary.ts");
38
+ break;
36
39
  case "init":
37
40
  await import("./commands/init.ts");
38
41
  break;
@@ -97,6 +100,7 @@ Commands:
97
100
  pr [title] Create PR with metrics embedded (--draft, --base <branch>)
98
101
  init [--ai | --ai-since <YYYY-MM-DD>] Set attribution baseline in the cumulative minimap
99
102
  note-ai-commit [sha] [--push] [--if-ai-actor] Write 100% AI git note for a commit (GHA use)
103
+ pr-summary Export PR attribution metrics via OTLP/webhook (GHA use)
100
104
  start Mark session start for per-ticket scoping
101
105
  hook <name> Run an internal hook (used by installed git hooks)
102
106
  version Print version