Metadata-Version: 2.4
Name: agent-trace-cli
Version: 0.1.3
Summary: CLI tool for tracing AI-generated code changes
License-Expression: Apache-2.0
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: hypothesis>=6.92; extra == "dev"
Requires-Dist: jsonschema>=4.20; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

<h1 align="center">agent-trace CLI</h1>

<p align="center">
  Trace AI-generated code changes across Cursor, Claude Code, and Codex CLI.
</p>

<p align="center">
  <a href="https://pypi.org/project/agent-trace-cli/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/agent-trace-cli"></a>
  <a href="https://pypi.org/project/agent-trace-cli/"><img alt="PyPI downloads" src="https://pepy.tech/badge/agent-trace-cli"></a>
  <a href="https://github.com/ujjalsharma100/agent-trace-cli/releases"><img alt="GitHub downloads" src="https://img.shields.io/github/downloads/ujjalsharma100/agent-trace-cli/total"></a>
  <a href="https://github.com/ujjalsharma100/agent-trace-cli/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/ujjalsharma100/agent-trace-cli"></a>
  <a href="https://github.com/ujjalsharma100/agent-trace-cli/actions/workflows/docs.yml"><img alt="Documentation status" src="https://github.com/ujjalsharma100/agent-trace-cli/actions/workflows/docs.yml/badge.svg"></a>
</p>

<p align="center">
  <img src="docs/assets/gif-1-money-shot.gif" alt="Per-line AI attribution and the prompt behind any line" width="800">
</p>
<p align="center">
  <code>pip install agent-trace-cli</code> · <a href="https://www.youtube.com/watch?v=J4LPhV9wURg">▶ 3-min demo</a>
</p>

Includes the **file viewer** for browsing files with git + agent-trace blame in your browser.

