veto-leash 0.1.3 → 1.0.0

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 (96) hide show
  1. package/README.md +110 -195
  2. package/dist/ast/builtins.d.ts +28 -0
  3. package/dist/ast/builtins.d.ts.map +1 -0
  4. package/dist/ast/builtins.js +361 -0
  5. package/dist/ast/builtins.js.map +1 -0
  6. package/dist/ast/checker.d.ts +17 -0
  7. package/dist/ast/checker.d.ts.map +1 -0
  8. package/dist/ast/checker.js +97 -0
  9. package/dist/ast/checker.js.map +1 -0
  10. package/dist/ast/index.d.ts +5 -0
  11. package/dist/ast/index.d.ts.map +1 -0
  12. package/dist/ast/index.js +7 -0
  13. package/dist/ast/index.js.map +1 -0
  14. package/dist/ast/parser.d.ts +55 -0
  15. package/dist/ast/parser.d.ts.map +1 -0
  16. package/dist/ast/parser.js +210 -0
  17. package/dist/ast/parser.js.map +1 -0
  18. package/dist/ast/query.d.ts +48 -0
  19. package/dist/ast/query.d.ts.map +1 -0
  20. package/dist/ast/query.js +102 -0
  21. package/dist/ast/query.js.map +1 -0
  22. package/dist/ast/validate-cli.d.ts +21 -0
  23. package/dist/ast/validate-cli.d.ts.map +1 -0
  24. package/dist/ast/validate-cli.js +73 -0
  25. package/dist/ast/validate-cli.js.map +1 -0
  26. package/dist/cli.js +105 -21
  27. package/dist/cli.js.map +1 -1
  28. package/dist/compiler/builtins.d.ts.map +1 -1
  29. package/dist/compiler/builtins.js +721 -4
  30. package/dist/compiler/builtins.js.map +1 -1
  31. package/dist/compiler/commands.d.ts +40 -0
  32. package/dist/compiler/commands.d.ts.map +1 -0
  33. package/dist/compiler/commands.js +311 -0
  34. package/dist/compiler/commands.js.map +1 -0
  35. package/dist/compiler/content.d.ts +160 -0
  36. package/dist/compiler/content.d.ts.map +1 -0
  37. package/dist/compiler/content.js +461 -0
  38. package/dist/compiler/content.js.map +1 -0
  39. package/dist/compiler/index.d.ts.map +1 -1
  40. package/dist/compiler/index.js +34 -7
  41. package/dist/compiler/index.js.map +1 -1
  42. package/dist/compiler/llm.d.ts.map +1 -1
  43. package/dist/compiler/llm.js +96 -9
  44. package/dist/compiler/llm.js.map +1 -1
  45. package/dist/compiler/prompt.d.ts +1 -1
  46. package/dist/compiler/prompt.d.ts.map +1 -1
  47. package/dist/compiler/prompt.js +247 -15
  48. package/dist/compiler/prompt.js.map +1 -1
  49. package/dist/config/leash-parser.d.ts +29 -0
  50. package/dist/config/leash-parser.d.ts.map +1 -0
  51. package/dist/config/leash-parser.js +70 -0
  52. package/dist/config/leash-parser.js.map +1 -0
  53. package/dist/config/loader.d.ts +2 -1
  54. package/dist/config/loader.d.ts.map +1 -1
  55. package/dist/config/loader.js +18 -8
  56. package/dist/config/loader.js.map +1 -1
  57. package/dist/config/schema.d.ts +8 -0
  58. package/dist/config/schema.d.ts.map +1 -1
  59. package/dist/config/schema.js +19 -0
  60. package/dist/config/schema.js.map +1 -1
  61. package/dist/config/watcher.d.ts +18 -0
  62. package/dist/config/watcher.d.ts.map +1 -0
  63. package/dist/config/watcher.js +102 -0
  64. package/dist/config/watcher.js.map +1 -0
  65. package/dist/matcher.d.ts +18 -0
  66. package/dist/matcher.d.ts.map +1 -1
  67. package/dist/matcher.js +43 -0
  68. package/dist/matcher.js.map +1 -1
  69. package/dist/native/claude-code.d.ts.map +1 -1
  70. package/dist/native/claude-code.js +294 -50
  71. package/dist/native/claude-code.js.map +1 -1
  72. package/dist/native/cursor.d.ts +14 -1
  73. package/dist/native/cursor.d.ts.map +1 -1
  74. package/dist/native/cursor.js +340 -34
  75. package/dist/native/cursor.js.map +1 -1
  76. package/dist/native/index.d.ts +5 -0
  77. package/dist/native/index.d.ts.map +1 -1
  78. package/dist/native/index.js +56 -10
  79. package/dist/native/index.js.map +1 -1
  80. package/dist/native/opencode.d.ts.map +1 -1
  81. package/dist/native/opencode.js +15 -3
  82. package/dist/native/opencode.js.map +1 -1
  83. package/dist/native/validator.d.ts +15 -0
  84. package/dist/native/validator.d.ts.map +1 -0
  85. package/dist/native/validator.js +343 -0
  86. package/dist/native/validator.js.map +1 -0
  87. package/dist/types.d.ts +114 -0
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/types.js.map +1 -1
  90. package/dist/wrapper/daemon.d.ts.map +1 -1
  91. package/dist/wrapper/daemon.js +31 -2
  92. package/dist/wrapper/daemon.js.map +1 -1
  93. package/languages/tree-sitter-javascript.wasm +0 -0
  94. package/languages/tree-sitter-tsx.wasm +0 -0
  95. package/languages/tree-sitter-typescript.wasm +0 -0
  96. package/package.json +5 -2
