toolgovern-cli 0.1.2__tar.gz → 0.1.3__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 (55) hide show
  1. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/PKG-INFO +81 -3
  2. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/README.md +79 -1
  3. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/pyproject.toml +2 -2
  4. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/.gitignore +0 -0
  5. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/LICENSE +0 -0
  6. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/__init__.py +0 -0
  7. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/approval/__init__.py +0 -0
  8. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/approval/pending_registry.py +0 -0
  9. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/__init__.py +0 -0
  10. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/credential_access.py +0 -0
  11. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/cross_agent_inheritance.py +0 -0
  12. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/filesystem_scope.py +0 -0
  13. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/index.py +0 -0
  14. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/information_flow.py +0 -0
  15. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/network_egress.py +0 -0
  16. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/shell_risk.py +0 -0
  17. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/classifier/util.py +0 -0
  18. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/cli.py +0 -0
  19. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/mcp_trust/__init__.py +0 -0
  20. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/middleware/__init__.py +0 -0
  21. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/middleware/idempotency_cache.py +0 -0
  22. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/middleware/on_tool_call.py +0 -0
  23. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/policy/__init__.py +0 -0
  24. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/policy/load_policy.py +0 -0
  25. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/policy/validate_policy.py +0 -0
  26. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/py.typed +0 -0
  27. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/scoping/__init__.py +0 -0
  28. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/scoping/inheritance_enforcer.py +0 -0
  29. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/scoping/scope_declaration.py +0 -0
  30. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/shared/__init__.py +0 -0
  31. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/shared/paths.py +0 -0
  32. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/trace/__init__.py +0 -0
  33. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/trace/canonical_json.py +0 -0
  34. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/trace/trace_reader.py +0 -0
  35. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/trace/trace_writer.py +0 -0
  36. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/src/toolgovern/types.py +0 -0
  37. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/__init__.py +0 -0
  38. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/conftest.py +0 -0
  39. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_credential_access.py +0 -0
  40. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_cross_agent_inheritance.py +0 -0
  41. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_filesystem_scope.py +0 -0
  42. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_index.py +0 -0
  43. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_information_flow.py +0 -0
  44. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_network_egress.py +0 -0
  45. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_classifier_shell_risk.py +0 -0
  46. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_cli.py +0 -0
  47. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_mcp_trust.py +0 -0
  48. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_middleware_on_tool_call.py +0 -0
  49. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_pending_registry.py +0 -0
  50. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_policy.py +0 -0
  51. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_scoping_inheritance_enforcer.py +0 -0
  52. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_scoping_scope_declaration.py +0 -0
  53. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_trace_canonical_json.py +0 -0
  54. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_trace_reader.py +0 -0
  55. {toolgovern_cli-0.1.2 → toolgovern_cli-0.1.3}/tests/test_trace_writer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: toolgovern-cli
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Runtime governance middleware for AI agent tool calls -- gate shell, filesystem, network, and credential access before a tool executes.
5
5
  Project-URL: Homepage, https://github.com/RudrenduPaul/toolgovern
6
6
  Project-URL: Repository, https://github.com/RudrenduPaul/toolgovern
@@ -12,7 +12,7 @@ Project-URL: Author - Sourav Nandy, https://github.com/Sourav-nandy-ai
12
12
  Author: Rudrendu Paul, Sourav Nandy
13
13
  License-Expression: Apache-2.0
14
14
  License-File: LICENSE
15
- Keywords: agent-governance,ai-agents,audit-trail,cli,mcp,runtime-security,security,tool-calling
15
+ Keywords: agent-governance,ai-agents,audit-trail,cli,mcp,policy-enforcement,runtime-security,scope-narrowing,security,tool-calling
16
16
  Classifier: Development Status :: 3 - Alpha
17
17
  Classifier: Environment :: Console
18
18
  Classifier: Intended Audience :: Developers
@@ -259,6 +259,35 @@ from toolgovern import (
259
259
  )
