tweek 0.3.0__py3-none-any.whl → 0.4.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.
Files changed (63) hide show
  1. tweek/__init__.py +2 -2
  2. tweek/audit.py +2 -2
  3. tweek/cli.py +78 -6559
  4. tweek/cli_config.py +643 -0
  5. tweek/cli_configure.py +413 -0
  6. tweek/cli_core.py +718 -0
  7. tweek/cli_dry_run.py +390 -0
  8. tweek/cli_helpers.py +316 -0
  9. tweek/cli_install.py +1666 -0
  10. tweek/cli_logs.py +301 -0
  11. tweek/cli_mcp.py +148 -0
  12. tweek/cli_memory.py +343 -0
  13. tweek/cli_plugins.py +748 -0
  14. tweek/cli_protect.py +564 -0
  15. tweek/cli_proxy.py +405 -0
  16. tweek/cli_security.py +236 -0
  17. tweek/cli_skills.py +289 -0
  18. tweek/cli_uninstall.py +551 -0
  19. tweek/cli_vault.py +313 -0
  20. tweek/config/__init__.py +8 -0
  21. tweek/config/allowed_dirs.yaml +16 -17
  22. tweek/config/families.yaml +4 -1
  23. tweek/config/manager.py +49 -0
  24. tweek/config/models.py +307 -0
  25. tweek/config/patterns.yaml +29 -5
  26. tweek/config/templates/config.yaml.template +212 -0
  27. tweek/config/templates/env.template +45 -0
  28. tweek/config/templates/overrides.yaml.template +121 -0
  29. tweek/config/templates/tweek.yaml.template +20 -0
  30. tweek/config/templates.py +136 -0
  31. tweek/config/tiers.yaml +5 -4
  32. tweek/diagnostics.py +112 -32
  33. tweek/hooks/overrides.py +4 -0
  34. tweek/hooks/post_tool_use.py +46 -1
  35. tweek/hooks/pre_tool_use.py +149 -49
  36. tweek/integrations/openclaw.py +84 -0
  37. tweek/licensing.py +1 -1
  38. tweek/mcp/__init__.py +7 -9
  39. tweek/mcp/clients/chatgpt.py +2 -2
  40. tweek/mcp/clients/claude_desktop.py +2 -2
  41. tweek/mcp/clients/gemini.py +2 -2
  42. tweek/mcp/proxy.py +165 -1
  43. tweek/memory/provenance.py +438 -0
  44. tweek/memory/queries.py +2 -0
  45. tweek/memory/safety.py +23 -4
  46. tweek/memory/schemas.py +1 -0
  47. tweek/memory/store.py +101 -71
  48. tweek/plugins/screening/heuristic_scorer.py +1 -1
  49. tweek/security/integrity.py +77 -0
  50. tweek/security/llm_reviewer.py +162 -68
  51. tweek/security/local_reviewer.py +44 -2
  52. tweek/security/model_registry.py +73 -7
  53. tweek/skill_template/overrides-reference.md +1 -1
  54. tweek/skills/context.py +221 -0
  55. tweek/skills/scanner.py +2 -2
  56. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/METADATA +9 -7
  57. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/RECORD +62 -39
  58. tweek/mcp/server.py +0 -320
  59. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/WHEEL +0 -0
  60. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/entry_points.txt +0 -0
  61. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/LICENSE +0 -0
  62. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/NOTICE +0 -0
  63. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/top_level.txt +0 -0