package/README.md CHANGED
@@ -3,7 +3,6 @@
3
3
  <p align="center"><strong>sudo for AI agents</strong></p>
4
4
  <p align="center">
5
5
  <a href="https://www.npmjs.com/package/veto-leash"><img src="https://img.shields.io/npm/v/veto-leash?style=flat-square&color=black" alt="npm version"></a>
6
- <a href="https://github.com/VulnZap/veto-leash/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/VulnZap/veto-leash/ci.yml?style=flat-square&color=black&label=tests" alt="CI"></a>
7
6
  <a href="https://github.com/VulnZap/veto-leash/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/veto-leash?style=flat-square&color=black" alt="License"></a>
8
7
  <a href="https://www.npmjs.com/package/veto-leash"><img src="https://img.shields.io/npm/dm/veto-leash?style=flat-square&color=black" alt="Downloads"></a>
9
8
  </p>
@@ -12,247 +11,163 @@
12
11
  Your AI agent has root access to your codebase. You have... vibes.
13
12
 
14
13
  ```bash
15
- leash cc "don't delete test files"
14
+ # One file. That's it.
15
+ echo "no lodash
16
+ no any types" > .leash
17
+
18
+ leash init # Auto-detects agents, installs hooks
16
19
  ```
17
20
 
18
- Now every destructive action requires explicit policy. No regex. No config files. Just English.
21
+ Now every action is validated with **AST-level precision**. Zero false positives. Zero config.
22
+
23
+ ## What's New in 1.0
24
+
25
+ - **🎯 AST Validation** - Tree-sitter parsing means `// import lodash` in comments is ignored
26
+ - **📄 Simple `.leash` format** - One rule per line, no YAML boilerplate
27
+ - **🔍 Auto-detection** - `leash init` finds and configures all your AI agents
28
+ - **⚡ Instant** - 95%+ policies use built-in rules (no LLM call needed)
19
29
 
20
30
  ## The Problem
21
31
 
22
- AI coding agents can delete your test files, wipe your .env, run arbitrary migrations. Current permission systems require you to write regex patterns and understand glob syntax. You want to say "protect my tests" and be done.
32
+ AI coding agents can `npm install lodash` when you want native methods. They'll sprinkle `any` types everywhere. They'll `git push --force` to main.
33
+
34
+ Regex-based blockers create false positives. A comment saying `// TODO: remove lodash` shouldn't trigger a block.
23
35
 
24
36
  ## The Solution
25
37
 
26
- veto-leash compiles natural language restrictions into precise policies **once**, then enforces them at runtime with zero LLM latency.
38
+ veto-leash uses **AST parsing** for surgical precision:
27
39
 
28
- ```
29
- "don't delete test files"
30
-
31
-
32
- ┌─────────────────────────────────────┐
33
- │ Semantic Compilation (100ms)
34
- │ • Understands "test files" = test │
35
- │ source code, not test-results.xml│
36
- │ • Gemini 2.0 Flash + JSON Schema │
37
- │ • Cached for instant reuse │
38
- └─────────────────────────────────────┘
39
-
40
-
41
- ┌─────────────────────────────────────┐
42
- │ Policy │
43
- │ action: delete │
44
- │ include: *.test.*, *.spec.*, │
45
- │ __tests__/**, test/** │
46
- │ exclude: test-results.*, coverage/ │
47
- └─────────────────────────────────────┘
48
-
49
-
50
- Enforcement (0ms per check)
51
- ```
40
+ | Code | Regex Result | AST Result |
41
+ | ------------------------ | ------------ | -------------------------- |
42
+ | `// import lodash` | ❌ BLOCKED | ✅ ALLOWED (comment) |
43
+ | `"use any type"` | ❌ BLOCKED | ✅ ALLOWED (string) |
44
+ | `const anyValue = 5` | ❌ BLOCKED | ✅ ALLOWED (variable name) |
45
+ | `import _ from 'lodash'` | ✅ BLOCKED | ✅ BLOCKED (correct) |
46
+
47
+ **This precision is our moat.** No other tool achieves zero false positives.
52
48
 
