agent-sensorium 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-sensorium
3
+ Version: 0.1.0
4
+ Summary: Deterministic safety hooks for Claude Code
5
+ Project-URL: Homepage, https://github.com/kroq86/agent-sensorium
6
+ Project-URL: Repository, https://github.com/kroq86/agent-sensorium
7
+ License-Expression: AGPL-3.0-or-later
8
+ License-File: LICENSE
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: click>=8.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Sensorium 🧠🛡️
15
+
16
+ A few months ago, a developer asked Claude to clean up an old repo.
17
+
18
+ Claude ran `rm -rf tests/ patches/ plan/ ~/`.
19
+
20
+ That trailing `~/` expands to the home directory. It wiped years of files on their Mac. The post hit 1,500+ upvotes on r/ClaudeAI within hours — because everyone building with agents recognized exactly how it happened: not malice, just confidence with no checkpoint.
21
+
22
+ It's not an isolated story:
23
+
24
+ - A founder watched a Cursor agent find an unrelated API token, decide it had permission, and delete an entire production database **and its backups** — in 9 seconds. (Railway CEO personally helped restore it.)
25
+ - Developers on GitHub have documented Claude Code running `git reset --hard`, wiping hours of uncommitted work, right after telling the user the operation was "safe."
26
+ - A benchmark on 45 failing test suites found agents reporting "45/45 pass" when only 26 actually did — the other 19 quietly never ran the tests that would've said otherwise.
27
+
28
+ Same root cause every time: **the model's confidence and the actual safety of the action are two different variables, and nothing was checking the second one.**
29
+
30
+ So I built the boundary myself. Excited to share **Sensorium** — deterministic safety hooks for Claude Code. 👇
31
+
32
+ ---
33
+
34
+ ## The problem nobody puts in the demo video
35
+
36
+ LLM agents are incredible at writing code. They are also, occasionally, incredible at:
37
+
38
+ - 🔥 running `rm -rf` with a trailing `~/` nobody meant to include
39
+ - 🔥 running `git reset --hard` on your uncommitted work, confidently
40
+ - 🔥 `curl -X DELETE`-ing a resource because the docs made it sound safe
41
+ - 🔥 declaring "all tests pass" without running the ones that don't
42
+ - 🔥 reapplying a stale cached manifest as if it were current state
43
+
44
+ None of this is malice. It's confidence without a checkpoint. And "just review every diff" doesn't scale when the agent is running fifty tool calls a session.
45
+
46
+ ## The insight
47
+
48
+ You don't need a second LLM watching the first one. You need **sensors** — small, deterministic, boring rules that wake up on a specific kind of change, check exactly what they care about, and say yes/no/wait.
49
+
50
+ No vibes. No judgment calls. Pattern matching and policy, all the way down.
51
+
52
+ ```
53
+ Claude wants to use a tool
54
+ → PreToolUse hook
55
+ → Sensorium reads the tool input
56
+ → sensors match
57
+ → allow / block / warn
58
+ → tool executes (or doesn't)
59
+ → PostToolUse hook
60
+ → Sensorium checks the resulting file content
61
+ → writes an audit ledger
62
+ ```
63
+
64
+ ## What this actually catches, out of the box
65
+
66
+ | Protects against | How | Gate |
67
+ |---|---|---|
68
+ | `rm -rf /`, `rm -rf ~`, `dd ... of=/dev/sd*` | `filesystem.wipe` | unconditional block |
69
+ | Bulk delete without a backup | `filesystem.bulk_delete` | needs `backup_exists` + `dry_run_passed` |
70
+ | `git reset --hard`, `git clean -fxd` | `git.destructive` | needs `backup_exists` |
71
+ | `curl -X POST/PUT/DELETE/PATCH` | `external_api.write` | needs a snapshot + rollback plan |
72
+ | `kubectl apply/delete`, `terraform apply/destroy`, `aws ... delete` | `infra.mutation` | needs snapshot + dry-run + rollback |
73
+ | Direct `psql`/`mysql` writes | `db.write` | needs snapshot + rollback plan |
74
+ | Reapplying a stale archive/cache as truth | `data.apply_from_archive` | unconditional block |
75
+ | Skipped tests slipped in quietly | `test_skip_introduced` | warn, shows up in the audit report |
76
+
77
+ `--dry-run` on the command bypasses the gate — sensors check for it explicitly.
78
+
79
+ ## Bring your own rules 🔧
80
+
81
+ This is the part I actually wanted to ship. Your project has opinions Sensorium can't guess — so tell it:
82
+
83
+ ```yaml
84
+ # .sensorium/sensors.yaml
85
+ sensors:
86
+ - name: no_force_push
87
+ description: Block git push --force (plain push still allowed)
88
+ tools: [Bash]
89
+ action: block
90
+ patterns:
91
+ - 'git\s+push\b.*(--force\b|-f\b)'
92
+ unless:
93
+ - '--dry-run'
94
+ message: |
95
+ Blocked: force-push detected. Use --force-with-lease and confirm
96
+ with a human first.
97
+ ```
98
+
99
+ Drop it in, no restart, no config reload — the next tool call picks it up.
100
+
101
+ **Sensor fields:**
102
+
103
+ - `tools` — which Claude Code tools trigger this sensor (`Bash`, `Edit`, `Write`, `MultiEdit`)
104
+ - `on_file_change` — glob patterns for file paths (PostToolUse, checks content)
105
+ - `action` — `block` (exit 2, Claude sees the message) or `warn` (logged, shown in report)
106
+ - `patterns` — regex list matched against the Bash command or file path
107
+ - `unless` — if any of these match, the sensor does not trigger
108
+ - `block_if_contains` — regex matched against file content after an edit
109
+ - `require_contains` — regex that must be present in file content (absence triggers the sensor)
110
+ - `message` — shown to Claude when blocked or warned
111
+
112
+ ## Install (2 minutes, I promise)
113
+
114
+ **Step 1 — the CLI**
115
+
116
+ ```bash
117
+ pipx install agent-sensorium
118
+ # or: pip install agent-sensorium
119
+ ```
120
+
121
+ **Step 2 — wire up Claude Code**
122
+
123
+ ```bash
124
+ cd my-project
125
+ sensorium init claude-code # this project only
126
+ sensorium init claude-code --global # every project
127
+ ```
128
+
129
+ Writes `.claude/settings.json` with the absolute path to the `sensorium` binary. Claude Code picks it up immediately.
130
+
131
+ **Step 3 (optional) — your own rules**
132
+
133
+ ```bash
134
+ mkdir -p .sensorium
135
+ # add .sensorium/sensors.yaml, see above
136
+ ```
137
+
138
+ That's it. Claude Code works exactly as before — Sensorium just quietly rides along on every tool call.
139
+
140
+ ## Receipts, not vibes
141
+
142
+ ```bash
143
+ sensorium report # show session audit log
144
+ sensorium report --clear # show and reset
145
+ ```
146
+
147
+ ```
148
+ === Sensorium Audit Report ===
149
+
150
+ Tools used: 12
151
+ Sensors triggered: 3
152
+ Blocked actions: 2
153
+ File violations: 1
154
+
155
+ --- Blocked Actions ---
156
+ 2026-07-03T10:14:22 [filesystem.wipe] Bash: rm -rf /tmp/old-data
157
+ 2026-07-03T10:17:05 [git.destructive] Bash: git reset --hard origin/main
158
+
159
+ --- File Sensor Violations ---
160
+ 2026-07-03T10:19:11 [full_object_overwrite] src/apply.js
161
+ required: ['delta|changed_fields', 'precondition|current_hash']
162
+
163
+ --- Sensor Activity ---
164
+ external_api.write: 3x
165
+ filesystem.wipe: 2x
166
+ ```
167
+
168
+ Every block, every warning, every proof registered — append-only, in `.sensorium/state.jsonl`. Nothing silently disappears.
169
+
170
+ ## The architecture, for the nerds (me too)
171
+
172
+ Sensorium follows the [State-Delta pattern](https://github.com/kroq86/cursor-global-rules/blob/main/rules/global/State-Delta.mdc):
173
+
174
+ ```
175
+ world change (Claude tool use)
176
+ → typed delta/event (PreToolUse / PostToolUse)
177
+ → matching sensors wake up
178
+ → each sensor selects the narrow context it needs
179
+ → deterministic policy evaluates
180
+ → allow / block / warn
181
+ → ledger records the fact
182
+ ```
183
+
184
+ No broad rescans. No LLM judge. No polling. A sensor declares exactly what it listens for and what invariant it protects — that's the whole contract.
185
+
186
+ ```
187
+ .sensorium/
188
+ state.jsonl # append-only event ledger
189
+ snapshots/ # file snapshots before edits (content-addressed)
190
+ sensors.yaml # your project-specific rules (optional)
191
+ ```
192
+
193
+ ## The honest part
194
+
195
+ This is regex and policy, not a sandbox. It catches the direct, literal case — an agent typing a dangerous command in the open. It is not a defense against something actively trying to route around it (a script file, an interpreter, a clever quote). Self-reported proofs are exactly that — self-reported. Treat it as a seatbelt, not a cage, and you'll use it correctly.
196
+
197
+ ## Hook format reference
198
+
199
+ `sensorium init claude-code` writes this to `.claude/settings.json`:
200
+
201
+ ```json
202
+ {
203
+ "hooks": {
204
+ "PreToolUse": [
205
+ {
206
+ "matcher": "Bash|Edit|Write|MultiEdit",
207
+ "hooks": [{ "type": "command", "command": "/path/to/sensorium hook pretool" }]
208
+ }
209
+ ],
210
+ "PostToolUse": [
211
+ {
212
+ "matcher": "Bash|Edit|Write|MultiEdit",
213
+ "hooks": [{ "type": "command", "command": "/path/to/sensorium hook posttool" }]
214
+ }
215
+ ],
216
+ "Stop": [
217
+ {
218
+ "hooks": [{ "type": "command", "command": "/path/to/sensorium hook stop" }]
219
+ }
220
+ ]
221
+ }
222
+ }
223
+ ```
224
+
225
+ Exit code 2 from `pretool` blocks the tool. Exit 0 allows it.
226
+
227
+ ## License
228
+
229
+ AGPL-3.0. See [LICENSE](LICENSE).
230
+
231
+ ---
232
+
233
+ ## The incidents this is built around
234
+
235
+ Not hypotheticals — these happened, and each one maps directly to a sensor above:
236
+
237
+ - [Coding Agent Horror Stories: The `rm -rf ~/` Incident](https://www.docker.com/blog/coding-agent-horror-stories-the-rm-rf-incident/) — Docker's write-up of the r/ClaudeAI post
238
+ - [Cursor AI coding agent deletes entire production database and backups in nine seconds](https://www.techradar.com/pro/it-took-9-seconds-tech-founder-outlines-how-rogue-claude-powered-ai-tool-wiped-entire-company-database-and-backups-but-says-theres-no-such-thing-as-bad-publicity) — TechRadar
239
+ - [Claude Code's Silent Git Reset](https://dev.to/shuicici/claude-codes-silent-git-reset-what-actually-happened-and-what-it-means-for-ai-dev-tools-3449) — dev.to
240
+ - [Why AI Coding Agents Say All Tests Pass When They Actually Fail](https://docs.bswen.com/blog/2026-06-25-ai-coding-agent-false-positive-failure/) — the 45-task benchmark
241
+
242
+ If you're shipping agents with real filesystem/shell/API access and you're not doing this yet — you're one confidently-wrong tool call away from a bad afternoon.
243
+
244
+ Would love thoughts from anyone else building guardrails for agentic coding tools. 🙏
245
+
246
+ #AIagents #ClaudeCode #DeveloperTools #AgentSafety #OpenSource
@@ -0,0 +1,26 @@
1
+ sensorium/__init__.py,sha256=IkIBcmkhJVNG8xHCzbOF2eetp82wE3cy0Y8nD-Edb7A,180
2
+ sensorium/cli.py,sha256=Cw11JjuUPDlcFB9e6sKqE5zHFYuYZaIHaRfD1djE6a8,5466
3
+ sensorium/report.py,sha256=zECi3VSh4upBoj513gghF-i47272morsCIACxOlCJkM,1773
4
+ sensorium/classifier/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
5
+ sensorium/classifier/engine.py,sha256=L1s5_C23oTzVKNGu2b55lh1SzE2Xg2HwNO2WQ-4B1BQ,6477
6
+ sensorium/classifier/normalizer.py,sha256=mawegIN9jNpKbvgtcx9H7p9cLfTgoFbbke4z4_jpBc4,1683
7
+ sensorium/classifier/rules.yaml,sha256=tPUZpYAWul62O_QpOPMxuSrsRW4482vfbaJUnguhp4U,3284
8
+ sensorium/hooks/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
9
+ sensorium/hooks/posttool.py,sha256=cnKf92zvxCVoiAcUbMCStRZvUNltVmwCGtrbOCNbheM,1868
10
+ sensorium/hooks/pretool.py,sha256=PlovHiUhsVVdt2ka2NwRaLaIIfNF_bq7p1zEHEE4Sjw,8840
11
+ sensorium/hooks/stop.py,sha256=GdAlljcfNSHVD1KW_jNNYc1NFAULiLjr4HGj8MsW9WA,1860
12
+ sensorium/install/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
13
+ sensorium/install/claude_code.py,sha256=w0ix7MjN47PSzKj54CBVq3lY5Q5eScFH9FCz_JE-5Lw,2340
14
+ sensorium/proofs/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
15
+ sensorium/proofs/auto_detect.py,sha256=A5J2xm2gSZ2JlzO55Z8CGU9viYdYb6S4q-CzDtW3r8g,4769
16
+ sensorium/proofs/grant.py,sha256=KrhYqk4KowHfahOADvH4c92-ewQDiqMe_vetmNKe1S8,2658
17
+ sensorium/proofs/registry.py,sha256=ROXhJsshh87tbafrFtWvt8-da99OFFSduHeXubR-k-w,3463
18
+ sensorium/sensors/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
19
+ sensorium/sensors/registry.py,sha256=8dyTMqxcwm4NTfrFpmeEUWz954j6taM1i3KjTAC1XdY,3522
20
+ sensorium/state/__init__.py,sha256=sp9l8WwKc3tsXq9s8qBV6jka5JrrLIWJjCJClkyW8mY,158
21
+ sensorium/state/ledger.py,sha256=SecWnQMslsd95n8nL8ZVwG2YjQMCqeobOxUvHVSpelE,3681
22
+ agent_sensorium-0.1.0.dist-info/METADATA,sha256=cx6GzyYpbh82S4mWjswarO4TId09gmYAUvSVCAKSX1w,9760
23
+ agent_sensorium-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
24
+ agent_sensorium-0.1.0.dist-info/entry_points.txt,sha256=dlyDhhaa7A152SPxHqbB7bfVnQrJpoCiIpciv_nLSQY,48
25
+ agent_sensorium-0.1.0.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
26
+ agent_sensorium-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sensorium = sensorium.cli:cli