tweek 0.2.1__tar.gz → 0.3.1__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 (171) hide show
  1. tweek-0.3.1/NOTICE +199 -0
  2. {tweek-0.2.1 → tweek-0.3.1}/PKG-INFO +22 -15
  3. {tweek-0.2.1 → tweek-0.3.1}/README.md +17 -14
  4. {tweek-0.2.1 → tweek-0.3.1}/pyproject.toml +23 -2
  5. {tweek-0.2.1 → tweek-0.3.1}/tests/test_cli.py +28 -28
  6. {tweek-0.2.1 → tweek-0.3.1}/tests/test_cli_helpers.py +11 -11
  7. tweek-0.3.1/tests/test_config_models.py +1000 -0
  8. {tweek-0.2.1 → tweek-0.3.1}/tests/test_diagnostics.py +11 -4
  9. {tweek-0.2.1 → tweek-0.3.1}/tests/test_installer_improvements.py +16 -16
  10. tweek-0.3.1/tests/test_local_model.py +2220 -0
  11. tweek-0.3.1/tests/test_property_based.py +823 -0
  12. {tweek-0.2.1 → tweek-0.3.1}/tests/test_protect_command.py +13 -13
  13. tweek-0.3.1/tests/test_vault_cross_platform.py +657 -0
  14. {tweek-0.2.1 → tweek-0.3.1}/tweek/__init__.py +1 -1
  15. {tweek-0.2.1 → tweek-0.3.1}/tweek/audit.py +2 -2
  16. {tweek-0.2.1 → tweek-0.3.1}/tweek/cli.py +698 -439
  17. {tweek-0.2.1 → tweek-0.3.1}/tweek/cli_helpers.py +6 -6
  18. {tweek-0.2.1 → tweek-0.3.1}/tweek/cli_model.py +7 -7
  19. tweek-0.3.1/tweek/config/__init__.py +21 -0
  20. {tweek-0.2.1 → tweek-0.3.1}/tweek/config/manager.py +33 -1
  21. tweek-0.3.1/tweek/config/models.py +307 -0
  22. {tweek-0.2.1 → tweek-0.3.1}/tweek/config/patterns.yaml +1 -1
  23. {tweek-0.2.1 → tweek-0.3.1}/tweek/diagnostics.py +59 -7
  24. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/post_tool_use.py +1 -1
  25. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/pre_tool_use.py +3 -3
  26. {tweek-0.2.1 → tweek-0.3.1}/tweek/licensing.py +1 -1
  27. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/approval_cli.py +4 -4
  28. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/linux.py +5 -5
  29. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/SKILL.md +2 -3
  30. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/cli-reference.md +33 -18
  31. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/scripts/check_installed.py +4 -4
  32. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/PKG-INFO +22 -15
  33. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/SOURCES.txt +5 -0
  34. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/requires.txt +3 -0
  35. tweek-0.2.1/tests/test_local_model.py +0 -700
  36. tweek-0.2.1/tweek/config/__init__.py +0 -13
  37. {tweek-0.2.1 → tweek-0.3.1}/LICENSE +0 -0
  38. {tweek-0.2.1 → tweek-0.3.1}/setup.cfg +0 -0
  39. {tweek-0.2.1 → tweek-0.3.1}/tests/test_approval_queue.py +0 -0
  40. {tweek-0.2.1 → tweek-0.3.1}/tests/test_audit.py +0 -0
  41. {tweek-0.2.1 → tweek-0.3.1}/tests/test_break_glass.py +0 -0
  42. {tweek-0.2.1 → tweek-0.3.1}/tests/test_config_manager.py +0 -0
  43. {tweek-0.2.1 → tweek-0.3.1}/tests/test_credential_scanner.py +0 -0
  44. {tweek-0.2.1 → tweek-0.3.1}/tests/test_enforcement.py +0 -0
  45. {tweek-0.2.1 → tweek-0.3.1}/tests/test_feedback.py +0 -0
  46. {tweek-0.2.1 → tweek-0.3.1}/tests/test_heuristic_scorer.py +0 -0
  47. {tweek-0.2.1 → tweek-0.3.1}/tests/test_language_detection.py +0 -0
  48. {tweek-0.2.1 → tweek-0.3.1}/tests/test_licensing.py +0 -0
  49. {tweek-0.2.1 → tweek-0.3.1}/tests/test_llm_local.py +0 -0
  50. {tweek-0.2.1 → tweek-0.3.1}/tests/test_llm_reviewer.py +0 -0
  51. {tweek-0.2.1 → tweek-0.3.1}/tests/test_log_bundle.py +0 -0
  52. {tweek-0.2.1 → tweek-0.3.1}/tests/test_logging.py +0 -0
  53. {tweek-0.2.1 → tweek-0.3.1}/tests/test_logging_enhanced.py +0 -0
  54. {tweek-0.2.1 → tweek-0.3.1}/tests/test_mcp_clients.py +0 -0
  55. {tweek-0.2.1 → tweek-0.3.1}/tests/test_mcp_proxy.py +0 -0
  56. {tweek-0.2.1 → tweek-0.3.1}/tests/test_mcp_server.py +0 -0
  57. {tweek-0.2.1 → tweek-0.3.1}/tests/test_openclaw_integration.py +0 -0
  58. {tweek-0.2.1 → tweek-0.3.1}/tests/test_overrides.py +0 -0
  59. {tweek-0.2.1 → tweek-0.3.1}/tests/test_path_boundary.py +0 -0
  60. {tweek-0.2.1 → tweek-0.3.1}/tests/test_pattern_families.py +0 -0
  61. {tweek-0.2.1 → tweek-0.3.1}/tests/test_patterns.py +0 -0
  62. {tweek-0.2.1 → tweek-0.3.1}/tests/test_plugin_scoping.py +0 -0
  63. {tweek-0.2.1 → tweek-0.3.1}/tests/test_post_tool_use.py +0 -0
  64. {tweek-0.2.1 → tweek-0.3.1}/tests/test_prompt_injection_patterns.py +0 -0
  65. {tweek-0.2.1 → tweek-0.3.1}/tests/test_proxy_detection.py +0 -0
  66. {tweek-0.2.1 → tweek-0.3.1}/tests/test_rate_limiter.py +0 -0
  67. {tweek-0.2.1 → tweek-0.3.1}/tests/test_redaction.py +0 -0
  68. {tweek-0.2.1 → tweek-0.3.1}/tests/test_screening_context.py +0 -0
  69. {tweek-0.2.1 → tweek-0.3.1}/tests/test_session_analyzer.py +0 -0
  70. {tweek-0.2.1 → tweek-0.3.1}/tweek/_keygen.py +0 -0
  71. {tweek-0.2.1 → tweek-0.3.1}/tweek/config/allowed_dirs.yaml +0 -0
  72. {tweek-0.2.1 → tweek-0.3.1}/tweek/config/families.yaml +0 -0
  73. {tweek-0.2.1 → tweek-0.3.1}/tweek/config/tiers.yaml +0 -0
  74. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/__init__.py +0 -0
  75. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/break_glass.py +0 -0
  76. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/feedback.py +0 -0
  77. {tweek-0.2.1 → tweek-0.3.1}/tweek/hooks/overrides.py +0 -0
  78. {tweek-0.2.1 → tweek-0.3.1}/tweek/integrations/__init__.py +0 -0
  79. {tweek-0.2.1 → tweek-0.3.1}/tweek/integrations/openclaw.py +0 -0
  80. {tweek-0.2.1 → tweek-0.3.1}/tweek/integrations/openclaw_server.py +0 -0
  81. {tweek-0.2.1 → tweek-0.3.1}/tweek/logging/__init__.py +0 -0
  82. {tweek-0.2.1 → tweek-0.3.1}/tweek/logging/bundle.py +0 -0
  83. {tweek-0.2.1 → tweek-0.3.1}/tweek/logging/json_logger.py +0 -0
  84. {tweek-0.2.1 → tweek-0.3.1}/tweek/logging/security_log.py +0 -0
  85. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/__init__.py +0 -0
  86. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/approval.py +0 -0
  87. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/clients/__init__.py +0 -0
  88. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/clients/chatgpt.py +0 -0
  89. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/clients/claude_desktop.py +0 -0
  90. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/clients/gemini.py +0 -0
  91. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/proxy.py +0 -0
  92. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/screening.py +0 -0
  93. {tweek-0.2.1 → tweek-0.3.1}/tweek/mcp/server.py +0 -0
  94. {tweek-0.2.1 → tweek-0.3.1}/tweek/memory/__init__.py +0 -0
  95. {tweek-0.2.1 → tweek-0.3.1}/tweek/memory/queries.py +0 -0
  96. {tweek-0.2.1 → tweek-0.3.1}/tweek/memory/safety.py +0 -0
  97. {tweek-0.2.1 → tweek-0.3.1}/tweek/memory/schemas.py +0 -0
  98. {tweek-0.2.1 → tweek-0.3.1}/tweek/memory/store.py +0 -0
  99. {tweek-0.2.1 → tweek-0.3.1}/tweek/platform/__init__.py +0 -0
  100. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/__init__.py +0 -0
  101. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/base.py +0 -0
  102. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/__init__.py +0 -0
  103. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/gdpr.py +0 -0
  104. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/gov.py +0 -0
  105. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/hipaa.py +0 -0
  106. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/legal.py +0 -0
  107. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/pci.py +0 -0
  108. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/compliance/soc2.py +0 -0
  109. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/__init__.py +0 -0
  110. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/continue_dev.py +0 -0
  111. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/copilot.py +0 -0
  112. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/cursor.py +0 -0
  113. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/openclaw.py +0 -0
  114. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/detectors/windsurf.py +0 -0
  115. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/git_discovery.py +0 -0
  116. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/git_installer.py +0 -0
  117. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/git_lockfile.py +0 -0
  118. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/git_registry.py +0 -0
  119. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/git_security.py +0 -0
  120. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/__init__.py +0 -0
  121. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/anthropic.py +0 -0
  122. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/azure_openai.py +0 -0
  123. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/bedrock.py +0 -0
  124. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/google.py +0 -0
  125. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/providers/openai.py +0 -0
  126. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/scope.py +0 -0
  127. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/__init__.py +0 -0
  128. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/heuristic_scorer.py +0 -0
  129. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/llm_reviewer.py +0 -0
  130. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/local_model_reviewer.py +0 -0
  131. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/pattern_matcher.py +0 -0
  132. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/rate_limiter.py +0 -0
  133. {tweek-0.2.1 → tweek-0.3.1}/tweek/plugins/screening/session_analyzer.py +0 -0
  134. {tweek-0.2.1 → tweek-0.3.1}/tweek/proxy/__init__.py +0 -0
  135. {tweek-0.2.1 → tweek-0.3.1}/tweek/proxy/addon.py +0 -0
  136. {tweek-0.2.1 → tweek-0.3.1}/tweek/proxy/interceptor.py +0 -0
  137. {tweek-0.2.1 → tweek-0.3.1}/tweek/proxy/server.py +0 -0
  138. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/__init__.py +0 -0
  139. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/docker_bridge.py +0 -0
  140. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/executor.py +0 -0
  141. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/layers.py +0 -0
  142. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/profile_generator.py +0 -0
  143. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/project.py +0 -0
  144. {tweek-0.2.1 → tweek-0.3.1}/tweek/sandbox/registry.py +0 -0
  145. {tweek-0.2.1 → tweek-0.3.1}/tweek/screening/__init__.py +0 -0
  146. {tweek-0.2.1 → tweek-0.3.1}/tweek/screening/context.py +0 -0
  147. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/__init__.py +0 -0
  148. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/language.py +0 -0
  149. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/llm_reviewer.py +0 -0
  150. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/local_model.py +0 -0
  151. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/local_reviewer.py +0 -0
  152. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/model_registry.py +0 -0
  153. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/rate_limiter.py +0 -0
  154. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/secret_scanner.py +0 -0
  155. {tweek-0.2.1 → tweek-0.3.1}/tweek/security/session_analyzer.py +0 -0
  156. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/__init__.py +0 -0
  157. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/overrides-reference.md +0 -0
  158. {tweek-0.2.1 → tweek-0.3.1}/tweek/skill_template/scripts/__init__.py +0 -0
  159. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/__init__.py +0 -0
  160. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/config.py +0 -0
  161. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/fingerprints.py +0 -0
  162. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/guard.py +0 -0
  163. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/isolation.py +0 -0
  164. {tweek-0.2.1 → tweek-0.3.1}/tweek/skills/scanner.py +0 -0
  165. {tweek-0.2.1 → tweek-0.3.1}/tweek/vault/__init__.py +0 -0
  166. {tweek-0.2.1 → tweek-0.3.1}/tweek/vault/cross_platform.py +0 -0
  167. {tweek-0.2.1 → tweek-0.3.1}/tweek/vault/keychain.py +0 -0
  168. {tweek-0.2.1 → tweek-0.3.1}/tweek-openclaw-plugin/node_modules/flatted/python/flatted.py +0 -0
  169. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/dependency_links.txt +0 -0
  170. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/entry_points.txt +0 -0
  171. {tweek-0.2.1 → tweek-0.3.1}/tweek.egg-info/top_level.txt +0 -0