This implementation follows the [Agent Trace](https://agent-trace.dev/) specification: 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).

When your host gives a trace **remote URL** and a **Bearer token**, add the remote with **`agent-trace remote add <name> <url> --token`** or **`--token-env`**. URLs may use a gateway path prefix such as **`/at/<org>/<project>`** before **`/api/v1/...`** sync routes.

**How it behaves:**

- **Local-first** — Hooks write JSONL under `AGENT_TRACE_HOME` (default `~/.agent-trace/`). Nothing is written into your working tree. Each repo gets a stable `project_id` anchored in `.git/agent-trace-id`, so data lives at `~/.agent-trace/projects/<project_id>/` and stays put across renames and worktrees.
- **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.
- **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`).

Use **`agent-trace blame <file>`** for per-line attribution from the ledger (and git note inline ledger when present). Attribution is **binary** — each line is **AI** or **No attribution**. There is **no heuristic blame path**: if there is no ledger (and no usable git note), lines are **No attribution**.

**Zero external dependencies** — uses only the Python standard library (requires Python 3.9+).

---

## Attribution ledger

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.

1. **Per-line content hashing** — Traces record hashes for touched lines so matching survives inserts and reordering within reason.
2. **Session edit sequence** — Resolves “last writer wins” when multiple traces touch the same line.
3. **Post-commit hook** — Runs `agent-trace commit-link`: links the commit to traces and appends a ledger for that commit.
4. **Cross-file matching** — The ledger builder can match hashes across files (e.g. moves/refactors) when appropriate.
5. **Post-rewrite hook** — After rebase or amend, `agent-trace rewrite-ledger` remaps ledger commit SHAs.

`agent-trace blame` uses the ledger only. Missing ledger → **No attribution** (honest absence of proof, not a guess).

---

## Installation

### One-liner (curl install)

```bash
curl -fsSL https://raw.githubusercontent.com/ujjalsharma100/agent-trace-cli/main/install.sh | bash
```

Downloads the **latest GitHub Release** install tarball (see `agent-trace-cli.tar.gz` on each release). Requires at least one published release with that asset.

### From the repo (local install)

```bash
git clone https://github.com/ujjalsharma100/agent-trace-cli
cd agent-trace-cli
bash install.sh
```

### pip (PyPI)

```bash
pip install agent-trace-cli
```

Installs the `agent-trace` CLI. The **file viewer** is not included — use the one-liner or `install.sh` above for `agent-trace viewer`. See [Installation](https://ujjalsharma100.github.io/agent-trace-cli/installation/) for upgrade/uninstall notes.

From a clone (contributors), in a virtualenv:

```bash
pip install .
# tests + hypothesis + jsonschema:
pip install -e ".[dev]"
```

Build release wheels with `python -m build` after `pip install -e ".[dev]"` (or `pip install build`).

### What the installer does

1. If run via curl, downloads the **latest GitHub Release** install tarball and runs the installer
2. Checks for Python 3.9+
3. Copies Python source to `~/.agent-trace/lib/`
4. Creates executables at `~/.agent-trace/bin/agent-trace` and a short alias `~/.agent-trace/bin/at`
5. Installs the **file viewer** to `~/.agent-trace/viewer/` and creates `~/.agent-trace/bin/agent-trace-viewer`
   - If `npm` is available, builds the frontend from source; otherwise uses the pre-built `dist/`
6. Adds `~/.agent-trace/bin` to your shell PATH (zsh, bash, or fish)
7. **Offers to set up global hooks** for Cursor, Claude Code, and Codex CLI (optional, per-tool prompt)

After installing, restart your shell (or `source ~/.zshrc`) and verify:

```bash
agent-trace --version
at --version        # short alias, same binary
```

### Uninstall

```bash
rm -rf ~/.agent-trace/bin ~/.agent-trace/lib ~/.agent-trace/viewer
```

Then remove the `# agent-trace` + `export PATH=...` lines from your `~/.zshrc` / `~/.bashrc`.

---

## Commands

### `agent-trace init`

Zero-prompt initialization — like `git init`. Writes `project-config.json` for the repo, enables notes (including **all-session conversations** by default), turns on **session summaries** with the built-in **ollama-summary** preset (default model **llama3.1:8b**; requires `ollama` on `PATH` when hooks run), 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.

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.

```bash
cd my-project
agent-trace init      # or: at init
```

### `agent-trace status`

Show project id, data paths, counts, hook status, remote/sync-related status, and whether unpushed data exists (git-style overview).

```bash
agent-trace status
```

### `agent-trace config {show,set,reset}`

Show the full persisted configuration (human-readable field list by default, or `--json`), or update/reset a specific field without going through the full interactive reset flow. Token values are masked in `config show`.

```bash
agent-trace config show
agent-trace config show --json
agent-trace config set notes.include-summary false
agent-trace config reset notes
agent-trace config reset summary.command
agent-trace config reset summary.command --yes
```

`config reset` is interactive by default for the selected field/group; pressing Enter accepts the reset default. Use `--yes` for non-interactive direct reset.

### `agent-trace doctor`

Verify hooks, config, storage, remotes, and optional tools (e.g. summary command).

```bash
agent-trace doctor
```

### `agent-trace reset`

Interactive reconfiguration — prompts for notes sections, summary command, and hook installation. Remotes are managed separately (`agent-trace remote`).

```bash
agent-trace reset
```

### `agent-trace hooks {setup-global,remove-global,status}`

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.

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.

```bash
# Install global hooks for all supported tools
agent-trace hooks setup-global

# Install for a specific tool only
agent-trace hooks setup-global --tool cursor
agent-trace hooks setup-global --tool claude
agent-trace hooks setup-global --tool codex

# Check current status
agent-trace hooks status

# Remove global hooks
agent-trace hooks remove-global
agent-trace hooks remove-global --tool claude
```

| Subcommand | Options | Description |
|------------|---------|-------------|
| `setup-global` | `--tool cursor\|claude\|codex` | Install global hooks (default: all tools) |
| `remove-global` | `--tool cursor\|claude\|codex` | Remove global hooks (default: all tools) |
| `status` | — | Show whether global hooks are configured |

**Where hooks are written:**
- Cursor: `~/.cursor/hooks.json`
- Claude Code: `~/.claude/settings.json`
- Codex CLI: `~/.codex/config.toml`

### `agent-trace record`

Record a trace from stdin. This is what the hooks call — you don't run this manually.

```bash
echo '{"hook_event_name":"sessionStart",...}' | agent-trace record
```

### `agent-trace commit-link`

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, binary per-line map of which lines are AI-attributed versus not.

```bash
agent-trace commit-link
```

### `agent-trace rewrite-ledger`

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 the project's `ledgers.jsonl` (under `~/.agent-trace/projects/<id>/`) accordingly.

```bash
# Called by .git/hooks/post-rewrite — not typically run manually
agent-trace rewrite-ledger
```

### `agent-trace viewer [--project /path]`

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.

<p align="center">
  <img src="docs/assets/gif-3-local-viewer.gif" alt="Local file viewer: git blame plus AI authorship overlay, no account required" width="800">
</p>

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.

```bash
agent-trace viewer
agent-trace viewer --project /path/to/repo
```

### `agent-trace context <file>`

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:

- **Default** — returns attribution metadata plus a short preview (~200 chars) and conversation size stats (characters, lines, turns). Light enough to use inline.
- **Full (`--full`)** — adds the complete conversation transcript for each AI-attributed segment.

```bash
agent-trace context src/utils/parser.ts
agent-trace context src/utils/parser.ts --lines 10-50
agent-trace context src/utils/parser.ts --lines 10-50 --full
agent-trace context src/utils/parser.ts --json
agent-trace context src/utils/parser.ts --lines 10-50 --query "why was this approach chosen?"
```

| Option | Short | Description |
|--------|--------|-------------|
| `--lines` | `-l` | Line range to focus on (e.g. `10-50`) |
| `--full` | | Include full conversation transcript in output |
| `--json` | | Output as JSON (for machine / subagent consumption) |
| `--query` | `-q` | Pass a query through to the output (for subagent instruction forwarding) |

The JSON output includes per-segment fields such as: `start_line`, `end_line`, `attribution` (`ai` / `no_attribution`), `model_id`, `tool`, `trace_id`, `confidence`, `conversation_id`, `conversation_size`, `preview`, optional `summary` (when session summaries are recorded), and optional `query` when `--query` is set. When `--full` is set, `conversation_content` is also included.

Conversation content is resolved from local `file://` paths recorded alongside the trace.

---

### `agent-trace rule {add,remove,show,list}`

Manage **prebuilt rules** that teach coding agents (Cursor, Claude Code, Codex CLI) how to use agent-trace features. Rules are written as `.mdc` (Cursor) or `.md` (Claude Code, Codex CLI) files in the project's rules directory.

```bash
# List available prebuilt rules
agent-trace rule list

# Add a rule for a tool
agent-trace rule add context-for-agents --tool claude
agent-trace rule add context-for-agents --tool cursor

# Show which rules are currently configured
agent-trace rule show

# Remove a rule
agent-trace rule remove context-for-agents --tool claude
```

| Subcommand | Options | Description |
|------------|---------|-------------|
| `list` | — | List all available prebuilt rules with descriptions |
| `add <name>` | `--tool cursor\|claude\|codex` | Write the rule file for the given tool |
| `remove <name>` | `--tool cursor\|claude\|codex` | Remove the rule file |
| `show` | — | Show all active agent-trace rules in the project |

**Available rules:**

| Name | Description |
|------|-------------|
| `context-for-agents` | Teaches the agent to retrieve conversation context behind AI-attributed code using `agent-trace context` |

Rules are written to:
- Cursor: `.cursor/rules/agent-trace-<name>.mdc`
- Claude Code: `.claude/rules/agent-trace-<name>.md`
- Codex CLI: `.codex/rules/agent-trace-<name>.md`

---

### `agent-trace blame <file>`

Show **AI attribution** for a file using **deterministic, ledger-only** logic. Attribution is **binary** — each line is **AI** or **No attribution**:

- **AI** — For each commit, if the project's `ledgers.jsonl` contains a ledger segment (built at commit time from traces and line hashes) matching the line, it is labelled **AI**.
- **No attribution** — If there is no ledger for the introducing commit, or a line is not covered by an AI segment, the output is **No attribution** (nothing is inferred from heuristics or scoring; the tool never claims a line was human-written).

The command runs `git blame --porcelain`, groups lines by commit, then resolves attribution from the ledger only. Traces in the project's `traces.jsonl` are used to enrich model and tool metadata when a `trace_id` is present in the ledger.

```bash
agent-trace blame src/utils/parser.ts
agent-trace blame src/utils/parser.ts --line 42
agent-trace blame src/utils/parser.ts --range 10-100
agent-trace blame src/utils/parser.ts --json
agent-trace blame src/utils/parser.ts --show-no-attribution    # Include No-attribution ranges in output
agent-trace blame src/utils/parser.ts --require-attribution   # Exit 1 if any line is unattributed (CI)
```

| Option | Short | Description |
|--------|--------|-------------|
| `--line` | `-l` | Blame a single line |
| `--range` | `-r` | Blame a line range (e.g. `10-25`) |
| `--json` | | Output attributions as JSON (`kind`: `AI` or `NO_ATTRIBUTION`) |
| `--show-no-attribution` | | List No-attribution ranges (default is to omit them from text output) |
| `--require-attribution` | | Fail with non-zero exit if any line is No attribution |

### `agent-trace set globaluser <token>`

Store an auth token globally (`~/.agent-trace/config.json`) so it's used across all projects.

```bash
agent-trace set globaluser eyJhbGci...
```

### `agent-trace remove globaluser`

Remove the global auth token.

```bash
agent-trace remove globaluser
```

### `agent-trace remote` — `add` | `list` | `show` | `set-url` | `set-token` | `remove` | `rename` | `default`

Manage named HTTP remotes (like `git remote`). Defaults are used by `push` / `pull` / `sync`.

### `agent-trace push` | `pull` | `sync`

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).

