@klars/agentobs 0.1.0 → 0.1.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.
package/README.md CHANGED
@@ -1,190 +1,231 @@
1
- # AgentObs
2
-
3
- **See every tool call, token, and dollar your AI coding agents spend — and stop them before they do something risky.**
4
-
5
- AgentObs is an observability and control layer for AI coding agents. It runs
6
- entirely on your machine: a CLI, a local SQLite database, and a dashboard. No
7
- account, no cloud, no telemetry.
8
-
9
- [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg)](LICENSE)
10
-
11
- ---
12
-
13
- ## Quick start
14
-
15
- ```bash
16
- npm install -g @klars/agentobs
17
- agentobs init
18
- ```
19
-
20
- `init` prints a hook configuration block. Paste it into `~/.claude/settings.json`
21
- (or a project's `.claude/settings.json`), then:
22
-
23
- ```bash
24
- agentobs dashboard
25
- ```
26
-
27
- Run Claude Code as usual. Tool calls appear in the dashboard within seconds.
28
-
29
- ---
30
-
31
- ## What you get
32
-
33
- | | |
34
- | ---------------------- | ------------------------------------------------------------ |
35
- | **Cost tracking** | Per session, per tool, per day — or blank if the model's price is unknown. Never guessed. |
36
- | **Tool-call timeline** | Every call, its duration, status, and truncated input. |
37
- | **Guardrails** | Block `rm -rf`, require approval for `.env` edits, stop `curl \| sh`. |
38
- | **Audit trail** | Every policy decision recorded with the rule that fired. |
39
- | **Any agent** | Native Claude Code hooks; JSONL ingestion or process-wrapping for everything else. |
40
-
41
- ---
42
-
43
- ## Privacy
44
-
45
- This is the part that matters most, since AgentObs sits in the middle of
46
- everything your agent does.
47
-
48
- - **Nothing leaves your machine.** No network calls, no analytics, no account.
49
- - **Secrets are redacted before anything is written to disk.** Tool inputs and
50
- outputs pass through a redaction layer that recognises AWS keys, Anthropic /
51
- OpenAI / GitHub / GitLab / Slack / Stripe / Google / npm tokens, JWTs, PEM
52
- private keys, `KEY=value` assignments, `--flag secret` arguments,
53
- `Authorization:` headers, and credentials embedded in URLs.
54
- - **Summaries are truncated** to ~500 characters.
55
- - The redaction rules are unit-tested in
56
- [`src/core/redact.test.ts`](src/core/redact.test.ts) — the tests are the
57
- guarantee, and they have caught real leaks during development.
58
-
59
- Everything lives in `~/.agentobs/`. Uninstalling is `rm -rf ~/.agentobs`.
60
-
61
- ---
62
-
63
- ## Commands
64
-
65
- ```
66
- agentobs init Set up ~/.agentobs and print the hook config
67
- agentobs dashboard [--port] [--host] Serve the dashboard (default 127.0.0.1:4300)
68
- agentobs stats [--today] [--since] Print totals in the terminal
69
- agentobs run -- <command...> Observe any command (coarse detail)
70
- agentobs watch <file.jsonl> Ingest a JSONL agent log
71
- agentobs export --format csv|json Export sessions, tool calls, or decisions
72
-
73
- agentobs policy init Write a starter policy.json
74
- agentobs policy check Validate it and list active rules
75
- agentobs policy test <tool> <input> Dry-run a call against the policy
76
- ```
77
-
78
- ---
79
-
80
- ## Guardrails
81
-
82
- `agentobs policy init` writes `~/.agentobs/policy.json`:
83
-
84
- ```json
85
- {
86
- "rules": [
87
- {
88
- "name": "no-recursive-force-delete",
89
- "match": { "tool": "Bash", "command_pattern": "*rm -rf*" },
90
- "decision": "block",
91
- "message": "Recursive force-delete is blocked by AgentObs policy."
92
- },
93
- {
94
- "name": "protect-env-files",
95
- "match": { "tool": "*", "path_pattern": "**/.env*" },
96
- "decision": "needs_approval"
97
- }
98
- ],
99
- "default_decision": "allow"
100
- }
101
- ```
102
-
103
- Rules are evaluated top to bottom; **the first match wins**, so you can put a
104
- narrow `allow` above a broad `block`. Check what a rule will do *before* it
105
- fires mid-task:
106
-
107
- ```bash
108
- $ agentobs policy test Bash "rm -rf ./build"
109
-
110
- Tool Bash
111
- Input rm -rf ./build
112
- Decision BLOCK
113
- Rule no-recursive-force-delete
114
-
115
- This call would be BLOCKED before running.
116
- ```
117
-
118
- Two deliberate behaviours worth knowing:
119
-
120
- - **`needs_approval` currently behaves as a block** with a clearer message.
121
- There is no channel for a hook to prompt you interactively mid-call.
122
- - **A broken policy file fails open.** Invalid JSON or a malformed rule
123
- degrades to allow-everything and reports the problem, because a guardrail
124
- that wedges your agent is worse than no guardrail. Run `agentobs policy check`.
125
-
126
- ---
127
-
128
- ## Agent support
129
-
130
- | Agent | How | Detail |
131
- | --------------- | -------------------------- | ------------------------------------------------- |
132
- | **Claude Code** | Native hooks | **Rich** — every tool call, plus policy enforcement |
133
- | Any CLI agent | `agentobs run -- <cmd>` | **Coarse** — duration and exit code only |
134
- | Custom / in-house | `agentobs watch <file>` | **Rich**, if it writes JSONL |
135
-
136
- The dashboard labels coarse sessions as `coarse` rather than implying detail it
137
- does not have.
138
-
139
- ### A note on cost accuracy
140
-
141
- Claude Code's `PostToolUse` hook payload carries **no token or cost fields**.
142
- AgentObs therefore reads token usage from the session transcript at
143
- `SessionEnd`, which makes **session-level cost accurate** but leaves
144
- **per-tool-call cost blank** for hook-sourced data. It does not divide a total
145
- across calls to manufacture a number.
146
-
147
- Model prices live in `~/.agentobs/pricing.json` and are yours to edit. A model
148
- missing from that file shows cost as `—`, never `$0.00`.
149
-
150
- ---
151
-
152
- ## Dashboard access
153
-
154
- Binds to `127.0.0.1` with no authenticationsame machine, same user, same
155
- trust boundary as the database file.
156
-
157
- Binding anywhere else **requires a token**, printed at startup and included in
158
- the URL:
159
-
160
- ```bash
161
- agentobs dashboard --host 0.0.0.0
162
- ```
163
-
164
- **Never expose the dashboard to the public internet.** It shows tool inputs and
165
- file paths from your repositories.
166
-
167
- ---
168
-
169
- ## Requirements
170
-
171
- Node.js **≥ 22.5** — AgentObs uses the built-in `node:sqlite` module, so there
172
- is no native addon to compile and no C++ toolchain to install.
173
-
174
- ---
175
-
176
- ## Development
177
-
178
- ```bash
179
- npm install
180
- npm run build
181
- npm test
182
- ```
183
-
184
- Adding an adapter for another agent: see [CONTRIBUTING.md](CONTRIBUTING.md).
185
-
186
- ---
187
-
188
- ## License
189
-
190
- MIT © [Klars AI](https://klars.ai)
1
+ <div align="center">
2
+
3
+ <img src="docs/assets/logo.svg" width="72" height="72" alt="" />
4
+
5
+ # AgentObs
6
+
7
+ **See every tool call, token, and dollar your AI agents spend — and stop the risky ones.**
8
+
9
+ [![npm](https://img.shields.io/npm/v/@klars/agentobs?color=2a78d6&label=npm)](https://www.npmjs.com/package/@klars/agentobs)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg)](LICENSE)
11
+ [![Node](https://img.shields.io/badge/node-%E2%89%A522.5-1baf7a)](https://nodejs.org)
12
+
13
+ [Website](https://agents.klars.ai) · [npm](https://www.npmjs.com/package/@klars/agentobs) · [Contributing](CONTRIBUTING.md)
14
+
15
+ </div>
16
+
17
+ <br>
18
+
19
+ <picture>
20
+ <source srcset="docs/assets/dashboard-dark.png" media="(prefers-color-scheme: dark)" />
21
+ <img src="docs/assets/dashboard.png" alt="The AgentObs dashboard: spend for the week, tool call and error-rate tiles with trend sparklines, an activity chart, and tables of tools and sessions." />
22
+ </picture>
23
+
24
+ <br>
25
+
26
+ ## Guardrails that actually stop things
27
+
28
+ <img src="docs/assets/demo.gif" alt="Terminal demo: agentobs policy test blocks an rm -rf command, then agentobs stats shows the cost, calls, errors and blocked totals." width="820" />
29
+
30
+ AgentObs is an observability and control layer for AI coding agents. It runs
31
+ entirely on your machine: a CLI, a local SQLite database, and a dashboard. No
32
+ account, no cloud, no telemetry.
33
+
34
+ ## Quick start
35
+
36
+ ```bash
37
+ npm install -g @klars/agentobs
38
+ agentobs init
39
+ ```
40
+
41
+ `init` prints a hook configuration block. Paste it into `~/.claude/settings.json`
42
+ (or a project's `.claude/settings.json`), then:
43
+
44
+ ```bash
45
+ agentobs dashboard
46
+ ```
47
+
48
+ Run Claude Code as usual. Tool calls appear in the dashboard within seconds.
49
+
50
+ ---
51
+
52
+ ## What you get
53
+
54
+ | | |
55
+ | ---------------------- | ------------------------------------------------------------ |
56
+ | **Cost tracking** | Per session, per tool, per day or blank if the model's price is unknown. Never guessed. |
57
+ | **Tool-call timeline** | Every call, its duration, status, and truncated input. |
58
+ | **Guardrails** | Block `rm -rf`, require approval for `.env` edits, stop `curl \| sh`. |
59
+ | **Audit trail** | Every policy decision recorded with the rule that fired. |
60
+ | **Any agent** | Native Claude Code hooks; JSONL ingestion or process-wrapping for everything else. |
61
+
62
+ ---
63
+
64
+ ## Privacy
65
+
66
+ This is the part that matters most, since AgentObs sits in the middle of
67
+ everything your agent does.
68
+
69
+ - **Nothing leaves your machine.** No network calls, no analytics, no account.
70
+ - **Secrets are redacted before anything is written to disk.** Tool inputs and
71
+ outputs pass through a redaction layer that recognises AWS keys, Anthropic /
72
+ OpenAI / GitHub / GitLab / Slack / Stripe / Google / npm tokens, JWTs, PEM
73
+ private keys, `KEY=value` assignments, `--flag secret` arguments,
74
+ `Authorization:` headers, and credentials embedded in URLs.
75
+ - **Summaries are truncated** to ~500 characters.
76
+ - The redaction rules are unit-tested in
77
+ [`src/core/redact.test.ts`](src/core/redact.test.ts) — the tests are the
78
+ guarantee, and they have caught real leaks during development.
79
+
80
+ Everything lives in `~/.agentobs/`. Uninstalling is `rm -rf ~/.agentobs`.
81
+
82
+ ---
83
+
84
+ ## Commands
85
+
86
+ ```
87
+ agentobs init Set up ~/.agentobs and print the hook config
88
+ agentobs dashboard [--port] [--host] Serve the dashboard (default 127.0.0.1:4300)
89
+ agentobs stats [--today] [--since] Print totals in the terminal
90
+ agentobs run -- <command...> Observe any command (coarse detail)
91
+ agentobs watch <file.jsonl> Ingest a JSONL agent log
92
+ agentobs export --format csv|json Export sessions, tool calls, or decisions
93
+
94
+ agentobs policy init Write a starter policy.json
95
+ agentobs policy check Validate it and list active rules
96
+ agentobs policy test <tool> <input> Dry-run a call against the policy
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Guardrails
102
+
103
+ `agentobs policy init` writes `~/.agentobs/policy.json`:
104
+
105
+ ```json
106
+ {
107
+ "rules": [
108
+ {
109
+ "name": "no-recursive-force-delete",
110
+ "match": { "tool": "Bash", "command_pattern": "*rm -rf*" },
111
+ "decision": "block",
112
+ "message": "Recursive force-delete is blocked by AgentObs policy."
113
+ },
114
+ {
115
+ "name": "protect-env-files",
116
+ "match": { "tool": "*", "path_pattern": "**/.env*" },
117
+ "decision": "needs_approval"
118
+ }
119
+ ],
120
+ "default_decision": "allow"
121
+ }
122
+ ```
123
+
124
+ Rules are evaluated top to bottom; **the first match wins**, so you can put a
125
+ narrow `allow` above a broad `block`. Check what a rule will do *before* it
126
+ fires mid-task:
127
+
128
+ ```bash
129
+ $ agentobs policy test Bash "rm -rf ./build"
130
+
131
+ Tool Bash
132
+ Input rm -rf ./build
133
+ Decision BLOCK
134
+ Rule no-recursive-force-delete
135
+
136
+ This call would be BLOCKED before running.
137
+ ```
138
+
139
+ Two deliberate behaviours worth knowing:
140
+
141
+ - **`needs_approval` currently behaves as a block** with a clearer message.
142
+ There is no channel for a hook to prompt you interactively mid-call.
143
+ - **A broken policy file fails open.** Invalid JSON or a malformed rule
144
+ degrades to allow-everything and reports the problem, because a guardrail
145
+ that wedges your agent is worse than no guardrail. Run `agentobs policy check`.
146
+
147
+ ---
148
+
149
+ ## Agent support
150
+
151
+ | Agent | How | Detail |
152
+ | --------------- | -------------------------- | ------------------------------------------------- |
153
+ | **Claude Code** | Native hooks | **Rich** — every tool call, plus policy enforcement |
154
+ | Any CLI agent | `agentobs run -- <cmd>` | **Coarse** duration and exit code only |
155
+ | Custom / in-house | `agentobs watch <file>` | **Rich**, if it writes JSONL |
156
+
157
+ The dashboard labels coarse sessions as `coarse` rather than implying detail it
158
+ does not have.
159
+
160
+ ### A note on cost accuracy
161
+
162
+ Claude Code's `PostToolUse` hook payload carries **no token or cost fields**.
163
+ AgentObs therefore reads token usage from the session transcript at
164
+ `SessionEnd`, which makes **session-level cost accurate** but leaves
165
+ **per-tool-call cost blank** for hook-sourced data. It does not divide a total
166
+ across calls to manufacture a number.
167
+
168
+ Model prices live in `~/.agentobs/pricing.json` and are yours to edit. A model
169
+ missing from that file shows cost as `—`, never `$0.00`.
170
+
171
+
172
+ ### Hook latency
173
+
174
+ The hook does its own work in **well under 1ms** (measured: ~0.3ms per
175
+ invocation, including the SQLite write). What you actually pay per tool call is
176
+ **Node.js process startup**, since Claude Code spawns the hook as a fresh
177
+ process each time.
178
+
179
+ On a typical Linux/macOS machine that is ~40-80ms. On Windows with real-time
180
+ antivirus scanning it can reach **1-1.5 seconds** - and that cost is not
181
+ specific to AgentObs: a bare `node -e "0"` measures the same. Check yours with:
182
+
183
+ ```bash
184
+ node -e "0" # time this; it is the floor for any Node-based hook
185
+ ```
186
+
187
+ If it is slow, adding an exclusion for your Node install directory and
188
+ `~/.agentobs` in your antivirus settings is the fix. There is no code change
189
+ that avoids it - the cost is paid before AgentObs runs at all.
190
+
191
+ ---
192
+
193
+ ## Dashboard access
194
+
195
+ Binds to `127.0.0.1` with no authentication — same machine, same user, same
196
+ trust boundary as the database file.
197
+
198
+ Binding anywhere else **requires a token**, printed at startup and included in
199
+ the URL:
200
+
201
+ ```bash
202
+ agentobs dashboard --host 0.0.0.0
203
+ ```
204
+
205
+ **Never expose the dashboard to the public internet.** It shows tool inputs and
206
+ file paths from your repositories.
207
+
208
+ ---
209
+
210
+ ## Requirements
211
+
212
+ Node.js **≥ 22.5** — AgentObs uses the built-in `node:sqlite` module, so there
213
+ is no native addon to compile and no C++ toolchain to install.
214
+
215
+ ---
216
+
217
+ ## Development
218
+
219
+ ```bash
220
+ npm install
221
+ npm run build
222
+ npm test
223
+ ```
224
+
225
+ Adding an adapter for another agent: see [CONTRIBUTING.md](CONTRIBUTING.md).
226
+
227
+ ---
228
+
229
+ ## License
230
+
231
+ MIT © [Klars AI](https://klars.ai)
@@ -22,7 +22,31 @@ import { existsSync } from 'node:fs';
22
22
  */
23
23
  export function hookCommandPath() {
24
24
  const here = dirname(fileURLToPath(import.meta.url));
25
- // dist/commands -> package root
25
+ // On Windows, prefer npm's generated .cmd shim in the global bin directory.
26
+ //
27
+ // The raw bin/agentobs-hook file has no extension, and Windows cannot
28
+ // execute an extensionless file - cmd.exe reports "not recognized as an
29
+ // internal or external command". Claude Code swallows that, so the hook
30
+ // silently never runs and no data is ever recorded: the worst possible
31
+ // failure for an observability tool, because it looks like "no activity"
32
+ // rather than "broken". npm generates the .cmd shim for exactly this.
33
+ if (process.platform === 'win32') {
34
+ // dist/commands -> .../node_modules/@klars/agentobs -> up to the dir
35
+ // holding npm's shims (node_modules/.bin, or the global npm root).
36
+ const packageRoot = resolve(here, '..', '..');
37
+ const shims = [
38
+ resolve(packageRoot, '..', '..', '..', 'agentobs-hook.cmd'), // global npm root
39
+ resolve(packageRoot, '..', '..', '.bin', 'agentobs-hook.cmd'), // local node_modules/.bin
40
+ ];
41
+ for (const shim of shims) {
42
+ if (existsSync(shim))
43
+ return shim;
44
+ }
45
+ // No shim found (e.g. running from a source checkout): fall back to the
46
+ // bare name so PATH resolution can still find it, rather than emitting a
47
+ // path that is guaranteed not to execute.
48
+ return 'agentobs-hook.cmd';
49
+ }
26
50
  const candidate = resolve(here, '..', '..', 'bin', 'agentobs-hook');
27
51
  if (existsSync(candidate))
28
52
  return candidate;