tweek-0.3.1/NOTICE ADDED
@@ -0,0 +1,199 @@
1
+ Tweek
2
+ Copyright 2025 Tommy Mancino / Tweek, LLC
3
+
4
+ This product includes software developed at Tweek, LLC.
5
+
6
+ =========================================================================
7
+
8
+ Third-Party Components
9
+ =========================================================================
10
+
11
+ This project uses the following third-party components. Their licenses
12
+ and copyright notices are reproduced below, as required by their
13
+ respective licenses.
14
+
15
+ -------------------------------------------------------------------------
16
+ ProtectAI DeBERTa-v3-base Prompt Injection v2
17
+ -------------------------------------------------------------------------
18
+
19
+ Source: https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2
20
+ License: Apache License 2.0
21
+ Copyright (c) 2024 Protect AI, Inc.
22
+
23
+ A fine-tuned DeBERTa-v3-base model for binary prompt injection
24
+ classification. Used by Tweek as an on-device classifier for detecting
25
+ prompt injection attacks. The model is downloaded at user request via
26
+ `tweek model download` and stored locally at ~/.tweek/models/.
27
+
28
+ Tweek does not modify or redistribute the model weights. The model is
29
+ downloaded directly from HuggingFace by the end user.
30
+
31
+ Citation:
32
+ @misc{deberta-v3-base-prompt-injection-v2,
33
+ author = {ProtectAI.com},
34
+ title = {Fine-Tuned DeBERTa-v3-base for Prompt Injection Detection},
35
+ year = {2024},
36
+ publisher = {HuggingFace},
37
+ url = {https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2},
38
+ }
39
+
40
+ Licensed under the Apache License, Version 2.0 (the "License");
41
+ you may not use this file except in compliance with the License.
42
+ You may obtain a copy of the License at
43
+
44
+ http://www.apache.org/licenses/LICENSE-2.0
45
+
46
+ Unless required by applicable law or agreed to in writing, software
47
+ distributed under the License is distributed on an "AS IS" BASIS,
48
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49
+ See the License for the specific language governing permissions and
50
+ limitations under the License.
51
+
52
+ -------------------------------------------------------------------------
53
+ Microsoft DeBERTa-v3-base (upstream base model)
54
+ -------------------------------------------------------------------------
55
+
56
+ Source: https://huggingface.co/microsoft/deberta-v3-base
57
+ License: MIT License
58
+ Copyright (c) Microsoft Corporation.
59
+
60
+ The ProtectAI prompt injection model above is fine-tuned from
61
+ Microsoft's DeBERTa-v3-base pre-trained language model.
62
+
63
+ Citation:
64
+ @misc{he2021debertav3,
65
+ title = {DeBERTaV3: Improving DeBERTa using ELECTRA-Style
66
+ Pre-Training with Gradient-Disentangled Embedding Sharing},
67
+ author = {Pengcheng He and Jianfeng Gao and Weizhu Chen},
68
+ year = {2021},
69
+ eprint = {2111.09543},
70
+ archivePrefix = {arXiv},
71
+ primaryClass = {cs.CL},
72
+ }
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ "Software"), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
88
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
89
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
90
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
91
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
92
+
93
+ -------------------------------------------------------------------------
94
+ ONNX Runtime
95
+ -------------------------------------------------------------------------
96
+
97
+ Source: https://github.com/microsoft/onnxruntime
98
+ License: MIT License
99
+ Copyright (c) Microsoft Corporation.
100
+
101
+ Used as the inference engine for the local prompt injection classifier.
102
+ Installed as an optional dependency via `pip install tweek[local-models]`.
103
+
104
+ Permission is hereby granted, free of charge, to any person obtaining
105
+ a copy of this software and associated documentation files (the
106
+ "Software"), to deal in the Software without restriction, including
107
+ without limitation the rights to use, copy, modify, merge, publish,
108
+ distribute, sublicense, and/or sell copies of the Software, and to
109
+ permit persons to whom the Software is furnished to do so, subject to
110
+ the following conditions:
111
+
112
+ The above copyright notice and this permission notice shall be
113
+ included in all copies or substantial portions of the Software.
114
+
115
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
116
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
117
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
118
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
119
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
120
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
121
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
122
+
123
+ -------------------------------------------------------------------------
124
+ HuggingFace Tokenizers
125
+ -------------------------------------------------------------------------
126
+
127
+ Source: https://github.com/huggingface/tokenizers
128
+ License: Apache License 2.0
129
+ Copyright (c) 2019 HuggingFace Inc.
130
+
131
+ Used for tokenizing input text before feeding to the local ONNX model.
132
+ Installed as an optional dependency via `pip install tweek[local-models]`.
133
+
134
+ Licensed under the Apache License, Version 2.0.
135
+
136
+ -------------------------------------------------------------------------
137
+ NumPy
138
+ -------------------------------------------------------------------------
139
+
140
+ Source: https://github.com/numpy/numpy
141
+ License: BSD 3-Clause License
142
+ Copyright (c) 2005-2024, NumPy Developers.
143
+
144
+ Used for numerical operations in the local model inference pipeline
145
+ (softmax scoring, tensor manipulation). Installed as an optional
146
+ dependency via `pip install tweek[local-models]`.
147
+
148
+ Redistribution and use in source and binary forms, with or without
149
+ modification, are permitted provided that the following conditions are
150
+ met:
151
+
152
+ 1. Redistributions of source code must retain the above copyright
153
+ notice, this list of conditions and the following disclaimer.
154
+
155
+ 2. Redistributions in binary form must reproduce the above copyright
156
+ notice, this list of conditions and the following disclaimer in
157
+ the documentation and/or other materials provided with the
158
+ distribution.
159
+
160
+ 3. Neither the name of the copyright holder nor the names of its
161
+ contributors may be used to endorse or promote products derived
162
+ from this software without specific prior written permission.
163
+
164
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
165
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
166
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
167
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
168
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
169
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
170
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
171
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
172
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
173
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
174
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
175
+
176
+ =========================================================================
177
+
178
+ Runtime Dependencies
179
+ =========================================================================
180
+
181
+ The following packages are installed via pip as runtime dependencies.
182
+ They are NOT bundled or vendored — each carries its own license in its
183
+ distribution. Listed here for transparency.
184
+
185
+ click >=8.0 BSD-3-Clause Pallets Projects
186
+ pyyaml >=6.0 MIT Kirill Simonov / YAML community
187
+ rich >=13.0 MIT Will McGugan
188
+ keyring >=25.0 MIT Jason R. Coombs
189
+
190
+ Optional dependencies (installed only when the user requests them):
191
+
192
+ anthropic >=0.18.0 MIT Anthropic, PBC
193
+ openai >=1.0.0 MIT OpenAI
194
+ google-generativeai Apache-2.0 Google LLC
195
+ mcp >=1.0.0 MIT Anthropic, PBC
196
+ mitmproxy >=10.0 MIT mitmproxy contributors
197
+ secretstorage >=3.0 BSD-3-Clause Dmitry Shachnev
198
+
199
+ =========================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tweek
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: Defense-in-depth security for AI coding assistants - protect credentials, code, and system from prompt injection attacks
5
5
  Author: Tommy Mancino
