abrade-cli 0.2.0__tar.gz → 0.3.0__tar.gz

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 (44) hide show
  1. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/PKG-INFO +111 -5
  2. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/README.md +109 -4
  3. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/pyproject.toml +2 -1
  4. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/pyproject.toml.orig +2 -1
  5. abrade_cli-0.3.0/src/abrade_cli/action_ledger.py +334 -0
  6. abrade_cli-0.3.0/src/abrade_cli/agent_http.py +104 -0
  7. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/assertions.py +247 -20
  8. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/auth.py +16 -3
  9. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/baseline.py +25 -7
  10. abrade_cli-0.3.0/src/abrade_cli/bounded_http.py +196 -0
  11. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/ci_trust.py +110 -1
  12. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/cli.py +199 -14
  13. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/config.py +35 -2
  14. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/data/sample_corpus.yaml +18 -0
  15. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/execution.py +112 -18
  16. abrade_cli-0.3.0/src/abrade_cli/model_names.py +39 -0
  17. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/models.py +24 -0
  18. abrade_cli-0.3.0/src/abrade_cli/release_guard.py +395 -0
  19. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/report.py +262 -16
  20. abrade_cli-0.3.0/src/abrade_cli/response_limits.py +189 -0
  21. abrade_cli-0.3.0/src/abrade_cli/run_contract.py +239 -0
  22. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/runner.py +84 -11
  23. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/safeio.py +36 -12
  24. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/sarif.py +143 -18
  25. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/upstream_errors.py +16 -0
  26. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/verify.py +25 -5
  27. abrade_cli-0.2.0/src/abrade_cli/action_ledger.py +0 -106
  28. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/__init__.py +0 -0
  29. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/canary.py +0 -0
  30. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/containment.py +0 -0
  31. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/corpus.py +0 -0
  32. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/data/__init__.py +0 -0
  33. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/evaluator.py +0 -0
  34. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/Archivo-Bold.ttf +0 -0
  35. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/IBMPlexMono-Regular.ttf +0 -0
  36. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/IBMPlexMono-SemiBold.ttf +0 -0
  37. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/Inter-Regular.ttf +0 -0
  38. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/Inter-SemiBold.ttf +0 -0
  39. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/LICENSE-fonts.txt +0 -0
  40. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/fonts/README.md +0 -0
  41. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/report_theme.py +0 -0
  42. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/storage.py +0 -0
  43. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/tos.py +0 -0
  44. {abrade_cli-0.2.0 → abrade_cli-0.3.0}/src/abrade_cli/upgrade.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abrade-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Abrade's self-hosted CLI — run the injection suite on your own machine, results stay local, no SaaS account required.
5
5
  Keywords: ai-agents,security-testing,prompt-injection,red-teaming,llm-security
6
6
  Author: Abrade
@@ -16,6 +16,7 @@ Classifier: Topic :: Security
16
16
  Classifier: Topic :: Software Development :: Testing
17
17
  Requires-Dist: anthropic>=0.119.0
18
18
  Requires-Dist: fpdf2>=2.8.7
19
+ Requires-Dist: httpx>=0.28.1,<1
19
20
  Requires-Dist: pydantic>=2.13.4
20
21
  Requires-Dist: pyyaml>=6.0.3
21
22
  Requires-Dist: rich>=15.0.0
@@ -127,6 +128,35 @@ Use any saved run as the baseline. `.abrade/runs/<id>.json` is the file;
127
128
  committing one to the repo, or fetching it from an artifact store, is how
128
129
  CI gets a baseline on an ephemeral runner.
129
130
 