### `agent-trace notes` — `show` | `attach` | `rebuild` | `backfill` | `strip` | `push` | `pull`

Build and manage JSON under **`refs/notes/agent-trace`** so teammates can receive trace pointers and optional inline ledgers via normal git fetch.

### `agent-trace summary` — `enable` | `disable` | `generate` | `show`

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>`).

```bash
# Enable: command takes transcript text on stdin, prints summary text on stdout.
agent-trace summary enable --command 'my-summarizer'
agent-trace summary enable --command 'my-summarizer' --timeout 60

# Discover built-in presets (local CLI tools)
agent-trace summary presets

# Configure a built-in preset
agent-trace summary use claude-summary
agent-trace summary use cursor-summary
agent-trace summary use ollama-summary --model llama3.1:8b

# Manually regenerate for one URL or for every URL touched by a session.
agent-trace summary generate --conversation-url 'file:///path/to/transcript.jsonl'
agent-trace summary generate --session-id <conversation_id>

# Inspect summaries attached to a commit.
agent-trace summary show              # HEAD
agent-trace summary show <commit>

agent-trace summary disable
```

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.

Built-in preset aliases:

- `claude-summary` → runs `claude -p "<prompt>"`
- `cursor-summary` → runs `cursor agent --print --trust` (prompt piped on stdin)
- `ollama-summary` → runs `ollama run <model> --think=false` (prompt piped on stdin; `--model` optional, default `llama3.1:8b`)

### `agent-trace projects` | `adopt`

List registered projects or adopt a repo directory and print its `project_id`.

---

## Configuration

### Global — `~/.agent-trace/config.json`

```json
{
  "auth_token": "your-token-here"
}
```

### Project identity — `.git/agent-trace-id` anchor

On `init`, each repo gets a stable opaque `project_id` (`at-<32 hex>`) written to `.git/agent-trace-id`. Nothing is written into the working tree, and the anchor is never committed. Because the id lives inside `.git`, it is shared across linked worktrees and survives moving or renaming the repo; a fresh clone gets a new anchor. Before `init` (or outside a git repo) the tool falls back to a sanitized path-derived id.

### Project settings — `~/.agent-trace/projects/<project_id>/project-config.json`

Created/managed by `agent-trace init`. Holds `notes.*`, `summary.*`, and per-project remote defaults. Lives under `AGENT_TRACE_HOME` — never committed.

### Resolution order

| Setting | Priority |
|---------|----------|
| Sync auth token | Per-remote token bound by `agent-trace remote add --token` / `--token-env`. `AGENT_TRACE_TOKEN` and `set globaluser` are **legacy** and are not consulted by `push` / `pull` / `sync`. |
| Remote URL | Named remote from `agent-trace remote` (per-project) |

---

## How hooks work

Hooks pipe coding agent events through `agent-trace record`. They can be installed at two levels:

- **Global** (recommended) — `~/.cursor/hooks.json`, `~/.claude/settings.json`, `~/.codex/config.toml`. Fire for *every* project, like `git config --global`. Set up once with `agent-trace hooks setup-global`.
- **Project-level** — `<project>/.cursor/hooks.json`, `<project>/.claude/settings.json`. Set up per-project during `agent-trace init`.

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:

- Edits to files inside an initialised repo are recorded for that project
- Edits to files outside any initialised repo are silently ignored
- An agent running from a parent directory editing files in a subfolder project works correctly
- An agent running from a subfolder of an initialised project works correctly

When global hooks are present, `agent-trace init` skips the per-tool hook prompts — they'd be redundant.

There are two kinds of hook events:

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.
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`.

