claude-attribution 1.2.0 → 1.2.1
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 +38 -24
- package/package.json +1 -1
- package/src/attribution/minimap.ts +35 -15
package/README.md
CHANGED
|
@@ -6,18 +6,14 @@
|
|
|
6
6
|
> ```bash
|
|
7
7
|
> npm install -g claude-attribution
|
|
8
8
|
> claude-attribution install ~/Code/your-repo
|
|
9
|
-
>
|
|
9
|
+
> claude-attribution init --ai # repo built with Claude Code — or --human if human/mixed
|
|
10
|
+
> git add .claude/settings.json .gitignore && git commit -m "chore: install claude-attribution hooks"
|
|
10
11
|
> ```
|
|
11
|
-
> From then on, just work normally. After each `git commit` you'll see a one-line attribution summary in your terminal. When you open a PR
|
|
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.
|
|
12
13
|
>
|
|
13
|
-
> **
|
|
14
|
-
> - **All Claude Code:** `claude-attribution init --ai && git push origin refs/notes/claude-attribution-map`
|
|
15
|
-
> - **All human (or mixed):** `claude-attribution init` (or `--human`) — prints a confirmation, no note written; human is the default
|
|
16
|
-
> - **Not sure?** Default to `--human`. Attribution accumulates accurately from new commits forward.
|
|
14
|
+
> **Using Copilot?** The tool still works for tracking Claude usage alongside Copilot. Copilot line-level attribution isn't supported yet — for Copilot-specific stats, use the GitHub Copilot usage dashboard. Both tools' org-level data flows into the VP Datadog dashboard automatically on every PR merge.
|
|
17
15
|
>
|
|
18
|
-
> **
|
|
19
|
-
>
|
|
20
|
-
> **Requirements:** [Bun](https://bun.sh) (preferred) or Node 18+, and `gh` (GitHub CLI) authenticated.
|
|
16
|
+
> **Requirements:** [Bun](https://bun.sh) (preferred) or Node 18+, and `gh` (GitHub CLI) authenticated for the `/pr` command.
|
|
21
17
|
|
|
22
18
|
---
|
|
23
19
|
|
|
@@ -51,17 +47,45 @@ bun install
|
|
|
51
47
|
|
|
52
48
|
### Install into a repo (per repo, per developer)
|
|
53
49
|
|
|
54
|
-
**
|
|
50
|
+
**Step 1 — Run the installer:**
|
|
51
|
+
|
|
55
52
|
```bash
|
|
53
|
+
# npm install:
|
|
56
54
|
claude-attribution install ~/Code/your-repo
|
|
55
|
+
|
|
56
|
+
# clone install:
|
|
57
|
+
bun ~/Code/claude-attribution/src/setup/install.ts ~/Code/your-repo
|
|
57
58
|
```
|
|
58
59
|
|
|
59
|
-
**
|
|
60
|
+
**Step 2 — Declare your attribution baseline (`init`):**
|
|
61
|
+
|
|
62
|
+
This step tells the tool whether the codebase was written by Claude or by humans before this install. It only needs to be run once.
|
|
63
|
+
|
|
60
64
|
```bash
|
|
61
|
-
|
|
65
|
+
# Repo was built entirely with Claude Code — mark all files as AI-written:
|
|
66
|
+
claude-attribution init --ai
|
|
67
|
+
|
|
68
|
+
# Repo is human-written, or a mix — confirm the default (no note written):
|
|
69
|
+
claude-attribution init --human
|
|
70
|
+
|
|
71
|
+
# Not sure? Run with no flag — same as --human, prints a confirmation:
|
|
72
|
+
claude-attribution init
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> **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.
|
|
76
|
+
|
|
77
|
+
**Step 3 — Commit and push:**
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git add .claude/settings.json .github/workflows/claude-attribution-pr.yml .gitignore
|
|
81
|
+
git commit -m "chore: install claude-attribution hooks"
|
|
82
|
+
git push
|
|
83
|
+
|
|
84
|
+
# If you ran init --ai, also push the minimap notes:
|
|
85
|
+
git push origin refs/notes/claude-attribution-map
|
|
62
86
|
```
|
|
63
87
|
|
|
64
|
-
The installer makes
|
|
88
|
+
The installer makes the following changes to the target repo:
|
|
65
89
|
|
|
66
90
|
**`.claude/settings.json`** — merges six Claude Code hooks:
|
|
67
91
|
|
|
@@ -85,17 +109,7 @@ The installer makes six changes to the target repo:
|
|
|
85
109
|
|
|
86
110
|
**`.gitignore`** — adds `.claude/logs/` so tool usage logs don't end up in version control.
|
|
87
111
|
|
|
88
|
-
###
|
|
89
|
-
|
|
90
|
-
The `.claude/settings.json` and workflow changes should be committed so all developers get the hooks and all PRs get metrics automatically.
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
# After running the installer:
|
|
94
|
-
git add .claude/settings.json .github/workflows/claude-attribution-pr.yml .gitignore
|
|
95
|
-
git commit -m "chore: install claude-attribution hooks"
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Backfilling the attribution minimap
|
|
112
|
+
### Attribution minimap — detailed options
|
|
99
113
|
|
|
100
114
|
The attribution minimap tracks cumulative AI% across the entire codebase, carrying attribution forward across sessions and developers. For new commits it is updated automatically. For the history that predates the install, you declare the baseline once using `claude-attribution init`.
|
|
101
115
|
|
package/package.json
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { execFile } from "child_process";
|
|
20
20
|
import { promisify } from "util";
|
|
21
|
+
import { writeFile, unlink, mkdtemp, rmdir } from "fs/promises";
|
|
22
|
+
import { tmpdir } from "os";
|
|
23
|
+
import { join } from "path";
|
|
21
24
|
import { hashLine } from "./differ.ts";
|
|
22
25
|
|
|
23
26
|
const execFileAsync = promisify(execFile);
|
|
@@ -107,21 +110,38 @@ export async function writeMinimap(
|
|
|
107
110
|
repoRoot: string,
|
|
108
111
|
commitSha = "HEAD",
|
|
109
112
|
): Promise<void> {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
// Write JSON to a temp file and use -F to avoid E2BIG on large repos.
|
|
114
|
+
// Passing the full minimap as a -m argument fails when the JSON exceeds
|
|
115
|
+
// the OS argument size limit (~500KB on macOS).
|
|
116
|
+
//
|
|
117
|
+
// Use mkdtemp to create a unique, isolated temp directory rather than a
|
|
118
|
+
// predictable filename in the shared OS temp dir — prevents collisions
|
|
119
|
+
// under concurrent runs and symlink/race attacks.
|
|
120
|
+
const tmpDir = await mkdtemp(join(tmpdir(), "claude-attribution-minimap-"));
|
|
121
|
+
const tmpFile = join(tmpDir, "minimap.json");
|
|
122
|
+
try {
|
|
123
|
+
await writeFile(tmpFile, JSON.stringify(result, null, 2), {
|
|
124
|
+
encoding: "utf8",
|
|
125
|
+
flag: "wx",
|
|
126
|
+
});
|
|
127
|
+
await run(
|
|
128
|
+
"git",
|
|
129
|
+
[
|
|
130
|
+
"notes",
|
|
131
|
+
"--ref",
|
|
132
|
+
MINIMAP_NOTES_REF,
|
|
133
|
+
"add",
|
|
134
|
+
"--force",
|
|
135
|
+
"-F",
|
|
136
|
+
tmpFile,
|
|
137
|
+
commitSha,
|
|
138
|
+
],
|
|
139
|
+
repoRoot,
|
|
140
|
+
);
|
|
141
|
+
} finally {
|
|
142
|
+
await unlink(tmpFile).catch(() => {});
|
|
143
|
+
await rmdir(tmpDir).catch(() => {});
|
|
144
|
+
}
|
|
125
145
|
}
|
|
126
146
|
|
|
127
147
|
export async function readMinimap(
|