veto-leash 1.2.0 → 2.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 (68) hide show
  1. package/README.md +76 -45
  2. package/bin/leash +0 -0
  3. package/bin/leash.js +45 -0
  4. package/dist/ast/builtins.d.ts.map +1 -1
  5. package/dist/ast/builtins.js +469 -9
  6. package/dist/ast/builtins.js.map +1 -1
  7. package/dist/ast/parser.d.ts +22 -2
  8. package/dist/ast/parser.d.ts.map +1 -1
  9. package/dist/ast/parser.js +124 -11
  10. package/dist/ast/parser.js.map +1 -1
  11. package/dist/cli.js +81 -31
  12. package/dist/cli.js.map +1 -1
  13. package/dist/compiler/llm.js +7 -7
  14. package/dist/compiler/llm.js.map +1 -1
  15. package/dist/compiler/prompt.d.ts +1 -1
  16. package/dist/compiler/prompt.d.ts.map +1 -1
  17. package/dist/compiler/prompt.js +148 -45
  18. package/dist/compiler/prompt.js.map +1 -1
  19. package/dist/config/loader.d.ts +1 -1
  20. package/dist/config/loader.d.ts.map +1 -1
  21. package/dist/config/loader.js +27 -11
  22. package/dist/config/loader.js.map +1 -1
  23. package/dist/config/schema.d.ts +1 -0
  24. package/dist/config/schema.d.ts.map +1 -1
  25. package/dist/config/schema.js +3 -2
  26. package/dist/config/schema.js.map +1 -1
  27. package/dist/native/claude-code.js +6 -5
  28. package/dist/native/claude-code.js.map +1 -1
  29. package/dist/native/cursor.d.ts +1 -1
  30. package/dist/native/cursor.d.ts.map +1 -1
  31. package/dist/native/cursor.js +65 -8
  32. package/dist/native/cursor.js.map +1 -1
  33. package/dist/native/index.js +2 -2
  34. package/dist/native/index.js.map +1 -1
  35. package/dist/native/opencode.d.ts +1 -1
  36. package/dist/native/opencode.d.ts.map +1 -1
  37. package/dist/native/opencode.js +181 -10
  38. package/dist/native/opencode.js.map +1 -1
  39. package/dist/native/validator.js +6 -4
  40. package/dist/native/validator.js.map +1 -1
  41. package/dist/native/windsurf.d.ts +1 -1
  42. package/dist/native/windsurf.d.ts.map +1 -1
  43. package/dist/native/windsurf.js +63 -8
  44. package/dist/native/windsurf.js.map +1 -1
  45. package/dist/opencode-plugin/veto-leash.d.ts +54 -0
  46. package/dist/opencode-plugin/veto-leash.d.ts.map +1 -0
  47. package/dist/opencode-plugin/veto-leash.js +226 -0
  48. package/dist/opencode-plugin/veto-leash.js.map +1 -0
  49. package/go/leash-darwin-amd64 +0 -0
  50. package/go/leash-darwin-arm64 +0 -0
  51. package/go/leash-linux-amd64 +0 -0
  52. package/go/leash-linux-arm64 +0 -0
  53. package/go/leash-windows-amd64.exe +0 -0
  54. package/package.json +9 -4
  55. package/scripts/postinstall.js +57 -0
  56. package/languages/tree-sitter-bash.wasm +0 -0
  57. package/languages/tree-sitter-c.wasm +0 -0
  58. package/languages/tree-sitter-cpp.wasm +0 -0
  59. package/languages/tree-sitter-go.wasm +0 -0
  60. package/languages/tree-sitter-java.wasm +0 -0
  61. package/languages/tree-sitter-javascript.wasm +0 -0
  62. package/languages/tree-sitter-kotlin.wasm +0 -0
  63. package/languages/tree-sitter-php.wasm +0 -0
  64. package/languages/tree-sitter-python.wasm +0 -0
  65. package/languages/tree-sitter-ruby.wasm +0 -0
  66. package/languages/tree-sitter-rust.wasm +0 -0
  67. package/languages/tree-sitter-tsx.wasm +0 -0
  68. package/languages/tree-sitter-typescript.wasm +0 -0
package/README.md CHANGED
@@ -15,17 +15,17 @@ Your AI agent has root access to your codebase. You have... vibes.
15
15
  echo "no lodash
16
16
  no any types" > .leash
17
17
 