53
49
  ## Quick Start
54
50
 
55
51
  ```bash
56
- # Install
52
+ # Install globally
57
53
  npm install -g veto-leash
58
54
 
59
- # Get free Gemini API key (optional - builtins work without it)
60
- # https://aistudio.google.com/apikey
61
- export GEMINI_API_KEY="your-key"
55
+ # Create a simple .leash file
56
+ echo "no lodash
57
+ no any types
58
+ no console.log" > .leash
62
59
 
63
- # Use it
64
- leash cc "don't delete test files"
60
+ # One command setup
61
+ leash init
65
62
  ```
66
63
 
67
- That's it. Your Claude Code session now blocks test file deletions.
68
-
69
- ## How It Works
70
-
71
- ### Three Enforcement Modes
72
-
73
- | Mode | Use Case | How |
74
- |------|----------|-----|
75
- | **Wrapper** | Any agent | PATH hijacking, TCP daemon |
76
- | **Native** | Claude Code, Windsurf, OpenCode | Hooks directly into agent |
77
- | **Watchdog** | Background protection | File system monitoring, auto-restore |
78
-
79
- ### Native Integrations
64
+ That's it. `leash init` will:
80
65
 
81
- ```bash
82
- # Claude Code - PreToolUse hooks
83
- leash add "don't delete test files"
84
- leash install cc
85
-
86
- # Windsurf - Cascade hooks
87
- leash add "protect .env"
88
- leash install windsurf
89
-
90
- # OpenCode - permission.bash rules
91
- leash add "no migrations"
92
- leash install oc
93
- ```
66
+ 1. Detect installed agents (Claude Code, Cursor, OpenCode, Windsurf)
67
+ 2. Install native hooks for each
68
+ 3. Your policies are now enforced
94
69
 
95
- ### Wrapper Mode (Works with anything)
70
+ ## Simple `.leash` Format
96
71
 
97
- ```bash
98
- # Works with ANY CLI agent
99
- leash cc "don't delete test files"
100
- leash opencode "protect .env"
101
- leash cursor "no database migrations"
102
- leash aider "read-only src/core"
103
- leash my-custom-agent "protect config"
104
72
  ```
105
-
106
- ### Watchdog Mode (Catches everything)
107
-
108
- ```bash
109
- # Background file protection - catches programmatic changes too
110
- leash watch "protect test files"
73
+ # .leash - One rule per line
74
+ no lodash
75
+ no any types - enforces strict TypeScript
76
+ no console.log
77
+ prefer pnpm over npm
111
78
  ```
112
79
 
113
- ## Supported Agents
114
-
115
- | Agent | Native | Wrapper | Notes |
116
- |-------|--------|---------|-------|
117
- | Claude Code | PreToolUse hooks | PATH shims | Best support |
118
- | Windsurf | Cascade hooks | PATH shims | Full support |
119
- | OpenCode | permission.bash | PATH shims | Full support |
120
- | Cursor | .cursorrules | PATH shims | Guidance only |
121
- | Aider | .aider.conf.yml | PATH shims | Read-only files |
122
- | Codex CLI | - | Watchdog | OS sandbox |
123
- | GitHub Copilot | - | Wrapper | No hooks |
124
- | Any CLI tool | - | PATH shims | Universal |
80
+ Lines starting with `#` are comments. Optional reasons after `-`.
125
81
 
126
- ## Project Configuration
82
+ ## Built-in AST Rules
127
83
 
128
- Create a `.leash` file for team-wide policies:
84
+ These work **instantly** with zero LLM calls:
129
85
 