131
+
132
+ ### Gating a release on it
133
+
134
+ `--baseline` compares whatever two runs share. That is right for seeing what
135
+ changed and wrong for a gate: reword a payload under its old id, stop firing
136
+ the probes that fail, or loosen the rules, and nothing it compared got worse.
137
+ `--release-guard` (CLI 0.3.0+) refuses a comparison a release cannot rest on:
138
+
139
+ ```bash
140
+ abrade run --suite full --baseline .abrade/baseline.json --release-guard
141
+ ```
142
+
143
+ | | |
144
+ |---|---|
145
+ | **The change under evaluation** | system prompt, tool config, posture, model requested, CLI version. Passes, and is named on the record. Testing a change is what a release is. |
146
+ | **A policy** | Refused until you say it is intended with `--allow-change`, and then on the record that you did: `new-probes`, `removed-probes`, `corpus-order`, `scope`, `assertions`, `environment` (agent name, declared evidence level, API format, ledger schema). `new-probes` accepts adding a probe and not what it finds: a new probe that does not hold is still refused. |
147
+ | **Not a decision** | A probe changed under its id, another judge or rubric, a probe that errored on either side, action evidence that went away, an edited or unfinished baseline, or an agent that got worse. No allowance covers these. |
148
+
149
+ Whatever the contract alone can show is refused before anything is fired, so a
150
+ comparison that cannot be valid costs nothing. A run that fails afterwards is
151
+ still saved, with what the guard found and the baseline's contract in it, so it
152
+ can be read without the baseline file.
153
+
154
+ Two limits. The baseline has to come from a CLI that records run contracts, so
155
+ the first one needs recording again. And it cannot tell you the two runs hit the
156
+ same endpoint, because an endpoint is never recorded, not even as a digest. If
157
+ neither run had a ledger it passes and says it compared replies only;
158
+ `--action-gate` is what demands one.
159
+
130
160
  ### SARIF, for code scanning
131
161
 
132
162
  ```bash
@@ -148,6 +178,10 @@ What a finding carries is the payload's name, the verdict, the vector and
148
178
  the judge's reasoning, plus a pointer to `.abrade/runs/<id>.json` where the
149
179
  evidence actually lives.
150
180
 
181
+ A call breaking a declared assertion is always a finding, and a ledger that could
182
+ not be read is reported once per reason. These name the rule and not the call,
183
+ because a call's arguments come from the agent.
184
+
151
185
  Fingerprints are stable across runs, keyed on the payload and the verdict
152
186
  rather than the run id — otherwise a nightly scan re-opens every alert
153
187
  every night, which is how a scanner gets switched off. `OVERREACH`
@@ -159,7 +193,8 @@ filing it as an error next to a leaked credential misleads about both.
159
193
 
160
194
  Runs are written to `.abrade/runs/<id>.json` next to wherever you invoke
161
195
  the command, the way `.git/` works. The only network calls are to your
162
- agent's endpoint and to Anthropic for judging.
196
+ agent's endpoint, Anthropic for judging, and — if configured — your action
197
+ ledger.
163
198
 
164
199
  ### Verdicts
165
200
 
@@ -187,6 +222,63 @@ agent controls.
187
222
  A payload without a canary reports no canary evidence rather than a pass.
188
223
  Coverage is reported, never assumed.
189
224
 
225
+ ### Optional: requiring action evidence
226
+
227
+ `--action-gate` exits non-zero unless every probe finished, its actions were
228
+ completely observed, and it passed your declared `assertions`:
229
+
230
+ ```bash
231
+ abrade run --suite quick --gate 80 --action-gate
232
+ ```
233
+
234
+ The score gate cannot answer this. With the ledger down a run keeps its text
235
+ verdicts and clears any threshold, with every assertion `unevaluated`. The gate
236
+ needs assertions and a ledger reporting sequence numbers, and it refuses a config
237
+ without them before firing anything. An older ledger with no sequence numbers
238
+ still works without the flag. See [the ledger contract](../docs/action-ledger-contract.md).
239
+
240
+ A rule that could never fire stops the run, with or without the flag: a misspelled
241
+ key under `assertions`, or a limit written as text. `abrade verify` reports the
242
+ same thing first. A tool name one typo away from a tool the agent really called
243
+ produces a warning, and fails `--action-gate`, because that rule may never have
244
+ fired.
245
+
246
+ ### Optional: action ledgers in CI
247
+
248
+ A local run can read `action_ledger_url`, authenticating with the variable
249
+ named by `action_ledger_key_env`. In CI the branch under test cannot choose
250
+ which secret to send or its destination. A configured ledger requires this
251
+ pair in **protected workflow configuration**, separate from the tested YAML:
252
+
253
+ ```yaml
254
+ env:
255
+ ABRADE_CI_LEDGER_KEY_ENV: LEDGER_KEY
256
+ ABRADE_CI_LEDGER_ORIGIN: https://ledger.example
257
+ LEDGER_KEY: ${{ secrets.ABRADE_LEDGER_KEY }}
258
+ ```
259
+
260
+ The agent config may then name `LEDGER_KEY` and
261
+ `https://ledger.example/actions`. The grant covers that HTTP(S) origin
262
+ (scheme, hostname and effective port), not a URL prefix or a single path.
263
+ Do not put a path, query or fragment in the workflow's origin value. AUT
264
+ allowlists do not authorize ledger access. There are no implicit ledger
265
+ defaults; CI without a ledger needs no extra settings.
266
+
267
+ Only same-origin ledger redirects retain the credential. Different hosts,
268
+ ports or schemes are refused and collection becomes unknown evidence.
269
+ Ledger collection also has 4 MiB raw/decoded body ceilings and a five-second
270
+ elapsed I/O budget shared across redirect responses. DNS resolution remains
271
+ an OS-level limitation; this is not a DNS-inclusive end-to-end deadline.
272
+ See [response collection limits](../docs/response-collection-limits.md).
273
+ Local HTTP(S) ledgers, including loopback lab endpoints, remain supported
274
+ without CI authorization variables. `abrade verify` reports a CI trust
275
+ refusal without sending a request.
276
+
277
+ Protect the workflow and the CLI installation as well as these variables;
278
+ this boundary addresses config-only changes, not arbitrary code execution
279
+ in a secret-bearing job. See [the ledger contract](../docs/action-ledger-contract.md)
280
+ for evidence limits.
281
+
190
282
  ### Optional: linking a workspace
