@lousy-agents/agent-shell 5.8.8 → 5.9.0

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
@@ -2,9 +2,9 @@
2
2
 
3
3
  ![agent-shell demo](https://raw.githubusercontent.com/zpratt/lousy-agents/main/media/agent-shell.gif)
4
4
 
5
- A flight recorder for npm script execution.
5
+ A flight recorder for AI agent tool usage and npm script execution.
6
6
 
7
- agent-shell is an npm `script-shell` shim that independently records what scripts ran, who initiated them, and whether they succeeded producing structured JSONL telemetry. It sits below the agent at the npm script-shell level, providing an audit trail that doesn't depend on agent self-reports.
7
+ agent-shell records structured JSONL telemetry for both npm script execution (via `script-shell` shim) and AI agent tool usage (via Copilot lifecycle hooks). It provides an audit trail that doesn't depend on agent self-reports.
8
8
 
9
9
  ## Quick Start
10
10
 
@@ -12,20 +12,23 @@ agent-shell is an npm `script-shell` shim that independently records what script
12
12
  # Install globally
13
13
  npm install -g @lousy-agents/agent-shell
14
14
 
15
- # Configure npm to use agent-shell as the script shell
16
- echo 'script-shell=agent-shell' >> .npmrc
15
+ # Initialize hooks and policy (interactive)
16
+ agent-shell init
17
17
 
18
18
  # Add event storage to .gitignore
19
19
  echo '.agent-shell/' >> .gitignore
20
20
 
21
21
  # Verify it's working
22
22
  agent-shell --version
23
-
24
- # Run any npm script — events are recorded automatically
25
- npm test
26
23
  ```
27
24
 
28
- > **Why global?** agent-shell is configured as npm's `script-shell`, so it must be available _before_ `npm ci` or `npm install` runs. A local dev dependency creates a circular dependency: npm needs agent-shell to execute the install script, but agent-shell isn't available until the install completes. Installing globally keeps the shim on `PATH` independent of `node_modules`.
25
+ `agent-shell init` detects your project, prompts for which features to enable (flight recording, policy blocking), and writes the Copilot hook configuration and policy files.
26
+
27
+ > **Note:** `agent-shell init` sets up Copilot hooks and policy files, but npm script execution recording is configured separately. To record npm script runs and emit `script_end` events, set npm's `script-shell` to `agent-shell` (for example by adding `script-shell=agent-shell` to your project's `.npmrc`).
28
+
29
+ <!-- -->
30
+
31
+ > **Why global?** agent-shell is configured as npm's `script-shell` and as a Copilot hook command, so it must be available _before_ `npm ci` or `npm install` runs. A local dev dependency creates a circular dependency. Installing globally keeps it on `PATH` independent of `node_modules`.
29
32
 
30
33
  ## How It Works
31
34
 
@@ -38,9 +41,84 @@ When npm runs a script (e.g., `npm test`), it invokes the configured `script-she
38
41
 
39
42
  Scripts behave identically — same output, same exit codes, same signals. agent-shell adds observability without changing behavior.
40
43
 
44
+ ## Setup with `agent-shell init`
45
+
46
+ The `init` subcommand is the recommended way to configure agent-shell for your project. It detects existing configuration and guides you through enabling features.
47
+
48
+ ### Interactive Mode (TTY)
49
+
50
+ ```bash
51
+ agent-shell init
52
+ ```
53
+
54
+ When run in a terminal, `init` prompts for each feature:
55
+
56
+ - **Flight recording** — Records all agent tool usage via `postToolUse` hook
57
+ - **Policy blocking** — Evaluates commands against allow/deny rules via `preToolUse` hook
58
+
59
+ If `hooks.json` already exists, only missing features are prompted.
60
+
61
+ ### Non-Interactive Mode (CI / Flags)
62
+
63
+ ```bash
64
+ # Enable specific features
65
+ agent-shell init --flight-recorder
66
+ agent-shell init --policy
67
+ agent-shell init --flight-recorder --policy
68
+
69
+ # Disable specific features
70
+ agent-shell init --no-flight-recorder
71
+ agent-shell init --no-policy
72
+ ```
73
+
74
+ In a non-TTY environment with no explicit flags, all missing features are auto-enabled with a message to stderr.
75
+
76
+ ### What It Generates
77
+
78
+ | File | Description |
79
+ | ------ | ------------- |
80
+ | `.github/hooks/agent-shell/hooks.json` | Copilot hook configuration with selected features |
81
+ | `.github/hooks/agent-shell/policy.json` | Allow/deny policy (only when policy is enabled) |
82
+
83
+ ## Flight Recording with `agent-shell record`
84
+
85
+ The `record` subcommand is a `postToolUse` hook handler that records every tool invocation as a `tool_use` telemetry event. It captures tool usage that happens outside npm scripts — file edits, code searches, API calls, and more.
86
+
87
+ ### Copilot Hook Configuration
88
+
89
+ When both flight recording and policy are enabled, `hooks.json` looks like this:
90
+
91
+ ```json
92
+ {
93
+ "version": 1,
94
+ "hooks": {
95
+ "preToolUse": [
96
+ {
97
+ "type": "command",
98
+ "bash": "agent-shell policy-check",
99
+ "timeoutSec": 30
100
+ }
101
+ ],
102
+ "postToolUse": [
103
+ {
104
+ "type": "command",
105
+ "bash": "agent-shell record",
106
+ "timeoutSec": 30
107
+ }
108
+ ]
109
+ }
110
+ }
111
+ ```
112
+
113
+ The `record` handler reads the JSON payload from Copilot's `postToolUse` hook via stdin. For terminal tools (`bash`, `zsh`, `ash`, `sh`), it extracts the command string from `toolArgs`. For non-terminal tools, the command is recorded as an empty string.
114
+
41
115
  ## Telemetry Schema (v1)
42
116
 
43
- Each script execution produces one JSON line:
117
+ Each event produces one JSON line. There are four event types:
118
+
119
+ ### `script_end` Event
120
+
121
+ Recorded when an npm script completes:
44
122
 
45
123
  ```json
46
124
  {
@@ -66,14 +144,75 @@ Each script execution produces one JSON line:
66
144
  }
67
145
  ```
68
146
 
147
+ ### `tool_use` Event
148
+
149
+ Recorded by the `postToolUse` hook when an agent uses any tool:
150
+
151
+ ```json
152
+ {
153
+ "v": 1,
154
+ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
155
+ "event": "tool_use",
156
+ "tool_name": "bash",
157
+ "command": "npm test",
158
+ "actor": "copilot",
159
+ "timestamp": "2026-03-08T14:32:01.000Z",
160
+ "env": {
161
+ "CI": "true"
162
+ },
163
+ "tags": {}
164
+ }
165
+ ```
166
+
167
+ For non-terminal tools (file edits, searches, etc.), `command` is an empty string and `tool_name` identifies the tool (e.g., `file_edit`, `curl`).
168
+
169
+ ### `policy_decision` Event
170
+
171
+ Recorded when the `preToolUse` policy-check hook evaluates a command:
172
+
173
+ ```json
174
+ {
175
+ "v": 1,
176
+ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
177
+ "event": "policy_decision",
178
+ "decision": "deny",
179
+ "matched_rule": "rm -rf *",
180
+ "command": "rm -rf /",
181
+ "actor": "copilot",
182
+ "timestamp": "2026-03-08T14:32:01.000Z",
183
+ "env": {
184
+ "CI": "true"
185
+ },
186
+ "tags": {}
187
+ }
188
+ ```
189
+
190
+ ### `shim_error` Event
191
+
192
+ Recorded when agent-shell encounters an internal error (e.g., failed to parse npm context):
193
+
194
+ ```json
195
+ {
196
+ "v": 1,
197
+ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
198
+ "event": "shim_error",
199
+ "command": "",
200
+ "actor": "copilot",
201
+ "timestamp": "2026-03-08T14:32:01.000Z",
202
+ "env": {},
203
+ "tags": {}
204
+ }
205
+ ```
206
+
69
207
  ### Field Reference
70
208
 
71
209
  | Field | Type | Description |
72
210
  | ------- | ------ | ------------- |
73
211
  | `v` | number | Schema version (always `1`) |
74
212
  | `session_id` | string | UUID identifying the session |
75
- | `event` | string | `script_end` or `shim_error` |
76
- | `script` | string? | npm lifecycle event name (e.g., `test`, `build`) |
213
+ | `event` | string | `script_end`, `tool_use`, `shim_error`, or `policy_decision` |
214
+ | `script` | string? | npm lifecycle event name (e.g., `test`, `build`) — `script_end` only |
215
+ | `tool_name` | string? | Tool identifier (e.g., `bash`, `file_edit`) — `tool_use` only |
77
216
  | `command` | string | The actual command executed |
78
217
  | `package` | string? | Package name from `package.json` |
79
218
  | `package_version` | string? | Package version |
@@ -103,7 +242,7 @@ agent-shell classifies who initiated each script execution:
103
242
 
104
243
  ## Querying Events
105
244
 
106
- Use the `log` subcommand to query execution history:
245
+ Use the `log` subcommand to query execution history. Both `script_end` and `tool_use` events are included in results:
107
246
 
108
247
  ```bash
109
248
  # Show events from the most recent session
@@ -112,13 +251,13 @@ agent-shell log
112
251
  # Show events from the last 2 hours
113
252
  agent-shell log --last 2h
114
253
 
115
- # Show only failures
254
+ # Show only failures (script_end events with non-zero exit)
116
255
  agent-shell log --failures
117
256
 
118
257
  # Filter by actor
119
258
  agent-shell log --actor claude-code
120
259
 
121
- # Filter by script name
260
+ # Filter by script name (script_end events only)
122
261
  agent-shell log --script test
123
262
 
124
263
  # Combine filters
@@ -170,7 +309,7 @@ Patterns support `*` wildcards for prefix, suffix, and infix matching (e.g., `np
170
309
 
171
310
  ### Copilot Hook Configuration
172
311
 
173
- Add the following to `.github/hooks/agent-shell/hooks.json` to use policy-check as a pre-tool-use hook:
312
+ Add the following to `.github/hooks/agent-shell/hooks.json`, or use `agent-shell init` to generate it automatically:
174
313
 
175
314
  ```json
176
315
  {
@@ -182,6 +321,13 @@ Add the following to `.github/hooks/agent-shell/hooks.json` to use policy-check
182
321
  "timeoutSec": 30,
183
322
  "bash": "agent-shell policy-check"
184
323
  }
324
+ ],
325
+ "postToolUse": [
326
+ {
327
+ "type": "command",
328
+ "timeoutSec": 30,
329
+ "bash": "agent-shell record"
330
+ }
185
331
  ]
186
332
  }
187
333
  }