130
- ```yaml
131
- # .leash
132
- version: 1
86
+ | Rule | What It Catches |
87
+ | --------------------- | ------------------------------------------ |
88
+ | `no lodash` | ES imports, require(), dynamic import() |
89
+ | `no any types` | Type annotations, generics, as expressions |
90
+ | `no console.log` | console.log(), console['log']() |
91
+ | `no eval` | eval(), new Function() |
92
+ | `no class components` | React.Component, PureComponent |
93
+ | `no innerhtml` | innerHTML, dangerouslySetInnerHTML |
94
+ | `no debugger` | debugger statements |
95
+ | `no var` | var declarations |
133
96
 
134
- policies:
135
- - "don't delete test files"
136
- - "protect .env"
137
- - "no database migrations"
97
+ ## Native Agent Support
138
98
 
139
- settings:
140
- fail_closed: true
141
- audit_log: true
142
- ```
143
-
144
- Then sync to your agents:
145
-
146
- ```bash
147
- leash sync cc
148
- leash sync windsurf
149
- ```
99
+ | Agent | How It Works | Status |
100
+ | --------------- | ------------------------------------ | ------------ |
101
+ | **Claude Code** | PreToolUse hooks with AST validation | ✅ Full |
102
+ | **Cursor** | hooks.json + beforeShellExecution | ✅ Full |
103
+ | **OpenCode** | permission.bash deny rules | ✅ Full |
104
+ | **Windsurf** | Cascade pre_write_code hooks | ✅ Full |
105
+ | **Aider** | .aider.conf.yml read-only | ✅ Partial |
106
+ | **Any CLI** | Wrapper mode (PATH hijacking) | ✅ Universal |
150
107
 
151
108
  ## Commands
152
109
 
153
110
  ```
154
- leash <agent> "<restriction>" Wrap agent with policy
155
- leash watch "<restriction>" Background file protection
156
- leash explain "<restriction>" Preview policy without installing
157
- leash add "<restriction>" Save policy for native install
158
- leash init Create .leash config file
159
- leash sync [agent] Apply .leash policies
160
- leash install <agent> Install native hooks
161
- leash uninstall <agent> Remove native hooks
162
- leash list Show saved policies
163
- leash audit [--tail] [--clear] View audit log
164
- leash login Leash Cloud (coming soon)
111
+ leash init Auto-detect agents, install hooks
112
+ leash sync [agent] Apply .leash policies to agents
113
+ leash add "<rule>" Add a policy
114
+ leash install <agent> Install hooks for specific agent
115
+ leash explain "<rule>" Preview what a rule catches
116
+ leash watch "<rule>" Background file protection
117
+ leash audit [--tail] View enforcement log
165
118
  leash status Show active sessions
166
- leash clear Clear compilation cache
167
119
  ```
168
120
 
