tweek 0.2.1__py3-none-any.whl → 0.3.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.
- tweek/__init__.py +1 -1
- tweek/cli.py +648 -435
- tweek/cli_helpers.py +6 -6
- tweek/cli_model.py +7 -7
- tweek/config/manager.py +1 -1
- tweek/diagnostics.py +59 -7
- tweek/hooks/pre_tool_use.py +3 -3
- tweek/mcp/approval_cli.py +4 -4
- tweek/sandbox/linux.py +5 -5
- tweek/skill_template/SKILL.md +2 -3
- tweek/skill_template/cli-reference.md +33 -18
- tweek/skill_template/scripts/check_installed.py +4 -4
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/METADATA +20 -14
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/RECORD +19 -18
- tweek-0.3.0.dist-info/licenses/NOTICE +199 -0
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/WHEEL +0 -0
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/entry_points.txt +0 -0
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {tweek-0.2.1.dist-info → tweek-0.3.0.dist-info}/top_level.txt +0 -0
tweek/cli_helpers.py
CHANGED
|
@@ -32,7 +32,7 @@ def print_error(message: str, fix_hint: str = "") -> None:
|
|
|
32
32
|
"""Print an error message with red X and optional fix hint."""
|
|
33
33
|
console.print(f"[red]\u2717[/red] {message}")
|
|
34
34
|
if fix_hint:
|
|
35
|
-
console.print(f" [
|
|
35
|
+
console.print(f" [white]Hint: {fix_hint}[/white]")
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def print_health_banner(checks: "List") -> None:
|
|
@@ -51,7 +51,7 @@ def print_health_banner(checks: "List") -> None:
|
|
|
51
51
|
|
|
52
52
|
panel = Panel(
|
|
53
53
|
f"[bold {color}]{verdict_text}[/bold {color}]\n"
|
|
54
|
-
f"[
|
|
54
|
+
f"[white]Run 'tweek doctor' for details[/white]",
|
|
55
55
|
border_style=color,
|
|
56
56
|
padding=(0, 2),
|
|
57
57
|
)
|
|
@@ -63,11 +63,11 @@ def format_command_example(command: str, description: str) -> str:
|
|
|
63
63
|
Format a single command example line.
|
|
64
64
|
|
|
65
65
|
Args:
|
|
66
|
-
command: The command string, e.g., "tweek
|
|
66
|
+
command: The command string, e.g., "tweek protect claude-code --scope global"
|
|
67
67
|
description: Brief explanation of what it does.
|
|
68
68
|
|
|
69
69
|
Returns:
|
|
70
|
-
Formatted string like " tweek
|
|
70
|
+
Formatted string like " tweek protect claude-code --scope global Install globally"
|
|
71
71
|
"""
|
|
72
72
|
return f" {command:<40s} {description}"
|
|
73
73
|
|
|
@@ -141,11 +141,11 @@ def print_doctor_results(checks: "List") -> None:
|
|
|
141
141
|
CheckStatus.OK: ("[green]OK[/green] ", "green"),
|
|
142
142
|
CheckStatus.WARNING: ("[yellow]WARN[/yellow] ", "yellow"),
|
|
143
143
|
CheckStatus.ERROR: ("[red]ERROR[/red] ", "red"),
|
|
144
|
-
CheckStatus.SKIPPED: ("[
|
|
144
|
+
CheckStatus.SKIPPED: ("[white]SKIP[/white] ", "white"),
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
for check in checks:
|
|
148
|
-
style_text, _ = status_styles.get(check.status, ("[
|
|
148
|
+
style_text, _ = status_styles.get(check.status, ("[white]???[/white] ", "white"))
|
|
149
149
|
console.print(f" {style_text} {check.label:<22s} {check.message}")
|
|
150
150
|
|
|
151
151
|
# Verdict
|
tweek/cli_model.py
CHANGED
|
@@ -90,7 +90,7 @@ def model_download(name: str, force: bool):
|
|
|
90
90
|
console.print()
|
|
91
91
|
console.print(f"[green]Model downloaded to {model_dir}[/green]")
|
|
92
92
|
console.print(
|
|
93
|
-
f"[
|
|
93
|
+
f"[white]Local screening is now active for risky/dangerous operations.[/white]"
|
|
94
94
|
)
|
|
95
95
|
|
|
96
96
|
except ModelDownloadError as e:
|
|
@@ -130,8 +130,8 @@ def model_list(available: bool):
|
|
|
130
130
|
defn.display_name,
|
|
131
131
|
f"~{defn.size_mb:.0f} MB",
|
|
132
132
|
defn.license,
|
|
133
|
-
"[green]yes[/green]" if installed else "[
|
|
134
|
-
"[green]yes[/green]" if active else "[
|
|
133
|
+
"[green]yes[/green]" if installed else "[white]no[/white]",
|
|
134
|
+
"[green]yes[/green]" if active else "[white]-[/white]",
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
console.print(table)
|
|
@@ -158,7 +158,7 @@ def model_list(available: bool):
|
|
|
158
158
|
name,
|
|
159
159
|
defn.display_name if defn else name,
|
|
160
160
|
size_str,
|
|
161
|
-
"[green]yes[/green]" if active else "[
|
|
161
|
+
"[green]yes[/green]" if active else "[white]-[/white]",
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
console.print(table)
|
|
@@ -221,10 +221,10 @@ def model_status():
|
|
|
221
221
|
)
|
|
222
222
|
else:
|
|
223
223
|
fallback_lines.append(
|
|
224
|
-
" Cloud LLM: [
|
|
224
|
+
" Cloud LLM: [white]none (no API keys configured)[/white]"
|
|
225
225
|
)
|
|
226
226
|
except Exception:
|
|
227
|
-
fallback_lines.append(" Cloud LLM: [
|
|
227
|
+
fallback_lines.append(" Cloud LLM: [white]unavailable[/white]")
|
|
228
228
|
|
|
229
229
|
# Overall status
|
|
230
230
|
if LOCAL_MODEL_AVAILABLE and installed:
|
|
@@ -232,7 +232,7 @@ def model_status():
|
|
|
232
232
|
elif LOCAL_MODEL_AVAILABLE and not installed:
|
|
233
233
|
status = "[yellow]Ready[/yellow] - Dependencies installed, model not downloaded"
|
|
234
234
|
else:
|
|
235
|
-
status = "[
|
|
235
|
+
status = "[white]Inactive[/white] - Install dependencies: pip install tweek[local-models]"
|
|
236
236
|
|
|
237
237
|
content = f"Status: {status}\n\n"
|
|
238
238
|
content += "[bold]Dependencies[/bold]\n" + "\n".join(deps_lines) + "\n\n"
|
tweek/config/manager.py
CHANGED
|
@@ -173,7 +173,7 @@ class ConfigManager:
|
|
|
173
173
|
"plugins", "mcp", "proxy", "sandbox", "isolation_chamber",
|
|
174
174
|
"llm_review", "local_model", "rate_limiting", "session_analysis",
|
|
175
175
|
"path_boundary", "non_english_handling", "version", "tiers",
|
|
176
|
-
"heuristic_scorer",
|
|
176
|
+
"heuristic_scorer", "openclaw",
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
def __init__(
|
tweek/diagnostics.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Tweek Diagnostics Engine
|
|
4
4
|
|
|
5
5
|
Health check system for verifying Tweek installation, configuration,
|
|
6
|
-
and runtime dependencies. Used by `tweek doctor` and the
|
|
6
|
+
and runtime dependencies. Used by `tweek doctor` and the health banner.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import json
|
|
@@ -30,7 +30,7 @@ class HealthCheck:
|
|
|
30
30
|
label: str # Human label: "Hook Installation"
|
|
31
31
|
status: CheckStatus
|
|
32
32
|
message: str # Description: "Global hooks installed at ~/.claude/"
|
|
33
|
-
fix_hint: str = "" # Recovery: "Run: tweek
|
|
33
|
+
fix_hint: str = "" # Recovery: "Run: tweek protect claude-code --global"
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def run_health_checks(verbose: bool = False) -> List[HealthCheck]:
|
|
@@ -168,7 +168,7 @@ def _check_hooks_installed(verbose: bool = False) -> HealthCheck:
|
|
|
168
168
|
label="Hook Installation",
|
|
169
169
|
status=CheckStatus.WARNING,
|
|
170
170
|
message="Installed in project only (./.claude)",
|
|
171
|
-
fix_hint="Run: tweek
|
|
171
|
+
fix_hint="Run: tweek protect claude-code --global (to protect all projects)",
|
|
172
172
|
)
|
|
173
173
|
else:
|
|
174
174
|
return HealthCheck(
|
|
@@ -176,7 +176,7 @@ def _check_hooks_installed(verbose: bool = False) -> HealthCheck:
|
|
|
176
176
|
label="Hook Installation",
|
|
177
177
|
status=CheckStatus.ERROR,
|
|
178
178
|
message="No hooks installed",
|
|
179
|
-
fix_hint="Run: tweek
|
|
179
|
+
fix_hint="Run: tweek protect claude-code",
|
|
180
180
|
)
|
|
181
181
|
|
|
182
182
|
|
|
@@ -597,18 +597,53 @@ def _check_llm_review(verbose: bool = False) -> HealthCheck:
|
|
|
597
597
|
get_llm_reviewer,
|
|
598
598
|
_detect_local_server,
|
|
599
599
|
FallbackReviewProvider,
|
|
600
|
+
DEFAULT_API_KEY_ENVS,
|
|
600
601
|
)
|
|
602
|
+
from tweek.security.local_model import LOCAL_MODEL_AVAILABLE
|
|
601
603
|
|
|
602
604
|
reviewer = get_llm_reviewer()
|
|
603
605
|
|
|
604
606
|
if not reviewer.enabled:
|
|
607
|
+
# Check which env vars are missing to give specific guidance
|
|
608
|
+
missing_keys = []
|
|
609
|
+
for provider, env_names in DEFAULT_API_KEY_ENVS.items():
|
|
610
|
+
if isinstance(env_names, list):
|
|
611
|
+
if not any(os.environ.get(e) for e in env_names):
|
|
612
|
+
missing_keys.append(f"{' or '.join(env_names)} ({provider})")
|
|
613
|
+
else:
|
|
614
|
+
if not os.environ.get(env_names):
|
|
615
|
+
missing_keys.append(f"{env_names} ({provider})")
|
|
616
|
+
|
|
617
|
+
hint_parts = [
|
|
618
|
+
"To enable cloud LLM review for uncertain classifications:",
|
|
619
|
+
" Set one of: " + ", ".join(
|
|
620
|
+
k.split(" (")[0] for k in missing_keys
|
|
621
|
+
),
|
|
622
|
+
]
|
|
623
|
+
|
|
624
|
+
if not LOCAL_MODEL_AVAILABLE:
|
|
625
|
+
hint_parts.append(
|
|
626
|
+
" Or install the local model: pip install 'tweek[local]'"
|
|
627
|
+
)
|
|
628
|
+
else:
|
|
629
|
+
hint_parts.append(
|
|
630
|
+
" Local ONNX model is available but could not initialize"
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
hint_parts.append(
|
|
634
|
+
" Or install Ollama (https://ollama.ai) for local LLM review"
|
|
635
|
+
)
|
|
636
|
+
hint_parts.append(
|
|
637
|
+
" See: docs/CONFIGURATION.md or ~/.tweek/config.yaml"
|
|
638
|
+
)
|
|
639
|
+
|
|
605
640
|
return HealthCheck(
|
|
606
641
|
name="llm_review",
|
|
607
642
|
label="LLM Review",
|
|
608
643
|
status=CheckStatus.WARNING,
|
|
609
|
-
message="No LLM provider available
|
|
610
|
-
|
|
611
|
-
|
|
644
|
+
message="No LLM provider available — review disabled, "
|
|
645
|
+
"pattern matching and heuristic scoring still active",
|
|
646
|
+
fix_hint="\n".join(hint_parts),
|
|
612
647
|
)
|
|
613
648
|
|
|
614
649
|
# Build status message
|
|
@@ -636,6 +671,23 @@ def _check_llm_review(verbose: bool = False) -> HealthCheck:
|
|
|
636
671
|
except Exception:
|
|
637
672
|
pass
|
|
638
673
|
|
|
674
|
+
# In verbose mode, report escalation path
|
|
675
|
+
if verbose:
|
|
676
|
+
if provider_name == "local":
|
|
677
|
+
# Check if cloud escalation is available
|
|
678
|
+
cloud_env_found = any(
|
|
679
|
+
os.environ.get(e) if isinstance(e, str)
|
|
680
|
+
else any(os.environ.get(v) for v in e)
|
|
681
|
+
for e in DEFAULT_API_KEY_ENVS.values()
|
|
682
|
+
)
|
|
683
|
+
if cloud_env_found:
|
|
684
|
+
parts.append("cloud escalation: available")
|
|
685
|
+
else:
|
|
686
|
+
parts.append("cloud escalation: not configured")
|
|
687
|
+
|
|
688
|
+
if LOCAL_MODEL_AVAILABLE:
|
|
689
|
+
parts.append("local ONNX: available")
|
|
690
|
+
|
|
639
691
|
return HealthCheck(
|
|
640
692
|
name="llm_review",
|
|
641
693
|
label="LLM Review",
|
tweek/hooks/pre_tool_use.py
CHANGED
|
@@ -925,10 +925,10 @@ def process_hook(input_data: dict, logger: SecurityLogger) -> dict:
|
|
|
925
925
|
}
|
|
926
926
|
}
|
|
927
927
|
|
|
928
|
-
# Block AI from running tweek trust/untrust/uninstall — human-only commands
|
|
928
|
+
# Block AI from running tweek trust/untrust/uninstall/unprotect — human-only commands
|
|
929
929
|
command_stripped = command.strip()
|
|
930
|
-
if re.match(r"tweek\s+(trust|untrust|uninstall)\b", command_stripped):
|
|
931
|
-
if "uninstall" in command_stripped:
|
|
930
|
+
if re.match(r"tweek\s+(trust|untrust|uninstall|unprotect)\b", command_stripped):
|
|
931
|
+
if "uninstall" in command_stripped or "unprotect" in command_stripped:
|
|
932
932
|
reason = (
|
|
933
933
|
"TWEEK SELF-PROTECTION: Uninstall must be done by a human.\n"
|
|
934
934
|
"Run this command directly in your terminal:\n"
|
tweek/mcp/approval_cli.py
CHANGED
|
@@ -39,7 +39,7 @@ def display_pending(queue: ApprovalQueue) -> int:
|
|
|
39
39
|
pending = queue.get_pending()
|
|
40
40
|
|
|
41
41
|
if not pending:
|
|
42
|
-
console.print("[
|
|
42
|
+
console.print("[white]No pending approval requests.[/white]")
|
|
43
43
|
return 0
|
|
44
44
|
|
|
45
45
|
table = Table(title="Pending Approval Requests", show_lines=True)
|
|
@@ -112,7 +112,7 @@ def display_request_detail(request: ApprovalRequest):
|
|
|
112
112
|
remaining = request.time_remaining
|
|
113
113
|
if remaining > 0:
|
|
114
114
|
lines.append("")
|
|
115
|
-
lines.append(f"[
|
|
115
|
+
lines.append(f"[white]Auto-deny in {int(remaining)}s[/white]")
|
|
116
116
|
|
|
117
117
|
panel = Panel(
|
|
118
118
|
"\n".join(lines),
|
|
@@ -160,7 +160,7 @@ def run_approval_daemon(
|
|
|
160
160
|
# Prompt for decision
|
|
161
161
|
decision = _prompt_decision(console, req)
|
|
162
162
|
if decision == "quit":
|
|
163
|
-
console.print("[
|
|
163
|
+
console.print("[white]Exiting approval daemon.[/white]")
|
|
164
164
|
return
|
|
165
165
|
elif decision == "skip":
|
|
166
166
|
continue
|
|
@@ -200,7 +200,7 @@ def run_approval_daemon(
|
|
|
200
200
|
time.sleep(poll_interval)
|
|
201
201
|
|
|
202
202
|
except KeyboardInterrupt:
|
|
203
|
-
console.print("\n[
|
|
203
|
+
console.print("\n[white]Approval daemon stopped.[/white]")
|
|
204
204
|
|
|
205
205
|
# Print summary
|
|
206
206
|
stats = queue.get_stats()
|
tweek/sandbox/linux.py
CHANGED
|
@@ -237,13 +237,13 @@ def prompt_install_firejail(console) -> bool:
|
|
|
237
237
|
pkg_info = get_linux_package_manager()
|
|
238
238
|
|
|
239
239
|
if not pkg_info:
|
|
240
|
-
console.print("[
|
|
240
|
+
console.print("[white]Could not detect package manager.[/white]")
|
|
241
241
|
console.print("Install firejail manually: https://firejail.wordpress.com/download-2/")
|
|
242
242
|
return False
|
|
243
243
|
|
|
244
244
|
manager, command = pkg_info
|
|
245
|
-
console.print(f"[
|
|
246
|
-
console.print(f"[
|
|
245
|
+
console.print(f"[white]Detected package manager: {manager}[/white]")
|
|
246
|
+
console.print(f"[white]Command: {' '.join(command)}[/white]\n")
|
|
247
247
|
|
|
248
248
|
if Confirm.ask("Install firejail for full sandbox protection?", default=False):
|
|
249
249
|
try:
|
|
@@ -260,13 +260,13 @@ def prompt_install_firejail(console) -> bool:
|
|
|
260
260
|
|
|
261
261
|
except subprocess.CalledProcessError as e:
|
|
262
262
|
console.print(f"[red]Installation failed (exit code {e.returncode})[/red]")
|
|
263
|
-
console.print("[
|
|
263
|
+
console.print("[white]Try running the install command manually with sudo[/white]")
|
|
264
264
|
return False
|
|
265
265
|
except KeyboardInterrupt:
|
|
266
266
|
console.print("\n[yellow]Installation cancelled.[/yellow]")
|
|
267
267
|
return False
|
|
268
268
|
else:
|
|
269
|
-
console.print("[
|
|
269
|
+
console.print("[white]Skipping firejail. Sandbox layer will be disabled.[/white]")
|
|
270
270
|
return False
|
|
271
271
|
|
|
272
272
|
|
tweek/skill_template/SKILL.md
CHANGED
|
@@ -28,7 +28,7 @@ The script returns JSON with these fields:
|
|
|
28
28
|
| Field | Meaning |
|
|
29
29
|
|-------|---------|
|
|
30
30
|
| `status: "fully_operational"` | Tweek is installed and hooks are active. Proceed to help user with their question. |
|
|
31
|
-
| `status: "installed_no_hooks"` | Tweek is installed but hooks are not registered. Tell user to run `tweek
|
|
31
|
+
| `status: "installed_no_hooks"` | Tweek is installed but hooks are not registered. Tell user to run `tweek protect claude-code`. |
|
|
32
32
|
| `status: "hooks_only"` | Hooks reference tweek but the package is missing. Tell user to reinstall. |
|
|
33
33
|
| `status: "not_installed"` | Tweek is not present. Check `install_declined` before offering to install. |
|
|
34
34
|
| `install_declined: true` | User previously declined installation. **Do not offer to install again** unless the user explicitly asks. |
|
|
@@ -142,7 +142,6 @@ Trust mode is auto-detected from the terminal environment. It can be overridden
|
|
|
142
142
|
|
|
143
143
|
| Command | What It Does |
|
|
144
144
|
|---------|-------------|
|
|
145
|
-
| `tweek status` | Show installation status and active configuration |
|
|
146
145
|
| `tweek doctor` | Health check — verify all layers are active |
|
|
147
146
|
| `tweek doctor --verbose` | Detailed diagnostics with fix suggestions |
|
|
148
147
|
| `tweek logs show` | View recent security events |
|
|
@@ -185,7 +184,7 @@ For the full configuration format and examples, see `overrides-reference.md` in
|
|
|
185
184
|
| "Tweek isn't working" | Run `tweek doctor --verbose` and review the output. Common issues: hooks not registered, outdated patterns, missing dependencies. |
|
|
186
185
|
| "How do I update patterns?" | Run `tweek update` to fetch the latest pattern definitions. |
|
|
187
186
|
| "I want to pause tweek for this project" | Tell the user to run `tweek trust` in their terminal. This exempts the current project from screening. They can resume with `tweek untrust`. |
|
|
188
|
-
| "I want to disable tweek entirely" | Tell the user to run `tweek
|
|
187
|
+
| "I want to disable tweek entirely" | Tell the user to run `tweek unprotect claude-code` to remove hooks. Run `tweek protect claude-code` to re-enable later. |
|
|
189
188
|
| "What has tweek blocked recently?" | Run `tweek logs show` to see recent security events with details. |
|
|
190
189
|
|
|
191
190
|
---
|
|
@@ -6,12 +6,21 @@ Complete command reference for the `tweek` command-line tool.
|
|
|
6
6
|
|
|
7
7
|
## Installation & Setup
|
|
8
8
|
|
|
9
|
-
### `tweek
|
|
9
|
+
### `tweek protect`
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Set up Tweek protection for AI tools. With no arguments, launches an interactive wizard.
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
tweek
|
|
14
|
+
tweek protect # Interactive wizard — detects and protects all tools
|
|
15
|
+
tweek protect --status # Show protection status for all tools
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### `tweek protect claude-code`
|
|
19
|
+
|
|
20
|
+
Install Tweek hooks into Claude Code (replaces the former `tweek install` command).
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
tweek protect claude-code [OPTIONS]
|
|
15
24
|
```
|
|
16
25
|
|
|
17
26
|
| Option | Description |
|
|
@@ -25,15 +34,29 @@ tweek install [OPTIONS]
|
|
|
25
34
|
| `--skip-env-scan` | Skip scanning for credential files to migrate |
|
|
26
35
|
| `--backup / --no-backup` | Backup existing hooks before installation (default: backup) |
|
|
27
36
|
|
|
28
|
-
### `tweek
|
|
37
|
+
### `tweek protect claude-desktop`
|
|
38
|
+
|
|
39
|
+
Install Tweek as MCP server for Claude Desktop.
|
|
40
|
+
|
|
41
|
+
### `tweek protect chatgpt`
|
|
42
|
+
|
|
43
|
+
Install Tweek as MCP server for ChatGPT Desktop.
|
|
29
44
|
|
|
30
|
-
|
|
45
|
+
### `tweek protect gemini`
|
|
46
|
+
|
|
47
|
+
Install Tweek as MCP server for Gemini CLI.
|
|
48
|
+
|
|
49
|
+
### `tweek unprotect`
|
|
50
|
+
|
|
51
|
+
Remove Tweek protection from an AI tool (replaces the former `tweek uninstall` command).
|
|
31
52
|
|
|
32
53
|
```
|
|
33
|
-
tweek
|
|
54
|
+
tweek unprotect <tool> [--confirm]
|
|
55
|
+
tweek unprotect --all [--confirm]
|
|
34
56
|
```
|
|
35
57
|
|
|
36
|
-
By default removes from `./.claude/` (current project). Use `--global` to remove from `~/.claude
|
|
58
|
+
By default removes from `./.claude/` (current project). Use `--global` to remove from `~/.claude/` (for claude-code).
|
|
59
|
+
Use `--all` to remove Tweek from all tools at once.
|
|
37
60
|
|
|
38
61
|
---
|
|
39
62
|
|
|
@@ -82,14 +105,6 @@ tweek untrust /path/to/project # Untrust specific directory
|
|
|
82
105
|
|
|
83
106
|
## Diagnostics
|
|
84
107
|
|
|
85
|
-
### `tweek status`
|
|
86
|
-
|
|
87
|
-
Show installation status and active configuration.
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
tweek status
|
|
91
|
-
```
|
|
92
|
-
|
|
93
108
|
### `tweek doctor`
|
|
94
109
|
|
|
95
110
|
Run health checks on all screening layers.
|
|
@@ -313,12 +328,12 @@ tweek plugins search QUERY
|
|
|
313
328
|
|
|
314
329
|
## Proxy (API Interception)
|
|
315
330
|
|
|
316
|
-
### `tweek protect`
|
|
331
|
+
### `tweek protect openclaw`
|
|
317
332
|
|
|
318
|
-
Set up protection for
|
|
333
|
+
Set up proxy protection for OpenClaw.
|
|
319
334
|
|
|
320
335
|
```
|
|
321
|
-
tweek protect
|
|
336
|
+
tweek protect openclaw
|
|
322
337
|
```
|
|
323
338
|
|
|
324
339
|
### `tweek proxy start / stop`
|
|
@@ -144,18 +144,18 @@ def check_installation():
|
|
|
144
144
|
result["status"] = "fully_operational"
|
|
145
145
|
elif result["tweek_in_path"] and not result["hooks_registered"]:
|
|
146
146
|
result["status"] = "installed_no_hooks"
|
|
147
|
-
result["install_command"] = "tweek
|
|
147
|
+
result["install_command"] = "tweek protect claude-code"
|
|
148
148
|
elif not result["tweek_in_path"] and result["hooks_registered"]:
|
|
149
149
|
result["status"] = "hooks_only"
|
|
150
150
|
result["install_command"] = "pip install tweek"
|
|
151
151
|
else:
|
|
152
152
|
result["status"] = "not_installed"
|
|
153
153
|
if result["pipx_available"]:
|
|
154
|
-
result["install_command"] = "pipx install tweek && tweek
|
|
154
|
+
result["install_command"] = "pipx install tweek && tweek protect claude-code"
|
|
155
155
|
elif result["pip_available"]:
|
|
156
|
-
result["install_command"] = "pip install tweek && tweek
|
|
156
|
+
result["install_command"] = "pip install tweek && tweek protect claude-code"
|
|
157
157
|
else:
|
|
158
|
-
result["install_command"] = "python3 -m pip install tweek && tweek
|
|
158
|
+
result["install_command"] = "python3 -m pip install tweek && tweek protect claude-code"
|
|
159
159
|
|
|
160
160
|
return result
|
|
161
161
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tweek
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
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,7 @@ 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"
|
|
45
48
|
Requires-Dist: black>=23.0; extra == "dev"
|
|
46
49
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
47
50
|
Requires-Dist: twine>=4.0; extra == "dev"
|
|
@@ -105,11 +108,12 @@ pip install --user tweek
|
|
|
105
108
|
### Protect Your Tools
|
|
106
109
|
|
|
107
110
|
```bash
|
|
108
|
-
tweek
|
|
111
|
+
tweek protect # Interactive wizard — detects and protects all tools
|
|
112
|
+
tweek protect claude-code # Claude Code (CLI hooks)
|
|
109
113
|
tweek protect openclaw # OpenClaw (HTTP proxy)
|
|
110
|
-
tweek
|
|
111
|
-
tweek
|
|
112
|
-
tweek
|
|
114
|
+
tweek protect claude-desktop # Claude Desktop (MCP proxy)
|
|
115
|
+
tweek protect chatgpt # ChatGPT Desktop (MCP proxy)
|
|
116
|
+
tweek protect gemini # Gemini CLI (MCP proxy)
|
|
113
117
|
tweek proxy setup # Cursor, Windsurf, Continue.dev (HTTP proxy)
|
|
114
118
|
```
|
|
115
119
|
|
|
@@ -127,11 +131,11 @@ That's it. Tweek auto-detects your tools, applies all 259 attack patterns across
|
|
|
127
131
|
|
|
128
132
|
| Client | Integration | Setup |
|
|
129
133
|
|--------|------------|-------|
|
|
130
|
-
| **Claude Code** | CLI hooks (native) | `tweek
|
|
134
|
+
| **Claude Code** | CLI hooks (native) | `tweek protect claude-code` |
|
|
131
135
|
| **OpenClaw** | Proxy wrapping | `tweek protect openclaw` |
|
|
132
|
-
| **Claude Desktop** | MCP proxy | `tweek
|
|
133
|
-
| **ChatGPT Desktop** | MCP proxy | `tweek
|
|
134
|
-
| **Gemini CLI** | MCP proxy | `tweek
|
|
136
|
+
| **Claude Desktop** | MCP proxy | `tweek protect claude-desktop` |
|
|
137
|
+
| **ChatGPT Desktop** | MCP proxy | `tweek protect chatgpt` |
|
|
138
|
+
| **Gemini CLI** | MCP proxy | `tweek protect gemini` |
|
|
135
139
|
| **Cursor** | HTTP proxy | `tweek proxy setup` |
|
|
136
140
|
| **Windsurf** | HTTP proxy | `tweek proxy setup` |
|
|
137
141
|
| **Continue.dev** | HTTP proxy | `tweek proxy setup` |
|
|
@@ -169,14 +173,16 @@ See the full [Attack Patterns Reference](docs/ATTACK_PATTERNS.md) for all 259 pa
|
|
|
169
173
|
|
|
170
174
|
Most security tools that use AI send your data to an API. Tweek doesn't.
|
|
171
175
|
|
|
172
|
-
Tweek
|
|
176
|
+
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
177
|
|
|
174
178
|
| Property | Value |
|
|
175
179
|
|----------|-------|
|
|
176
|
-
| **Model** | DeBERTa-v3-base
|
|
177
|
-
| **
|
|
180
|
+
| **Model** | [ProtectAI DeBERTa-v3-base Prompt Injection v2](https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2) (Apache 2.0) |
|
|
181
|
+
| **Base Model** | [Microsoft DeBERTa-v3-base](https://huggingface.co/microsoft/deberta-v3-base) (MIT) |
|
|
182
|
+
| **Runtime** | ONNX Runtime (CPU-only, single thread) |
|
|
178
183
|
| **Privacy** | 100% on-device — zero network calls |
|
|
179
|
-
|
|
184
|
+
|
|
185
|
+
See [NOTICE](./NOTICE) for full third-party license texts and attribution.
|
|
180
186
|
|
|
181
187
|
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
188
|
|
|
@@ -278,4 +284,4 @@ To report a security vulnerability, email security@gettweek.com.
|
|
|
278
284
|
|
|
279
285
|
## License
|
|
280
286
|
|
|
281
|
-
[Apache 2.0](LICENSE)
|
|
287
|
+
[Apache 2.0](LICENSE) | [Third-Party Notices](NOTICE)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
tweek/__init__.py,sha256=
|
|
1
|
+
tweek/__init__.py,sha256=v1mBM39Sp-MgonHi8fotmfcN7dxbow_Eh9xdbSYnjN4,360
|
|
2
2
|
tweek/_keygen.py,sha256=UapwIKNSwaRWdqHoJoF3hmKuiux6aIiFGe8WVskTbI8,1286
|
|
3
3
|
tweek/audit.py,sha256=Bp4RETwdiHpT2EEi45atZa0LlJUOtALhrc3UT8MHvF8,8868
|
|
4
|
-
tweek/cli.py,sha256=
|
|
5
|
-
tweek/cli_helpers.py,sha256=
|
|
6
|
-
tweek/cli_model.py,sha256=
|
|
7
|
-
tweek/diagnostics.py,sha256=
|
|
4
|
+
tweek/cli.py,sha256=0AxYSIQ56Y2OHNVGSocNksYkiiLfUFNx5XvBUzCtZZI,254670
|
|
5
|
+
tweek/cli_helpers.py,sha256=Q2NTOkyRTOIPNLMqY2jA5_tuzDPksAGwGXYPRK3bzoY,5538
|
|
6
|
+
tweek/cli_model.py,sha256=iMZStFqA0Nqyzm4rxSbhD4v-AqcO6h5NI72AR7cldoY,12853
|
|
7
|
+
tweek/diagnostics.py,sha256=KbtXQH8QrRBoyIFWumL6q9--aQQdR0tUo2GzjMhwpII,24601
|
|
8
8
|
tweek/licensing.py,sha256=4Pt34t8Y60jaLMBYLjnmLs_0o_LUahOhGflhXeZtuPU,11703
|
|
9
9
|
tweek/config/__init__.py,sha256=C_kQm0LqYdM67E9wNi6bsX2V7xz7GY4HiICb_XlrX8A,362
|
|
10
10
|
tweek/config/allowed_dirs.yaml,sha256=dMF_DqKgQThzkdIEoXzDBfAjbopGrk0HTkiM7ENmBaU,788
|
|
11
11
|
tweek/config/families.yaml,sha256=jkNO0UsmX3MFlTKC9Or3p8_MlD3ZtHM0SrQIYFqx9i8,18212
|
|
12
|
-
tweek/config/manager.py,sha256=
|
|
12
|
+
tweek/config/manager.py,sha256=FTBJ4sMwnENH9tfvKB5d1SFve1R__k5j2KXb38vn1CA,39347
|
|
13
13
|
tweek/config/patterns.yaml,sha256=8ow--0qdPJNjIY94j-vDEcrHt-TYgf9uuPCiqSMCIEQ,85376
|
|
14
14
|
tweek/config/tiers.yaml,sha256=9hIXQ9izVKXd8ptoCsQiBo2r_XY8RvIk7VWrhWggkbc,10191
|
|
15
15
|
tweek/hooks/__init__.py,sha256=GcgDjPdhZayxmyZ4-GfBa-ISARNtt9087RsuprRq2-s,54
|
|
@@ -17,7 +17,7 @@ tweek/hooks/break_glass.py,sha256=GNMhCtLWPylNMlQ5QfsoUkEjgIT1Uk1Ik7HvRWeE5N8,46
|
|
|
17
17
|
tweek/hooks/feedback.py,sha256=uuA4opHYyBHC5sElBz-fr2Je3cg2DAv-aRHvETZcag0,6555
|
|
18
18
|
tweek/hooks/overrides.py,sha256=1Yw_NPpZMvcFG_uyNY-ouBKSSomnxOptRedSjzkkhmE,18635
|
|
19
19
|
tweek/hooks/post_tool_use.py,sha256=DiAnWOBd9t4vpMz1JsgUjYzToU6i-igesP2Vk83AAAc,17195
|
|
20
|
-
tweek/hooks/pre_tool_use.py,sha256=
|
|
20
|
+
tweek/hooks/pre_tool_use.py,sha256=70XbonRSGh8rYpDlI4R_Z5Ug2LwU4iLyLsS87I5xlqc,71743
|
|
21
21
|
tweek/integrations/__init__.py,sha256=sl7wFwbygmnruugX4bO2EUjoXxBlCpzTKbj-1zHuUPg,78
|
|
22
22
|
tweek/integrations/openclaw.py,sha256=jX99__ODGI7Cq6gclSTK2pI5lsI7UGh5_iCHmq1R8RY,13798
|
|
23
23
|
tweek/integrations/openclaw_server.py,sha256=Ah7wxsxKE2lQmIdlrFINvt5jW9U_bqqERfG3X2N5Aps,12533
|
|
@@ -27,7 +27,7 @@ tweek/logging/json_logger.py,sha256=zXOsFAufj3MF0TboM5zSS7V8uNBDJea7YkJHR-uQgBA,
|
|
|
27
27
|
tweek/logging/security_log.py,sha256=BwHDdrN0VCpqssStvsZdASFnyxVpANCq9xiSkFsEFFk,28486
|
|
28
28
|
tweek/mcp/__init__.py,sha256=AOFDrzDfjOvICMcN15Hz-iNCT0Kf6oyUBB-iNEW5Vr4,791
|
|
29
29
|
tweek/mcp/approval.py,sha256=WIFQi4ryXEFtgQyzQIshwgP5h_Th7Cxepx9NIhf2o_4,17885
|
|
30
|
-
tweek/mcp/approval_cli.py,sha256=
|
|
30
|
+
tweek/mcp/approval_cli.py,sha256=8WtmJF7KTLmdEF5wHqENaUJUzKEQej4CjRtFey4RcGg,11281
|
|
31
31
|
tweek/mcp/proxy.py,sha256=0p5OEaRsFuNRcGR3rnqprkPjTdSSYgrsU_XXQiFPS8c,24819
|
|
32
32
|
tweek/mcp/screening.py,sha256=ax5TK8ZSXb9uo5DFx3mxiYrBKjDBP0cTLNhA05TXb80,5421
|
|
33
33
|
tweek/mcp/server.py,sha256=3pF3piXUNtIf2-SUJPCjGZPD42esg2KFsVXpaBXrq3E,10901
|
|
@@ -83,7 +83,7 @@ tweek/sandbox/__init__.py,sha256=bT4ZAQkY2WOELdrRwf87hVdePXq6QPmvBgDs4WqDWgU,229
|
|
|
83
83
|
tweek/sandbox/docker_bridge.py,sha256=QD17ZuPVRgrbg0zFHdvji-VA11Jo5Td73_Kn6gbRaxc,5030
|
|
84
84
|
tweek/sandbox/executor.py,sha256=MLgMps4CNH_rtbbvseIKuuusMUznv6U7njPKwVCT-Bo,13186
|
|
85
85
|
tweek/sandbox/layers.py,sha256=Qd-kRfEKnBWax6n9h9COJeCTkvqnLAf157bHpGMfRYg,3263
|
|
86
|
-
tweek/sandbox/linux.py,sha256=
|
|
86
|
+
tweek/sandbox/linux.py,sha256=mKA3rI--TmJnVU6uE2kAxBAD8DGZjHUHlZ-sSLzuoWs,8706
|
|
87
87
|
tweek/sandbox/profile_generator.py,sha256=J-nNold-J1YxuSaX5BdQ_lcCC03ElwPJT7fJ4UciXfc,10957
|
|
88
88
|
tweek/sandbox/project.py,sha256=SqD4g4i1VqfWTdm--6gBzTC8AZCdHuyPLR37Y9jp30k,19575
|
|
89
89
|
tweek/sandbox/registry.py,sha256=ZZDQYeJMNAJ0FrFEayo1KyC5r3qXSBx6Tu-JcXIMjtI,5060
|
|
@@ -98,12 +98,12 @@ tweek/security/model_registry.py,sha256=XscpZcWaaJwHldX2T9C1T1zSvJ3lm0aSW4nIhwRp
|
|
|
98
98
|
tweek/security/rate_limiter.py,sha256=bY8VIkQ-wCbNOYTLwD4MsMBoHk59zPWeZCkuE8Zntm8,24185
|
|
99
99
|
tweek/security/secret_scanner.py,sha256=G-bbMwsAJD197BEOnZJdn_qphS4RNPK_wpLfkpiLuFU,18774
|
|
100
100
|
tweek/security/session_analyzer.py,sha256=-Ylp583VZ_YJRkN5JZrYpaK1sVbiM6KP7ZwLBzWpiCI,24260
|
|
101
|
-
tweek/skill_template/SKILL.md,sha256=
|
|
101
|
+
tweek/skill_template/SKILL.md,sha256=gBk_Ken77scVYeCs8imm1ASnNLDpBl-C0ufgWrrkQIA,10274
|
|
102
102
|
tweek/skill_template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
103
|
-
tweek/skill_template/cli-reference.md,sha256=
|
|
103
|
+
tweek/skill_template/cli-reference.md,sha256=DdXIEfTPvYn6iybVwA-r3CKkV1Mlx5Ub_sJf_lJrV2k,6913
|
|
104
104
|
tweek/skill_template/overrides-reference.md,sha256=xlc07wXXsCOrx60wMD7LZ7fn5Z_dhLuj5Mgx04-xGQ0,4509
|
|
105
105
|
tweek/skill_template/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
|
-
tweek/skill_template/scripts/check_installed.py,sha256
|
|
106
|
+
tweek/skill_template/scripts/check_installed.py,sha256=-pMmfgBjdbwb5u2t9rJ0dMBz7MGYgiZM5db3tiNZgO4,5878
|
|
107
107
|
tweek/skills/__init__.py,sha256=DyTvK8n5Lb-idkJhXCVytpiZjNfWveCtNkSL6o8dxHM,1209
|
|
108
108
|
tweek/skills/config.py,sha256=I95wK9CBj_UiHwFuxfE8yRl7cmFiqdY0hXfF3BHP0X8,4782
|
|
109
109
|
tweek/skills/fingerprints.py,sha256=YjPsTxqotzGlyMIgfgewSoNDTLU8_-p9fY_a44LJTjU,6027
|
|
@@ -113,10 +113,11 @@ tweek/skills/scanner.py,sha256=PaeZNnwxLTGls2O3hQaDgBhGw9jVJThPjfKCY_05_nI,27574
|
|
|
113
113
|
tweek/vault/__init__.py,sha256=L408fjdRYL8-VqLEsyyHSO9PkBDhd_2mPIbrCu53YhM,980
|
|
114
114
|
tweek/vault/cross_platform.py,sha256=D4UvX_7OpSo8iRx5sc2OUUWQIk8JHhgeFBYk1MbyIj4,8251
|
|
115
115
|
tweek/vault/keychain.py,sha256=XL18-SUj7HwuqxLXZDViuCH81--KMu68jN9Szn1aeyw,10624
|
|
116
|
-
tweek-0.
|
|
116
|
+
tweek-0.3.0.dist-info/licenses/LICENSE,sha256=rjoDzr1vAf0bsqZglpIyekU5aewIkCk4jHZZDvVI2BE,15269
|
|
117
|
+
tweek-0.3.0.dist-info/licenses/NOTICE,sha256=taQokyDes5UTRNEC67G-13VmqvUyTOncrrT33pCcWL0,8729
|
|
117
118
|
tweek-openclaw-plugin/node_modules/flatted/python/flatted.py,sha256=UYburBDqkySaTfSpntPCUJRxiBGcplusJM7ECX8FEgA,3860
|
|
118
|
-
tweek-0.
|
|
119
|
-
tweek-0.
|
|
120
|
-
tweek-0.
|
|
121
|
-
tweek-0.
|
|
122
|
-
tweek-0.
|
|
119
|
+
tweek-0.3.0.dist-info/METADATA,sha256=4eLu77u_VjfeqHnZ_-sIXRthm3In7dOHRnGkAaqQy2Y,11889
|
|
120
|
+
tweek-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
121
|
+
tweek-0.3.0.dist-info/entry_points.txt,sha256=YXThD6UiF5XQXwqW33sphsvz-Bl4Zm6pm-xq-5wcCYE,1337
|
|
122
|
+
tweek-0.3.0.dist-info/top_level.txt,sha256=jtNcCxjoGXN8IBqEVL0F3LHDrZD_B0S-4XF9-Ur7Pbc,28
|
|
123
|
+
tweek-0.3.0.dist-info/RECORD,,
|