tweek/config/models.py ADDED
@@ -0,0 +1,307 @@
1
+ """
2
+ Pydantic models for Tweek configuration validation.
3
+
4
+ These models define the schema for tiers.yaml (the main configuration file)
5
+ and patterns.yaml (attack pattern definitions). They provide:
6
+ - Type-safe configuration loading with automatic validation
7
+ - Human-readable error messages for invalid configuration
8
+ - JSON Schema export for documentation and IDE support
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ from enum import Enum
15
+ from typing import Any, Dict, List, Optional
16
+
17
+ from pydantic import BaseModel, Field, field_validator, model_validator
18
+
19
+
20
+ # ============================================================================
21
+ # Enums
22
+ # ============================================================================
23
+
24
+
25
+ class SecurityTierValue(str, Enum):
26
+ """Valid security tier values."""
27
+ SAFE = "safe"
28
+ DEFAULT = "default"
29
+ RISKY = "risky"
30
+ DANGEROUS = "dangerous"
31
+
32
+
33
+ class NonEnglishHandling(str, Enum):
34
+ """How non-English content is handled during screening."""
35
+ ESCALATE = "escalate"
36
+ TRANSLATE = "translate"
37
+ BOTH = "both"
38
+ NONE = "none"
39
+
40
+
41
+ class PatternSeverity(str, Enum):
42
+ """Severity levels for attack patterns."""
43
+ CRITICAL = "critical"
44
+ HIGH = "high"
45
+ MEDIUM = "medium"
46
+ LOW = "low"
47
+
48
+
49
+ class PatternConfidence(str, Enum):
50
+ """Confidence levels for attack pattern matches."""
51
+ DETERMINISTIC = "deterministic"
52
+ HEURISTIC = "heuristic"
53
+ CONTEXTUAL = "contextual"
54
+
55
+
56
+ # ============================================================================
57
+ # Configuration Section Models
58
+ # ============================================================================
59
+
60
+
61
+ class LLMReviewLocalConfig(BaseModel):
62
+ """Configuration for local LLM server (Ollama, LM Studio)."""
63
+ enabled: bool = True
64
+ probe_timeout: float = Field(default=2.0, gt=0)
65
+ timeout_seconds: float = Field(default=30.0, gt=0)
66
+ ollama_host: Optional[str] = None
67
+ lm_studio_host: Optional[str] = None
68
+ preferred_models: List[str] = Field(default_factory=list)
69
+ validate_on_first_use: bool = True
70
+ min_validation_score: float = Field(default=0.6, ge=0.0, le=1.0)
71
+
72
+ model_config = {"extra": "allow"}
73
+
74
+
75
+ class LLMReviewFallbackConfig(BaseModel):
76
+ """Configuration for LLM fallback chain."""
77
+ enabled: bool = True
78
+ order: List[str] = Field(default_factory=lambda: ["local", "anthropic", "openai"])
79
+
80
+ model_config = {"extra": "allow"}
81
+
82
+
83
+ class LLMReviewConfig(BaseModel):
84
+ """Configuration for LLM-based semantic review."""
85
+ enabled: bool = True
86
+ provider: str = "auto"
87
+ model: str = "auto"
88
+ base_url: Optional[str] = None
89
+ api_key_env: Optional[str] = None
90
+ timeout_seconds: float = Field(default=15.0, gt=0)
91
+ local: LLMReviewLocalConfig = Field(default_factory=LLMReviewLocalConfig)
92
+ fallback: LLMReviewFallbackConfig = Field(default_factory=LLMReviewFallbackConfig)
93
+
94
+ model_config = {"extra": "allow"}
95
+
96
+
97
+ class RateLimitingConfig(BaseModel):
98
+ """Configuration for request rate limiting."""
99
+ enabled: bool = True
100
+ burst_window_seconds: int = Field(default=10, gt=0)
101
+ burst_threshold: int = Field(default=5, gt=0)
102
+ max_per_minute: int = Field(default=60, gt=0)
103
+ max_dangerous_per_minute: int = Field(default=10, gt=0)
104
+ max_same_command_per_minute: int = Field(default=5, gt=0)
105
+
106
+ model_config = {"extra": "allow"}
107
+
108
+
109
+ class SessionAnalysisConfig(BaseModel):
110
+ """Configuration for session-level analysis."""
111
+ enabled: bool = True
112
+ lookback_minutes: int = Field(default=30, gt=0)
113
+ alert_on_risk_score: float = Field(default=0.7, ge=0.0, le=1.0)
114
+
115
+ model_config = {"extra": "allow"}
116
+
117
+
118
+ class HeuristicScorerConfig(BaseModel):
119
+ """Configuration for heuristic scoring bridge."""
120
+ enabled: bool = True
121
+ threshold: float = Field(default=0.4, ge=0.0, le=1.0)
122
+ log_all_scores: bool = False
123
+
124
+ model_config = {"extra": "allow"}
125
+
126
+
127
+ class LocalModelConfig(BaseModel):
128
+ """Configuration for local ONNX model inference."""
129
+ enabled: bool = True
130
+ model: str = "auto"
131
+ escalate_to_llm: bool = True
132
+ escalate_min_confidence: float = Field(default=0.1, ge=0.0, le=1.0)
133
+ escalate_max_confidence: float = Field(default=0.9, ge=0.0, le=1.0)
134
+
135
+ @model_validator(mode="after")
136
+ def check_escalation_bounds(self) -> "LocalModelConfig":
137
+ if self.escalate_min_confidence >= self.escalate_max_confidence:
138
+ raise ValueError(
139
+ f"escalate_min_confidence ({self.escalate_min_confidence}) "
140
+ f"must be less than escalate_max_confidence ({self.escalate_max_confidence})"
141
+ )
142
+ return self
143
+
144
+ model_config = {"extra": "allow"}
145
+
146
+
147
+ class TierDefinition(BaseModel):
148
+ """Definition of a security tier."""
149
+ description: str
150
+ screening: List[str] = Field(default_factory=list)
151
+
152
+
153
+ class EscalationRule(BaseModel):
154
+ """A content-based escalation rule."""
155
+ pattern: str
156
+ description: str
157
+ escalate_to: SecurityTierValue
158
+
159
+ @field_validator("pattern")
160
+ @classmethod
161
+ def validate_regex(cls, v: str) -> str:
162
+ try:
163
+ re.compile(v)
164
+ except re.error as e:
165
+ raise ValueError(f"Invalid regex pattern: {e}") from e
166
+ return v
167
+
168
+
169
+ class SensitiveDirectory(BaseModel):
170
+ """A sensitive directory that triggers path boundary escalation."""
171
+ pattern: str
172
+ escalate_to: SecurityTierValue
173
+ description: str = ""
174
+
175
+
176
+ class PathBoundaryConfig(BaseModel):
177
+ """Configuration for path boundary escalation."""
178
+ enabled: bool = True
179
+ default_escalate_to: SecurityTierValue = SecurityTierValue.RISKY
180
+ sensitive_directories: List[SensitiveDirectory] = Field(default_factory=list)
181
+
182
+
183
+ class OpenClawConfig(BaseModel):
184
+ """Configuration for OpenClaw integration."""
185
+ enabled: bool = False
186
+ gateway_port: int = Field(default=18789, gt=0, le=65535)
187
+ scanner_port: int = Field(default=9878, gt=0, le=65535)
188
+ plugin_installed: bool = False
189
+ preset: str = "cautious"
190
+
191
+ model_config = {"extra": "allow"}
192
+
193
+
194
+ # ============================================================================
195
+ # Root Configuration Model
196
+ # ============================================================================
197
+
198
+
199
+ class TweekConfig(BaseModel):
200
+ """
201
+ Root Pydantic model for Tweek configuration (tiers.yaml / config.yaml).
202
+
203
+ Validates the merged configuration from builtin, user, and project layers.
204
+ Uses extra="allow" at the root level to be forward-compatible with new
205
+ config keys added in future versions.
206
+ """
207
+ version: Optional[int] = None
208
+
209
+ # Core tool/skill classification
210
+ tools: Dict[str, SecurityTierValue] = Field(default_factory=dict)
211
+ skills: Dict[str, SecurityTierValue] = Field(default_factory=dict)
212
+ default_tier: SecurityTierValue = SecurityTierValue.DEFAULT
213
+
214
+ # Tier definitions
215
+ tiers: Dict[str, TierDefinition] = Field(default_factory=dict)
216
+
217
+ # Screening configuration
218
+ llm_review: Optional[LLMReviewConfig] = None
219
+ rate_limiting: Optional[RateLimitingConfig] = None
220
+ session_analysis: Optional[SessionAnalysisConfig] = None
221
+ heuristic_scorer: Optional[HeuristicScorerConfig] = None
222
+ local_model: Optional[LocalModelConfig] = None
223
+
224
+ # Escalation rules
225
+ escalations: List[EscalationRule] = Field(default_factory=list)
226
+
227
+ # Path boundary
228
+ path_boundary: Optional[PathBoundaryConfig] = None
229
+
230
+ # Non-English handling
231
+ non_english_handling: NonEnglishHandling = NonEnglishHandling.ESCALATE
232
+
233
+ # Integration configs
234
+ proxy: Optional[Dict[str, Any]] = None
235
+ mcp: Optional[Dict[str, Any]] = None
236
+ sandbox: Optional[Dict[str, Any]] = None
237
+ isolation_chamber: Optional[Dict[str, Any]] = None
238
+ plugins: Optional[Dict[str, Any]] = None
239
+ openclaw: Optional[OpenClawConfig] = None
240
+
241
+ model_config = {"extra": "allow"}
242
+
243
+ @field_validator("tools", mode="before")
244
+ @classmethod
245
+ def coerce_tool_tiers(cls, v: Any) -> Any:
246
+ """Accept string tier values and coerce to SecurityTierValue."""
247
+ if isinstance(v, dict):
248
+ return {k: SecurityTierValue(val) if isinstance(val, str) else val for k, val in v.items()}
249
+ return v
250
+
251
+ @field_validator("skills", mode="before")
252
+ @classmethod
253
+ def coerce_skill_tiers(cls, v: Any) -> Any:
254
+ """Accept string tier values and coerce to SecurityTierValue."""
255
+ if isinstance(v, dict):
256
+ return {k: SecurityTierValue(val) if isinstance(val, str) else val for k, val in v.items()}
257
+ return v
258
+
259
+
260
+ # ============================================================================
261
+ # Pattern Schema Model
262
+ # ============================================================================
263
+
264
+
265
+ class PatternDefinition(BaseModel):
266
+ """A single attack pattern definition from patterns.yaml."""
267
+ id: int
268
+ name: str
269
+ description: str
270
+ regex: str
271
+ severity: PatternSeverity
272
+ confidence: PatternConfidence
273
+ family: Optional[str] = None
274
+
275
+ @field_validator("regex")
276
+ @classmethod
277
+ def validate_regex(cls, v: str) -> str:
278
+ try:
279
+ re.compile(v)
280
+ except re.error as e:
281
+ raise ValueError(f"Invalid regex in pattern: {e}") from e
282
+ return v
283
+
284
+
285
+ class PatternsConfig(BaseModel):
286
+ """Root model for patterns.yaml."""
287
+ version: int
288
+ pattern_count: int = 0
289
+ patterns: List[PatternDefinition] = Field(default_factory=list)
290
+
291
+ @model_validator(mode="after")
292
+ def check_pattern_count(self) -> "PatternsConfig":
293
+ actual = len(self.patterns)
294
+ if self.pattern_count > 0 and actual != self.pattern_count:
295
+ raise ValueError(
296
+ f"pattern_count ({self.pattern_count}) does not match "
297
+ f"actual number of patterns ({actual})"
298
+ )
299
+ return self
300
+
301
+ @model_validator(mode="after")
302
+ def check_unique_ids(self) -> "PatternsConfig":
303
+ ids = [p.id for p in self.patterns]
304
+ if len(ids) != len(set(ids)):
305
+ dupes = [i for i in ids if ids.count(i) > 1]
306
+ raise ValueError(f"Duplicate pattern IDs: {set(dupes)}")
307
+ return self
@@ -1,5 +1,5 @@
1
1
  # Tweek Attack Pattern Definitions v3
2
- # All 215 patterns included FREE
2
+ # All 262 patterns included FREE
3
3
  #
4
4
  # Update via: tweek update (pulls from github.com/gettweek/tweek)
5
5
  #
@@ -25,7 +25,7 @@
25
25
  # PRO tier adds: LLM review, session analysis, rate limiting
26
26
 
27
27
  version: 5
28
- pattern_count: 259
28
+ pattern_count: 262
29
29
 
30
30
  patterns:
31
31
  # ============================================================================
@@ -711,7 +711,7 @@ patterns:
711
711
  - id: 83
712
712
  name: document_metadata_injection
713
713
  description: "Hidden instructions in document metadata"
714
- regex: '(author|title|subject|keywords|description)\s*[=:]\s*.*?(execute|run|ignore|override|bypass)'
714
+ regex: '(author|title|subject|keywords|description)\s*[=:]\s*[^\n]{0,80}(execute|run|ignore|override|bypass)'
715
715
  severity: high
716
716
  confidence: heuristic
717
717
  family: prompt_injection
@@ -736,7 +736,7 @@ patterns:
736
736
  - id: 86
737
737
  name: log_to_leak
738
738
  description: "Log-To-Leak covert channel attack"
739
- regex: '(log|write|append|print).*?(secret|credential|token|key|password).*?(file|output|stream)'
739
+ regex: '(log|write|append|print)[^\n]{0,60}(secret|credential|token|key|password)[^\n]{0,60}(file|output|stream)'
740
740
  severity: high
741
741
  confidence: heuristic
742
742
  family: covert_channels
@@ -1514,7 +1514,7 @@ patterns:
1514
1514
  - id: 174
1515
1515
  name: leetspeak_instruction_bypass
1516
1516
  description: "Heavy character substitution of security-critical words"
1517
- regex: '([sS5$][yY][sS5$][tT7][eE3][mM]\s*[pP][rR][0oO][mM][pP][tT7]|[1iI][nN][sS5$][tT7][rR][uU][cC][tT7]|[cC][0oO][nN][fF][1iI][gG]|[eE3][xX][eE3][cC][uU][tT7][eE3])'
1517
+ regex: '((?=[a-zA-Z01357$]*[01357$])[sS5$][yY][sS5$][tT7][eE3][mM]\s*[pP][rR][0oO][mM][pP][tT7]|(?=[a-zA-Z01357$]*[01357$])[1iI][nN][sS5$][tT7][rR][uU][cC][tT7]|(?=[a-zA-Z01357$]*[01357$])[cC][0oO][nN][fF][1iI][gG]|(?=[a-zA-Z01357$]*[01357$])[eE3][xX][eE3][cC][uU][tT7][eE3])'
1518
1518
  severity: medium
1519
1519
  confidence: contextual
1520
1520
  family: prompt_injection
@@ -2251,3 +2251,27 @@ patterns:
2251
2251
  severity: low
2252
2252
  confidence: contextual
2253
2253
  family: prompt_injection
2254
+
2255
+ - id: 260
2256
+ name: summarize_instructions_extraction
2257
+ description: "Summarization-based system prompt extraction"
2258
+ regex: '(summarize|recap|outline|condense|describe|paraphrase)\s+.{0,30}(instructions|prompt|rules|guidelines|directives|configuration)\s+.{0,20}(given|told|provided|have|follow|received|programmed)'
2259
+ severity: medium
2260
+ confidence: contextual
2261
+ family: prompt_injection
2262
+
2263
+ - id: 261
2264
+ name: special_instructions_probe
2265
+ description: "Probing for special instructions or unique capabilities"
2266
+ regex: 'what\s+.{0,20}(instructions|capabilities|directives|rules)\s+.{0,30}(do\s+you\s+have|make\s+you|were\s+you|that\s+you)'
2267
+ severity: medium
2268
+ confidence: contextual
2269
+ family: prompt_injection
2270
+
2271
+ - id: 262
2272
+ name: system_prompt_reference_broad
2273
+ description: "Broad references to system prompt in extraction context"
2274
+ regex: '((your|my|the|its)\s+.{0,20}system[\s_]+prompt|system[\s_]+prompt\s*(say|would\s+say|output|reveal|share|display)|output\s+(system[\s_]+)?(prompt|configuration)\b|(instructions|directives)\s+(you|I|they|it)\s+(received|were\s+given|have\b|follow|got)|what.s\s+your\s+system[\s_]+prompt)'
2275
+ severity: medium
2276
+ confidence: contextual
2277
+ family: prompt_injection
@@ -0,0 +1,212 @@
1
+ # ============================================================================
2
+ # Tweek User Configuration (~/.tweek/config.yaml)
3
+ # ============================================================================
4
+ #
5
+ # This file overrides Tweek's bundled defaults. Only uncomment what you
6
+ # want to change -- everything else uses safe production defaults.
7
+ #
8
+ # Config hierarchy (highest priority wins):
9
+ # 1. Project: .tweek/config.yaml (per-project overrides)
10
+ # 2. User: ~/.tweek/config.yaml (this file)
11
+ # 3. Bundled: tweek/config/tiers.yaml (production defaults)
12
+ #
13
+ # Commands:
14
+ # tweek config edit Open this file in your editor
15
+ # tweek config show-defaults View all bundled defaults
16
+ # tweek config validate Check for errors
17
+ # tweek config list Show current tool/skill tiers
18
+ # tweek config preset <name> Apply a preset (paranoid|cautious|trusted)
19
+ #
20
+ # Full docs: https://github.com/gettweek/tweek/blob/main/docs/CONFIGURATION.md
21
+ # ============================================================================
22
+
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # LLM Review Provider (Layer 3 — semantic analysis)
26
+ # ---------------------------------------------------------------------------
27
+ # Analyzes suspicious commands/content using an LLM for deeper screening.
28
+ # Works alongside pattern matching (Layer 2) — not a replacement.
29
+ #
30
+ # Auto-detect order: Local ONNX model > Google > OpenAI > xAI > Anthropic
31
+ #
32
+ # IMPORTANT: API keys go in ~/.tweek/.env (not here). Run:
33
+ # tweek config edit env
34
+ #
35
+ # BILLING NOTE: Anthropic API keys are billed per-token, SEPARATELY from
36
+ # Claude Pro/Max subscriptions. Google Gemini has a free tier — recommended.
37
+ #
38
+ # llm_review:
39
+ # enabled: true
40
+ # provider: auto # auto | google | openai | xai | anthropic | local
41
+ # model: auto # auto = provider default. Defaults per provider:
42
+ # # google: gemini-2.0-flash
43
+ # # openai: gpt-4o-mini
44
+ # # xai: grok-2
45
+ # # anthropic: claude-3-5-haiku-latest
46
+ # # local: deberta-v3-injection
47
+ # timeout_seconds: 5.0 # Max wait for LLM response
48
+ # base_url: null # For OpenAI-compatible endpoints (Ollama, LM Studio, etc.)
49
+ # api_key_env: null # Override env var name (default: provider-specific)
50
+ #
51
+ # # Local LLM server settings (Ollama, LM Studio)
52
+ # local:
53
+ # enabled: true
54
+ # probe_timeout: 0.5 # Max probe time per server (seconds)
55
+ # timeout_seconds: 3.0 # Per-request timeout (local should be fast)
56
+ # ollama_host: null # Override (default: OLLAMA_HOST env or localhost:11434)
57
+ # lm_studio_host: null # Override (default: localhost:1234)
58
+ # preferred_models: [] # User override for model ranking
59
+ # validate_on_first_use: true
60
+ # min_validation_score: 0.6 # Must pass 3/5 validation commands
61
+ #
62
+ # # Fallback chain (try local first, then cloud)
63
+ # fallback:
64
+ # enabled: true
65
+ # order: [local, cloud]
66
+
67
+
68
+ # ---------------------------------------------------------------------------
69
+ # Local ONNX Model (Layer 3 — on-device classifier)
70
+ # ---------------------------------------------------------------------------
71
+ # On-device prompt injection classifier. No API key needed.
72
+ # Install: pip install tweek[local-models] && tweek model download
73
+ # When installed, runs before cloud LLM and escalates uncertain results.
74
+ #
75
+ # local_model:
76
+ # enabled: true
77
+ # model: auto # auto = default model, or explicit name
78
+ # escalate_to_llm: true # Escalate uncertain results to cloud LLM
79
+ # escalate_min_confidence: 0.1 # Below this = safe, skip escalation
80
+ # escalate_max_confidence: 0.9 # Above this = use local result, skip escalation
81
+
82
+
83
+ # ---------------------------------------------------------------------------
84
+ # Rate Limiting (Layer 1 — burst detection)
85
+ # ---------------------------------------------------------------------------
86
+ # Detects rapid-fire tool calls that may indicate automated attacks.
87
+ #
88
+ # rate_limiting:
89
+ # enabled: true
90
+ # burst_window_seconds: 5 # Time window for burst detection
91
+ # burst_threshold: 15 # Max calls in burst window
92
+ # max_per_minute: 60 # Overall rate limit
93
+ # max_dangerous_per_minute: 10 # Limit for dangerous-tier tools
94
+ # max_same_command_per_minute: 5 # Repeated identical commands
95
+
96
+
97
+ # ---------------------------------------------------------------------------
98
+ # Session Analysis (Layer 4 — cross-turn anomaly detection)
99
+ # ---------------------------------------------------------------------------
100
+ # Tracks patterns across multiple tool calls to detect multi-step attacks.
101
+ #
102
+ # session_analysis:
103
+ # enabled: true
104
+ # lookback_minutes: 30 # How far back to analyze
105
+ # alert_on_risk_score: 0.5 # Threshold for session risk alerts
106
+
107
+
108
+ # ---------------------------------------------------------------------------
109
+ # Heuristic Scorer (Layer 2.5 — signal-based escalation)
110
+ # ---------------------------------------------------------------------------
111
+ # Bridges pattern matching and LLM review. When no regex matches but
112
+ # content looks suspicious, scores it and may escalate to LLM.
113
+ #
114
+ # heuristic_scorer:
115
+ # enabled: true
116
+ # threshold: 0.4 # Score [0.0-1.0] to trigger LLM escalation
117
+ # log_all_scores: false # Log below-threshold scores (for tuning)
118
+
119
+
120
+ # ---------------------------------------------------------------------------
121
+ # Tool Tier Overrides
122
+ # ---------------------------------------------------------------------------
123
+ # Override the default security tier for specific tools.
124
+ # Tiers: safe | default | risky | dangerous
125
+ #
126
+ # Bundled defaults:
127
+ # Read: default (read-only but needs path screening)
128
+ # Glob: safe (file pattern matching)
129
+ # Grep: safe (search file contents)
130
+ # Edit: default (modify existing files)
131
+ # Write: risky (create/overwrite files)
132
+ # NotebookEdit: default (edit Jupyter notebooks)
133
+ # WebFetch: risky (fetch content from URLs)
134
+ # WebSearch: risky (search the web)
135
+ # Bash: dangerous (execute shell commands)
136
+ # Task: default (spawn subagent tasks)
137
+ #
138
+ # tools:
139
+ # Read: default
140
+ # Bash: dangerous
141
+
142
+
143
+ # ---------------------------------------------------------------------------
144
+ # Skill Tier Overrides
145
+ # ---------------------------------------------------------------------------
146
+ # Override the default tier for Claude Code skills.
147
+ #
148
+ # Bundled defaults:
149
+ # review-pr: safe (read-only PR review)
150
+ # explore: safe (read-only codebase exploration)
151
+ # commit: default (git commit operations)
152
+ # frontend-design: risky (generate frontend code)
153
+ # dev-browser: risky (browser automation)
154
+ # deploy: dangerous (deployment operations)
155
+ #
156
+ # skills:
157
+ # commit: default
158
+ # deploy: dangerous
159
+
160
+
161
+ # ---------------------------------------------------------------------------
162
+ # Non-English Language Handling
163
+ # ---------------------------------------------------------------------------
164
+ # English-only regex patterns can miss injection in other languages.
165
+ # Options:
166
+ # escalate - Auto-escalate to LLM review tier (default, recommended)
167
+ # translate - Translate to English before pattern matching (requires API key)
168
+ # both - Escalate AND translate (maximum coverage)
169
+ # none - No special handling (English-only patterns may miss attacks)
170
+ #
171
+ # non_english_handling: escalate
172
+
173
+
174
+ # ---------------------------------------------------------------------------
175
+ # Content-Based Escalations
176
+ # ---------------------------------------------------------------------------
177
+ # Regex patterns that bump a tool's tier based on content.
178
+ # These ADD to the bundled escalations (they don't replace them).
179
+ #
180
+ # escalations:
181
+ # - pattern: '\b(prod|production)\b'
182
+ # description: "Production environment reference"
183
+ # escalate_to: risky
184
+ #
185
+ # - pattern: 'rm\s+(-rf|-fr|--recursive)'
186
+ # description: "Recursive deletion"
187
+ # escalate_to: dangerous
188
+
189
+
190
+ # ---------------------------------------------------------------------------
191
+ # Path Boundary Escalation
192
+ # ---------------------------------------------------------------------------
193
+ # Escalates tier when tools access files outside the project directory.
194
+ #
195
+ # path_boundary:
196
+ # enabled: true
197
+ # default_escalate_to: risky # Generic out-of-project access
198
+ # sensitive_directories:
199
+ # - pattern: ".ssh"
200
+ # escalate_to: dangerous
201
+ # description: "SSH directory access"
202
+ # - pattern: ".aws"
203
+ # escalate_to: dangerous
204
+ # description: "AWS credentials directory"
205
+
206
+
207
+ # ---------------------------------------------------------------------------
208
+ # Default Tier
209
+ # ---------------------------------------------------------------------------
210
+ # Fallback tier for tools/skills not explicitly classified.
211
+ #
212
+ # default_tier: default
@@ -0,0 +1,45 @@
1
+ # ============================================================================
2
+ # Tweek API Keys (~/.tweek/.env)
3
+ # ============================================================================
4
+ #
5
+ # LLM provider keys for semantic security analysis (Layer 3).
6
+ # Only ONE provider key is needed. Uncomment the one you want to use.
7
+ #
8
+ # This file has restricted permissions (chmod 600) and is protected by
9
+ # Tweek's self-protection — only a human can edit it.
10
+ #
11
+ # Edit this file: tweek config edit env
12
+ # Test your key: tweek config llm
13
+ # ============================================================================
14
+
15
+
16
+ # --- Google Gemini (RECOMMENDED — free tier available) ---
17
+ # Get a free key: https://aistudio.google.com/apikey
18
+ # Default model: gemini-2.0-flash
19
+ #
20
+ # GOOGLE_API_KEY=your-google-api-key-here
21
+
22
+
23
+ # --- OpenAI ---
24
+ # Get a key: https://platform.openai.com/api-keys
25
+ # Default model: gpt-4o-mini
26
+ #
27
+ # OPENAI_API_KEY=your-openai-api-key-here
28
+
29
+
30
+ # --- xAI (Grok) ---
31
+ # Get a key: https://console.x.ai
32
+ # Default model: grok-2
33
+ #
34
+ # XAI_API_KEY=your-xai-api-key-here
35
+
36
+
37
+ # --- Anthropic ---
38
+ # Get a key: https://console.anthropic.com/settings/keys
39
+ # Default model: claude-3-5-haiku-latest
40
+ #
41
+ # IMPORTANT: Anthropic API keys are billed per-token, SEPARATELY from
42
+ # Claude Pro/Max subscriptions. Using this WILL incur additional charges
43
+ # on top of your plan. Google Gemini's free tier is recommended instead.
44
+ #
45
+ # ANTHROPIC_API_KEY=your-anthropic-api-key-here