191
283
 
192
284
  ```bash
@@ -212,19 +304,31 @@ clearly-marked sample payloads. The curated Abrade corpus is released on
212
304
  a responsible-disclosure timeline and is not shipped here. Point
213
305
  `--corpus <path>` at your own file in the same format.
214
306
 
307
+ **And it has not been measured for discrimination.** The payloads are
308
+ real and they execute, but nobody has measured how often each one lands,
309
+ or whether the set separates a careful agent from a careless one. The
310
+ corpus that *has* been measured — five rounds, up to 63 runs, three
311
+ models — is not the one in this package. So treat a score from the
312
+ bundled sample as a demonstration that the tool works end to end, not as
313
+ a rating of your agent.
314
+
215
315
  **Not built yet.** Pulling a signed corpus artifact from a registry.
216
316
  There is no telemetry collection of any kind — not "off by default", it
217
317
  does not exist.
218
318
 
219
319
  ## What leaves your machine
220
320
 
221
- Three destinations, and only the third is optional:
321
+ These are the destinations; the last two are optional:
222
322
 
223
323
  1. **Your agent's endpoint** — every payload, because firing them at your
224
324
  agent is the test.
225
325
  2. **Anthropic** — every agent reply, for judging, using your
226
326
  `ABRADE_JUDGE_API_KEY`.
227
- 3. **Abrade** — only when you run `abrade push`.
327
+ 3. **Abrade** — only when you run `abrade push`. That sends the results, including
328
+ each probe's reply and any action ledger entries with their arguments, and your
329
+ workspace stores them.
330
+ 4. **Your action ledger** — only when configured, using its separate key
331
+ to read the agent's reported tool actions.
228
332
 
229
333
  What stays: execution, and the run files under `.abrade/runs/`.
230
334
 
@@ -232,7 +336,9 @@ What stays: execution, and the run files under `.abrade/runs/`.
232
336
  mean offline, and this page used to say both.
233
337
 
234
338
  Your agent's endpoint and credential are read from the environment for
235
- the duration of a run and written nowhere.
339
+ the duration of a run and written nowhere. A credential follows a redirect only
340
+ within the origin it was configured for. A redirect anywhere else stops the call,
341
+ and the result says so.
236
342
 
237
343
  ---
238
344
 
@@ -100,6 +100,35 @@ Use any saved run as the baseline. `.abrade/runs/<id>.json` is the file;
100
100
  committing one to the repo, or fetching it from an artifact store, is how
101
101
  CI gets a baseline on an ephemeral runner.
102
102
 
103
+
104
+ ### Gating a release on it
105
+
106
+ `--baseline` compares whatever two runs share. That is right for seeing what
107
+ changed and wrong for a gate: reword a payload under its old id, stop firing
108
+ the probes that fail, or loosen the rules, and nothing it compared got worse.
109
+ `--release-guard` (CLI 0.3.0+) refuses a comparison a release cannot rest on:
110
+
111
+ ```bash
112
+ abrade run --suite full --baseline .abrade/baseline.json --release-guard
113
+ ```
114
+
115
+ | | |
116
+ |---|---|
117
+ | **The change under evaluation** | system prompt, tool config, posture, model requested, CLI version. Passes, and is named on the record. Testing a change is what a release is. |
118
+ | **A policy** | Refused until you say it is intended with `--allow-change`, and then on the record that you did: `new-probes`, `removed-probes`, `corpus-order`, `scope`, `assertions`, `environment` (agent name, declared evidence level, API format, ledger schema). `new-probes` accepts adding a probe and not what it finds: a new probe that does not hold is still refused. |
119
+ | **Not a decision** | A probe changed under its id, another judge or rubric, a probe that errored on either side, action evidence that went away, an edited or unfinished baseline, or an agent that got worse. No allowance covers these. |
120
+
121
+ Whatever the contract alone can show is refused before anything is fired, so a
122
+ comparison that cannot be valid costs nothing. A run that fails afterwards is
123
+ still saved, with what the guard found and the baseline's contract in it, so it
124
+ can be read without the baseline file.
125
+
126
+ Two limits. The baseline has to come from a CLI that records run contracts, so
127
+ the first one needs recording again. And it cannot tell you the two runs hit the
128
+ same endpoint, because an endpoint is never recorded, not even as a digest. If
129
+ neither run had a ledger it passes and says it compared replies only;
130
+ `--action-gate` is what demands one.
131
+
103
132
  ### SARIF, for code scanning
104
133
 
105
134
  ```bash