18
- leash init # Auto-detects agents, installs hooks
18
+ leash # Interactive dashboard
19
19
  ```
20
20
 
21
21
  Now every action is validated with **AST-level precision**. Zero false positives. Zero config.
22
22
 
23
- ## What's New in 1.0
23
+ ## What's New in 2.0
24
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)
25
+ - **Native Go TUI** - Beautiful interactive dashboard built with Bubble Tea
26
+ - **4.5MB binary** - Instant startup, no Node.js required at runtime
27
+ - **Cross-platform** - Native binaries for macOS, Linux, Windows (arm64 + amd64)
28
+ - **Hybrid engine** - Go for speed, TypeScript for LLM compilation + AST validation
29
29
 
30
30
  ## The Problem
31
31
 
@@ -39,10 +39,10 @@ veto-leash uses **AST parsing** for surgical precision:
39
39
 
40
40
  | Code | Regex Result | AST Result |
41
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) |
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
46
 
47
47
  **This precision is our moat.** No other tool achieves zero false positives.
48
48
 
@@ -52,20 +52,28 @@ veto-leash uses **AST parsing** for surgical precision:
52
52
  # Install globally
53
53
  npm install -g veto-leash
54
54
 
55
- # Create a simple .leash file
55
+ # Create policies
56
56
  echo "no lodash
57
57
  no any types
58
- no console.log" > .leash
58
+ prefer pnpm" > .leash
59
59
 
60
- # One command setup
61
- leash init
60
+ # Launch the dashboard
61
+ leash
62
62
  ```
63
63
 
64
- That's it. `leash init` will:
64
+ The interactive TUI lets you:
65
+ - Add and manage policies
66
+ - Install hooks for detected agents
67
+ - Monitor enforcement in real-time
68
+ - View audit logs
65
69
 
66
- 1. Detect installed agents (Claude Code, Cursor, OpenCode, Windsurf)
67
- 2. Install native hooks for each
68
- 3. Your policies are now enforced
70
+ Or use CLI commands directly:
71
+
72
+ ```bash
73
+ leash init # Auto-detect agents, install hooks
74
+ leash add "no axios" # Add a policy
75
+ leash sync # Apply to all agents
76
+ ```
69
77
 
70
78
  ## Simple `.leash` Format
71
79
 
@@ -75,11 +83,12 @@ no lodash
75
83
  no any types - enforces strict TypeScript
76
84
  no console.log
77
85
  prefer pnpm over npm
86
+ protect .env files
78
87
  ```
79
88
 
80
89
  Lines starting with `#` are comments. Optional reasons after `-`.
81
90
 
82
- ## Built-in AST Rules
91
+ ## Built-in Rules
83
92
 
84
93
  These work **instantly** with zero LLM calls:
85
94
 
@@ -93,31 +102,58 @@ These work **instantly** with zero LLM calls:
93
102
  | `no innerhtml` | innerHTML, dangerouslySetInnerHTML |
94
103
  | `no debugger` | debugger statements |
95
104
  | `no var` | var declarations |
105
+ | `prefer pnpm` | npm/yarn commands blocked |
106
+ | `protect .env` | Environment file modifications blocked |
107
+
108
+ 50+ built-in patterns cover most common policies.
96
109
 
97
110
  ## Native Agent Support
98
111
 
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 |
112
+ | Agent | How It Works | Status |
113
+ | --------------- | ------------------------------------ | ---------- |
114
+ | **Claude Code** | PreToolUse hooks with AST validation | Full |
115
+ | **OpenCode** | AGENTS.md injection | Full |
116
+ | **Cursor** | rules/ directory integration | Full |
117
+ | **Windsurf** | Cascade rules integration | Full |
118
+ | **Aider** | .aider.conf.yml configuration | Full |
107
119
 
108
120
  ## Commands
109
121
 
110
122
  ```
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
118
- leash status Show active sessions
123
+ leash Interactive dashboard
124
+ leash init Auto-detect agents, install hooks
125
+ leash add "<policy>" Add a policy
126
+ leash list Show current policies
127
+ leash explain "<policy>" Preview what a policy catches
128
+ leash sync [agent] Apply policies to agents
129
+ leash install <agent> Install hooks for specific agent
130
+ leash uninstall <agent> Remove agent hooks
131
+ leash status Show detected agents
132
+ leash audit [--tail] View enforcement log
119
133
  ```
120
134
 