### Git hooks

Two git hooks are installed when you configure git hooks during `agent-trace init`:

- **`post-commit`** — Runs `agent-trace commit-link` after every commit. This links the commit to its traces and builds the attribution ledger.
- **`post-rewrite`** — Runs `agent-trace rewrite-ledger` after rebase or amend. This remaps ledger SHAs from old commits to their new counterparts.

### Cursor — `.cursor/hooks.json` (project) or `~/.cursor/hooks.json` (global)

```json
{
  "version": 1,
  "hooks": {
    "sessionStart": [{ "command": "agent-trace record" }],
    "sessionEnd": [{ "command": "agent-trace record" }],
    "afterFileEdit": [{ "command": "agent-trace record" }],
    "afterTabFileEdit": [{ "command": "agent-trace record" }],
    "afterShellExecution": [{ "command": "agent-trace record" }],
    "afterAgentResponse": [{ "command": "agent-trace record" }]
  }
}
```

- **Trace events:** `sessionStart`, `sessionEnd`, `afterFileEdit`, `afterTabFileEdit`, `afterShellExecution`
- **Conversation sync only:** `afterAgentResponse` (no trace; refreshes transcript reference)

### Claude Code — `.claude/settings.json` (project) or `~/.claude/settings.json` (global)

```json
{
  "hooks": {
    "SessionStart": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }],
    "SessionEnd": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }],
    "PostToolUse": [
      { "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "agent-trace record" }] },
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "agent-trace record" }] }
    ],
    "Stop": [{ "hooks": [{ "type": "command", "command": "agent-trace record" }] }]
  }
}
```