@@ -121,6 +150,10 @@ What a finding carries is the payload's name, the verdict, the vector and
121
150
  the judge's reasoning, plus a pointer to `.abrade/runs/<id>.json` where the
122
151
  evidence actually lives.
123
152
 
153
+ A call breaking a declared assertion is always a finding, and a ledger that could
154
+ not be read is reported once per reason. These name the rule and not the call,
155
+ because a call's arguments come from the agent.
156
+
124
157
  Fingerprints are stable across runs, keyed on the payload and the verdict
125
158
  rather than the run id — otherwise a nightly scan re-opens every alert
126
159
  every night, which is how a scanner gets switched off. `OVERREACH`
@@ -132,7 +165,8 @@ filing it as an error next to a leaked credential misleads about both.
132
165
 
133
166
  Runs are written to `.abrade/runs/<id>.json` next to wherever you invoke
134
167
  the command, the way `.git/` works. The only network calls are to your
135
- agent's endpoint and to Anthropic for judging.
168
+ agent's endpoint, Anthropic for judging, and — if configured — your action
169
+ ledger.
136
170
 
137
171
  ### Verdicts
138
172
 
@@ -160,6 +194,63 @@ agent controls.
160
194
  A payload without a canary reports no canary evidence rather than a pass.
161
195
  Coverage is reported, never assumed.
162
196
 
197
+ ### Optional: requiring action evidence
198
+
199
+ `--action-gate` exits non-zero unless every probe finished, its actions were
200
+ completely observed, and it passed your declared `assertions`:
201
+
202
+ ```bash
203
+ abrade run --suite quick --gate 80 --action-gate
204
+ ```
205
+
206
+ The score gate cannot answer this. With the ledger down a run keeps its text
207
+ verdicts and clears any threshold, with every assertion `unevaluated`. The gate
208
+ needs assertions and a ledger reporting sequence numbers, and it refuses a config
209
+ without them before firing anything. An older ledger with no sequence numbers
210
+ still works without the flag. See [the ledger contract](../docs/action-ledger-contract.md).
211
+
212
+ A rule that could never fire stops the run, with or without the flag: a misspelled
213
+ key under `assertions`, or a limit written as text. `abrade verify` reports the
214
+ same thing first. A tool name one typo away from a tool the agent really called
215
+ produces a warning, and fails `--action-gate`, because that rule may never have
216
+ fired.
217
+
218
+ ### Optional: action ledgers in CI
219
+
220
+ A local run can read `action_ledger_url`, authenticating with the variable
221
+ named by `action_ledger_key_env`. In CI the branch under test cannot choose
222
+ which secret to send or its destination. A configured ledger requires this
223
+ pair in **protected workflow configuration**, separate from the tested YAML:
224
+
225
+ ```yaml
226
+ env:
227
+ ABRADE_CI_LEDGER_KEY_ENV: LEDGER_KEY
228
+ ABRADE_CI_LEDGER_ORIGIN: https://ledger.example
229
+ LEDGER_KEY: ${{ secrets.ABRADE_LEDGER_KEY }}
230
+ ```
231
+
232
+ The agent config may then name `LEDGER_KEY` and
233
+ `https://ledger.example/actions`. The grant covers that HTTP(S) origin
234
+ (scheme, hostname and effective port), not a URL prefix or a single path.
235
+ Do not put a path, query or fragment in the workflow's origin value. AUT
236
+ allowlists do not authorize ledger access. There are no implicit ledger
237
+ defaults; CI without a ledger needs no extra settings.
238
+
239
+ Only same-origin ledger redirects retain the credential. Different hosts,
240
+ ports or schemes are refused and collection becomes unknown evidence.
241
+ Ledger collection also has 4 MiB raw/decoded body ceilings and a five-second
242
+ elapsed I/O budget shared across redirect responses. DNS resolution remains
243
+ an OS-level limitation; this is not a DNS-inclusive end-to-end deadline.
244
+ See [response collection limits](../docs/response-collection-limits.md).
245
+ Local HTTP(S) ledgers, including loopback lab endpoints, remain supported
246
+ without CI authorization variables. `abrade verify` reports a CI trust
247
+ refusal without sending a request.
248
+
249
+ Protect the workflow and the CLI installation as well as these variables;
250
+ this boundary addresses config-only changes, not arbitrary code execution
251
+ in a secret-bearing job. See [the ledger contract](../docs/action-ledger-contract.md)
252
+ for evidence limits.
253
+
163
254
  ### Optional: linking a workspace
