# Ingest Hooks CLI

Use `provon ingest hooks install` to write trace hooks into AI coding tools so that agent sessions are
reported to Provon as OTel traces in real time. Unlike [`provon ingest sync`](./sync.md), which backfills
persisted transcript files, hooks fire on session events and upload traces while the agent is still
running.

```text
agent session event -> tool hook -> provon ingest trace <source> <hook> -> parse transcript -> OTLP -> POST /v1/traces
```

The hook command is non-blocking: it hands the payload to a detached child process and returns
immediately, so it never slows down the agent or trips a hook timeout.

## Supported Tools

| Tool     | Hook events                                 | Config location                                 |
| -------- | ------------------------------------------- | ----------------------------------------------- |
| Claude   | `PostToolUse`, `Stop`                       | `~/.claude/settings.json` (or `<dir>/.claude/`) |
| Codex    | `PostToolUse`, `Stop`                       | `~/.codex/hooks.json` + trust in `config.toml`  |
| OpenCode | `session.idle`                              | generated plugin `~/.config/opencode/plugins/`  |
| dsh      | `agent/turn-stopping`, `tools/post-execute` | generated plugin `$DSH_HOME/` (global only)     |
| Cursor   | `stop`, `sessionEnd`                        | `~/.cursor/hooks.json` (or `<dir>/.cursor/`)    |
| Pi       | `agent_settled`, `session_shutdown`         | generated extension `~/.pi/agent/extensions/`   |

Installation is idempotent: re-running `ingest hooks install` updates existing entries rather than
duplicating them. Only hooks that invoke `provon ingest trace` are modified; hooks owned by other tools
are left untouched.

## Prerequisites

1. Authenticate the CLI or provide a project API key:

   ```bash
   provon auth login
   # or
   export PROVON_API_KEY="your_project_api_key"
   export PROVON_PROJECT_ID="your_project_id"
   ```

2. The `provon` binary must be on `PATH` (or the hook will bake in the absolute node directory
   at install time).

## Quick Start

Install hooks for every detected tool on the system:

```bash
provon ingest hooks install
```

The command auto-detects targets by checking for the tool's config directory or the command on
`PATH`. Skipped tools are listed in the output with the reason.

Install for a single tool:

```bash
provon ingest hooks install --claude
provon ingest hooks install --codex --cursor
```

Force install even when a tool is not detected:

```bash
provon ingest hooks install --pi --skip-check
```

## Project-Level vs Global

By default hooks are written to the user's global config (`~/.claude/`, `~/.codex/`, etc.), so
they apply to every project. To install only for a specific project:

```bash
provon ingest hooks install --project-dir /path/to/project
```

This writes to `<project-dir>/.claude/settings.json`, `<project-dir>/.cursor/hooks.json`, etc.
dsh has no project-level config and is skipped when `--project-dir` is set.

## Reporting Configuration

Reporting credentials are resolved from the global CLI options and the active auth profile:

1. Global `--project <id>` / `--api-key <key>` flags
2. The active local auth profile (`provon auth login`)

```bash
# Using global flags
provon --project proj_abc123 --api-key pk_live_xxx ingest hooks install

# Or after `provon auth login`, credentials are read from the profile automatically
provon ingest hooks install
```

All reporting config is baked into the hook command as a `PROVON_TRACE_CONFIG` environment
variable, so hooks work in non-interactive shells and CI without extra env setup.

### Filtering

Limit which sessions are reported by adding filters at install time:

```bash
provon ingest hooks install \
  --repo my-org/my-repo \
  --path /workspace/project \
  --skill dangerous-bash \
  --mcp github \
  --keyword "deploy"
```

All filters are repeatable. A session is reported if it matches at least one value in each
provided filter category.

### Report Mode and Level

```bash
provon ingest hooks install --mode coding_write --report-level summary
```

| Option           | Values                                     | Default |
| ---------------- | ------------------------------------------ | ------- |
| `--mode`         | `coding`, `coding_write`, `in_repo`, `all` | `all`   |
| `--report-level` | `full`, `summary`                          | `full`  |

