@ev-ai/agent-hook 1.2.1 → 1.2.3
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 +33 -2
- package/dist/cli.mjs +34 -34
- package/dist/hook.mjs +29 -29
- package/dist/launcher-update.mjs +4 -4
- package/dist/launcher.mjs +3 -2
- package/dist/managed-hooks-snippet.cjs +1 -1
- package/dist/managed-hooks-snippet.mjs +1 -1
- package/dist/plugin-hooks.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,6 +11,37 @@ This is an **opt-in, first-party observability agent** that an ev-ai customer in
|
|
|
11
11
|
- **Collection is opt-out for prompt / tool-arg / tool-result / last-assistant-message bodies.** Those four `hook_input` fields are sent by default (size-capped). Set `EV_AI_HOOK_CAPTURE_CONTENT=off` or `capture_hook_input: "allowlist"` to drop them. On Claude that includes file bodies written or read through a tool, which arrive nested in `tool_input` / `tool_response`. Session titles, chat transcripts, keystrokes, and runner error prose stay dropped. `env_vars` is a fixed allowlist of non-secret CI/runtime markers; API keys and proxy vars are never read. See [Privacy defaults](#privacy-defaults).
|
|
12
12
|
- **What it is not:** it is not spyware, not a keylogger, and not a data broker. It does not collect keystrokes, does not scrape the filesystem, and does not exfiltrate to any endpoint the operator did not configure. It does forward the bodies of tool calls the agent makes, unless content capture is turned off.
|
|
13
13
|
|
|
14
|
+
## What this package does on your machine
|
|
15
|
+
|
|
16
|
+
A plain list of every behavior a security reviewer or supply-chain scanner will want to know about. Details and opt-outs are in the linked sections.
|
|
17
|
+
|
|
18
|
+
**At install time: nothing.** The package has no `preinstall` / `install` / `postinstall` scripts, no native modules, and no runtime dependencies. Code runs only when a runner (Claude Code, Cursor, Codex) fires a configured hook, or when you run the CLI yourself.
|
|
19
|
+
|
|
20
|
+
**Network requests** (all HTTPS, except `http://` to loopback for a local collector):
|
|
21
|
+
|
|
22
|
+
- `POST {collector_url}` on hook events — the runtime envelope described in [COLLECTED-DATA.md](COLLECTED-DATA.md). The destination is only the collector URL you configure (`--url`, the committed `ev-ai-runtime-report.json`, or `~/.ev-ai/config.json`).
|
|
23
|
+
- `GET /{orgToken}/version` on that same collector, and — when the collector returns a signed envelope — a download of `hook.mjs` from the signed URL — the auto-update path. See [Hook updates](#hook-updates-npx-path).
|
|
24
|
+
- Cloud instance metadata, **only in non-interactive contexts** (CI / cloud VMs, never a developer's interactive session), at most once per 24 h: AWS IMDSv2 (`169.254.169.254`), GCP (`metadata.google.internal`), Azure (`169.254.169.254`). Only provider, region and instance id are read; no credentials or tokens are requested beyond the short-lived IMDSv2 session token that AWS requires for the read.
|
|
25
|
+
|
|
26
|
+
**Auto-update: the package can run code it did not ship with.** On the npx path the launcher may run a newer `hook.mjs` that your collector selects, downloaded to `~/.ev-ai/agent-hook/js/signed-v1/`, verified against an ev-ai signed envelope (built-in public key) and SHA-512 of the bytes, and executed with the same Node that runs the launcher. It is on by default; turn it off with `EV_AI_AUTO_UPDATE=0` or `"auto_update": false` in `~/.ev-ai/config.json`, and the pinned, bundled hook is the only code that runs. A repo manifest cannot change this setting.
|
|
27
|
+
|
|
28
|
+
**Background processes.** To ack the runner quickly, most events are collected by a detached child process that exits after one POST. At session start the launcher may also spawn one detached `__refresh` process that performs the update check above and exits (skipped when auto-update is off).
|
|
29
|
+
|
|
30
|
+
**Files read** (identity and configuration only, never file contents from your projects):
|
|
31
|
+
|
|
32
|
+
- Runner configs: `.claude/`, `.cursor/`, `.codex/` hook / plugin / MCP settings at user, project and managed scope. MCP `env` blocks are reduced to variable **names**; values are never read into the envelope.
|
|
33
|
+
- Operator identity: `~/.claude.json` (the `oauthAccount` login email and name), `~/.cursor/cli-config.json`, Cursor's `state.vscdb` (only `cursorAuth/*` rows, with every key containing `token` excluded in the SQL query and again in code), and `~/.codex/auth.json` (only the ID-token's identity claims are decoded locally; the API key and access / refresh tokens are never read out or sent).
|
|
34
|
+
- Git: `remote.origin.url`, `user.email`, last commit author, repo root.
|
|
35
|
+
- A fixed allowlist of non-secret environment variables (CI / runtime markers). API keys, tokens and proxy variables are never read.
|
|
36
|
+
|
|
37
|
+
**Files written.** Only under `~/.ev-ai/` (installation id, caches, update artifacts, short-lived dedup claims) and, when you run `configure` / `install`, the runner hook config files and manifest in the repo. `uninstall` removes the ev-ai entries.
|
|
38
|
+
|
|
39
|
+
**Subprocesses.** `git`, and for OS / host detection `sw_vers`, `uname`, `lsb_release`, `tty`, `systemd-detect-virt`; `sqlite3` as a fallback reader for Cursor's `state.vscdb`. All are invoked with fixed argument lists (no shell) and short timeouts.
|
|
40
|
+
|
|
41
|
+
**Content capture.** Prompt, tool-argument, tool-result and last-assistant-message bodies are sent by default (size-capped). Turn them off with `EV_AI_HOOK_CAPTURE_CONTENT=off`. See [Privacy defaults](#privacy-defaults).
|
|
42
|
+
|
|
43
|
+
**Shipped code is bundled and minified** (`dist/*.mjs`, built with esbuild from TypeScript).
|
|
44
|
+
|
|
14
45
|
## Install
|
|
15
46
|
|
|
16
47
|
**Primary path:** enable the ev-ai **runner plugins** (Claude / Cursor / Codex) from the hosted marketplace. Their hooks run the shipped `hook.mjs` with Node (no package version in the command). Your repo commits only a shared `collector_url` manifest plus plugin enablement — not per-event blocks in `.claude/settings.json` / `.cursor/hooks.json` / `.codex/hooks.json`.
|
|
@@ -134,12 +165,12 @@ Per-event execution uses `npx` (primary) or the pinned binary (CDN path). The ru
|
|
|
134
165
|
|
|
135
166
|
### Hook updates (npx path)
|
|
136
167
|
|
|
137
|
-
The npx package's entry point is a small launcher. It runs the hook your collector selects, from a per-machine cache under `~/.ev-ai/agent-hook/js/`, and otherwise the hook bundled in the pinned package. A cached hook is re-verified (
|
|
168
|
+
The npx package's entry point is a small launcher. It runs the hook your collector selects, from a per-machine cache under `~/.ev-ai/agent-hook/js/signed-v1/`, and otherwise the hook bundled in the pinned package. A cached hook is re-verified (signature + SHA-512) on every event, and any problem with it (missing, altered, unsigned, incompatible with this Node or launcher, or failing to start twice in a row) falls back to the bundled hook for that event.
|
|
138
169
|
|
|
139
170
|
**Network.** Besides the collector POST, the launcher makes two kinds of request, both only on the npx path:
|
|
140
171
|
|
|
141
172
|
- `GET /{orgToken}/version` on the same collector, at most once per 6 h per collector: on the first event in a new collector scope, then from a detached background refresh at session start. No request is made on other events.
|
|
142
|
-
- When the collector
|
|
173
|
+
- When the collector returns a signed envelope, a download of that release's `hook.mjs` from the signed URL (`https://…/{version}/hook.mjs`). The launcher verifies the envelope with a built-in public key, then checks the bytes against the signed SHA-512 before they are written to the cache. The launcher never downloads from npm and does not hardcode a CDN hostname.
|
|
143
174
|
|
|
144
175
|
**Kill switch.** `EV_AI_AUTO_UPDATE=0`, or `"auto_update": false` in `~/.ev-ai/config.json`, always runs the bundled hook and makes neither request. Ephemeral CI homes start cold on every run, so their first event makes the `/version` check (within a 3 s budget); set `EV_AI_AUTO_UPDATE=0` in CI if you want the pinned hook with no extra request.
|
|
145
176
|
|