{"_id":"@agent-watch-ai/edge","name":"@agent-watch-ai/edge","dist-tags":{"latest":"0.2.5"},"versions":{"0.2.5":{"name":"@agent-watch-ai/edge","version":"0.2.5","description":"Connect Claude Code, Codex and Cursor telemetry to your backend with turn, Git and ticket-key attribution.","license":"MIT","type":"module","engines":{"node":">=20"},"bin":{"agentwatch":"dist/cli.js"},"exports":{"./events":{"types":"./dist/events/product-event.d.ts","default":"./dist/events/product-event.js"},"./llm-call":{"types":"./dist/events/llm-call.d.ts","default":"./dist/events/llm-call.js"},"./otlp":{"types":"./dist/otlp/normalize.d.ts","default":"./dist/otlp/normalize.js"},"./aggregate-turn":{"types":"./dist/turns/aggregate-usage.d.ts","default":"./dist/turns/aggregate-usage.js"},"./turn-summary":{"types":"./dist/turns/turn-summary.d.ts","default":"./dist/turns/turn-summary.js"}},"scripts":{"build":"tsc -p tsconfig.build.json","typecheck":"tsc --noEmit","lint":"eslint src tests","lint:fix":"eslint src tests --fix","test":"vitest run","test:watch":"vitest","example":"node example/server.mjs","prepack":"npm run build","prepare":"npm run build"},"repository":{"type":"git","url":"git+https://github.com/agent-watch-ai/agent-watch-edge.git"},"homepage":"https://github.com/agent-watch-ai/agent-watch-edge#readme","bugs":{"url":"https://github.com/agent-watch-ai/agent-watch-edge/issues"},"keywords":["telemetry","opentelemetry","claude-code","codex","ai-coding-agents","ai-cost","cost-attribution","feature-cost","observability","hooks"],"dependencies":{"smol-toml":"^1.3.1","zod":"^3.24.0"},"devDependencies":{"@eslint/js":"^9.17.0","@stylistic/eslint-plugin":"^5.10.0","@types/node":"^22.10.0","eslint":"^9.17.0","eslint-plugin-import-x":"^4.17.1","eslint-plugin-jsdoc":"^63.3.3","patch-package":"^8.0.1","typescript":"^5.7.0","typescript-eslint":"^8.19.0","vitest":"^2.1.8"},"gitHead":"c27f346646c05adc76cfd3501ee4465ed9aad5df","_id":"@agent-watch-ai/edge@0.2.5","_nodeVersion":"24.13.1","_npmVersion":"11.8.0","dist":{"integrity":"sha512-tGI+tipnWOrPwS1BqzZ1WgPAf4XBj0gw9EDsiqjN3fCKQbEREMwz73B39jIbETxdlvLen5Ew5Y0etyMyOBTxJQ==","shasum":"dc42f70b13672656b6f4813c2d26a1f64de637d4","tarball":"https://registry.npmjs.org/@agent-watch-ai/edge/-/edge-0.2.5.tgz","fileCount":364,"unpackedSize":910605,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDHsGRhncEojtz/byoxJFNDG4KgQyfNzyBIe9HnY6m76QIhAO5J19yg1z2gY6ewWtdLyGk5dMnCnyo1nDI6ipqx8xgT"}]},"_npmUser":{"name":"aleksandr_repetskyi","email":"aleks@agent-watch.ai"},"directories":{},"maintainers":[{"name":"aleksandr_repetskyi","email":"aleks@agent-watch.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/edge_0.2.5_1788299894238_0.3932652858945822"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-01T21:58:14.057Z","0.2.5":"2026-09-01T21:58:14.420Z","modified":"2026-09-01T21:58:14.693Z"},"maintainers":[{"name":"aleksandr_repetskyi","email":"aleks@agent-watch.ai"}],"description":"Connect Claude Code, Codex and Cursor telemetry to your backend with turn, Git and ticket-key attribution.","homepage":"https://github.com/agent-watch-ai/agent-watch-edge#readme","keywords":["telemetry","opentelemetry","claude-code","codex","ai-coding-agents","ai-cost","cost-attribution","feature-cost","observability","hooks"],"repository":{"type":"git","url":"git+https://github.com/agent-watch-ai/agent-watch-edge.git"},"bugs":{"url":"https://github.com/agent-watch-ai/agent-watch-edge/issues"},"license":"MIT","readme":"# AgentWatch Edge\n\n[![npm](https://img.shields.io/npm/v/@agent-watch-ai/edge)](https://www.npmjs.com/package/@agent-watch-ai/edge)\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nA lightweight, zero-daemon telemetry edge for AI coding agents (**Claude Code**, **OpenAI Codex**, **Cursor**, **Gemini CLI**, and **Google Antigravity**).\n\nIt connects agent lifecycle hooks and native OpenTelemetry (OTLP) to your observability backend to attribute LLM usage, costs, tool calls, Git branches, and ticket keys (e.g., `PAY-142`) — without model proxies, MITM intercepts, or background daemons.\n\n---\n\n## Quick Start\n\n**Requirements:** Node.js 20+\n\n```bash\n# 1. Install globally\nnpm install -g @agent-watch-ai/edge\n\n# 2. Configure with your backend\nagentwatch setup --endpoint https://backend.example.com --token YOUR_TOKEN\n\n# 3. Verify status & diagnostics\nagentwatch status\nagentwatch doctor\n```\n\n---\n\n## Supported Agents & Limitations\n\n| Agent | Hook Configuration | Native OTel Signals | Status |\n|---|---|---|---|\n| **Claude Code** | `~/.claude/settings.json` | Logs, Traces, Metrics | Full support |\n| **OpenAI Codex** | `~/.codex/hooks.json` | Logs, Traces (`~/.codex/config.toml`) | Full support |\n| **Gemini CLI** | `~/.gemini/settings.json` | Logs, Traces, Metrics | Full support |\n| **Cursor** | `~/.cursor/hooks.json` | None | Partial support |\n| **Google Antigravity** | `~/.gemini/config/hooks.json` | None | Partial support |\n\n### Agent Limitations & Notes\n\n* **Claude Code**:\n  * Running sessions must be restarted after `agentwatch setup` to apply telemetry environment variables.\n* **OpenAI Codex**:\n  * Requires trusting new hooks: launch `codex`, type `/hooks`, and approve AgentWatch entries.\n* **Gemini CLI**:\n  * Running sessions must be restarted after setup to load new hooks and OpenTelemetry configuration.\n  * Telemetry is enabled through `GEMINI_TELEMETRY_ENABLED` with `GEMINI_TELEMETRY_TARGET=local`, and the ingest token travels in `OTEL_EXPORTER_OTLP_HEADERS`. Gemini CLI does not support Claude Code's `otelHeadersHelper`.\n* **Google Antigravity**:\n  * **No native token usage**: Antigravity exposes no OpenTelemetry exporter configuration and no readable transcript usage, so `turn.summary` events remain `usage_status: \"pending\"` and carry no cost.\n  * **Turns, not model calls**: a turn is one *execution*. `PreInvocation`/`PostInvocation` bracket the individual model calls inside an execution, and only the `Stop` hook closes a turn.\n  * The prompt is read from `common.lastUserInput` — Antigravity has no user-prompt hook of its own.\n  * Running sessions must be restarted after `agentwatch setup` to load new hooks.\n* **Cursor**:\n  * **No native token usage**: Cursor exposes no token usage in hooks or transcripts, so `turn.summary` events remain `usage_status: \"pending\"`.\n  * **Cursor CLI**: Currently emits only shell hook events. Full hook lifecycle is available only in Cursor IDE sessions.\n  * **Cloud VMs**: Cloud agents do not have access to the local user hook or binary by default; they require an explicit committed `.cursor/hooks.json` and package installation in the cloud environment.\n  * **Tab suggestions**: AgentWatch monitors accepted edits (`afterTabFileEdit`) and intentionally ignores high-frequency `beforeTabFileRead` events.\n\n---\n\n## CLI Commands\n\n```bash\n# Setup & Configuration\nagentwatch setup --endpoint https://backend.example.com    # Interactive / automated setup\nagentwatch config                                         # Print active configuration (secrets redacted)\nagentwatch agents                                         # List detected agents & status\n\n# Diagnostics & Status\nagentwatch status                                         # Backend, queue, and agent health\nagentwatch doctor                                         # Run environment checks (use --json for CI)\n\n# Hook Execution (invoked automatically by agents)\nagentwatch hook --agent claude                            # Process stdin payload from agent\nagentwatch hook --agent codex --dry-run                   # Test hook output without sending\n\n# Telemetry & Teardown\nagentwatch otel-headers                                   # Output formatted OTel headers\nagentwatch uninstall                                      # Remove hooks and restore backups\nagentwatch uninstall --purge                              # Also delete ~/.agentwatch and queues\n```\n\n---\n\n## Parameters & Flags\n\n| Flag | Description | Default |\n|---|---|---|\n| `--endpoint <url>` | Backend base URL for event ingestion | — |\n| `--token <token>` | Bearer token for backend authentication | — |\n| `--developer-email <email>` | Identity attached to turn summaries and keyed on by per-developer enforcement. Setup refuses to write a config when neither this flag nor git names a developer | `git config user.email` |\n| `--otel <signals>` | OTLP signals exported by agents: `logs`, `traces`, `metrics`, `all`, or `none` | `logs` |\n| `--agent <id>` | Limit command to a single agent (`claude`, `codex`, `cursor`, `gemini`, `antigravity`) | All detected |\n| `--yes`, `--non-interactive` | Non-interactive mode (fail instead of prompting on missing args) | `false` |\n| `--purge` | Used with `uninstall`: removes `~/.agentwatch` and local queues | `false` |\n| `--dry-run` | Used with `hook`: prints canonical events to stdout instead of sending | `false` |\n| `--json` | Used with `doctor`: output machine-readable JSON | `false` |\n| `--verbose` | Print verbose diagnostic logs to stderr | `false` |\n| `--version` | Display edge version | — |\n\n---\n\n## Configuration\n\n* **Global configuration**: `~/.agentwatch/config.json` (managed via `agentwatch setup`).\n* **Repository overrides**: Place a `.agentwatch.json` in any repository root to adjust content capture:\n\n```json\n{\n  \"capture\": {\n    \"prompts\": true,\n    \"responses\": false,\n    \"toolInput\": true,\n    \"toolOutput\": false,\n    \"git\": true,\n    \"files\": true\n  }\n}\n```\n\n*Note: Infrastructure settings (`endpoint`, `token`, `developerEmail`, `enforcementUrl`) and the\n`delivery`, `otel` and `enforcement` blocks are global-only — a committed repo file cannot redirect\ndelivery or switch off a budget cap for everyone who clones the repository.*\n\n### Budget enforcement (pre-turn check)\n\nWhen a backend budget policy is set to **block** and the developer has breached it, the Edge stops\nthe turn before the agent's first LLM call: the prompt is refused in the agent's own protocol\n(Claude Code, Codex, Cursor, Gemini CLI) with the backend's explanation shown to the developer.\n\n```json\n{\n  \"enforcement\": { \"enabled\": true, \"timeoutMs\": 300, \"cacheTtlMs\": 60000 }\n}\n```\n\nThe check **fails open, always**. A turn stops only on an explicit `{\"decision\":\"block\",\"message\":\"…\"}`\nfrom `GET <backend>/v1/enforcement/decision`; an unreachable backend, a timeout, any other status and\nany body the Edge cannot read all let the turn proceed silently. Decisions are cached locally for\n`cacheTtlMs`, so the check costs one bounded request per turn at most. Set `enabled: false` to opt out.\n\nAntigravity is not gated: its pre-invocation hook carries no decision field, so there is no\nprompt-level refusal to send. Its usage is still reported and still raises alerts.\n\nTo try it locally: `BLOCK=1 npm run example` answers every check with a refusal.\n\n---\n\n## Data Flow & Backend Integration\n\n1. **`turn.summary`**: Generated via agent hooks (`POST <backend>/v1/events`). Captures user prompt, tools executed, files touched, Git branch, and ticket keys.\n2. **`llm.call`**: Emitted via native OTLP (`POST <backend>/v1/otlp/v1/logs`). Contains token usage, cost, and latency per model request.\n3. The backend joins `llm.call` to `turn.summary` records using conversation/turn IDs.\n\n### Backend SDK Helpers\n\n```ts\nimport type { ProductEvent } from '@agent-watch-ai/edge/events';\nimport { normalizeOtlpLogs } from '@agent-watch-ai/edge/otlp';\nimport { aggregateTurnUsage } from '@agent-watch-ai/edge/aggregate-turn';\n```\n\n---\n\n## License\n\nMIT © [Aleksandr Repetskyi](https://github.com/alexrepetskyi)\n","readmeFilename":"README.md","_rev":"1-e9915287e3bce4243a61353281cf44be"}