6
6
  License-Expression: Apache-2.0
@@ -21,7 +21,9 @@ Classifier: Topic :: Software Development :: Quality Assurance
21
21
  Requires-Python: >=3.9
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
+ License-File: NOTICE
24
25
  Requires-Dist: click>=8.0
26
+ Requires-Dist: pydantic>=2.0
25
27
  Requires-Dist: pyyaml>=6.0
26
28
  Requires-Dist: rich>=13.0
27
29
  Requires-Dist: keyring>=25.0
@@ -42,6 +44,8 @@ Requires-Dist: mitmproxy>=10.0; extra == "proxy"
42
44
  Provides-Extra: dev
43
45
  Requires-Dist: pytest>=7.0; extra == "dev"
44
46
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
47
+ Requires-Dist: pytest-xdist>=3.5.0; extra == "dev"
48
+ Requires-Dist: hypothesis>=6.98.0; extra == "dev"
45
49
  Requires-Dist: black>=23.0; extra == "dev"
46
50
  Requires-Dist: ruff>=0.1.0; extra == "dev"
47
51
  Requires-Dist: twine>=4.0; extra == "dev"
@@ -105,11 +109,12 @@ pip install --user tweek
105
109
  ### Protect Your Tools
106
110
 
107
111
  ```bash
108
- tweek install # Claude Code (CLI hooks)
112
+ tweek protect # Interactive wizard detects and protects all tools
113
+ tweek protect claude-code # Claude Code (CLI hooks)
109
114
  tweek protect openclaw # OpenClaw (HTTP proxy)
110
- tweek mcp install claude-desktop # Claude Desktop (MCP proxy)
111
- tweek mcp install chatgpt-desktop # ChatGPT Desktop (MCP proxy)
112
- tweek mcp install gemini # Gemini CLI (MCP proxy)
115
+ tweek protect claude-desktop # Claude Desktop (MCP proxy)
116
+ tweek protect chatgpt # ChatGPT Desktop (MCP proxy)
117
+ tweek protect gemini # Gemini CLI (MCP proxy)
113
118
  tweek proxy setup # Cursor, Windsurf, Continue.dev (HTTP proxy)
114
119
  ```