135
+ **Agent shortcuts:** `cc` (Claude Code), `oc` (OpenCode), `cursor`, `windsurf`, `aider`
136
+
137
+ ## Architecture
138
+
139
+ ```
140
+ ┌─────────────────────────────────────────────────────────┐
141
+ │ leash (Go, 4.5MB) │
142
+ ├─────────────────────────────────────────────────────────┤
143
+ │ TUI Dashboard │ Fast Commands │
144
+ │ - Policy management │ - list, status, sync │
145
+ │ - Agent installation │ - install, uninstall │
146
+ │ - Real-time monitoring │ - Pattern matching │
147
+ ├─────────────────────────┴───────────────────────────────┤
148
+ │ TypeScript Engine (when needed) │
149
+ │ - LLM policy compilation (custom rules) │
150
+ │ - AST validation (Tree-sitter) │
151
+ │ - 243 tests │
152
+ └─────────────────────────────────────────────────────────┘
153
+ ```
154
+
155
+ **Key insight**: 95%+ of policies use built-in rules (pure Go, instant). LLM compilation only runs for custom rules.
156
+
121
157
  ## How It Works
122
158
 
123
159
  ```
@@ -130,17 +166,12 @@ User: "no lodash"
130
166
 
131
167
  ┌─────────────────────────────────────────┐
132
168
  │ 2. Runtime: Write/Edit intercepted │
133
- │ → Regex pre-filter: contains
134
- │ "lodash"? Yes → continue │
169
+ │ → Regex pre-filter: "lodash"?
135
170
  │ → AST parse (5ms, cached) │
136
- │ → Query: import_statement with │
137
- │ source matching "lodash" │
138
171
  │ → BLOCKED with line/column │
139
172
  └─────────────────────────────────────────┘
140
173
  ```
141
174
 
142
- **Key insight**: Regex pre-filter skips 95%+ of files instantly. AST parsing only runs when needed.
143
-
144
175
  ## Environment Variables
145
176
 
146
177
  | Variable | Description |
@@ -153,14 +184,14 @@ Get a free API key: https://aistudio.google.com/apikey
153
184
 
154
185
  1. **Surgeon-level precision** - AST parsing = zero false positives
155
186
  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" }`
187
+ 3. **Native performance** - Go binary, instant startup
188
+ 4. **Natural language** - `no lodash` not `{ "rule": "no-import", "pattern": "^lodash" }`
158
189
 
159
190
  ## Test Suite
160
191
 
161
192
  ```
162
- 229 tests passing
163
- ├── 41 AST validation tests
193
+ 243 tests passing
194
+ ├── 77 AST validation tests
164
195
  ├── 93 content matching tests
165
196
  ├── 41 command interception tests
166
197
  ├── 17 pattern matcher tests
package/bin/leash ADDED
Binary file
package/bin/leash.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ // bin/leash.js - Wrapper that uses native binary or falls back to Node.js
3
+
4
+ import { spawn } from 'child_process';
5
+ import { existsSync } from 'fs';
6
+ import { join, dirname } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const rootDir = join(__dirname, '..');
11
+
12
+ // Try native binary first
13
+ const nativeBinary = process.platform === 'win32'
14
+ ? join(__dirname, 'leash.exe')
15
+ : join(__dirname, 'leash');
16
+
17
+ if (existsSync(nativeBinary)) {
18
+ // Use native binary
19
+ const child = spawn(nativeBinary, process.argv.slice(2), {
20
+ stdio: 'inherit',
21
+ env: process.env,
22
+ });
23
+
24
+ child.on('exit', (code) => {
25
+ process.exit(code || 0);
26
+ });
27
+ } else {
28
+ // Fall back to Node.js CLI
29
+ const nodeCLI = join(rootDir, 'dist', 'cli.js');
30
+
31
+ if (!existsSync(nodeCLI)) {
32
+ console.error('leash: Neither native binary nor Node.js CLI found.');
33
+ console.error('Run "pnpm build" to build the CLI.');
34
+ process.exit(1);
35
+ }
36
+
37
+ const child = spawn('node', [nodeCLI, ...process.argv.slice(2)], {
38
+ stdio: 'inherit',
39
+ env: process.env,
40
+ });
41
+
42
+ child.on('exit', (code) => {
43
+ process.exit(code || 0);
44
+ });
45
+ }
@@ -1 +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,CA0nBlD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CAiEjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}
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,CA+mClD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CAiEjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}