### Disabled Hooks

Install hooks in a switched-off state (registered but not reporting):

```bash
provon ingest hooks install --disable 1
```

Reinstall without `--disable` to turn reporting on.

## Multiple Reporting Targets

By default, installing for a project replaces any existing reporting target for that project in
the same hooks file. To append an additional target instead:

```bash
provon --project second-project --api-key second-key ingest hooks install --append
```

The same project can only have one target per hooks file. If another tool already reports to the
same project, installation is aborted with a `TARGET_CONFLICT` error to prevent double-reporting.

## Uninstall

Remove all Provon trace hooks from every tool:

```bash
provon ingest hooks uninstall
```

Or from specific tools:

```bash
provon ingest hooks uninstall --claude --codex
```

Only hooks that invoke `provon ingest trace` are removed. Other tools' hooks and unrelated config keys
are preserved. For Codex, the trust-state entries in `config.toml` are also cleared.

## How It Works

### Install phase

1. Resolve project ID, API key, and endpoint from global flags or the stored auth profile.
2. Detect which tools are present (config directory or command on `PATH`).
3. Check for cross-tool conflicts (same project reported by another tool's hooks).
4. For each target: write hook entries (Claude, Codex, Cursor) or generate a plugin file
   (OpenCode, dsh, Pi) that invokes `provon ingest trace <source> <hook>`.
5. For Codex: compute the `sha256` trust fingerprint and write it to `config.toml` before
   writing `hooks.json`, so Codex does not park the hook as "pending trust".

### Runtime phase

1. The tool fires the hook and pipes a JSON payload (containing `transcript_path` or session
   data) to `provon ingest trace <source> <hook>` on stdin.
2. The trace entry reads `PROVON_TRACE_CONFIG` to determine the reporting target.
3. It re-executes itself as a detached child process, hands over the payload, and returns
   immediately (milliseconds).
4. The detached child parses the transcript with `@provon/agent-transcripts`, projects it to
   OTel spans with `@provon/observability`, and POSTs to the OTLP endpoint.
5. Failures are logged to stderr only when `PROVON_TRACE_DEBUG=1`; they never surface to the
   agent.

### Environment Variables

| Variable               | Purpose                                                           |
| ---------------------- | ----------------------------------------------------------------- |
| `PROVON_TRACE_CONFIG`  | Baked into hooks; carries project ID, API key, endpoints, filters |
| `PROVON_TRACE_DISABLE` | Set to `1` to kill-switch all trace reporting                     |
| `PROVON_TRACE_DEBUG`   | Set to `1` to print debug logs to stderr                          |
| `PROVON_TRACE_SYNC`    | Set to `1` to run ingest in-process (for testing)                 |

## Troubleshooting

### No traces appear after installation

1. Confirm the tool was detected: `provon ingest hooks install` lists skipped targets with reasons.
2. Verify the hook entry exists in the tool's config file (see table above).
3. Run the trace entry manually with debug logging:

   ```bash
   echo '{"transcript_path":"/path/to/session.jsonl"}' | \
     PROVON_TRACE_CONFIG='{"project_id":"...","api_key":"..."}' \
     PROVON_TRACE_DEBUG=1 PROVON_TRACE_SYNC=1 \
     provon ingest trace claude stop
   ```

4. Check that the API key has the `telemetry:ingest` scope.

### Codex hooks show "pending trust"

Re-run `provon ingest hooks install --codex`. The installer writes the trust fingerprint to
`~/.codex/config.toml` before updating `hooks.json`. If Codex was running during install, restart
it to pick up the new trust state.

### Hooks slow down the agent

The hook command returns immediately after forking a detached child. If you still observe
latency, set `PROVON_TRACE_SYNC=0` (default) and ensure the `provon` binary is on `PATH`.

### Double-reporting

Each project can only have one reporting target per hooks file. If you see duplicate traces,
run `provon ingest hooks uninstall` and reinstall, or check that another tool is not also reporting to
the same project.