115
120
 
@@ -127,11 +132,11 @@ That's it. Tweek auto-detects your tools, applies all 259 attack patterns across
127
132
 
128
133
  | Client | Integration | Setup |
129
134
  |--------|------------|-------|
130
- | **Claude Code** | CLI hooks (native) | `tweek install` |
135
+ | **Claude Code** | CLI hooks (native) | `tweek protect claude-code` |
131
136
  | **OpenClaw** | Proxy wrapping | `tweek protect openclaw` |
132
- | **Claude Desktop** | MCP proxy | `tweek mcp install claude-desktop` |
133
- | **ChatGPT Desktop** | MCP proxy | `tweek mcp install chatgpt-desktop` |
134
- | **Gemini CLI** | MCP proxy | `tweek mcp install gemini` |
137
+ | **Claude Desktop** | MCP proxy | `tweek protect claude-desktop` |
138
+ | **ChatGPT Desktop** | MCP proxy | `tweek protect chatgpt` |
139
+ | **Gemini CLI** | MCP proxy | `tweek protect gemini` |
135
140
  | **Cursor** | HTTP proxy | `tweek proxy setup` |
136
141
  | **Windsurf** | HTTP proxy | `tweek proxy setup` |
137
142
  | **Continue.dev** | HTTP proxy | `tweek proxy setup` |
