@openlatch/client 0.1.14 → 0.2.2

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 (2) hide show
  1. package/README.md +221 -171
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/OpenLatch/openlatch-client/main/assets/banner.jpg" alt="OpenLatch — Security infrastructure for AI agents" width="600" />
2
+ <img src="https://raw.githubusercontent.com/OpenLatch/openlatch-client/main/assets/banner.jpg" alt="OpenLatch — the execution control layer for enterprise AI agents" width="600" />
3
3
  </p>
4
4
 
5
- <h3 align="center">See what your agent does. Block what it shouldn't.</h3>
5
+ <h3 align="center">Greater control should enable greater autonomy.<br /><em>Dare to Let Go.</em></h3>
6
6
 
7
7
  <p align="center">
8
8
  <a href="https://github.com/OpenLatch/openlatch-client/actions/workflows/pr-checks.yml"><img src="https://github.com/OpenLatch/openlatch-client/actions/workflows/pr-checks.yml/badge.svg" alt="PR Checks" /></a>
@@ -15,252 +15,303 @@
15
15
 
16
16
  ---
17
17
 
18
- **OpenLatch** is a thin, open-source security forwarder that plugs into AI agents via their **native lifecycle hooks**. One command installs protection across all your agents — no proxies, no code changes, no configuration.
18
+ **[OpenLatch](https://openlatch.ai) is the agent-agnostic execution control layer for enterprise AI agents.** This repository is its open-source **capture-and-enforce adapter**: the node that runs inside a coding agent's own execution path, evaluates every covered action against that agent's Autonomy Zone before it runs, and is what gives an agent the control level **Enforced**.
19
19
 
20
- ```bash
21
- npx @openlatch/client init
22
- ```
20
+ It is **Mode 1 — the native hook** — the first of three adapters onto one policy brain. It plugs into agents through their native lifecycle hooks, decides locally, and forwards what it sees to the control plane.
23
21
 
24
- That's it. `init` auto-detects your installed agents, writes the hook configs, and starts the daemon that forwards events to the cloud for real-time security analysis.
22
+ **This README is for people working on the client.** If you want to *use* OpenLatch, start at [docs.openlatch.ai](https://docs.openlatch.ai) — `npx @openlatch/client init` and you are done.
25
23
 
26
- <!-- TODO: Replace with VHS terminal recording once available -->
27
- <!-- <p align="center">
28
- <img src="https://raw.githubusercontent.com/OpenLatch/openlatch-client/main/assets/demo.gif" alt="OpenLatch demo" width="700" />
29
- </p> -->
24
+ ---
30
25
 
31
- ## Why OpenLatch?
26
+ ## Where this node sits
32
27
 
33
- AI agents execute shell commands, read files, call APIs, and install tools — all with your permissions. Most users have **zero visibility** into what their agents actually do.
28
+ OpenLatch runs a five-step control loop around each agent's **Agent Autonomy Zone** — the operating envelope of what an agent may do, authored on the platform as intent policies across five dimensions (Quality, Economics, Security, Safety, Compliance) and compiled to deterministic rules. This client touches four of the five steps. None of the authoring happens here.
34
29
 
35
- OpenLatch gives you:
30
+ | Step | What this node does | What it does not do |
31
+ | ---- | ------------------- | ------------------- |
32
+ | **1 · Identify** | Stamps every event with agent type, session, host and identity, so the platform's record of a sanctioned agent stays live rather than quarterly | Discovery. An agent arrives here by being installed onto, never by being found |
33
+ | **2 · Define** | Nothing. It receives the compiled zone as a signed policy bundle and holds it resident | Author policy. Intent policies are written and compiled on the platform |
34
+ | **3 · Detect** | Captures the actions the execution graph is built from — tool calls, commands, file changes, model calls, cost — and matches them against the resident bundle | Detection of its own. No models, no scanning, no cross-host correlation |
35
+ | **4 · Act** | Returns the verdict at the hook boundary, before the action runs, from an in-process evaluation | Ask the network for it |
36
+ | **5 · Improve** | Writes the local audit log and forwards every event, verdict and mode asynchronously | Report, alert, or render a dashboard |
36
37
 
37
- - **Visibility** — audit logs of every tool call, shell command, and file access across all your agents
38
- - **Protection** — real-time detection of tool poisoning, credential leakage, prompt injection, and dangerous shell commands
39
- - **Zero friction** — deploys from inside your agent in one command, auto-detects platforms, requires no security expertise
38
+ Four properties shape the code more than any feature does:
40
39
 
41
- ## Supported Platforms
40
+ | Property | What it means here |
41
+ | -------- | ------------------ |
42
+ | **Inside the agent, not a proxy in front of it** | The decision point is the agent's own hook lifecycle, so it sees the *action* rather than the traffic. It is not a sandbox — the threat model is a **misbehaving** agent, not an operator working to defeat it |
43
+ | **Local-authoritative** | The resident bundle is the authority, not a cache of one. Evaluation reads an in-memory handle and returns, so the node keeps deciding with the network unplugged |
44
+ | **Sanctioned agents only** | Depth over dragnet. This node makes the agents an enterprise has already blessed enforceable; it does not go looking for the ones it has not |
45
+ | **Coverage is a deployment outcome** | An adapter in the execution path is what makes an agent **Enforced**. Without one an agent can still be **Monitored** (visible through an integration) or **Known** (identified and classified). The record always states which level applies |
42
46
 
43
- OpenLatch works across **3 operating systems** and **8 agent platforms** from day one.
47
+ ### The three adapters
44
48
 
45
- | Agent Platform | macOS | Windows | Linux | Hook Events |
46
- | -------------- | :---: | :-----: | :---: | ----------: |
47
- | Claude Code | :white_check_mark: | :white_check_mark: | :white_check_mark: | 24 |
48
- | Cursor | :white_check_mark: | :white_check_mark: | :white_check_mark: | 5 |
49
- | Windsurf | :white_check_mark: | :white_check_mark: | :white_check_mark: | 5 |
50
- | GitHub Copilot | :white_check_mark: | :white_check_mark: | :white_check_mark: | 6 |
51
- | Codex CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: | 4 |
52
- | Gemini CLI | :white_check_mark: | :white_check_mark: | :white_check_mark: | 4 |
53
- | Cline | :white_check_mark: | :white_check_mark: | :white_check_mark: | 4 |
54
- | OpenClaw | :white_check_mark: | :white_check_mark: | :white_check_mark: | 4 |
49
+ | Mode | Surface | This repo |
50
+ | ---- | ------- | --------- |
51
+ | **Mode 1 — native hook** | Coding agents, including hosted ones | **Yes.** Ships first |
52
+ | **Mode 2 — framework middleware** | LangChain / LangGraph | No. Ships second |
53
+ | **Mode 3 — SDK + tool / MCP gate** | Bedrock, Azure AI Foundry, custom agents | No. Ships third, or on demand |
55
54
 
56
- ## Threat Coverage
55
+ ### Verdicts, and which ones this node enforces today
57
56
 
58
- | Threat Category | What it catches |
59
- | --------------- | --------------- |
60
- | **Tool Poisoning** | Malicious MCP servers, tampered tool definitions, supply chain attacks on agent tooling |
61
- | **PII & Credential Leakage** | API keys, tokens, passwords, and personal data leaving your machine via agent actions |
62
- | **Prompt Injection** | Injected instructions hidden in files, tool outputs, or web content that hijack agent behavior |
63
- | **Shell Command Guardrails** | Destructive commands (`rm -rf /`), privilege escalation, crypto miners, reverse shells |
64
- | **Supply Chain** | Compromised dependencies, typosquatted packages, unsigned binaries |
65
- | **Attack Path Analysis** | Multi-step attack chains that combine individually benign actions into a malicious sequence |
57
+ The verdict vocabulary is **Allow, Ask, Block or Optimize**. What this binary can express is narrower than the vocabulary, and this is the honest map of it. A verdict is deterministic because an explicit policy produced it.
66
58
 
67
- ## Quick Start
59
+ | Verdict | On the wire / in the bundle | What this node does today |
60
+ | ------- | --------------------------- | ------------------------- |
61
+ | **Allow** | `allow`, `approve` | The action proceeds. `approve` is a user-confirmed allow |
62
+ | **Ask** | No wire variant — an `allow` / `approve` carrying `context` | Rendered to Claude Code as `permissionDecision: "ask"`, the alert as its reason. It **allows and flags**; it does not hold the agent waiting on a human. It prevents recurrence, not the first occurrence |
63
+ | **Block** | `deny` — the only action a `kind=command` rule may take | Reaches the agent as a native deny at `pre_tool_use`, naming the rule that produced it |
64
+ | **Optimize** | `kind=request` rules: `prefix_reorder`, `history_trim`, `prompt_edit` | **Measurement only.** `history_trim` and `prompt_edit` are rewritten to `observe` at bundle load whatever the config says; `prefix_reorder` may act only behind `boundary.transforms_act`, which ships `false`. Out of the box the boundary observes, reports what a transform *would* have saved, and forwards the original bytes |
68
65
 
69
- ### Install via npm (recommended)
66
+ Staging is per rule: `observe` records the match and allows the action, `enforce` applies the verdict — Monitor and Enforce in the product. Most restrictive wins across matching rules, and every rule is coerced to `observe` when the bundle's `enforcement_enabled` is false.
70
67
 
71
- ```bash
72
- npx @openlatch/client init
73
- ```
68
+ Deny enforcement is event-scoped. Only pre-action events have somewhere to put a deny; on a post-action event it degrades to `{}` and survives in the record alone.
74
69
 
75
- ### Install via Cargo
70
+ ---
71
+
72
+ ## Develop
76
73
 
77
74
  ```bash
78
- cargo install openlatch-client
79
- openlatch init
75
+ git clone https://github.com/OpenLatch/openlatch-client && cd openlatch-client
76
+ cargo build
77
+ cargo test
80
78
  ```
81
79
 
82
- ### Download binary
80
+ Rust 1.88+, no other prerequisites. `cargo build` produces both binaries in `target/debug/`.
83
81
 
84
- Pre-built binaries for macOS (ARM, Intel), Linux (x86_64, ARM), and Windows are available on the [Releases](https://github.com/OpenLatch/openlatch-client/releases) page. After the binary is on your `PATH`, run `openlatch init` to auto-detect agents and install hooks.
82
+ ### Work in a sandbox, not on your own machine
85
83
 
86
- ## Usage
87
-
88
- ```bash
89
- # Auto-detect agents, install hooks, and start the daemon
90
- openlatch init
84
+ `openlatch init` installs into `~/.openlatch`, writes `~/.claude/settings.json`, and points every live Claude Code session on the host at its boundary listener. You do not want your work-in-progress build doing that.
91
85
 
92
- # Check daemon status, uptime, and event counts
93
- openlatch status
86
+ `olbox` gives you a complete install that cannot touch your own — its own state directory, its own agent config, its own ports:
94
87
 
95
- # View the 20 most recent security events
96
- openlatch logs
88
+ ```bash
89
+ cargo install --path tools/sandbox --locked # once
97
90
 
98
- # Tail events in real time
99
- openlatch logs -f
91
+ olbox enter dev # a shell inside the sandbox
92
+ openlatch init # installs into the sandbox and nothing else
93
+ claude # this session — and only this session — is routed
94
+ exit # and you are back on your own machine
95
+ ```
100
96
 
101
- # Show events from the last hour
102
- openlatch logs --since 1h
97
+ It lives in [`tools/sandbox`](tools/sandbox/README.md) rather than in the client, because sandboxing is what *we* need and the client is what customers install. `olbox list`, `olbox exec dev -- <cmd>`, `olbox destroy dev`, and `eval "$(olbox env dev)"` if you would rather not use a subshell — the README covers all of it.
103
98
 
104
- # Start/stop/restart the daemon
105
- openlatch start
106
- openlatch stop
107
- openlatch restart
99
+ Under the hood it is five environment variables derived from the name, which are supported client seams you can also set by hand. Getting one wrong is not a failed test — it writes your real `~/.claude/settings.json` — which is why the tool exists.
108
100
 
109
- # Run daemon in foreground (useful for debugging)
110
- openlatch start --foreground
101
+ | Variable | Role |
102
+ | -------- | ---- |
103
+ | `OPENLATCH_DIR` | State: config, token, logs, outbox |
104
+ | `CLAUDE_CONFIG_DIR` | Agent config. **Claude Code's own variable**, so the daemon and the session it captures cannot end up pointed at different directories |
105
+ | `OPENLATCH_PORT` | Daemon port (sandboxes: 17400–17499) |
106
+ | `OPENLATCH_BOUNDARY_PORT` | Model-boundary port (sandboxes: 17600–17699) |
107
+ | `OPENLATCH_BOUNDARY_OWN_WIRING` | Lets a non-default-port instance write *its own* agent config. Never inferred — see [`.claude/rules/isolated-instances.md`](.claude/rules/isolated-instances.md) |
111
108
 
112
- # Diagnose configuration and connectivity issues
113
- openlatch doctor
109
+ `openlatch uninstall --purge` works inside a sandbox and removes the install; `olbox destroy` removes the sandbox itself.
114
110
 
115
- # Remove hooks and stop daemon
116
- openlatch uninstall
111
+ A sandbox is never supervised: the OS unit is machine-global and carries no environment, so one installed from a sandbox shell would supervise your *real* install from your dev binary. `supervision enable` refuses there, `init` skips it, and `doctor` reports Persistence as not applicable. Use `openlatch start` — a sandbox is a session of work, not something that should survive a reboot.
117
112
 
118
- # Remove hooks, stop daemon, and delete all data (~/.openlatch/)
119
- openlatch uninstall --purge
113
+ ### Verify before you push
120
114
 
121
- # Open documentation in browser
122
- openlatch docs
115
+ ```bash
116
+ cargo fmt --all -- --check
117
+ cargo clippy --all-targets --all-features -- -D warnings
118
+ cargo test --all-features
119
+ cargo test --lib --no-default-features # proves openlatch-hook links no `core`
123
120
  ```
124
121
 
125
- ### Command Reference
122
+ `tools/e2e` holds the end-to-end harness; it drives a real daemon, so run it under `olbox exec <name> --` or in its Docker mode — never straight against your own install. It enforces that itself and will refuse to start on a machine whose isolation seams are unset, printing the commands to fix it.
126
123
 
127
- | Command | Description |
128
- | ------- | ----------- |
129
- | `openlatch init` | Auto-detect agents, install hooks, start daemon. Safe to re-run. |
130
- | `openlatch status` | Show daemon status, uptime, and event counts |
131
- | `openlatch start [--foreground]` | Start the daemon (or run in foreground) |
132
- | `openlatch stop` | Stop the daemon |
133
- | `openlatch restart` | Restart the daemon |
134
- | `openlatch logs [-f] [-n N] [--since T]` | View event logs. `-f` follows, `-n` limits count, `--since` filters by time |
135
- | `openlatch doctor` | Diagnose configuration and connectivity issues |
136
- | `openlatch doctor --fix` | Auto-heal common issues (config, hooks, daemon, binary). Creates `.bak` siblings and a journal so changes can be reverted with `--restore`. |
137
- | `openlatch doctor --restore` | Reverse the most recent `--fix` run. Surgical merge for `~/.claude/settings.json` preserves user edits to non-OpenLatch hooks. |
138
- | `openlatch doctor --rescue [--since 24h] [--output PATH] [--yes]` | Bundle a redacted diagnostic ZIP for sharing with support. Privacy filter runs on every text file; tokens are hard-redacted. |
139
- | `openlatch uninstall [--purge] [--yes]` | Remove hooks and stop daemon. `--purge` deletes all data |
140
- | `openlatch supervision {install,uninstall,enable,disable,status}` | Manage the OS-native supervisor that keeps the daemon alive after reboot (launchd / systemd --user / Task Scheduler). Installed by default during `openlatch init`; opt out with `openlatch init --no-persistence`. |
141
- | `openlatch docs` | Open documentation in browser |
142
-
143
- Noun-verb aliases are also available: `openlatch hooks install` = `init`, `openlatch hooks uninstall` = `uninstall`, `openlatch daemon start` = `start`, etc.
124
+ ---
144
125
 
145
- #### Persistence
126
+ ## The output contract
146
127
 
147
- `openlatch init` registers an OS-native supervisor by default so the daemon auto-starts when you log in or reboot — persistence is a security property, not a convenience. All three backends (macOS launchd, Linux systemd --user, Windows Task Scheduler) are user-scope only; no admin prompt, no sudo. Opt out with `openlatch init --no-persistence`, or toggle later with `openlatch supervision disable` / `enable`. `openlatch uninstall` always tears the supervisor down before stopping the daemon so it cannot auto-restart underneath you.
128
+ Every command that reports health renders from one model (`src/cli/report.rs`) over the same eleven sections. Three rules decide what you see, and they are enforced by tests rather than by review:
148
129
 
149
- ### Troubleshooting
130
+ | State | Mark | Means |
131
+ | ----- | :--: | ----- |
132
+ | `Ok` | `✓` | Enabled **and proven working**. The only green. |
133
+ | `Off` | `⚠` | Switched off deliberately. Always carries a code and a remedy. |
134
+ | `Degraded` / `Pending` | `⚠` | Working, but not at full capability, or still verifying |
135
+ | `Unknown` | `⚠` | Blocked by another section, which it names. One outage, one cross. |
136
+ | `Failed` | `✗` | Enabled and not working |
137
+ | `NotApplicable` | `·` | Absent from the build, or an exercised privacy opt-out |
150
138
 
151
- When something goes wrong, prefer this order:
139
+ Eleven sections, always all reported, under three groups — the questions a reader asks in the order they ask them:
152
140
 
153
- 1. **Diagnose** — `openlatch doctor` lists every check that's failing (8 today: agent detection, config file, crash-report consent, auth token, daemon liveness, cloud reachability, hook installation, and recent fallback-log activity).
154
- 2. **Heal** — `openlatch doctor --fix` rewrites broken state files (config, token, hooks) and restarts the daemon. Every mutation is backed up to a `.bak` sibling and a journal at `~/.openlatch/fix-journal.json`. Exit code is 0 when post-fix checks all pass and 1 otherwise.
155
- 3. **Roll back** — `openlatch doctor --restore` reads the journal and reverses each reversible action. `~/.claude/settings.json` is restored via a surgical merge — non-OpenLatch hook entries you've added since `--fix` are preserved.
156
- 4. **Bundle for support** — `openlatch doctor --rescue --yes` produces `openlatch-rescue-<ts>-<machid>.zip` in `$PWD`. The bundle includes redacted state files, daemon `/health` + `/metrics` snapshots, binary metadata (SHA256 only — never bytes), and a per-pattern privacy-filter hit summary in `MANIFEST.json`. The bearer token in `daemon.token` is hard-redacted; absolute paths are anonymised to `~`.
141
+ | Group | Sections | Question |
142
+ | ----- | -------- | -------- |
143
+ | **Runtime** | Environment · Daemon · Persistence · Update | is it running, and will it keep running? |
144
+ | **Coverage** | Hooks · Boundary · Policy · Inventory · Integrity | is it seeing everything, and enforcing? |
145
+ | **Platform** | Cloud · Telemetry | is any of it leaving this machine? |
157
146
 
158
- Combined `openlatch doctor --fix --rescue` runs the rescue first to snapshot the pre-fix state, then heals.
147
+ A green section is one line. Anything else lists what needs attention, with its cause and its remedy. `-v` unfolds every check.
159
148
 
160
- ### Global Flags
149
+ ```
150
+ Runtime
151
+ Environment ✓ 3 passed, 1 not applicable
152
+ Daemon ✓ 2 checks passed
153
+ Persistence ⚠ Disabled at your request (user_opt_out) [OL-1513]
154
+ The daemon will not restart after a logout, a reboot, or a crash.
155
+ source : [supervision] disabled_reason = "user_opt_out"
156
+ remedy : Run `openlatch supervision enable` to re-arm it.
157
+ Update ✓ Daemon is serving the installed version (0.1.18)
158
+
159
+ Platform
160
+ Cloud ✓ Connected: http://localhost:5173 (0 event(s) forwarded)
161
+ Telemetry · Disabled by user (opt-out honoured)
162
+ ```
161
163
 
162
- | Flag | Description |
163
- | ---- | ----------- |
164
- | `--json` | Machine-readable JSON output (parseable by `jq`) |
165
- | `--verbose` / `-v` | Show extra operational detail |
166
- | `--debug` | Show internal state and timings (implies `--verbose`) |
167
- | `--quiet` / `-q` | Suppress all output except errors |
168
- | `--no-color` | Disable colored output |
164
+ `Policy` sits under Coverage, not Platform: the bundle arrives from the cloud but the evaluation is local and authoritative — it is about what this host enforces, not about what leaves it.
169
165
 
170
- ### Exit Codes
166
+ ### Exit codes
171
167
 
172
168
  | Code | Meaning |
173
169
  | ---- | ------- |
174
- | 0 | Success |
175
- | 1 | Security findings detected |
176
- | 2 | Usage error (invalid arguments) |
170
+ | 0 | Healthy |
171
+ | 1 | Something enabled is not working |
172
+ | 2 | Usage error (clap) |
177
173
  | 3 | Resource not found |
178
174
  | 4 | Permission denied |
179
- | 5 | Conflict |
180
- | 130 | Interrupted (Ctrl+C) |
175
+ | 5 | Conflict — `OL-1501` only, because systemd's `RestartPreventExitStatus=5` keys off it |
176
+ | **7** | **Degraded** — everything runs, but something is switched off or not at full capability |
177
+ | 130 | Interrupted |
181
178
 
182
- ### Binaries
179
+ `7` matters: `openlatch doctor && deploy` must not succeed on a host where nothing is captured or enforced.
183
180
 
184
- OpenLatch ships two binaries:
181
+ ---
185
182
 
186
- - **`openlatch`** (<30MB) — full CLI for setup, daemon management, and log viewing.
187
- - **`openlatch-hook`** (<20MB) — minimal hook handler spawned by agent hooks. Reads event JSON from stdin, forwards to the daemon on `localhost:7443`, and writes the verdict to stdout. If the daemon is unreachable, it fails open (returns allow) and logs to `~/.openlatch/logs/fallback.jsonl`. Not invoked directly by users.
183
+ ## Commands
184
+
185
+ | Command | Notes |
186
+ | ------- | ----- |
187
+ | `openlatch init` | Complete, idempotent reinstall. Reclaims the ports first — identifying the holder **by the port**, not by `daemon.pid` — then proves the daemon it started is the one serving (PID, version, `/health`). |
188
+ | `openlatch status` | Dashboard plus the eleven-section verdict |
189
+ | `openlatch start [--foreground] [--port N] [--boundary-port N]` | Refuses when a daemon already runs (`OL-1501`, exit 5) |
190
+ | `openlatch stop` / `restart` | `stop` also removes the agent's boundary wiring, and says so |
191
+ | `openlatch doctor` | Full diagnosis with causes and remedies |
192
+ | `openlatch doctor --fix` | Heals what it can, backs up to `.bak` siblings + `~/.openlatch/fix-journal.json`. Never re-enables what you switched off. |
193
+ | `openlatch doctor --restore` | Reverses the last `--fix`. Surgical merge preserves your non-OpenLatch hooks. |
194
+ | `openlatch doctor --rescue [--since 24h] [--yes]` | Redacted diagnostic ZIP for support |
195
+ | `openlatch boundary status` | Full classification, not a port probe |
196
+ | `openlatch boundary {enable,disable} [-y] [--no-restart]` | Writes `[boundary] enabled`, then offers the restart that applies it |
197
+ | `openlatch hooks status` | The Hooks section in detail |
198
+ | `openlatch supervision {install,uninstall,enable,disable,status}` | OS-native supervisor (launchd / systemd --user / Task Scheduler), user-scope only |
199
+ | `openlatch inventory {list,log,rescan,status,inspect,projects,ack}` | Configuration-plane monitoring |
200
+ | `openlatch auth {login,logout,status}` · `openlatch telemetry {…}` · `openlatch update` · `openlatch logs` · `openlatch uninstall [--purge]` · `openlatch docs` | |
201
+
202
+ Noun-verb aliases: `hooks install` = `init`, `daemon start` = `start`, and so on — identical arguments, pinned by test.
203
+
204
+ Global flags: `--json`, `--verbose`/`-v`, `--debug`, `--quiet`/`-q`, `--no-color`. Every diagnostic's JSON carries the same `sections[]` the human rendering shows.
188
205
 
189
- ## How It Works
206
+ ---
190
207
 
191
- OpenLatch uses a **three-layer architecture** — hooks live inside your agents, the client forwards events, and the cloud runs detection:
208
+ ## Architecture
209
+
210
+ Hooks live inside the agent, the client decides locally, the platform authors rules and runs analysis.
192
211
 
193
212
  ```
194
213
  ┌─────────────────────────────────────────────────────────────────┐
195
214
  │ Your Machine │
196
215
  │ │
197
216
  │ ┌──────────┐ hook event ┌──────────────────────────────┐ │
198
- │ │ Claude │─────────────▶│ │ │
199
- │ │ Code │ │ OpenLatch Client │ │
200
- │ ├──────────┤ │ (localhost:7443) │ │
201
- │ │ Cursor │─────────────▶│ │ │
202
- │ ├──────────┤ │ 1. Wrap in envelope │ │
203
- │ │ Copilot │─────────────▶│ 2. Redact credentials │ │
204
- │ ├──────────┤ │ 3. Forward to cloud │────┼──▶ OpenLatch Cloud
205
- │ │ Gemini │─────────────▶│ 4. Return verdict │◀───┼── (allow / deny)
206
- │ │ CLI │ │ 5. Write local audit log │ │
207
- │ ├──────────┤ │ │ │
208
- │ │ ... │─────────────▶│ │ │
209
- │ └──────────┘ ◀─ verdict ─ └──────────────────────────────┘ │
210
- │ │
217
+ │ │ Claude │──────────────▶│ OpenLatch Client │ │
218
+ │ │ Code │ │ (localhost:7443) │ │
219
+ │ │ │ │ │ │
220
+ │ │ │ │ 1. Wrap in envelope │ │
221
+ │ │ │ │ 2. Evaluate resident │ │
222
+ │ │ │ │ policy in-process │ │
223
+ │ │ │ ◀─ verdict ──│ 3. Redact credentials │ │
224
+ │ └──────────┘ │ 4. Write local audit log │ │
225
+ │ │ 5. Batch → forward │────┼──▶ OpenLatch platform
226
+ │ │ ◀── policy bundle │◀───┼── (the policy brain:
227
+ │ └──────────────────────────────┘ │ zone, rules, analysis)
211
228
  └─────────────────────────────────────────────────────────────────┘
212
229
  ```
213
230
 
214
- **Key design decisions:**
231
+ - **Hook-native, not a proxy** — the decision point runs inside the agent's own runtime, so it evaluates the action rather than the traffic. Model-call economics additionally use a loopback listener on `127.0.0.1`.
232
+ - **Local-authoritative verdicts** — the daemon evaluates a resident policy bundle in-process; the verdict path never touches the network. The cloud serves rules, it does not decide.
233
+ - **The daemon owns `ANTHROPIC_BASE_URL`** — written after its bind succeeds and a synthetic round trip proves the listener can reach the provider, removed on teardown. Nothing else writes it, so the agent config can never name a listener that does not exist.
234
+ - **Fail-static, not fail-open** — a resident bundle keeps enforcing offline forever. Genuine fail-open is limited to "no bundle was ever fetched" and "the hook binary cannot reach the daemon".
235
+ - **Privacy-first** — credentials are redacted locally before anything leaves the machine.
236
+
237
+ Two binaries ship: **`openlatch`** (<30 MB, the CLI and daemon) and **`openlatch-hook`** (<20 MB, spawned per hook event, fails open to `~/.openlatch/logs/fallback.jsonl`).
238
+
239
+ The product perimeter — what the client does, and what it deliberately does not — is **[AGENTS.md](AGENTS.md)**. Subsystem detail (envelope format, policy engine, subsystem supervision, the boundary's wiring invariants, releasing) lives in [`.claude/rules/`](.claude/rules/), one file per subsystem, scoped to the paths it governs.
240
+
241
+ ### Supported agents
215
242
 
216
- - **Hook-native** — OpenLatch plugs into each agent's official hook/extension system. It runs inside the agent runtime, not as a network proxy. Events cannot be bypassed.
217
- - **Thin client, smart cloud** — the client wraps events in a standard envelope and forwards them. All detection, normalization, and analysis happens cloud-side.
218
- - **Privacy-first** — credentials and secrets are redacted locally via regex-based filtering before anything leaves your machine.
219
- - **Fail-open** — if the cloud is unreachable, agents continue working normally. Events are logged locally and synced later.
243
+ Claude Code, on macOS, Windows and Linux, across 12 hook events. It is the reference implementation, and the only agent this node can currently make **Enforced**. Other coding agents are recognised as envelope `agent_type` values — `cursor`, `windsurf`, `github-copilot`, `codex-cli`, `gemini-cli`, `cline`, `openclaw` — so their events store and attribute correctly, but `init` cannot install their hooks yet.
244
+
245
+ Adding one means an `AgentBinding` in `src/hooks/bindings/` **and** a verdict translator in `src/hook_output/` — without the translator a `deny` is discarded before the developer ever sees it, which is worse than not enforcing. The translator comes first.
246
+
247
+ ---
220
248
 
221
249
  ## Configuration
222
250
 
223
- OpenLatch works with zero configuration. For advanced use cases:
251
+ Precedence: CLI flags → environment (`OPENLATCH_*`) → `~/.openlatch/config.toml` → defaults.
252
+
253
+ | Variable | Description | Default |
254
+ | -------- | ----------- | ------- |
255
+ | `OPENLATCH_DIR` | State directory | `~/.openlatch` |
256
+ | `OPENLATCH_PORT` | Daemon port. `init` binds this exact port; unset, it probes 7443–7543. | `7443` |
257
+ | `OPENLATCH_API_URL` | Cloud API base URL | `https://app.openlatch.ai` |
258
+ | `OPENLATCH_API_KEY` | API key (credential chain: environment → keychain → encrypted file) | — |
259
+ | `OPENLATCH_SKIP_KEYRING` | Treat the OS keychain as unavailable, so the env var wins | unset |
260
+ | `OPENLATCH_LOG` | `error` / `warn` / `info` / `debug` / `trace` | `info` |
261
+ | `OPENLATCH_BOUNDARY_ENABLED` | Model-boundary listener. While on, the daemon points the agent at it — but only once a synthetic request proves the listener can reach the provider. Being wired disables Claude Code Remote Control. | `true` |
262
+ | `OPENLATCH_BOUNDARY_PORT` | Boundary port. A non-default port makes the instance isolated. | `7600` |
263
+ | `OPENLATCH_BOUNDARY_OWN_WIRING` | Let an isolated instance write its own agent config | derived from the port |
264
+ | `OPENLATCH_BOUNDARY_UPSTREAM` | Where the boundary forwards. Every model call and provider credential goes here — change it only for a local harness. | `https://api.anthropic.com` |
265
+ | `OPENLATCH_BOUNDARY_TRANSFORMS_ACT` | Whether an acting `prefix_reorder` rule may rewrite the forwarded request body. Off, the boundary measures and forwards the original bytes. See [Optimize](#verdicts-and-which-ones-this-node-enforces-today) for what it does and does not gate. | `false` |
266
+ | `OPENLATCH_POLICY_ENABLED` | Local policy evaluation. `false` is a complete off switch, not observe mode. | `true` |
267
+ | `OPENLATCH_INVENTORY_ENABLED` | Configuration-plane monitoring | `true` |
268
+ | `OPENLATCH_CLOUD_BATCH_MAX_EVENTS` | Events per ingest batch, clamped to `1..=100` | `50` |
269
+ | `OPENLATCH_CLOUD_BATCH_MAX_WAIT_MS` | Flush deadline, anchored to the first buffered event | `5000` |
270
+ | `OPENLATCH_CLOUD_OUTBOX_MAX_BYTES` | Outbox cap before drop-oldest (0 disables) | `104857600` |
271
+ | `OPENLATCH_CLOUD_FALLBACK_MAX_BYTES` | Fallback-log cap before drop-oldest (0 disables) | `52428800` |
272
+ | `OPENLATCH_AUTO_UPDATE` | Background auto-update worker | `true` |
273
+ | `OPENLATCH_UPDATE_CHECK` | Startup version check | `true` |
274
+ | `OPENLATCH_NPM_REGISTRY` | Registry origin for `openlatch update` | `https://registry.npmjs.org` |
275
+ | `OPENLATCH_TELEMETRY_DISABLED` | `1` opts out of anonymous usage telemetry | unset |
276
+
277
+ **Cloud forwarding is not optional.** `[cloud] enabled` and `OPENLATCH_CLOUD_ENABLED` are still parsed so existing configs keep loading, but they are ignored — a client that captures events and sends them nowhere is a log rotator. Point `[cloud] api_url` elsewhere to change *where* events go.
278
+
279
+ Auto-update, its quiet-window deferral and its rollback sentinel are documented in the module rustdoc of [`src/core/update.rs`](src/core/update.rs); `openlatch update --check --json` is the manual probe.
224
280
 
225
- ```bash
226
- # Configuration precedence (highest to lowest):
227
- # 1. CLI flags
228
- # 2. Environment variables (OPENLATCH_*)
229
- # 3. Project config (.openlatch.json)
230
- # 4. User config (~/.openlatch/config.toml)
231
- # 5. Defaults
232
- ```
281
+ ---
233
282
 
234
- | Environment Variable | Description | Default |
235
- | -------------------- | ----------- | ------- |
236
- | `OPENLATCH_API_KEY` | Your OpenLatch API key | — |
237
- | `OPENLATCH_API_URL` | Cloud API base URL. Callers append `/api/v1/...` path segments. | `https://app.openlatch.ai` |
238
- | `OPENLATCH_APP_URL` | Web app URL used for browser auth. Falls back to `OPENLATCH_API_URL` (with a trailing `/api` stripped, for back-compat with overrides). | `https://app.openlatch.ai` |
239
- | `OPENLATCH_LOG_LEVEL` | Logging verbosity | `info` |
240
- | `OPENLATCH_FAIL_MODE` | Behavior when cloud is unreachable | `open` |
283
+ ## Releases
241
284
 
242
- ## Security
285
+ Two artifacts on independent version lines, both cut by [release-please](https://github.com/googleapis/release-please) from Conventional Commits:
243
286
 
244
- OpenLatch is a security product — we hold ourselves to a high standard:
287
+ | Artifact | Tag | Where |
288
+ | -------- | --- | ----- |
289
+ | The client | `v1.2.3` | GitHub Releases, npm, crates.io |
290
+ | The wire-format JSON Schemas | `schemas-v1.2.3` | npm, PyPI |
245
291
 
246
- - **Responsible disclosure** — report vulnerabilities to **security@openlatch.ai**
247
- - **Private vulnerability reporting** enabled on this repository
248
- - All releases are built with **SLSA provenance** via GitHub Actions
249
- - See [SECURITY.md](SECURITY.md) for our full security policy
292
+ The schema packages are versioned **only** by changes under `schemas/`, so a major bump means a breaking change to the events exchanged with the platform and nothing else. Pin them independently. Details in [`.claude/rules/release-lines.md`](.claude/rules/release-lines.md).
250
293
 
251
- ## Contributing
294
+ ## Why it is open source
252
295
 
253
- We welcome contributions! Whether it's bug fixes, new agent integrations, or documentation improvements.
296
+ The platform is closed; this node is Apache-2.0, for three enterprise reasons.
254
297
 
255
- - Read our [Contributing Guide](.github/CONTRIBUTING.md) to get started
256
- - Check [good first issues](https://github.com/OpenLatch/openlatch-client/labels/good%20first%20issue) for entry points
257
- - Join our [Slack](https://openlatch.slack.com) to connect with the team
298
+ | Reason | Why it matters |
299
+ | ------ | -------------- |
300
+ | **Transparency** | A node that sits in the execution path of every agent action cannot be a black box. Source access is a hard procurement gate at regulated enterprises. |
301
+ | **Auditability** | Security reviews, internal AppSec and third-party testers all need to read the code that enforces policy on production agents. |
302
+ | **Distribution** | The developer inside the account is who runs `npx @openlatch/client init` first. Open source removes the friction from that. |
258
303
 
259
- ## License
304
+ ## Security
305
+
306
+ - Report vulnerabilities to **security@openlatch.ai**; private vulnerability reporting is enabled on this repository
307
+ - Releases are built with SLSA provenance via GitHub Actions
308
+ - Full policy: [SECURITY.md](SECURITY.md)
309
+
310
+ ## Contributing
260
311
 
261
- Licensed under the [Apache License 2.0](LICENSE).
312
+ Read the [Contributing Guide](.github/CONTRIBUTING.md), pick a [good first issue](https://github.com/OpenLatch/openlatch-client/labels/good%20first%20issue), and join us on [Slack](https://openlatch.slack.com).
262
313
 
263
- ## Links
314
+ Licensed under [Apache-2.0](LICENSE).
264
315
 
265
316
  | Resource | URL |
266
317
  | -------- | --- |
@@ -268,4 +319,3 @@ Licensed under the [Apache License 2.0](LICENSE).
268
319
  | Documentation | [docs.openlatch.ai](https://docs.openlatch.ai) |
269
320
  | Slack | [openlatch.slack.com](https://openlatch.slack.com) |
270
321
  | Twitter / X | [@openlatch](https://x.com/openlatch) |
271
- | GitHub | [github.com/OpenLatch](https://github.com/OpenLatch) |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openlatch/client",
3
- "version": "0.1.14",
4
- "description": "OpenLatch — the open-source security layer for AI agents",
3
+ "version": "0.2.2",
4
+ "description": "OpenLatch runtime enforcement node — the capture-and-enforce adapter that evaluates every covered action against a coding agent's Autonomy Zone before it runs",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,10 +20,10 @@
20
20
  "postinstall": "node lib/postinstall.js"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@openlatch/client-darwin-arm64": "0.1.14",
24
- "@openlatch/client-darwin-x64": "0.1.14",
25
- "@openlatch/client-linux-x64": "0.1.14",
26
- "@openlatch/client-linux-arm64": "0.1.14",
27
- "@openlatch/client-win32-x64": "0.1.14"
23
+ "@openlatch/client-darwin-arm64": "0.2.2",
24
+ "@openlatch/client-darwin-x64": "0.2.2",
25
+ "@openlatch/client-linux-x64": "0.2.2",
26
+ "@openlatch/client-linux-arm64": "0.2.2",
27
+ "@openlatch/client-win32-x64": "0.2.2"
28
28
  }
29
29
  }