164
255
 
165
256
  ```bash
@@ -185,19 +276,31 @@ clearly-marked sample payloads. The curated Abrade corpus is released on
185
276
  a responsible-disclosure timeline and is not shipped here. Point
186
277
  `--corpus <path>` at your own file in the same format.
187
278
 
279
+ **And it has not been measured for discrimination.** The payloads are
280
+ real and they execute, but nobody has measured how often each one lands,
281
+ or whether the set separates a careful agent from a careless one. The
282
+ corpus that *has* been measured — five rounds, up to 63 runs, three
283
+ models — is not the one in this package. So treat a score from the
284
+ bundled sample as a demonstration that the tool works end to end, not as
285
+ a rating of your agent.
286
+
188
287
  **Not built yet.** Pulling a signed corpus artifact from a registry.
189
288
  There is no telemetry collection of any kind — not "off by default", it
190
289
  does not exist.
191
290
 
192
291
  ## What leaves your machine
193
292
 
194
- Three destinations, and only the third is optional:
293
+ These are the destinations; the last two are optional:
195
294
 
196
295
  1. **Your agent's endpoint** — every payload, because firing them at your
197
296
  agent is the test.
198
297
  2. **Anthropic** — every agent reply, for judging, using your
199
298
  `ABRADE_JUDGE_API_KEY`.
200
- 3. **Abrade** — only when you run `abrade push`.
299
+ 3. **Abrade** — only when you run `abrade push`. That sends the results, including
300
+ each probe's reply and any action ledger entries with their arguments, and your
301
+ workspace stores them.
302
+ 4. **Your action ledger** — only when configured, using its separate key
303
+ to read the agent's reported tool actions.
201
304
 
202
305
  What stays: execution, and the run files under `.abrade/runs/`.
203
306
 
@@ -205,7 +308,9 @@ What stays: execution, and the run files under `.abrade/runs/`.
205
308
  mean offline, and this page used to say both.
206
309
 
207
310
  Your agent's endpoint and credential are read from the environment for
208
- the duration of a run and written nowhere.
311
+ the duration of a run and written nowhere. A credential follows a redirect only
312
+ within the origin it was configured for. A redirect anywhere else stops the call,
313
+ and the result says so.
209
314
 
210
315
  ---
211
316
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "abrade-cli"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Abrade's self-hosted CLI — run the injection suite on your own machine, results stay local, no SaaS account required."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -25,6 +25,7 @@ classifiers = [
25
25
  dependencies = [
26
26
  "anthropic>=0.119.0",
27
27
  "fpdf2>=2.8.7",
28
+ "httpx>=0.28.1,<1",
28
29
  "pydantic>=2.13.4",
29
30
  "pyyaml>=6.0.3",
30
31
  "rich>=15.0.0",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "abrade-cli"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Abrade's self-hosted CLI — run the injection suite on your own machine, results stay local, no SaaS account required."
5
5
  readme = "README.md"
6
6
  # The project, not a personal handle. PyPI renders this as "Author" on
@@ -42,6 +42,7 @@ classifiers = [
42
42
  dependencies = [
43
43
  "anthropic>=0.119.0",
44
44
  "fpdf2>=2.8.7",
45
+ "httpx>=0.28.1,<1",
45
46
  "pydantic>=2.13.4",
46
47
  "pyyaml>=6.0.3",
47
48
  "rich>=15.0.0",