260
260
  ```
261
261
 
262
+ ## How it compares to other agent governance projects
263
+
264
+ Same facts as the [project README's full comparison
265
+ table](https://github.com/RudrenduPaul/toolgovern#how-it-compares-to-other-agent-governance-projects)
266
+ -- condensed here to the rows that matter most for picking a package, not re-derived. The "Rules
267
+ out of the box" row below is 36, not 35, because this Python port folds the DNS-resolution check
268
+ (`TG03-dns-resolves-private`) directly into its one synchronous `classify()` instead of needing a
269
+ separate async entry point -- see [What it does](#what-it-does) above. Every other row applies
270
+ equally to both the TypeScript and Python distributions.
271
+
272
+ | | **toolgovern** | [Microsoft Agent Governance Toolkit](https://github.com/microsoft/agent-governance-toolkit) | [NVIDIA NeMo Relay](https://github.com/NVIDIA/NeMo-Relay) | [LangGraph human-in-the-loop](https://docs.langchain.com/oss/python/langchain/human-in-the-loop) |
273
+ | -------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
274
+ | What it actually gates | Tool calls, pre-execution, against a built-in rule set | Tool calls, messages, and delegation, pre-execution, against policy you author (YAML/OPA/Cedar) | Tool and LLM calls via pre-tool hooks -- coverage depends on the host agent | A single tool call, paused for a human decision -- no automated risk classification |
275
+ | Rules out of the box | 36 (this Python port), across 6 categories, zero config | None shipped -- you write the policy | None shipped -- pre-tool hooks call your own logic, not a built-in classifier | None -- you decide per call |
276
+ | Per-agent scope narrowing | Yes -- a sub-agent can never exceed its coordinator's granted scope | Yes -- documented delegation-chain narrowing and a 4-ring privilege model | Not publicly documented | No |
277
+ | Tamper-evident audit trail | Yes -- signed, hash-chained local JSONL | Yes -- Merkle-audit-backed, 157 conformance tests just for the audit layer | No -- raw JSONL trajectory export (ATOF/ATIF format), not signed | No |
278
+ | Hosted component required | No, never | No -- self-hosted by design, Azure integration is optional | No -- local CLI gateway | No for the OSS library; LangGraph's own hosted server runtime is separately licensed |
279
+ | License | Apache 2.0 | MIT | Apache 2.0 | MIT |
280
+
281
+ Two things worth repeating from the full narrative rather than leaving implicit: Microsoft's
282
+ Agent Governance Toolkit already matches or exceeds this project on scoping and audit-trail
283
+ maturity (a formal delegation-chain spec, 157 conformance tests just for its audit layer) -- this
284
+ table is not a claim that toolgovern beats AGT. And NeMo Relay / LangGraph HITL are doing a
285
+ genuinely different job, not a weaker version of the same one -- listing them here is about scope,
286
+ not a claim of superiority at the task each of them is actually built for. Read the [full
287
+ comparison and both honest
288
+ caveats](https://github.com/RudrenduPaul/toolgovern#how-it-compares-to-other-agent-governance-projects)
289
+ in the project README before deciding what you need.
290
+
262
291
  ## CLI
263
292
 
264
293
  ```bash
@@ -322,6 +351,56 @@ pytest
322
351
 
323
352
  Report a vulnerability per the project's [`SECURITY.md`](https://github.com/RudrenduPaul/toolgovern/blob/main/SECURITY.md); please don't open a public issue for one.
324
353
 
