agent-trace-cli 0.1.0__py3-none-any.whl

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.
Files changed (42) hide show
  1. agent_trace/__init__.py +3 -0
  2. agent_trace/blame.py +471 -0
  3. agent_trace/blame_git.py +133 -0
  4. agent_trace/blame_meta.py +167 -0
  5. agent_trace/cli.py +2680 -0
  6. agent_trace/commit_link.py +226 -0
  7. agent_trace/config.py +137 -0
  8. agent_trace/context.py +385 -0
  9. agent_trace/conversations.py +358 -0
  10. agent_trace/git_notes.py +491 -0
  11. agent_trace/hooks/__init__.py +163 -0
  12. agent_trace/hooks/base.py +233 -0
  13. agent_trace/hooks/claude.py +483 -0
  14. agent_trace/hooks/codex.py +232 -0
  15. agent_trace/hooks/cursor.py +278 -0
  16. agent_trace/hooks/git.py +144 -0
  17. agent_trace/ledger.py +955 -0
  18. agent_trace/models.py +618 -0
  19. agent_trace/record.py +417 -0
  20. agent_trace/registry.py +230 -0
  21. agent_trace/remote.py +673 -0
  22. agent_trace/rewrite.py +176 -0
  23. agent_trace/rules.py +209 -0
  24. agent_trace/schemas/commit-link.schema.json +34 -0
  25. agent_trace/schemas/git-note.schema.json +88 -0
  26. agent_trace/schemas/ledger.schema.json +97 -0
  27. agent_trace/schemas/remotes.schema.json +30 -0
  28. agent_trace/schemas/sync-state.schema.json +49 -0
  29. agent_trace/schemas/trace-record.schema.json +130 -0
  30. agent_trace/session.py +136 -0
  31. agent_trace/storage.py +229 -0
  32. agent_trace/summary.py +465 -0
  33. agent_trace/summary_presets.py +188 -0
  34. agent_trace/sync.py +1182 -0
  35. agent_trace/telemetry.py +142 -0
  36. agent_trace/trace.py +460 -0
  37. agent_trace_cli-0.1.0.dist-info/METADATA +535 -0
  38. agent_trace_cli-0.1.0.dist-info/RECORD +42 -0
  39. agent_trace_cli-0.1.0.dist-info/WHEEL +5 -0
  40. agent_trace_cli-0.1.0.dist-info/entry_points.txt +2 -0
  41. agent_trace_cli-0.1.0.dist-info/licenses/LICENSE +201 -0
  42. agent_trace_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,535 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-trace-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for tracing AI-generated code changes
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Provides-Extra: dev
10
+ Requires-Dist: build; extra == "dev"
11
+ Requires-Dist: hypothesis>=6.92; extra == "dev"
12
+ Requires-Dist: jsonschema>=4.20; extra == "dev"
13
+ Requires-Dist: pytest; extra == "dev"
14
+ Dynamic: license-file
15
+
16
+ # agent-trace CLI
17
+
18
+ A command-line tool for tracing AI-generated code changes across coding agents like **Cursor** and **Claude Code**. Includes the **file viewer** for browsing files with git + agent-trace blame in your browser.
19
+
20
+ This implementation follows the [Agent Trace](https://agent-trace.dev/) specification and the **redesign** described in the umbrella workspace: deterministic-only attribution, local-first storage, **git-like** `push` / `pull` / `sync`, **git notes** (`refs/notes/agent-trace`) for sharing metadata with the repo, and an optional HTTP remote as a **pure datastore** (no server-side blame).
21
+
22
+ **How it behaves:**
23
+
24
+ - **Local-first** — Hooks write JSONL under `AGENT_TRACE_HOME` (default `~/.agent-trace/`). Nothing is written into the repo. The `project_id` is derived from the repo's absolute path (Claude-Code convention: `/Users/jane/myrepo` → `-Users-jane-myrepo`), so data lives at `~/.agent-trace/projects/<project_id>/`.
25
+ - **Git-like flow** — `agent-trace init` is zero-prompt and sets up everything locally (like `git init`). Add remotes later with `agent-trace remote add` and run **`agent-trace push` / `pull` / `sync`** explicitly when you want to share. Nothing syncs automatically during editing.
26
+ - **Git notes** — `agent-trace notes …` attaches composable JSON to commits under `refs/notes/agent-trace`, so attribution travels with `git fetch` / `git push` once the notes refspec is configured (set up automatically for `origin` during `init`).
27
+
28
+ Use **`agent-trace blame <file>`** for per-line **AI**, **HUMAN**, **MIXED**, or **UNKNOWN** labels from the ledger (and git note inline ledger when present). There is **no heuristic blame path**: if there is no ledger (and no usable git note), lines are **UNKNOWN**.
29
+
30
+ **Zero external dependencies** — uses only the Python standard library (requires Python 3.9+).
31
+
32
+ ---
33
+
34
+ ## Attribution ledger
35
+
36
+ The **deterministic attribution ledger** is built at **commit time** by the post-commit hook. Each changed line is classified by comparing committed line content (SHA-256 per line) against trace line hashes — not by scoring or probabilities at blame time.
37
+
38
+ 1. **Per-line content hashing** — Traces record hashes for touched lines so matching survives inserts and reordering within reason.
39
+ 2. **Session edit sequence** — Resolves “last writer wins” when multiple traces touch the same line.
40
+ 3. **Post-commit hook** — Runs `agent-trace commit-link`: links the commit to traces and appends a ledger for that commit.
41
+ 4. **Cross-file matching** — The ledger builder can match hashes across files (e.g. moves/refactors) when appropriate.
42
+ 5. **Post-rewrite hook** — After rebase or amend, `agent-trace rewrite-ledger` remaps ledger commit SHAs.
43
+
44
+ `agent-trace blame` uses the ledger only. Missing ledger → **UNKNOWN** (honest absence of proof, not a guess).
45
+
46
+ ---
47
+
48
+ ## Installation
49
+
50
+ ### One-liner (install from GitHub)
51
+
52
+ ```bash
53
+ curl -fsSL https://raw.githubusercontent.com/ujjalsharma100/agent-trace-cli/main/install.sh | bash
54
+ ```
55
+
56
+ ### From the repo (local install)
57
+
58
+ ```bash
59
+ git clone https://github.com/ujjalsharma100/agent-trace-cli
60
+ cd agent-trace-cli
61
+ bash install.sh
62
+ ```
63
+
64
+ ### pip / Python package
65
+
66
+ The project is published as a wheel (`pyproject.toml`). From a clone, in a virtualenv:
67
+
68
+ ```bash
69
+ pip install .
70
+ # contributors (tests + hypothesis + jsonschema):
71
+ pip install -e ".[dev]"
72
+ ```
73
+
74
+ When released to PyPI: `pip install agent-trace-cli`. Build artifacts locally with `python -m build` after `pip install -e ".[dev]"` (or `pip install build`).
75
+
76
+ ### What the installer does
77
+
78
+ 1. If run via curl, downloads the repo from GitHub and runs the installer
79
+ 2. Checks for Python 3.9+
80
+ 3. Copies Python source to `~/.agent-trace/lib/`
81
+ 4. Creates executables at `~/.agent-trace/bin/agent-trace` and a short alias `~/.agent-trace/bin/at`
82
+ 5. Installs the **file viewer** to `~/.agent-trace/viewer/` and creates `~/.agent-trace/bin/agent-trace-viewer`
83
+ - If `npm` is available, builds the frontend from source; otherwise uses the pre-built `dist/`
84
+ 6. Adds `~/.agent-trace/bin` to your shell PATH (zsh, bash, or fish)
85
+ 7. **Offers to set up global hooks** for Cursor and Claude Code (optional, per-tool prompt)
86
+
87
+ After installing, restart your shell (or `source ~/.zshrc`) and verify:
88
+
89
+ ```bash
90
+ agent-trace --version
91
+ at --version # short alias, same binary
92
+ ```
93
+
94
+ ### Uninstall
95
+
96
+ ```bash
97
+ rm -rf ~/.agent-trace/bin ~/.agent-trace/lib ~/.agent-trace/viewer
98
+ ```
99
+
100
+ Then remove the `# agent-trace` + `export PATH=...` lines from your `~/.zshrc` / `~/.bashrc`.
101
+
102
+ ---
103
+
104
+ ## Commands
105
+
106
+ ### `agent-trace init`
107
+
108
+ Zero-prompt initialization — like `git init`. Writes `project-config.json` for the repo, enables notes with default sections, installs git hooks (`post-commit`, `post-rewrite`) and per-tool hooks (Cursor, Claude Code) when a global hook is not already present, and auto-configures the git notes refspec (`refs/notes/agent-trace`) for `origin` if one exists.
109
+
110
+ No prompts, no remote. If you want to share traces with a team, add a remote later with `agent-trace remote add`. Re-run with `agent-trace reset` to reconfigure interactively.
111
+
112
+ ```bash
113
+ cd my-project
114
+ agent-trace init # or: at init
115
+ ```
116
+
117
+ ### `agent-trace status`
118
+
119
+ Show project id, data paths, counts, hook status, remote/sync-related status, and whether unpushed data exists (git-style overview).
120
+
121
+ ```bash
122
+ agent-trace status
123
+ ```
124
+
125
+ ### `agent-trace config {show,set,reset}`
126
+
127
+ Show the full persisted configuration, or update/reset a specific field without going through the full interactive reset flow. Token values are masked in `config show`.
128
+
129
+ ```bash
130
+ agent-trace config show
131
+ agent-trace config show --json
132
+ agent-trace config set notes.include-summary false
133
+ agent-trace config reset notes
134
+ agent-trace config reset summary.command
135
+ agent-trace config reset summary.command --yes
136
+ ```
137
+
138
+ `config reset` is interactive by default for the selected field/group; pressing Enter accepts the reset default. Use `--yes` for non-interactive direct reset.
139
+
140
+ ### `agent-trace doctor`
141
+
142
+ Verify hooks, config, storage, remotes, and optional tools (e.g. summary command).
143
+
144
+ ```bash
145
+ agent-trace doctor
146
+ ```
147
+
148
+ ### `agent-trace reset`
149
+
150
+ Interactive reconfiguration — prompts for notes sections, summary command, and hook installation. Remotes are managed separately (`agent-trace remote`).
151
+
152
+ ```bash
153
+ agent-trace reset
154
+ ```
155
+
156
+ ### `agent-trace hooks {setup-global,remove-global,status}`
157
+
158
+ Manage **global hooks** for coding tools. Global hooks are installed once in your home directory and fire for every project — like `git config --global`. Edits in an initialised repo are traced; edits elsewhere are silently ignored.
159
+
160
+ This is the recommended setup: install global hooks once, then `agent-trace init` in each repo you want to trace (for project config, git hooks, and git notes). No per-project Cursor/Claude hook configuration needed.
161
+
162
+ ```bash
163
+ # Install global hooks for all supported tools
164
+ agent-trace hooks setup-global
165
+
166
+ # Install for a specific tool only
167
+ agent-trace hooks setup-global --tool cursor
168
+ agent-trace hooks setup-global --tool claude
169
+
170
+ # Check current status
171
+ agent-trace hooks status
172
+
173
+ # Remove global hooks
174
+ agent-trace hooks remove-global
175
+ agent-trace hooks remove-global --tool claude
176
+ ```
177
+
178
+ | Subcommand | Options | Description |
179
+ |------------|---------|-------------|
180
+ | `setup-global` | `--tool cursor\|claude` | Install global hooks (default: all tools) |
181
+ | `remove-global` | `--tool cursor\|claude` | Remove global hooks (default: all tools) |
182
+ | `status` | — | Show whether global hooks are configured |
183
+
184
+ **Where hooks are written:**
185
+ - Cursor: `~/.cursor/hooks.json`
186
+ - Claude Code: `~/.claude/settings.json`
187
+
188
+ ### `agent-trace record`
189
+
190
+ Record a trace from stdin. This is what the hooks call — you don't run this manually.
191
+
192
+ ```bash
193
+ echo '{"hook_event_name":"sessionStart",...}' | agent-trace record
194
+ ```
195
+
196
+ ### `agent-trace commit-link`
197
+
198
+ Link the current git commit to the traces that were active in this session. Called automatically by the post-commit hook when you have configured git hooks. Also builds an **attribution ledger** for the commit — a deterministic per-line map of which lines are AI-authored, human-authored, or mixed.
199
+
200
+ ```bash
201
+ agent-trace commit-link
202
+ ```
203
+
204
+ ### `agent-trace rewrite-ledger`
205
+
206
+ Remap ledger commit SHAs after `git rebase` or `git commit --amend`. Called automatically by the post-rewrite hook — you don't normally run this manually. Git provides old-SHA/new-SHA pairs on stdin; this command updates `.agent-trace/ledgers.jsonl` accordingly.
207
+
208
+ ```bash
209
+ # Called by .git/hooks/post-rewrite — not typically run manually
210
+ agent-trace rewrite-ledger
211
+ ```
212
+
213
+ ### `agent-trace viewer [--project /path]`
214
+
215
+ Open the **file viewer** in your browser. The viewer lets you browse the project's file tree, view file contents, and see git blame and agent-trace blame inline.
216
+
217
+ The viewer is installed automatically by `install.sh`. If it's missing, re-run `install.sh` to reinstall. Once launched, open **http://127.0.0.1:8765** in your browser.
218
+
219
+ ```bash
220
+ agent-trace viewer
221
+ agent-trace viewer --project /path/to/repo
222
+ ```
223
+
224
+ ### `agent-trace context <file>`
225
+
226
+ Get **conversation context** for AI-attributed lines in a file. Builds on `agent-trace blame` — runs attribution first, then resolves the conversation transcript behind each AI-attributed segment. Two modes:
227
+
228
+ - **Default** — returns attribution metadata plus a short preview (~200 chars) and conversation size stats (characters, lines, turns). Light enough to use inline.
229
+ - **Full (`--full`)** — adds the complete conversation transcript for each AI-attributed segment.
230
+
231
+ ```bash
232
+ agent-trace context src/utils/parser.ts
233
+ agent-trace context src/utils/parser.ts --lines 10-50
234
+ agent-trace context src/utils/parser.ts --lines 10-50 --full
235
+ agent-trace context src/utils/parser.ts --json
236
+ agent-trace context src/utils/parser.ts --lines 10-50 --query "why was this approach chosen?"
237
+ ```
238
+
239
+ | Option | Short | Description |
240
+ |--------|--------|-------------|
241
+ | `--lines` | `-l` | Line range to focus on (e.g. `10-50`) |
242
+ | `--full` | | Include full conversation transcript in output |
243
+ | `--json` | | Output as JSON (for machine / subagent consumption) |
244
+ | `--query` | `-q` | Pass a query through to the output (for subagent instruction forwarding) |
245
+
246
+ The JSON output includes per-segment fields: `start_line`, `end_line`, `attribution` (`ai`/`mixed`/`human`), `model_id`, `tool`, `trace_id`, `confidence`, `conversation_url`, `conversation_size`, and `preview`. When `--full` is set, `conversation_content` is also included.
247
+
248
+ Conversation content is resolved from local `file://` paths recorded alongside the trace.
249
+
250
+ ---
251
+
252
+ ### `agent-trace rule {add,remove,show,list}`
253
+
254
+ Manage **prebuilt rules** that teach coding agents (Cursor, Claude Code) how to use agent-trace features. Rules are written as `.mdc` (Cursor) or `.md` (Claude Code) files in the project's rules directory.
255
+
256
+ ```bash
257
+ # List available prebuilt rules
258
+ agent-trace rule list
259
+
260
+ # Add a rule for a tool
261
+ agent-trace rule add context-for-agents --tool claude
262
+ agent-trace rule add context-for-agents --tool cursor
263
+
264
+ # Show which rules are currently configured
265
+ agent-trace rule show
266
+
267
+ # Remove a rule
268
+ agent-trace rule remove context-for-agents --tool claude
269
+ ```
270
+
271
+ | Subcommand | Options | Description |
272
+ |------------|---------|-------------|
273
+ | `list` | — | List all available prebuilt rules with descriptions |
274
+ | `add <name>` | `--tool cursor\|claude` | Write the rule file for the given tool |
275
+ | `remove <name>` | `--tool cursor\|claude` | Remove the rule file |
276
+ | `show` | — | Show all active agent-trace rules in the project |
277
+
278
+ **Available rules:**
279
+
280
+ | Name | Description |
281
+ |------|-------------|
282
+ | `context-for-agents` | Teaches the agent to retrieve conversation context behind AI-attributed code using `agent-trace context` |
283
+
284
+ Rules are written to:
285
+ - Cursor: `.cursor/rules/agent-trace-<name>.mdc`
286
+ - Claude Code: `.claude/rules/agent-trace-<name>.md`
287
+
288
+ ---
289
+
290
+ ### `agent-trace blame <file>`
291
+
292
+ Show **AI attribution** for a file using **deterministic, ledger-only** logic:
293
+
294
+ - **Ledger** — For each commit, if `.agent-trace/ledgers.jsonl` contains a ledger (built at commit time from traces and line hashes), lines are labelled **AI**, **HUMAN**, or **MIXED** according to that ledger.
295
+ - **UNKNOWN** — If there is no ledger for the introducing commit, or a line range is not covered by the ledger, the output is **UNKNOWN** (nothing is inferred from heuristics or scoring).
296
+
297
+ The command runs `git blame --porcelain`, groups lines by commit, then resolves attribution from the ledger only. Traces in `.agent-trace/traces.jsonl` are used to enrich model and tool metadata when a `trace_id` is present in the ledger.
298
+
299
+ ```bash
300
+ agent-trace blame src/utils/parser.ts
301
+ agent-trace blame src/utils/parser.ts --line 42
302
+ agent-trace blame src/utils/parser.ts --range 10-100
303
+ agent-trace blame src/utils/parser.ts --json
304
+ agent-trace blame src/utils/parser.ts --show-unknown # Include UNKNOWN ranges in output
305
+ agent-trace blame src/utils/parser.ts --require-attribution # Exit 1 if any line is UNKNOWN (CI)
306
+ ```
307
+
308
+ | Option | Short | Description |
309
+ |--------|--------|-------------|
310
+ | `--line` | `-l` | Blame a single line |
311
+ | `--range` | `-r` | Blame a line range (e.g. `10-25`) |
312
+ | `--json` | | Output attributions as JSON (`kind`: `AI`, `HUMAN`, `MIXED`, `UNKNOWN`) |
313
+ | `--show-unknown` | | List UNKNOWN ranges (default is to omit them from text output) |
314
+ | `--require-attribution` | | Fail with non-zero exit if any line would be UNKNOWN |
315
+
316
+ ### `agent-trace set globaluser <token>`
317
+
318
+ Store an auth token globally (`~/.agent-trace/config.json`) so it's used across all projects.
319
+
320
+ ```bash
321
+ agent-trace set globaluser eyJhbGci...
322
+ ```
323
+
324
+ ### `agent-trace remove globaluser`
325
+
326
+ Remove the global auth token.
327
+
328
+ ```bash
329
+ agent-trace remove globaluser
330
+ ```
331
+
332
+ ### `agent-trace remote` — `add` | `list` | `show` | `set-url` | `set-token` | `remove` | `rename` | `default`
333
+
334
+ Manage named HTTP remotes (like `git remote`). Defaults are used by `push` / `pull` / `sync`.
335
+
336
+ ### `agent-trace push` | `pull` | `sync`
337
+
338
+ Explicit sync with the configured service: upload/download traces, ledgers, commit-links, and conversations (see `agent-trace push --help` for options such as attributed-only vs full scope).
339
+
340
+ ### `agent-trace notes` — `show` | `attach` | `rebuild` | `backfill` | `strip` | `push` | `pull`
341
+
342
+ Build and manage JSON under **`refs/notes/agent-trace`** so teammates can receive trace pointers and optional inline ledgers via normal git fetch.
343
+
344
+ ### `agent-trace summary` — `enable` | `disable` | `generate` | `show`
345
+
346
+ Optional pluggable summaries of the agent's conversation transcript. When enabled, agent-trace pipes the raw transcript file (whatever the agent writes to `transcript_path` — Claude Code JSONL, Cursor's equivalent, etc.) on stdin to your configured command. The command's stdout is treated as the summary text and stored keyed by `conversation_url` (`file://<transcript_path>`).
347
+
348
+ ```bash
349
+ # Enable: command takes transcript text on stdin, prints summary text on stdout.
350
+ agent-trace summary enable --command 'my-summarizer'
351
+ agent-trace summary enable --command 'my-summarizer' --timeout 60
352
+
353
+ # Discover built-in presets (local CLI tools)
354
+ agent-trace summary presets
355
+
356
+ # Configure a built-in preset
357
+ agent-trace summary use claude-summary
358
+ agent-trace summary use cursor-summary
359
+ agent-trace summary use ollama-summary --model llama3.1:8b
360
+
361
+ # Manually regenerate for one URL or for every URL touched by a session.
362
+ agent-trace summary generate --conversation-url 'file:///path/to/transcript.jsonl'
363
+ agent-trace summary generate --session-id <conversation_id>
364
+
365
+ # Inspect summaries attached to a commit.
366
+ agent-trace summary show # HEAD
367
+ agent-trace summary show <commit>
368
+
369
+ agent-trace summary disable
370
+ ```
371
+
372
+ The schema of the transcript is opaque to agent-trace — your command decides how to parse it. Storage is `~/.agent-trace/projects/<id>/session-summaries.jsonl`; latest row per `conversation_url` wins. `agent-trace blame` and `agent-trace context` will show the summary in place of the raw transcript preview / URL when one exists.
373
+
374
+ Built-in preset aliases:
375
+
376
+ - `claude-summary` → runs `claude -p "<prompt>"`
377
+ - `cursor-summary` → runs `cursor agent -p "<prompt>" --trust`
378
+ - `ollama-summary` → runs `ollama run <model> "<prompt>"` (`--model` optional; default `llama3.1:8b`)
379
+
380
+ ### `agent-trace projects` | `adopt`
381
+
382
+ List registered projects or adopt a repo directory and print its `project_id`.
383
+
384
+ ---
385
+
386
+ ## Configuration
387
+
388
+ ### Global — `~/.agent-trace/config.json`
389
+
390
+ ```json
391
+ {
392
+ "auth_token": "your-token-here"
393
+ }
394
+ ```
395
+
396
+ ### Project identity — no in-repo file
397
+
398
+ The `project_id` is derived from the canonical repo path (e.g. `/Users/jane/myrepo` → `-Users-jane-myrepo`). Nothing is written into the repo to identify it; every invocation recomputes the id from the working directory. Moving the repo changes the id — same as `git init`'ing a fresh copy.
399
+
400
+ ### Project settings — `~/.agent-trace/projects/<project_id>/project-config.json`
401
+
402
+ Created/managed by `agent-trace init`. Holds `notes.*`, `summary.*`, and per-project remote defaults. Lives under `AGENT_TRACE_HOME` — never committed.
403
+
404
+ ### Resolution order
405
+
406
+ | Setting | Priority |
407
+ |---------|----------|
408
+ | Auth token | `AGENT_TRACE_TOKEN` env > global config |
409
+ | Remote URL | Named remote from `agent-trace remote` (per-project) |
410
+
411
+ ---
412
+
413
+ ## How hooks work
414
+
415
+ Hooks pipe coding agent events through `agent-trace record`. They can be installed at two levels:
416
+
417
+ - **Global** (recommended) — `~/.cursor/hooks.json`, `~/.claude/settings.json`. Fire for *every* project, like `git config --global`. Set up once with `agent-trace hooks setup-global`.
418
+ - **Project-level** — `<project>/.cursor/hooks.json`, `<project>/.claude/settings.json`. Set up per-project during `agent-trace init`.
419
+
420
+ Global hooks are the recommended approach. The recording pipeline resolves the correct project from the **file being edited** (via its git root), not from the agent's working directory. This means:
421
+
422
+ - Edits to files inside an initialised repo are recorded for that project
423
+ - Edits to files outside any initialised repo are silently ignored
424
+ - An agent running from a parent directory editing files in a subfolder project works correctly
425
+ - An agent running from a subfolder of an initialised project works correctly
426
+
427
+ When global hooks are present, `agent-trace init` skips the per-tool hook prompts — they'd be redundant.
428
+
429
+ There are two kinds of hook events:
430
+
431
+ 1. **Trace-recording hooks** — after file edits, shell runs, and session start/end. Each event produces a trace record (written to JSONL under `AGENT_TRACE_HOME`). Traces include per-line content hashes and edit sequence numbers for deterministic attribution.
432
+ 2. **Conversation-sync hooks** — after the assistant has finished a full response. These do **not** create a trace; they refresh the local reference to the conversation transcript so later `agent-trace context` calls see the full turn. Sharing with a remote happens explicitly via `agent-trace push` / `sync`.
433
+
434
+ ### Git hooks
435
+
436
+ Two git hooks are installed when you configure git hooks during `agent-trace init`:
437
+
438
+ - **`post-commit`** — Runs `agent-trace commit-link` after every commit. This links the commit to its traces and builds the attribution ledger.
439
+ - **`post-rewrite`** — Runs `agent-trace rewrite-ledger` after rebase or amend. This remaps ledger SHAs from old commits to their new counterparts.
440
+
441
+ ### Cursor — `.cursor/hooks.json` (project) or `~/.cursor/hooks.json` (global)
442
+
443
+ ```json
444
+ {
445
+ "version": 1,
446
+ "hooks": {
447
+ "sessionStart": [{ "command": "agent-trace record" }],
448
+ "sessionEnd": [{ "command": "agent-trace record" }],
449
+ "afterFileEdit": [{ "command": "agent-trace record" }],
450
+ "afterTabFileEdit": [{ "command": "agent-trace record" }],
451
+ "afterShellExecution": [{ "command": "agent-trace record" }],
452
+ "afterAgentResponse": [{ "command": "agent-trace record" }]
453
+ }
454
+ }
455
+ ```
456
+
457
+ - **Trace events:** `sessionStart`, `sessionEnd`, `afterFileEdit`, `afterTabFileEdit`, `afterShellExecution`
458
+ - **Conversation sync only:** `afterAgentResponse` (no trace; refreshes transcript reference)
459
+
460
+ ### Claude Code — `.claude/settings.json` (project) or `~/.claude/settings.json` (global)
461
+
462
+ ```json
463
+ {
464
+ "hooks": {
465
+ "SessionStart": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }],
466
+ "SessionEnd": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }],
467
+ "PostToolUse": [
468
+ { "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "agent-trace record" }] },
469
+ { "matcher": "Bash", "hooks": [{ "type": "command", "command": "agent-trace record" }] }
470
+ ],
471
+ "Stop": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }]
472
+ }
473
+ }
474
+ ```
475
+
476
+ - **Trace events:** `SessionStart`, `SessionEnd`, `PostToolUse` (Write/Edit, Bash)
477
+ - **Conversation sync only:** `Stop` (no trace; refreshes transcript reference when the agent loop ends)
478
+
479
+ Existing hooks are **preserved** — agent-trace entries are merged in without overwriting anything.
480
+
481
+ ---
482
+
483
+ ## File structure
484
+
485
+ ```
486
+ ~/.cursor/hooks.json # Cursor global hooks (optional, via hooks setup-global)
487
+ ~/.claude/settings.json # Claude Code global hooks (optional, via hooks setup-global)
488
+
489
+ ~/.agent-trace/
490
+ bin/agent-trace # CLI executable (on PATH)
491
+ bin/at # short alias → agent-trace
492
+ bin/agent-trace-viewer # viewer launcher (on PATH)
493
+ lib/agent_trace/ # Python source
494
+ __init__.py
495
+ cli.py # CLI commands (argparse)
496
+ config.py # Global + project settings
497
+ storage.py # Path-based project_id + AGENT_TRACE_HOME paths
498
+ registry.py # Optional metadata registry (first commit, origin, known_roots)
499
+ hooks.py # Cursor, Claude Code & git hook setup (project + global)
500
+ record.py # Trace recording from hooks
501
+ trace.py # Trace record construction + per-line hashing
502
+ blame.py # Deterministic blame (ledger + git notes; UNKNOWN when missing)
503
+ context.py # Conversation context for AI-attributed segments
504
+ rules.py # Prebuilt agent rules (Cursor, Claude Code)
505
+ commit_link.py # Commit-link + ledger build (post-commit)
506
+ ledger.py # Ledger construction
507
+ rewrite.py # Post-rewrite SHA remapping
508
+ sync.py # Push/pull/sync to HTTP remote
509
+ git_notes.py # Git notes (refs/notes/agent-trace)
510
+ remote.py # Named remotes
511
+ ...
512
+ viewer/ # file viewer (installed by install.sh)
513
+ config.json # global config (auth_token)
514
+ projects.json # optional metadata registry
515
+
516
+ ~/.agent-trace/projects/<project_id>/ # project_id = sanitized absolute repo path
517
+ project-config.json # project settings
518
+ traces.jsonl
519
+ commit-links.jsonl
520
+ ledgers.jsonl
521
+ session-state.json
522
+ session-summaries.jsonl
523
+ sync-state.json # push/pull cursors (when using remotes)
524
+
525
+ <your-project>/ # NOTHING is written into the repo itself for identity
526
+ .cursor/hooks.json # Cursor project hooks (only if no global hooks)
527
+ .claude/settings.json # Claude Code project hooks (only if no global hooks)
528
+ .git/hooks/post-commit # agent-trace commit-link
529
+ .git/hooks/post-rewrite # agent-trace rewrite-ledger
530
+ .git/config # notes refspec added for `origin` so notes travel with push/fetch
531
+ ```
532
+
533
+ ## License
534
+
535
+ Licensed under the [Apache License 2.0](LICENSE).
@@ -0,0 +1,42 @@
1
+ agent_trace/__init__.py,sha256=6ueWuOT30F1Q4FkP32ibpPM8JgGJQQ-Mez3T47i3E9w,93
2
+ agent_trace/blame.py,sha256=GJrBFDCmbLu-ymYp3ZpLOJil57pF9QFhDIhJ_FwrcEs,16911
3
+ agent_trace/blame_git.py,sha256=Cyo_uJl31B9UXDTjTlvCHR8kIhJ0IR-AXv490mMI7Wk,4437
4
+ agent_trace/blame_meta.py,sha256=2F12Eqbsv4EVJP-yB9y530oiyb2GZwTZSEIIzn8aEp4,6279
5
+ agent_trace/cli.py,sha256=HJeaHuDCUuiPS9cmB6NODbw9XJmTJVzY7RxxFmKjvDg,101372
6
+ agent_trace/commit_link.py,sha256=XZoS_fxVZYQ8m4g2kE_9qhH6M4zJ-MXsJ5mOnOs_a8o,6973
7
+ agent_trace/config.py,sha256=s9VwPO3CXYnfOcQIGKZSRu4I2Kza7ZkIDDj2HUGNbJ8,4296
8
+ agent_trace/context.py,sha256=yEaSNX53U3RWXhZW3QSRxvOEcv3Ey9kWwK3lkDONU2A,12435
9
+ agent_trace/conversations.py,sha256=VIZtspOWK-Ngg1qh2cs0UL-3BiRO07gHo3SueZdq4jI,12213
10
+ agent_trace/git_notes.py,sha256=CkVRrse8LDyWOBMdk8ghQTxjKVL27XBgneE_gG7QJMc,16561
11
+ agent_trace/ledger.py,sha256=KugkGUqT9SwcBSFfTef-17pNU8PaCVHA08HvyaabH3g,34513
12
+ agent_trace/models.py,sha256=0RrzSe8ND3hjKlO6TBnfG3pcrkXAMqKhBzIMr8apg6M,19379
13
+ agent_trace/record.py,sha256=NR2judgYFTCGxr5kZBSCO-88i72Cdq8YWmr7wdzjAK8,14191
14
+ agent_trace/registry.py,sha256=d1aj6kMwLQWpj0LbQMA-3Fl07aDJQVsVUoGBazSOkec,7033
15
+ agent_trace/remote.py,sha256=sGv0N7HdN9_W7GUc322tft_aom-rSmK7I06QtrX13_Q,22735
16
+ agent_trace/rewrite.py,sha256=6IWF1Py0-JxEF04jq-tX44J4BDqqnDCNSRDxTIVl3co,6259
17
+ agent_trace/rules.py,sha256=fSncdvLJx-IgMJXirxly3-Do79XDTy0Bhc4aZOcECPo,7670
18
+ agent_trace/session.py,sha256=-_dSaR4eZCWbnytzneQw9aoYDC7KVAZcT8oynWLHO_Q,4192
19
+ agent_trace/storage.py,sha256=kVKlriSeZqg00-x9aZh8GhsPFYwdQaIgjycnTFSafEw,7488
20
+ agent_trace/summary.py,sha256=96EpIpSPcqxGN8bNY8jrWOYV9WbmNZS0x8-zYD6cRcU,15465
21
+ agent_trace/summary_presets.py,sha256=a2dKBuIHB4l1ZxguKnjwilab_ETEHLM_907K7P6mrjE,6589
22
+ agent_trace/sync.py,sha256=skie4GrDKZc9Er4RUqbrwfzDxYAECQX_vYckzUwK4sY,40274
23
+ agent_trace/telemetry.py,sha256=Vk09aW5AMBHZjSHJ9I-cKa1km6TlgEb60XyvkxyVyGo,4403
24
+ agent_trace/trace.py,sha256=DrqaCaEnhm8YV7OYc-9LipttEvA8sVYg-63PJfxYbtw,14881
25
+ agent_trace/hooks/__init__.py,sha256=9YM3ixHSI3WhXc8Qmp3zixa4xXUQGXI-sLo784QE6l0,4730
26
+ agent_trace/hooks/base.py,sha256=K7A5_r6d4nMigkWmcRVNUJBk_6BQujEuDrVfYyQ1rGM,8683
27
+ agent_trace/hooks/claude.py,sha256=o_aFOacJq5oWQNNpbJPr44GM1AiNs1m6KQpK_mBILzo,16046
28
+ agent_trace/hooks/codex.py,sha256=x7ygZvE5WG2m-8-83XiBKXvM0oSXgk057K3ilt9pjbg,8461
29
+ agent_trace/hooks/cursor.py,sha256=fjBxwa-RDSdwbN0vZ0u-75efcWD7Je99wbHufQxFpks,8891
30
+ agent_trace/hooks/git.py,sha256=ZhDfp8AXYMpDjScMT6pL-57j6mEZQlwKxtJyIMCZOfE,3996
31
+ agent_trace/schemas/commit-link.schema.json,sha256=0GLYQgFkilBJHucpV6LJJDjm0tT19uZCkpD0B-RRe4Q,1029
32
+ agent_trace/schemas/git-note.schema.json,sha256=gvAxMop-niWnQSngK50EtrXmdqkdf0AgPO_MogNAzMg,3026
33
+ agent_trace/schemas/ledger.schema.json,sha256=BrB6Tl7WA9j1N_dK_4F1OgJbU0rhx_-5pjexUsdzep0,3261
34
+ agent_trace/schemas/remotes.schema.json,sha256=b8zPdwthXiv0DZfbHS_BY2Fnf_XR94N4lBYpWZOBXP8,919
35
+ agent_trace/schemas/sync-state.schema.json,sha256=pgvFVQ3V6qtyE7xWdAxIgdk1AeoYQAx2dDrjhb9QhZM,1905
36
+ agent_trace/schemas/trace-record.schema.json,sha256=1G0GdvMQWjEkJeuFkPUZUNHc08YyP3aCCYrLhhX3D94,4062
37
+ agent_trace_cli-0.1.0.dist-info/licenses/LICENSE,sha256=vxtOivPsRCj28bl-RQPbK2aVc5uVgDXFH4Av4WgU4RI,11322
38
+ agent_trace_cli-0.1.0.dist-info/METADATA,sha256=5BO4N2sFc7207CQGUPX1aL3nH-BY5ilL8T_Ib4TYmuU,24207
39
+ agent_trace_cli-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
40
+ agent_trace_cli-0.1.0.dist-info/entry_points.txt,sha256=iLXgh4SHH9idebpRD7wD2K9qnliMt6mIwKMR9EdWKF0,53
41
+ agent_trace_cli-0.1.0.dist-info/top_level.txt,sha256=q7SNXVNT4uSjUXakTmdGCdRP2Zc1NhzNgXl8ZQUvy0Y,12
42
+ agent_trace_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agent-trace = agent_trace.cli:main