@@ -161,7 +166,7 @@ Turn 3: cat ~/.ssh/id_rsa → BLOCKED: path_escalation anomaly
161
166
 
162
167
  **Response injection** — Malicious instructions hidden in tool responses are caught at ingestion.
163
168
 
164
- See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 patterns across 22 categories.
169
+ See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 patterns across 11 categories.
165
170
 
166
171
  ---
167
172
 
@@ -169,14 +174,16 @@ See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 pa
169
174
 
170
175
  Most security tools that use AI send your data to an API. Tweek doesn't.
171
176
 
172
- Tweek ships with a **custom-trained prompt injection classifier** ([DeBERTa-v3-base](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2)) that runs entirely on your machine via ONNX Runtime. No API keys. No cloud calls. No data leaves your computer.
177
+ Tweek uses [ProtectAI's DeBERTa-v3-base Prompt Injection v2](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2) classifier, fine-tuned from [Microsoft's DeBERTa-v3-base](https://huggingface.co/microsoft/deberta-v3-base), running entirely on your machine via [ONNX Runtime](https://onnxruntime.ai). No API keys. No cloud calls. No data leaves your computer.
173
178
 
174
179
  | Property | Value |
175
180
  |----------|-------|
176
- | **Model** | DeBERTa-v3-base, fine-tuned for prompt injection |
177
- | **Runtime** | ONNX (CPU-only, single thread) |
181
+ | **Model** | [ProtectAI DeBERTa-v3-base Prompt Injection v2](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2) (Apache 2.0) |
182
+ | **Base Model** | [Microsoft DeBERTa-v3-base](https://huggingface.co/microsoft/deberta-v3-base) (MIT) |
183
+ | **Runtime** | ONNX Runtime (CPU-only, single thread) |
178
184
  | **Privacy** | 100% on-device — zero network calls |
179
- | **License** | Apache 2.0 |
185
+
186
+ See [NOTICE](./NOTICE) for full third-party license texts and attribution.
180
187
 
181
188
  The local model handles the gray-area attacks that pattern matching alone cannot catch — encoded instructions, novel injection techniques, social engineering disguised as legitimate content. High-confidence results are returned instantly. Uncertain results can optionally escalate to a cloud LLM for deeper analysis (you bring your own API key).
182
189
 
@@ -278,4 +285,4 @@ To report a security vulnerability, email security@gettweek.com.
278
285
 
279
286
  ## License
280
287
 
281
- [Apache 2.0](LICENSE)
288
+ [Apache 2.0](LICENSE) | [Third-Party Notices](NOTICE)
@@ -53,11 +53,12 @@ pip install --user tweek
53
53
  ### Protect Your Tools
54
54
 
55
55
  ```bash
56
- tweek install # Claude Code (CLI hooks)
56
+ tweek protect # Interactive wizard detects and protects all tools
57
+ tweek protect claude-code # Claude Code (CLI hooks)
57
58
  tweek protect openclaw # OpenClaw (HTTP proxy)
58
- tweek mcp install claude-desktop # Claude Desktop (MCP proxy)
59
- tweek mcp install chatgpt-desktop # ChatGPT Desktop (MCP proxy)
60
- tweek mcp install gemini # Gemini CLI (MCP proxy)
59
+ tweek protect claude-desktop # Claude Desktop (MCP proxy)
60
+ tweek protect chatgpt # ChatGPT Desktop (MCP proxy)
61
+ tweek protect gemini # Gemini CLI (MCP proxy)
61
62
  tweek proxy setup # Cursor, Windsurf, Continue.dev (HTTP proxy)
62
63
  ```
63
64
 
@@ -75,11 +76,11 @@ That's it. Tweek auto-detects your tools, applies all 259 attack patterns across
75
76
 
76
77
  | Client | Integration | Setup |
77
78
  |--------|------------|-------|
78
- | **Claude Code** | CLI hooks (native) | `tweek install` |
79
+ | **Claude Code** | CLI hooks (native) | `tweek protect claude-code` |
79
80
  | **OpenClaw** | Proxy wrapping | `tweek protect openclaw` |
80
- | **Claude Desktop** | MCP proxy | `tweek mcp install claude-desktop` |
81
- | **ChatGPT Desktop** | MCP proxy | `tweek mcp install chatgpt-desktop` |
82
- | **Gemini CLI** | MCP proxy | `tweek mcp install gemini` |
81
+ | **Claude Desktop** | MCP proxy | `tweek protect claude-desktop` |
82
+ | **ChatGPT Desktop** | MCP proxy | `tweek protect chatgpt` |
83
+ | **Gemini CLI** | MCP proxy | `tweek protect gemini` |
83
84
  | **Cursor** | HTTP proxy | `tweek proxy setup` |
84
85
  | **Windsurf** | HTTP proxy | `tweek proxy setup` |
85
86
  | **Continue.dev** | HTTP proxy | `tweek proxy setup` |
@@ -109,7 +110,7 @@ Turn 3: cat ~/.ssh/id_rsa → BLOCKED: path_escalation anomaly
109
110
 
110
111
  **Response injection** — Malicious instructions hidden in tool responses are caught at ingestion.
111
112
 
112
- See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 patterns across 22 categories.
113
+ See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 patterns across 11 categories.
113
114
 
114
115
  ---
115
116
 
@@ -117,14 +118,16 @@ See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 pa
117
118
 
118
119
  Most security tools that use AI send your data to an API. Tweek doesn't.
119
120
 
120
- Tweek ships with a **custom-trained prompt injection classifier** ([DeBERTa-v3-base](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2)) that runs entirely on your machine via ONNX Runtime. No API keys. No cloud calls. No data leaves your computer.
121
+ Tweek uses [ProtectAI's DeBERTa-v3-base Prompt Injection v2](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2) classifier, fine-tuned from [Microsoft's DeBERTa-v3-base](https://huggingface.co/microsoft/deberta-v3-base), running entirely on your machine via [ONNX Runtime](https://onnxruntime.ai). No API keys. No cloud calls. No data leaves your computer.
121
122
 
122
123
  | Property | Value |
123
124
  |----------|-------|
124
- | **Model** | DeBERTa-v3-base, fine-tuned for prompt injection |
125
- | **Runtime** | ONNX (CPU-only, single thread) |
125
+ | **Model** | [ProtectAI DeBERTa-v3-base Prompt Injection v2](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2) (Apache 2.0) |
126
+ | **Base Model** | [Microsoft DeBERTa-v3-base](https://huggingface.co/microsoft/deberta-v3-base) (MIT) |
127
+ | **Runtime** | ONNX Runtime (CPU-only, single thread) |
126
128
  | **Privacy** | 100% on-device — zero network calls |
127
- | **License** | Apache 2.0 |
129
+
130
+ See [NOTICE](./NOTICE) for full third-party license texts and attribution.
128
131
 
129
132
  The local model handles the gray-area attacks that pattern matching alone cannot catch — encoded instructions, novel injection techniques, social engineering disguised as legitimate content. High-confidence results are returned instantly. Uncertain results can optionally escalate to a cloud LLM for deeper analysis (you bring your own API key).
130
133
 
@@ -226,4 +229,4 @@ To report a security vulnerability, email security@gettweek.com.
226
229
 
227
230
  ## License
228
231
 
229
- [Apache 2.0](LICENSE)
232
+ [Apache 2.0](LICENSE) | [Third-Party Notices](NOTICE)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tweek"
7
- version = "0.2.1"
7
+ version = "0.3.1"
8
8
  description = "Defense-in-depth security for AI coding assistants - protect credentials, code, and system from prompt injection attacks"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -27,6 +27,7 @@ classifiers = [
27
27
  ]
28
28
  dependencies = [
29
29
  "click>=8.0",
30
+ "pydantic>=2.0",
30
31
  "pyyaml>=6.0",
31
32
  "rich>=13.0",
32
33
  "keyring>=25.0",
@@ -55,6 +56,8 @@ proxy = [
55
56
  dev = [
56
57
  "pytest>=7.0",
57
58
  "pytest-cov>=4.0",
59
+ "pytest-xdist>=3.5.0",
60
+ "hypothesis>=6.98.0",
58
61
  "black>=23.0",
59
62
  "ruff>=0.1.0",
60
63
  "twine>=4.0",
@@ -119,7 +122,7 @@ tweek = [
119
122
  [tool.pytest.ini_options]
120
123
  testpaths = ["tests"]
121
124
  python_files = ["test_*.py"]
122
- addopts = "-v --cov=tweek --cov-report=term-missing"
125
+ addopts = "-v --cov=tweek --cov-report=term-missing --cov-fail-under=65"
123
126
  markers = [
124
127
  "patterns: Regex pattern matching and prompt injection detection (slow, ~37s)",
125
128
  "hooks: Pre/post tool use hook pipeline and path boundary escalation",
@@ -170,3 +173,21 @@ ignore = [
170
173
  [tool.ruff.lint.per-file-ignores]
171
174
  "tests/**" = ["S101", "S106", "T201"]
172
175
  "tweek/hooks/**" = ["T201"] # Hooks communicate via stdout
176
+
177
+ [tool.coverage.run]
178
+ branch = true
179
+ source = ["tweek"]
180
+ omit = [
181
+ "tweek/sandbox/linux.py",
182
+ "tweek/skill_template/*",
183
+ ]
184
+
185
+ [tool.coverage.report]
186
+ fail_under = 65
187
+ show_missing = true
188
+ exclude_lines = [
189
+ "pragma: no cover",
190
+ "if TYPE_CHECKING:",
191
+ "if __name__",
192
+ "@overload",
193
+ ]
@@ -3,7 +3,7 @@
3
3
  Tests for Tweek CLI commands.
4
4
 
5
5
  Tests coverage of:
6
- - Install/uninstall commands
6
+ - Protect/unprotect commands
7
7
  - License commands
8
8
  - Config commands
9
9
  - Vault commands
@@ -20,7 +20,7 @@ import sys
20
20
 
21
21
  sys.path.insert(0, str(Path(__file__).parent.parent))
22
22
 
23
- from tweek.cli import main, install, uninstall, update
23
+ from tweek.cli import main, update
24
24
  from tweek.licensing import License, Tier
25
25
  from tweek._keygen import generate_license_key
26
26
 
@@ -44,17 +44,17 @@ def temp_home(tmp_path):
44
44
 
45
45
 
46
46
  class TestInstallCommand:
47
- """Tests for the install command."""
47
+ """Tests for the protect claude-code command (formerly install)."""
48
48
 
49
49
  def test_install_global_creates_settings(self, runner, tmp_path):
50
- """Test global install creates settings.json."""
50
+ """Test global protect claude-code creates settings.json."""
51
51
  claude_dir = tmp_path / ".claude"
52
52
 
53
53
  with patch.object(Path, 'home', return_value=tmp_path):
54
54
  with patch('tweek.cli.Path.home', return_value=tmp_path):
55
55
  result = runner.invoke(
56
56
  main,
57
- ['install', '--skip-env-scan'],
57
+ ['protect', 'claude-code', '--skip-env-scan'],
58
58
  catch_exceptions=False
59
59
  )
60
60
 
@@ -62,11 +62,11 @@ class TestInstallCommand:
62
62
  assert result.exit_code == 0 or "Installation complete" in result.output
63
63
 
64
64
  def test_install_project_scope(self, runner, tmp_path):
65
- """Test project-scoped install."""
65
+ """Test project-scoped protect claude-code."""
66
66
  with runner.isolated_filesystem(temp_dir=tmp_path):
67
67
  result = runner.invoke(
68
68
  main,
69
- ['install', '--scope', 'project', '--skip-env-scan']
69
+ ['protect', 'claude-code', '--scope', 'project', '--skip-env-scan']
70
70
  )
71
71
 
72
72
  # Check .claude directory was created
@@ -76,21 +76,21 @@ class TestInstallCommand:
76
76
  assert settings.exists() or "Installation complete" in result.output
77
77
 
78
78
  def test_install_with_preset(self, runner, tmp_path):
79
- """Test install with security preset."""
79
+ """Test protect claude-code with security preset."""
80
80
  with patch.object(Path, 'home', return_value=tmp_path):
81
81
  result = runner.invoke(
82
82
  main,
83
- ['install', '--preset', 'paranoid', '--skip-env-scan']
83
+ ['protect', 'claude-code', '--preset', 'paranoid', '--skip-env-scan']
84
84
  )
85
85
 
86
86
  assert "paranoid" in result.output.lower() or result.exit_code == 0
87
87
 
88
88
  def test_install_skip_proxy_check(self, runner, tmp_path):
89
- """Test install with --skip-proxy-check skips openclaw detection."""
89
+ """Test protect claude-code with --skip-proxy-check skips openclaw detection."""
90
90
  with patch.object(Path, 'home', return_value=tmp_path):
91
91
  result = runner.invoke(
92
92
  main,
93
- ['install', '--skip-env-scan', '--skip-proxy-check']
93
+ ['protect', 'claude-code', '--skip-env-scan', '--skip-proxy-check']
94
94
  )
95
95
 
96
96
  # Should not mention openclaw
@@ -98,7 +98,7 @@ class TestInstallCommand:
98
98
  assert result.exit_code == 0 or "Installation complete" in result.output
99
99
 
100
100
  def test_install_detects_openclaw_installed(self, runner, tmp_path):
101
- """Test install detects when openclaw is installed."""
101
+ """Test protect claude-code detects when openclaw is installed."""
102
102
  openclaw_status = {
103
103
  "installed": True,
104
104
  "running": False,
@@ -112,7 +112,7 @@ class TestInstallCommand:
112
112
  with patch('tweek.proxy.detect_proxy_conflicts', return_value=[]):
113
113
  result = runner.invoke(
114
114
  main,
115
- ['install', '--skip-env-scan'],
115
+ ['protect', 'claude-code', '--skip-env-scan'],
116
116
  input='n\n' # Answer 'no' to proxy override prompt
117
117
  )
118
118
 
@@ -120,7 +120,7 @@ class TestInstallCommand:
120
120
  assert "openclaw" in result.output.lower() or result.exit_code == 0
121
121
 
122
122
  def test_install_detects_openclaw_gateway_running(self, runner, tmp_path):
123
- """Test install detects when openclaw gateway is actively running."""
123
+ """Test protect claude-code detects when openclaw gateway is actively running."""
124
124
  openclaw_status = {
125
125
  "installed": True,
126
126
  "running": True,
@@ -134,7 +134,7 @@ class TestInstallCommand:
134
134
  with patch('tweek.proxy.detect_proxy_conflicts', return_value=[]):
135
135
  result = runner.invoke(
136
136
  main,
137
- ['install', '--skip-env-scan'],
137
+ ['protect', 'claude-code', '--skip-env-scan'],
138
138
  input='n\n' # Answer 'no' to proxy override prompt
139
139
  )
140
140
 
@@ -142,7 +142,7 @@ class TestInstallCommand:
142
142
  assert "gateway" in result.output.lower() or "running" in result.output.lower() or result.exit_code == 0
143
143
 
144
144
  def test_install_force_proxy_flag(self, runner, tmp_path):
145
- """Test install with --force-proxy enables proxy override."""
145
+ """Test protect claude-code with --force-proxy enables proxy override."""
146
146
  openclaw_status = {
147
147
  "installed": True,
148
148
  "running": True,
@@ -156,7 +156,7 @@ class TestInstallCommand:
156
156
  with patch('tweek.proxy.detect_proxy_conflicts', return_value=[]):
157
157
  result = runner.invoke(
158
158
  main,
159
- ['install', '--skip-env-scan', '--force-proxy']
159
+ ['protect', 'claude-code', '--skip-env-scan', '--force-proxy']
160
160
  )
161
161
 
162
162
  # Should mention force/override
@@ -179,7 +179,7 @@ class TestInstallCommand:
179
179
  with patch('tweek.proxy.detect_proxy_conflicts', return_value=[]):
180
180
  result = runner.invoke(
181
181
  main,
182
- ['install', '--skip-env-scan', '--force-proxy']
182
+ ['protect', 'claude-code', '--skip-env-scan', '--force-proxy']
183
183
  )
184
184
 
185
185
  # Check config file was created
@@ -192,7 +192,7 @@ class TestInstallCommand:
192
192
  assert config.get("proxy", {}).get("override_openclaw") is True
193
193
 
194
194
  def test_install_user_accepts_proxy_override(self, runner, tmp_path):
195
- """Test install when user accepts proxy override prompt."""
195
+ """Test protect claude-code when user accepts proxy override prompt."""
196
196
  openclaw_status = {
197
197
  "installed": True,
198
198
  "running": False,
@@ -206,7 +206,7 @@ class TestInstallCommand:
206
206
  with patch('tweek.proxy.detect_proxy_conflicts', return_value=[]):
207
207
  result = runner.invoke(
208
208
  main,
209
- ['install', '--skip-env-scan'],
209
+ ['protect', 'claude-code', '--skip-env-scan'],
210
210
  input='y\n' # Answer 'yes' to proxy override prompt
211
211
  )
212
212
 
@@ -215,21 +215,21 @@ class TestInstallCommand:
215
215
 
216
216
 
217
217
  class TestUninstallCommand:
218
- """Tests for the uninstall command."""
218
+ """Tests for the unprotect command (formerly uninstall)."""
219
219
 
220
220
  @patch('tweek.cli.sys')
221
221
  def test_uninstall_not_installed(self, mock_sys, runner, tmp_path):
222
- """Test uninstall when not installed (project scope, empty directory)."""
222
+ """Test unprotect when not installed (project scope, empty directory)."""
223
223
  mock_sys.stdin.isatty.return_value = True
224
224
  mock_sys.stderr = sys.stderr
225
225
  with runner.isolated_filesystem(temp_dir=tmp_path):
226
- result = runner.invoke(main, ['uninstall', '--confirm'])
226
+ result = runner.invoke(main, ['unprotect', 'claude-code', '--confirm'])
227
227
 
228
228
  assert "No Tweek installation" in result.output or result.exit_code == 0
229
229
 
230
230
  @patch('tweek.cli.sys')
231
231
  def test_uninstall_removes_hooks(self, mock_sys, runner, tmp_path):
232
- """Test uninstall removes Tweek hooks."""
232
+ """Test unprotect removes Tweek hooks."""
233
233
  mock_sys.stdin.isatty.return_value = True
234
234
  mock_sys.stderr = sys.stderr
235
235
  with runner.isolated_filesystem(temp_dir=tmp_path) as td:
@@ -249,7 +249,7 @@ class TestUninstallCommand:
249
249
  }
250
250
  }))
251
251
 
252
- result = runner.invoke(main, ['uninstall', '--confirm'])
252
+ result = runner.invoke(main, ['unprotect', 'claude-code', '--confirm'])
253
253
 
254
254
  # Check hooks were removed
255
255
  if settings_file.exists():
@@ -450,9 +450,9 @@ class TestCLIHelp:
450
450
  assert result.exit_code == 0
451
451
  assert "Tweek" in result.output or "security" in result.output.lower()
452
452
 
453
- def test_install_help(self, runner):
454
- """Test install help message."""
455
- result = runner.invoke(main, ['install', '--help'])
453
+ def test_protect_claude_code_help(self, runner):
454
+ """Test protect claude-code help message."""
455
+ result = runner.invoke(main, ['protect', 'claude-code', '--help'])
456
456
  assert result.exit_code == 0
457
457
  assert "global" in result.output.lower()
458
458
 
@@ -76,17 +76,17 @@ class TestFormatCommandExample:
76
76
  """Tests for format_command_example()."""
77
77
 
78
78
  def test_basic_example(self):
79
- result = format_command_example("tweek install", "Install globally")
80
- assert "tweek install" in result
81
- assert "Install globally" in result
79
+ result = format_command_example("tweek protect claude-code", "Protect Claude Code globally")
80
+ assert "tweek protect claude-code" in result
81
+ assert "Protect Claude Code globally" in result
82
82
 
83
83
  def test_long_command(self):
84
84
  result = format_command_example(
85
- "tweek install --scope project --force",
86
- "Force install for project"
85
+ "tweek protect claude-code --scope project --force",
86
+ "Force protect for project"
87
87
  )
88
- assert "tweek install --scope project --force" in result
89
- assert "Force install for project" in result
88
+ assert "tweek protect claude-code --scope project --force" in result
89
+ assert "Force protect for project" in result
90
90
 
91
91
 
92
92
  class TestBuildExamplesEpilog:
@@ -94,13 +94,13 @@ class TestBuildExamplesEpilog:
94
94
 
95
95
  def test_builds_epilog(self):
96
96
  examples = [
97
- ("tweek install", "Install globally"),
98
- ("tweek install --scope project", "Install for project"),
97
+ ("tweek protect claude-code", "Protect Claude Code globally"),
98
+ ("tweek protect claude-code --scope project", "Protect for project"),
99
99
  ]
100
100
  result = build_examples_epilog(examples)
101
101
  assert "Examples:" in result
102
- assert "tweek install" in result
103
- assert "tweek install --scope project" in result
102
+ assert "tweek protect claude-code" in result
103
+ assert "tweek protect claude-code --scope project" in result
104
104
  assert result.endswith("\n")
105
105
 
106
106
  def test_empty_examples(self):