- **Trace events:** `SessionStart`, `SessionEnd`, `PostToolUse` (Write/Edit, Bash)
- **Conversation sync only:** `Stop` (no trace; refreshes transcript reference when the agent loop ends)

Existing hooks are **preserved** — agent-trace entries are merged in without overwriting anything.

---

## File structure

```
~/.cursor/hooks.json             # Cursor global hooks (optional, via hooks setup-global)
~/.claude/settings.json          # Claude Code global hooks (optional, via hooks setup-global)
~/.codex/config.toml             # Codex CLI global hooks (optional, via hooks setup-global)

~/.agent-trace/
  bin/agent-trace                # CLI executable (on PATH)
  bin/at                         # short alias → agent-trace
  bin/agent-trace-viewer         # viewer launcher (on PATH)
  lib/agent_trace/               # Python source
    __init__.py
    cli.py                       # CLI commands (argparse)
    config.py                    # Global + project settings
    storage.py                   # project_id anchor (.git/agent-trace-id) + AGENT_TRACE_HOME paths
    registry.py                  # Optional metadata registry (first commit, origin, known_roots)
    hooks.py                     # Cursor, Claude Code, Codex CLI & git hook setup (project + global)
    record.py                    # Trace recording from hooks
    trace.py                     # Trace record construction + per-line hashing
    blame.py                     # Deterministic blame (ledger + git notes; No attribution when missing)
    context.py                   # Conversation context for AI-attributed segments
    rules.py                     # Prebuilt agent rules (Cursor, Claude Code, Codex CLI)
    commit_link.py               # Commit-link + ledger build (post-commit)
    ledger.py                    # Ledger construction
    rewrite.py                   # Post-rewrite SHA remapping
    sync.py                      # Push/pull/sync to HTTP remote
    git_notes.py                 # Git notes (refs/notes/agent-trace)
    remote.py                    # Named remotes
    ...
  viewer/                        # file viewer (installed by install.sh)
  config.json                    # global config (auth_token)
  projects.json                  # optional metadata registry

~/.agent-trace/projects/<project_id>/     # project_id = opaque anchor id from .git/agent-trace-id
  project-config.json            # project settings
  traces.jsonl
  commit-links.jsonl
  ledgers.jsonl
  session-state.json
  session-summaries.jsonl
  sync-state.json                # push/pull cursors (when using remotes)

<your-project>/                  # nothing is written into the working tree
  .cursor/hooks.json             # Cursor project hooks (only if no global hooks)
  .claude/settings.json          # Claude Code project hooks (only if no global hooks)
  .git/agent-trace-id            # opaque project_id anchor (inside .git; never committed)
  .git/hooks/post-commit         # agent-trace commit-link
  .git/hooks/post-rewrite        # agent-trace rewrite-ledger
  .git/config                    # notes refspec added for `origin` so notes travel with push/fetch
```

## License

Licensed under the [Apache License 2.0](LICENSE).