354
+ ## FAQ
355
+
356
+ **What does toolgovern do?**
357
+ It's a runtime gate that checks every tool call an AI agent makes -- shell, filesystem, network,
358
+ credential access -- against a 36-rule classifier before the call executes, not after.
359
+ `govern_tool()` wraps any `ToolDefinition(name, execute)` you already have and runs each call
360
+ through the classifier, the per-agent scope registry, and (if wired in) the signed trace writer
361
+ before your real `execute()` ever fires. See [Why this exists](#why-this-exists) and [What it
362
+ does](#what-it-does) above for the full case.
363
+
364
+ **How does this Python package differ from the npm package, if at all?**
365
+ Functionally, barely. It ships the same 36-rule classifier (the npm/TypeScript package runs 35
366
+ rules synchronously plus one additional async-only DNS-resolution rule, landing at 36 checks total
367
+ through its `classifyAsync()` path; this Python port folds that same DNS check into its one
368
+ synchronous `classify()` instead, so it's 36 either way), the same intersection-only scope
369
+ registry, the same durable approval registry, the same MCP-server trust boundary, and the same
370
+ signed trace format -- a genuine Python port, not a wrapper around the Node binary. Two real gaps
371
+ today: `toolgovern-cli init [oma|langgraph]` (the npm CLI's TypeScript integration-file scaffolder)
372
+ isn't ported, since it generates a `.ts` file importing JS/TS-only packages; and the two npm-only
373
+ integration packages (`toolgovern-integration-oma`, `toolgovern-integration-langgraph` for
374
+ LangGraph.js) have no Python equivalent by design -- wire `govern_tool()` directly into your
375
+ Python framework's own call site instead. See [CLI](#cli) and [Framework
376
+ integrations](#framework-integrations) above.
377
+
378
+ **Does it need API keys or an account?**
379
+ No. Nothing in this package calls out to a hosted service. No call payload, argument, trace
380
+ content, or policy leaves your process unless code you write sends it somewhere -- there's no
381
+ server dependency, no account, and nothing to sign up for.
382
+
383
+ **Is it safe to run -- does an `allow` decision mean a tool call is safe?**
384
+ Running the package itself is safe: it's a local, in-process classifier that makes no network
385
+ calls of its own (the one exception, `TG03-dns-resolves-private`, only performs a DNS lookup of an
386
+ argument value your own tool call passes it). But an `allow` decision is not a safety guarantee --
387
+ it means the call was checked against the current 36-rule set and nothing fired.
388
+ [`docs/security-model.md`](https://github.com/RudrenduPaul/toolgovern/blob/main/docs/security-model.md)
389
+ in the main repo documents exactly what the classifier does and doesn't catch, including disclosed
390
+ obfuscation techniques it can still miss.
391
+
392
+ **How do I use it from an agent?**
393
+ Five real Python framework integrations exist in the main repo -- LangGraph (using the real
394
+ `wrap_tool_call` `ToolNode` parameter), CrewAI, AutoGen, Microsoft Agent Framework, and the Claude
395
+ Agent SDK (using its real `PreToolUse` hook) -- each installable from source (none are published to
396
+ PyPI yet). For a framework without a dedicated integration, wrap your own tool definitions with
397
+ `govern_tool()` directly at whatever call site your framework dispatches tool calls from. See
398
+ [Framework integrations](#framework-integrations) above for install commands and worked examples.
399
+
400
+ **Is there a hosted version of toolgovern?**
401
+ No. Everything that exists today is in the GitHub repository, Apache 2.0, self-hosted only, for
402
+ both the Python and TypeScript distributions.
403
+
325
404
  ## Links
326
405
 
327
406
  - [GitHub repository](https://github.com/RudrenduPaul/toolgovern)
@@ -335,4 +414,3 @@ Report a vulnerability per the project's [`SECURITY.md`](https://github.com/Rudr
335
414
  ## License
336
415
 
337
416
  Apache 2.0 -- see [LICENSE](../LICENSE).
338
-
@@ -222,6 +222,35 @@ from toolgovern import (
222
222
  )
223
223
  ```
224
224
 
225
+ ## How it compares to other agent governance projects
226
+
227
+ Same facts as the [project README's full comparison
228
+ table](https://github.com/RudrenduPaul/toolgovern#how-it-compares-to-other-agent-governance-projects)
229
+ -- condensed here to the rows that matter most for picking a package, not re-derived. The "Rules
230
+ out of the box" row below is 36, not 35, because this Python port folds the DNS-resolution check
231
+ (`TG03-dns-resolves-private`) directly into its one synchronous `classify()` instead of needing a
232
+ separate async entry point -- see [What it does](#what-it-does) above. Every other row applies
233
+ equally to both the TypeScript and Python distributions.
234
+
235
+ | | **toolgovern** | [Microsoft Agent Governance Toolkit](https://github.com/microsoft/agent-governance-toolkit) | [NVIDIA NeMo Relay](https://github.com/NVIDIA/NeMo-Relay) | [LangGraph human-in-the-loop](https://docs.langchain.com/oss/python/langchain/human-in-the-loop) |
236
+ | -------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
237
+ | What it actually gates | Tool calls, pre-execution, against a built-in rule set | Tool calls, messages, and delegation, pre-execution, against policy you author (YAML/OPA/Cedar) | Tool and LLM calls via pre-tool hooks -- coverage depends on the host agent | A single tool call, paused for a human decision -- no automated risk classification |
238
+ | Rules out of the box | 36 (this Python port), across 6 categories, zero config | None shipped -- you write the policy | None shipped -- pre-tool hooks call your own logic, not a built-in classifier | None -- you decide per call |
239
+ | Per-agent scope narrowing | Yes -- a sub-agent can never exceed its coordinator's granted scope | Yes -- documented delegation-chain narrowing and a 4-ring privilege model | Not publicly documented | No |
240
+ | Tamper-evident audit trail | Yes -- signed, hash-chained local JSONL | Yes -- Merkle-audit-backed, 157 conformance tests just for the audit layer | No -- raw JSONL trajectory export (ATOF/ATIF format), not signed | No |
241
+ | Hosted component required | No, never | No -- self-hosted by design, Azure integration is optional | No -- local CLI gateway | No for the OSS library; LangGraph's own hosted server runtime is separately licensed |
242
+ | License | Apache 2.0 | MIT | Apache 2.0 | MIT |
243
+
244
+ Two things worth repeating from the full narrative rather than leaving implicit: Microsoft's
245
+ Agent Governance Toolkit already matches or exceeds this project on scoping and audit-trail
246
+ maturity (a formal delegation-chain spec, 157 conformance tests just for its audit layer) -- this
247
+ table is not a claim that toolgovern beats AGT. And NeMo Relay / LangGraph HITL are doing a
248
+ genuinely different job, not a weaker version of the same one -- listing them here is about scope,
249
+ not a claim of superiority at the task each of them is actually built for. Read the [full
250
+ comparison and both honest
251
+ caveats](https://github.com/RudrenduPaul/toolgovern#how-it-compares-to-other-agent-governance-projects)
252
+ in the project README before deciding what you need.
253
+
225
254
  ## CLI
226
255
 
227
256
  ```bash
@@ -285,6 +314,56 @@ pytest
285
314
 
286
315
  Report a vulnerability per the project's [`SECURITY.md`](https://github.com/RudrenduPaul/toolgovern/blob/main/SECURITY.md); please don't open a public issue for one.
287
316
 
317
+ ## FAQ
318
+
319
+ **What does toolgovern do?**
320
+ It's a runtime gate that checks every tool call an AI agent makes -- shell, filesystem, network,
321
+ credential access -- against a 36-rule classifier before the call executes, not after.
322
+ `govern_tool()` wraps any `ToolDefinition(name, execute)` you already have and runs each call
323
+ through the classifier, the per-agent scope registry, and (if wired in) the signed trace writer
324
+ before your real `execute()` ever fires. See [Why this exists](#why-this-exists) and [What it
325
+ does](#what-it-does) above for the full case.
326
+
327
+ **How does this Python package differ from the npm package, if at all?**
328
+ Functionally, barely. It ships the same 36-rule classifier (the npm/TypeScript package runs 35
329
+ rules synchronously plus one additional async-only DNS-resolution rule, landing at 36 checks total
330
+ through its `classifyAsync()` path; this Python port folds that same DNS check into its one
331
+ synchronous `classify()` instead, so it's 36 either way), the same intersection-only scope
332
+ registry, the same durable approval registry, the same MCP-server trust boundary, and the same
333
+ signed trace format -- a genuine Python port, not a wrapper around the Node binary. Two real gaps
334
+ today: `toolgovern-cli init [oma|langgraph]` (the npm CLI's TypeScript integration-file scaffolder)
335
+ isn't ported, since it generates a `.ts` file importing JS/TS-only packages; and the two npm-only
336
+ integration packages (`toolgovern-integration-oma`, `toolgovern-integration-langgraph` for
337
+ LangGraph.js) have no Python equivalent by design -- wire `govern_tool()` directly into your
338
+ Python framework's own call site instead. See [CLI](#cli) and [Framework
339
+ integrations](#framework-integrations) above.
340
+
341
+ **Does it need API keys or an account?**
342
+ No. Nothing in this package calls out to a hosted service. No call payload, argument, trace
343
+ content, or policy leaves your process unless code you write sends it somewhere -- there's no
344
+ server dependency, no account, and nothing to sign up for.
345
+
346
+ **Is it safe to run -- does an `allow` decision mean a tool call is safe?**
347
+ Running the package itself is safe: it's a local, in-process classifier that makes no network
348
+ calls of its own (the one exception, `TG03-dns-resolves-private`, only performs a DNS lookup of an
349
+ argument value your own tool call passes it). But an `allow` decision is not a safety guarantee --
350
+ it means the call was checked against the current 36-rule set and nothing fired.
351
+ [`docs/security-model.md`](https://github.com/RudrenduPaul/toolgovern/blob/main/docs/security-model.md)
352
+ in the main repo documents exactly what the classifier does and doesn't catch, including disclosed
353
+ obfuscation techniques it can still miss.
354
+
355
+ **How do I use it from an agent?**
356
+ Five real Python framework integrations exist in the main repo -- LangGraph (using the real
357
+ `wrap_tool_call` `ToolNode` parameter), CrewAI, AutoGen, Microsoft Agent Framework, and the Claude
358
+ Agent SDK (using its real `PreToolUse` hook) -- each installable from source (none are published to
359
+ PyPI yet). For a framework without a dedicated integration, wrap your own tool definitions with
360
+ `govern_tool()` directly at whatever call site your framework dispatches tool calls from. See
361
+ [Framework integrations](#framework-integrations) above for install commands and worked examples.
362
+
363
+ **Is there a hosted version of toolgovern?**
364
+ No. Everything that exists today is in the GitHub repository, Apache 2.0, self-hosted only, for
365
+ both the Python and TypeScript distributions.
366
+
288
367
  ## Links
289
368
 
290
369
  - [GitHub repository](https://github.com/RudrenduPaul/toolgovern)
@@ -298,4 +377,3 @@ Report a vulnerability per the project's [`SECURITY.md`](https://github.com/Rudr
298
377
  ## License
299
378
 
300
379
  Apache 2.0 -- see [LICENSE](../LICENSE).
301
-
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "toolgovern-cli"
7
- version = "0.1.2"
7
+ version = "0.1.3"
8
8
  description = "Runtime governance middleware for AI agent tool calls -- gate shell, filesystem, network, and credential access before a tool executes."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -13,7 +13,7 @@ authors = [
13
13
  { name = "Rudrendu Paul" },
14
14
  { name = "Sourav Nandy" },
15
15
  ]
16
- keywords = ["security", "ai-agents", "agent-governance", "tool-calling", "runtime-security", "audit-trail", "cli", "mcp"]
16
+ keywords = ["security", "ai-agents", "agent-governance", "tool-calling", "runtime-security", "audit-trail", "cli", "mcp", "policy-enforcement", "scope-narrowing"]
17
17
  classifiers = [
18
18
  "Development Status :: 3 - Alpha",
19
19
  "Environment :: Console",
File without changes