169
- ## Built-in Patterns
170
-
171
- These work instantly without an API key:
172
-
173
- | Phrase | What It Protects |
174
- |--------|------------------|
175
- | `test files` | `*.test.*`, `*.spec.*`, `__tests__/**` |
176
- | `.env` | `.env`, `.env.*`, excluding `.env.example` |
177
- | `migrations` | `**/migrations/**`, `prisma/migrations/**` |
178
- | `config` | `*.config.*`, `tsconfig*`, `.eslintrc*` |
179
- | `lock files` | `package-lock.json`, `yarn.lock`, etc. |
180
-
181
- ## Examples
182
-
183
- ```bash
184
- # Preview what a policy protects
185
- leash explain "don't delete test files"
186
-
187
- # Wrapper mode - intercepts shell commands
188
- leash cc "don't delete test files"
189
-
190
- # Native mode - integrates with agent's permission system
191
- leash add "don't delete test files"
192
- leash add "protect .env"
193
- leash install cc
194
-
195
- # Watchdog mode - file system monitoring
196
- leash watch "protect test files"
121
+ ## How It Works
197
122
 
198
- # Team config
199
- leash init # Creates .leash
200
- leash sync windsurf # Applies to agent
123
+ ```
124
+ User: "no lodash"
125
+
126
+ ┌─────────────────────────────────────────┐
127
+ │ 1. Check builtins (instant, no LLM) │
128
+ │ → Found: "no lodash" builtin │
129
+ └─────────────────────────────────────────┘
130
+
131
+ ┌─────────────────────────────────────────┐
132
+ │ 2. Runtime: Write/Edit intercepted │
133
+ │ → Regex pre-filter: contains │
134
+ │ "lodash"? Yes → continue │
135
+ │ → AST parse (5ms, cached) │
136
+ │ → Query: import_statement with │
137
+ │ source matching "lodash" │
138
+ │ → BLOCKED with line/column │
139
+ └─────────────────────────────────────────┘
201
140
  ```
202
141
 
203
- ## Environment Variables
204
-
205
- | Variable | Description |
206
- |----------|-------------|
207
- | `GEMINI_API_KEY` | Required for custom restrictions (not builtins) |
208
- | `LEASH_CLOUD_URL` | Leash Cloud API endpoint (coming soon) |
209
- | `LEASH_API_KEY` | Leash Cloud API key (coming soon) |
142
+ **Key insight**: Regex pre-filter skips 95%+ of files instantly. AST parsing only runs when needed.
210
143
 
211
- ## Leash Cloud (Coming Soon)
144
+ ## Environment Variables
212
145
 
213
- - Team-wide policy sync
214
- - Centralized audit logs
215
- - LLM credits for compilation
216
- - Policy analytics
146
+ | Variable | Description |
147
+ | ---------------- | ------------------------------------------- |
148
+ | `GEMINI_API_KEY` | Only needed for custom rules (not builtins) |
217
149
 
218
- Join the waitlist: https://leash.cloud
150
+ Get a free API key: https://aistudio.google.com/apikey
219
151
 
220
152
  ## Philosophy
221
153
 
222
- 1. **Semantic over syntactic** - "test files" means test source code, not files with "test" in the name
223
- 2. **Compile once, enforce always** - LLM runs once at startup, enforcement is instant
224
- 3. **Fail closed** - If the daemon is unreachable, commands are blocked
225
- 4. **Defense in depth** - Native hooks + wrapper mode + watchdog = comprehensive protection
226
- 5. **No config tax** - Natural language in, protection out
227
-
228
- ## How veto-leash Protects Files
229
-
230
- When you run `leash cc "don't delete test files"`:
231
-
232
- 1. **Compile**: Natural language → glob patterns (via Gemini 2.0 Flash)
233
- 2. **Start daemon**: TCP server on localhost (random port)
234
- 3. **Create shims**: Shell wrappers for `rm`, `git rm`, etc.
235
- 4. **Launch agent**: With modified PATH
236
- 5. **Intercept**: Every shell command checks daemon first
237
- 6. **Block or allow**: Based on policy
154
+ 1. **Surgeon-level precision** - AST parsing = zero false positives
155
+ 2. **Invisible until needed** - Auto-detection, background enforcement
156
+ 3. **Steroid, not weight** - Makes AI agents _better_, not slower
157
+ 4. **Natural language policies** - `no lodash` not `{ "rule": "no-import", "pattern": "^lodash" }`
238
158
 
239
- The agent never knows veto-leash is there - it just sees commands failing with clear error messages.
159
+ ## Test Suite
240
160
 
241
- ## Security Model
242
-
243
- - Localhost only (`127.0.0.1`)
244
- - Random port each session
245
- - Temp directory cleaned on exit
246
- - No eval - patterns validated with micromatch
247
- - Fail closed by default
248
- - API key from environment only
249
-
250
- ## Platform Support
251
-
252
- - macOS
253
- - Linux
254
- - Windows (PowerShell shims)
255
- - WSL
161
+ ```
162
+ 229 tests passing
163
+ ├── 41 AST validation tests
164
+ ├── 93 content matching tests
165
+ ├── 41 command interception tests
166
+ ├── 17 pattern matcher tests
167
+ ├── 16 builtin rules tests
168
+ ├── 12 parser tests
169
+ └── 9 session tests
170
+ ```
256
171
 
257
172
  ## License
258
173
 
@@ -0,0 +1,28 @@
1
+ import type { ASTRule } from '../types.js';
2
+ /**
3
+ * Pre-compiled AST queries for common restrictions.
4
+ * These replace regex-based content rules with precise structural queries.
5
+ *
6
+ * Key advantages over regex:
7
+ * - Zero false positives (AST ignores comments and strings)
8
+ * - Catches all variants (destructuring, bracket notation, dynamic imports)
9
+ * - Can express structural constraints regex cannot
10
+ *
11
+ * Query syntax: tree-sitter S-expressions
12
+ * - (node_type) matches any node of that type
13
+ * - (node_type field: (child)) matches with specific field
14
+ * - @name captures the node
15
+ * - (#eq? @name "value") exact string match on node text
16
+ * - (#match? @name "regex") regex match on node text
17
+ */
18
+ export declare const AST_BUILTINS: Record<string, ASTRule[]>;
19
+ /**
20
+ * Get all AST rules for a restriction
21
+ * Normalizes common variations (e.g., "no any" vs "no any types")
22
+ */
23
+ export declare function getASTRules(restriction: string): ASTRule[] | null;
24
+ /**
25
+ * List all available AST builtin keys
26
+ */
27
+ export declare function listASTBuiltins(): string[];
28
+ //# sourceMappingURL=builtins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/ast/builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAyUlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CA0BjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}