veto-leash 0.1.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.
- package/IMPLEMENTATION_PLAN.md +2194 -0
- package/LICENSE +201 -0
- package/README.md +260 -0
- package/dist/audit/index.d.ts +38 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +132 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +406 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud/index.d.ts +40 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +115 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/compiler/builtins.d.ts +6 -0
- package/dist/compiler/builtins.d.ts.map +1 -0
- package/dist/compiler/builtins.js +129 -0
- package/dist/compiler/builtins.js.map +1 -0
- package/dist/compiler/cache.d.ts +6 -0
- package/dist/compiler/cache.d.ts.map +1 -0
- package/dist/compiler/cache.js +49 -0
- package/dist/compiler/cache.js.map +1 -0
- package/dist/compiler/index.d.ts +3 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +48 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/compiler/llm.d.ts +3 -0
- package/dist/compiler/llm.d.ts.map +1 -0
- package/dist/compiler/llm.js +69 -0
- package/dist/compiler/llm.js.map +1 -0
- package/dist/compiler/prompt.d.ts +2 -0
- package/dist/compiler/prompt.d.ts.map +1 -0
- package/dist/compiler/prompt.js +37 -0
- package/dist/compiler/prompt.js.map +1 -0
- package/dist/config/loader.d.ts +22 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +100 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +42 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +93 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/matcher.d.ts +22 -0
- package/dist/matcher.d.ts.map +1 -0
- package/dist/matcher.js +69 -0
- package/dist/matcher.js.map +1 -0
- package/dist/native/aider.d.ts +10 -0
- package/dist/native/aider.d.ts.map +1 -0
- package/dist/native/aider.js +120 -0
- package/dist/native/aider.js.map +1 -0
- package/dist/native/claude-code.d.ts +14 -0
- package/dist/native/claude-code.d.ts.map +1 -0
- package/dist/native/claude-code.js +273 -0
- package/dist/native/claude-code.js.map +1 -0
- package/dist/native/cursor.d.ts +11 -0
- package/dist/native/cursor.d.ts.map +1 -0
- package/dist/native/cursor.js +105 -0
- package/dist/native/cursor.js.map +1 -0
- package/dist/native/index.d.ts +35 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +171 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/opencode.d.ts +22 -0
- package/dist/native/opencode.d.ts.map +1 -0
- package/dist/native/opencode.js +225 -0
- package/dist/native/opencode.js.map +1 -0
- package/dist/native/windsurf.d.ts +14 -0
- package/dist/native/windsurf.d.ts.map +1 -0
- package/dist/native/windsurf.js +198 -0
- package/dist/native/windsurf.js.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/colors.d.ts +21 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +41 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/watchdog/index.d.ts +25 -0
- package/dist/watchdog/index.d.ts.map +1 -0
- package/dist/watchdog/index.js +57 -0
- package/dist/watchdog/index.js.map +1 -0
- package/dist/watchdog/restore.d.ts +16 -0
- package/dist/watchdog/restore.d.ts.map +1 -0
- package/dist/watchdog/restore.js +56 -0
- package/dist/watchdog/restore.js.map +1 -0
- package/dist/watchdog/snapshot.d.ts +38 -0
- package/dist/watchdog/snapshot.d.ts.map +1 -0
- package/dist/watchdog/snapshot.js +166 -0
- package/dist/watchdog/snapshot.js.map +1 -0
- package/dist/watchdog/watcher.d.ts +28 -0
- package/dist/watchdog/watcher.d.ts.map +1 -0
- package/dist/watchdog/watcher.js +117 -0
- package/dist/watchdog/watcher.js.map +1 -0
- package/dist/wrapper/daemon.d.ts +12 -0
- package/dist/wrapper/daemon.d.ts.map +1 -0
- package/dist/wrapper/daemon.js +103 -0
- package/dist/wrapper/daemon.js.map +1 -0
- package/dist/wrapper/shims.d.ts +4 -0
- package/dist/wrapper/shims.d.ts.map +1 -0
- package/dist/wrapper/shims.js +390 -0
- package/dist/wrapper/shims.js.map +1 -0
- package/dist/wrapper/spawn.d.ts +4 -0
- package/dist/wrapper/spawn.d.ts.map +1 -0
- package/dist/wrapper/spawn.js +35 -0
- package/dist/wrapper/spawn.js.map +1 -0
- package/package.json +46 -0
- package/src/audit/index.ts +172 -0
- package/src/cli.ts +503 -0
- package/src/cloud/index.ts +139 -0
- package/src/compiler/builtins.ts +137 -0
- package/src/compiler/cache.ts +51 -0
- package/src/compiler/index.ts +59 -0
- package/src/compiler/llm.ts +83 -0
- package/src/compiler/prompt.ts +37 -0
- package/src/config/loader.ts +126 -0
- package/src/config/schema.ts +136 -0
- package/src/matcher.ts +89 -0
- package/src/native/aider.ts +150 -0
- package/src/native/claude-code.ts +308 -0
- package/src/native/cursor.ts +131 -0
- package/src/native/index.ts +233 -0
- package/src/native/opencode.ts +310 -0
- package/src/native/windsurf.ts +231 -0
- package/src/types.ts +48 -0
- package/src/ui/colors.ts +50 -0
- package/src/watchdog/index.ts +82 -0
- package/src/watchdog/restore.ts +74 -0
- package/src/watchdog/snapshot.ts +209 -0
- package/src/watchdog/watcher.ts +150 -0
- package/src/wrapper/daemon.ts +133 -0
- package/src/wrapper/shims.ts +409 -0
- package/src/wrapper/spawn.ts +47 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/config/schema.ts
|
|
2
|
+
// .leash file schema and validation
|
|
3
|
+
/**
|
|
4
|
+
* Default settings
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_SETTINGS = {
|
|
7
|
+
fail_closed: true,
|
|
8
|
+
audit_log: false,
|
|
9
|
+
verbose: false,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Validate a .leash config object
|
|
13
|
+
*/
|
|
14
|
+
export function validateConfig(config) {
|
|
15
|
+
if (typeof config !== 'object' || config === null) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const c = config;
|
|
19
|
+
// Version check
|
|
20
|
+
if (c.version !== 1) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
// Policies must be array of strings
|
|
24
|
+
if (!Array.isArray(c.policies)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
for (const policy of c.policies) {
|
|
28
|
+
if (typeof policy !== 'string') {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Settings are optional
|
|
33
|
+
if (c.settings !== undefined) {
|
|
34
|
+
if (typeof c.settings !== 'object' || c.settings === null) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate a default .leash config
|
|
42
|
+
*/
|
|
43
|
+
export function generateDefaultConfig() {
|
|
44
|
+
return {
|
|
45
|
+
version: 1,
|
|
46
|
+
policies: [
|
|
47
|
+
"don't delete test files",
|
|
48
|
+
"protect .env",
|
|
49
|
+
],
|
|
50
|
+
settings: {
|
|
51
|
+
fail_closed: true,
|
|
52
|
+
audit_log: false,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate YAML content for a .leash file
|
|
58
|
+
*/
|
|
59
|
+
export function generateLeashYaml(config) {
|
|
60
|
+
const lines = [
|
|
61
|
+
'# .leash - Veto Leash project configuration',
|
|
62
|
+
'# Commit this file to version control',
|
|
63
|
+
'',
|
|
64
|
+
'version: 1',
|
|
65
|
+
'',
|
|
66
|
+
'# Natural language restrictions',
|
|
67
|
+
'policies:',
|
|
68
|
+
];
|
|
69
|
+
for (const policy of config.policies) {
|
|
70
|
+
lines.push(` - "${policy}"`);
|
|
71
|
+
}
|
|
72
|
+
if (config.settings) {
|
|
73
|
+
lines.push('');
|
|
74
|
+
lines.push('# Optional settings');
|
|
75
|
+
lines.push('settings:');
|
|
76
|
+
if (config.settings.fail_closed !== undefined) {
|
|
77
|
+
lines.push(` fail_closed: ${config.settings.fail_closed}`);
|
|
78
|
+
}
|
|
79
|
+
if (config.settings.audit_log !== undefined) {
|
|
80
|
+
lines.push(` audit_log: ${config.settings.audit_log}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (config.cloud) {
|
|
84
|
+
lines.push('');
|
|
85
|
+
lines.push('# Leash Cloud (coming soon)');
|
|
86
|
+
lines.push('# cloud:');
|
|
87
|
+
lines.push('# team_id: "team_xxx"');
|
|
88
|
+
lines.push('# sync: true');
|
|
89
|
+
}
|
|
90
|
+
lines.push('');
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Policy } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a path for cross-platform pattern matching.
|
|
4
|
+
* - Converts backslashes to forward slashes (Windows paths)
|
|
5
|
+
* - Removes trailing slashes
|
|
6
|
+
* - Normalizes . and .. segments
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizePath(p: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a target path is protected by the policy.
|
|
11
|
+
* Returns true if the target matches include patterns and doesn't match exclude patterns.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isProtected(target: string, policy: Policy): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Get all files in a list that would be protected by the policy.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getProtectedFiles(files: string[], policy: Policy): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Get all files in a list that would be excluded (allowed) by the policy.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getExcludedFiles(files: string[], policy: Policy): string[];
|
|
22
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAUzC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA2B/C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAenE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS1E"}
|
package/dist/matcher.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// src/matcher.ts
|
|
2
|
+
import micromatch from 'micromatch';
|
|
3
|
+
const { isMatch } = micromatch;
|
|
4
|
+
const MATCH_OPTIONS = {
|
|
5
|
+
basename: true, // *.test.ts matches src/foo.test.ts
|
|
6
|
+
dot: true, // Match dotfiles
|
|
7
|
+
nocase: true, // Case insensitive (important for Windows)
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Normalize a path for cross-platform pattern matching.
|
|
11
|
+
* - Converts backslashes to forward slashes (Windows paths)
|
|
12
|
+
* - Removes trailing slashes
|
|
13
|
+
* - Normalizes . and .. segments
|
|
14
|
+
*/
|
|
15
|
+
export function normalizePath(p) {
|
|
16
|
+
// Convert Windows backslashes to forward slashes
|
|
17
|
+
let normalized = p.replace(/\\/g, '/');
|
|
18
|
+
// Remove trailing slash
|
|
19
|
+
if (normalized.endsWith('/') && normalized.length > 1) {
|
|
20
|
+
normalized = normalized.slice(0, -1);
|
|
21
|
+
}
|
|
22
|
+
// Simple normalization of . and ..
|
|
23
|
+
const parts = normalized.split('/');
|
|
24
|
+
const result = [];
|
|
25
|
+
for (const part of parts) {
|
|
26
|
+
if (part === '..') {
|
|
27
|
+
result.pop();
|
|
28
|
+
}
|
|
29
|
+
else if (part !== '.' && part !== '') {
|
|
30
|
+
result.push(part);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Preserve leading slash for absolute paths
|
|
34
|
+
if (normalized.startsWith('/')) {
|
|
35
|
+
return '/' + result.join('/');
|
|
36
|
+
}
|
|
37
|
+
return result.join('/') || '.';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a target path is protected by the policy.
|
|
41
|
+
* Returns true if the target matches include patterns and doesn't match exclude patterns.
|
|
42
|
+
*/
|
|
43
|
+
export function isProtected(target, policy) {
|
|
44
|
+
// Normalize the target path for cross-platform matching
|
|
45
|
+
const normalizedTarget = normalizePath(target);
|
|
46
|
+
const matchesInclude = policy.include.some((p) => isMatch(normalizedTarget, p, MATCH_OPTIONS));
|
|
47
|
+
if (!matchesInclude)
|
|
48
|
+
return false;
|
|
49
|
+
const matchesExclude = policy.exclude.some((p) => isMatch(normalizedTarget, p, MATCH_OPTIONS));
|
|
50
|
+
return !matchesExclude;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get all files in a list that would be protected by the policy.
|
|
54
|
+
*/
|
|
55
|
+
export function getProtectedFiles(files, policy) {
|
|
56
|
+
return files.filter((f) => isProtected(f, policy));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get all files in a list that would be excluded (allowed) by the policy.
|
|
60
|
+
*/
|
|
61
|
+
export function getExcludedFiles(files, policy) {
|
|
62
|
+
return files.filter((f) => {
|
|
63
|
+
const matchesInclude = policy.include.some((p) => isMatch(f, p, MATCH_OPTIONS));
|
|
64
|
+
if (!matchesInclude)
|
|
65
|
+
return false;
|
|
66
|
+
return policy.exclude.some((p) => isMatch(f, p, MATCH_OPTIONS));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install veto-leash restrictions into Aider config
|
|
3
|
+
* Uses the 'read' option to mark files as read-only
|
|
4
|
+
*/
|
|
5
|
+
export declare function installAiderConfig(target?: 'project' | 'global'): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Uninstall veto-leash from Aider config
|
|
8
|
+
*/
|
|
9
|
+
export declare function uninstallAiderConfig(target?: 'project' | 'global'): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=aider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aider.d.ts","sourceRoot":"","sources":["../../src/native/aider.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,GAAE,SAAS,GAAG,QAAoB,GACvC,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAmDD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,GAAE,SAAS,GAAG,QAAoB,GACvC,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// src/native/aider.ts
|
|
2
|
+
// Aider integration via .aider.conf.yml
|
|
3
|
+
// Aider supports read-only files via the 'read' config option
|
|
4
|
+
import { existsSync, writeFileSync, readFileSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { COLORS, SYMBOLS } from '../ui/colors.js';
|
|
8
|
+
import { glob } from 'glob';
|
|
9
|
+
const AIDER_CONFIG_FILE = '.aider.conf.yml';
|
|
10
|
+
const AIDER_GLOBAL_CONFIG = join(homedir(), '.aider.conf.yml');
|
|
11
|
+
/**
|
|
12
|
+
* Install veto-leash restrictions into Aider config
|
|
13
|
+
* Uses the 'read' option to mark files as read-only
|
|
14
|
+
*/
|
|
15
|
+
export async function installAiderConfig(target = 'project') {
|
|
16
|
+
console.log(`\n${COLORS.info}Installing veto-leash for Aider (${target})...${COLORS.reset}\n`);
|
|
17
|
+
const policies = loadStoredPolicies();
|
|
18
|
+
if (policies.length === 0) {
|
|
19
|
+
console.log(`${COLORS.warning}${SYMBOLS.warning} No policies found. Add policies first:${COLORS.reset}`);
|
|
20
|
+
console.log(` ${COLORS.dim}leash add "protect .env"${COLORS.reset}\n`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const configPath = target === 'global' ? AIDER_GLOBAL_CONFIG : AIDER_CONFIG_FILE;
|
|
24
|
+
// Collect protected files based on policies
|
|
25
|
+
const protectedFiles = await collectProtectedFiles(policies);
|
|
26
|
+
if (protectedFiles.length === 0) {
|
|
27
|
+
console.log(`${COLORS.warning}${SYMBOLS.warning} No matching files found in current directory${COLORS.reset}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Generate YAML config
|
|
31
|
+
const yamlContent = generateAiderYaml(protectedFiles, configPath);
|
|
32
|
+
writeFileSync(configPath, yamlContent);
|
|
33
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Updated: ${configPath}`);
|
|
34
|
+
console.log(` ${COLORS.dim}Protected ${protectedFiles.length} files as read-only${COLORS.reset}`);
|
|
35
|
+
console.log(`\n${COLORS.warning}${SYMBOLS.warning} Note: Aider 'read' makes files read-only, preventing modifications.${COLORS.reset}`);
|
|
36
|
+
console.log(`For delete protection, use wrapper mode:`);
|
|
37
|
+
console.log(` ${COLORS.dim}leash aider "<restriction>"${COLORS.reset}\n`);
|
|
38
|
+
}
|
|
39
|
+
async function collectProtectedFiles(policies) {
|
|
40
|
+
const files = [];
|
|
41
|
+
for (const policy of policies) {
|
|
42
|
+
// Only protect modify actions (read-only)
|
|
43
|
+
if (policy.action !== 'modify' && policy.action !== 'delete')
|
|
44
|
+
continue;
|
|
45
|
+
for (const pattern of policy.include) {
|
|
46
|
+
const matches = await glob(pattern, {
|
|
47
|
+
dot: true,
|
|
48
|
+
nodir: true,
|
|
49
|
+
ignore: ['node_modules/**', '.git/**'],
|
|
50
|
+
});
|
|
51
|
+
files.push(...matches);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Dedupe
|
|
55
|
+
return [...new Set(files)];
|
|
56
|
+
}
|
|
57
|
+
function generateAiderYaml(protectedFiles, existingPath) {
|
|
58
|
+
let existing = '';
|
|
59
|
+
let existingLines = [];
|
|
60
|
+
if (existsSync(existingPath)) {
|
|
61
|
+
existing = readFileSync(existingPath, 'utf-8');
|
|
62
|
+
existingLines = existing.split('\n');
|
|
63
|
+
// Remove existing veto-leash section
|
|
64
|
+
const startIdx = existingLines.findIndex(l => l.includes('# veto-leash'));
|
|
65
|
+
const endIdx = existingLines.findIndex((l, i) => i > startIdx && l.includes('# end veto-leash'));
|
|
66
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
67
|
+
existingLines.splice(startIdx, endIdx - startIdx + 1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Add veto-leash section
|
|
71
|
+
const vetoSection = [
|
|
72
|
+
'# veto-leash protected files (read-only)',
|
|
73
|
+
'read:',
|
|
74
|
+
...protectedFiles.map(f => ` - ${f}`),
|
|
75
|
+
'# end veto-leash',
|
|
76
|
+
];
|
|
77
|
+
return [...existingLines.filter(l => l.trim()), '', ...vetoSection].join('\n');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Uninstall veto-leash from Aider config
|
|
81
|
+
*/
|
|
82
|
+
export async function uninstallAiderConfig(target = 'project') {
|
|
83
|
+
const configPath = target === 'global' ? AIDER_GLOBAL_CONFIG : AIDER_CONFIG_FILE;
|
|
84
|
+
if (!existsSync(configPath)) {
|
|
85
|
+
console.log(`${COLORS.dim}No Aider config found at ${configPath}${COLORS.reset}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
89
|
+
const lines = content.split('\n');
|
|
90
|
+
const startIdx = lines.findIndex(l => l.includes('# veto-leash'));
|
|
91
|
+
const endIdx = lines.findIndex((l, i) => i > startIdx && l.includes('# end veto-leash'));
|
|
92
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
93
|
+
lines.splice(startIdx, endIdx - startIdx + 1);
|
|
94
|
+
const updated = lines.filter(l => l.trim()).join('\n');
|
|
95
|
+
if (updated.trim()) {
|
|
96
|
+
writeFileSync(configPath, updated);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
require('fs').unlinkSync(configPath);
|
|
100
|
+
}
|
|
101
|
+
console.log(`${COLORS.success}${SYMBOLS.success} Removed veto-leash from ${configPath}${COLORS.reset}`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.log(`${COLORS.dim}No veto-leash config found in ${configPath}${COLORS.reset}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function loadStoredPolicies() {
|
|
108
|
+
const policiesFile = join(homedir(), '.config', 'veto-leash', 'policies.json');
|
|
109
|
+
try {
|
|
110
|
+
if (existsSync(policiesFile)) {
|
|
111
|
+
const data = JSON.parse(readFileSync(policiesFile, 'utf-8'));
|
|
112
|
+
return data.policies?.map((p) => p.policy) || [];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Ignore
|
|
117
|
+
}
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=aider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aider.js","sourceRoot":"","sources":["../../src/native/aider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Policy } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Install veto-leash as a Claude Code PreToolUse hook
|
|
4
|
+
*/
|
|
5
|
+
export declare function installClaudeCodeHook(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Add a policy to Claude Code's veto-leash policies
|
|
8
|
+
*/
|
|
9
|
+
export declare function addClaudeCodePolicy(policy: Policy, name: string): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Uninstall veto-leash from Claude Code
|
|
12
|
+
*/
|
|
13
|
+
export declare function uninstallClaudeCodeHook(): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=claude-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/native/claude-code.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAoB1C;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CA+D3D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwB7D"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// src/native/claude-code.ts
|
|
2
|
+
// Claude Code native hook integration
|
|
3
|
+
// Generates PreToolUse hooks that integrate directly with Claude Code's permission system
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
import { COLORS, SYMBOLS } from '../ui/colors.js';
|
|
8
|
+
const CLAUDE_CONFIG_DIR = join(homedir(), '.claude');
|
|
9
|
+
const CLAUDE_HOOKS_DIR = join(CLAUDE_CONFIG_DIR, 'hooks', 'veto-leash');
|
|
10
|
+
const CLAUDE_SETTINGS_FILE = join(CLAUDE_CONFIG_DIR, 'settings.json');
|
|
11
|
+
/**
|
|
12
|
+
* Install veto-leash as a Claude Code PreToolUse hook
|
|
13
|
+
*/
|
|
14
|
+
export async function installClaudeCodeHook() {
|
|
15
|
+
console.log(`\n${COLORS.info}Installing veto-leash for Claude Code...${COLORS.reset}\n`);
|
|
16
|
+
// Create hooks directory
|
|
17
|
+
mkdirSync(CLAUDE_HOOKS_DIR, { recursive: true });
|
|
18
|
+
mkdirSync(join(CLAUDE_HOOKS_DIR, 'policies'), { recursive: true });
|
|
19
|
+
// Write the validator script (Python for cross-platform compatibility)
|
|
20
|
+
const validatorPath = join(CLAUDE_HOOKS_DIR, 'validator.py');
|
|
21
|
+
writeFileSync(validatorPath, VALIDATOR_SCRIPT, { mode: 0o755 });
|
|
22
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Created validator: ${validatorPath}`);
|
|
23
|
+
// Update Claude settings
|
|
24
|
+
let settings = {};
|
|
25
|
+
if (existsSync(CLAUDE_SETTINGS_FILE)) {
|
|
26
|
+
try {
|
|
27
|
+
settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_FILE, 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Start fresh if parse fails
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Ensure hooks structure exists
|
|
34
|
+
if (!settings.hooks) {
|
|
35
|
+
settings.hooks = {};
|
|
36
|
+
}
|
|
37
|
+
if (!settings.hooks.PreToolUse) {
|
|
38
|
+
settings.hooks.PreToolUse = [];
|
|
39
|
+
}
|
|
40
|
+
// Check if veto-leash hook already exists
|
|
41
|
+
const existingIndex = settings.hooks.PreToolUse.findIndex((h) => h.hooks.some((cmd) => cmd.command.includes('veto-leash')));
|
|
42
|
+
const hookEntry = {
|
|
43
|
+
matcher: 'Bash|Write|Edit|MultiEdit',
|
|
44
|
+
hooks: [
|
|
45
|
+
{
|
|
46
|
+
type: 'command',
|
|
47
|
+
command: `python3 "${validatorPath}"`,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
if (existingIndex >= 0) {
|
|
52
|
+
settings.hooks.PreToolUse[existingIndex] = hookEntry;
|
|
53
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Updated hook in settings`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
settings.hooks.PreToolUse.push(hookEntry);
|
|
57
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Added hook to settings`);
|
|
58
|
+
}
|
|
59
|
+
// Write settings back
|
|
60
|
+
mkdirSync(CLAUDE_CONFIG_DIR, { recursive: true });
|
|
61
|
+
writeFileSync(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2));
|
|
62
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Updated: ${CLAUDE_SETTINGS_FILE}`);
|
|
63
|
+
console.log(`\n${COLORS.success}${SYMBOLS.success} veto-leash installed for Claude Code${COLORS.reset}\n`);
|
|
64
|
+
console.log(`To add a policy:`);
|
|
65
|
+
console.log(` ${COLORS.dim}leash add "don't delete test files"${COLORS.reset}\n`);
|
|
66
|
+
console.log(`To remove:`);
|
|
67
|
+
console.log(` ${COLORS.dim}leash uninstall cc${COLORS.reset}\n`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Add a policy to Claude Code's veto-leash policies
|
|
71
|
+
*/
|
|
72
|
+
export async function addClaudeCodePolicy(policy, name) {
|
|
73
|
+
const policiesDir = join(CLAUDE_HOOKS_DIR, 'policies');
|
|
74
|
+
mkdirSync(policiesDir, { recursive: true });
|
|
75
|
+
const policyFile = join(policiesDir, `${name}.json`);
|
|
76
|
+
writeFileSync(policyFile, JSON.stringify(policy, null, 2));
|
|
77
|
+
console.log(`${COLORS.success}${SYMBOLS.success}${COLORS.reset} Policy saved: ${policyFile}`);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Uninstall veto-leash from Claude Code
|
|
81
|
+
*/
|
|
82
|
+
export async function uninstallClaudeCodeHook() {
|
|
83
|
+
console.log(`\n${COLORS.info}Removing veto-leash from Claude Code...${COLORS.reset}\n`);
|
|
84
|
+
// Remove from settings
|
|
85
|
+
if (existsSync(CLAUDE_SETTINGS_FILE)) {
|
|
86
|
+
try {
|
|
87
|
+
const settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_FILE, 'utf-8'));
|
|
88
|
+
if (settings.hooks?.PreToolUse) {
|
|
89
|
+
settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter((h) => !h.hooks.some((cmd) => cmd.command.includes('veto-leash')));
|
|
90
|
+
writeFileSync(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2));
|
|
91
|
+
console.log(` ${COLORS.success}${SYMBOLS.success}${COLORS.reset} Removed hook from settings`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
console.log(` ${COLORS.warning}${SYMBOLS.warning}${COLORS.reset} Could not parse settings file`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
console.log(`\n${COLORS.success}${SYMBOLS.success} veto-leash removed from Claude Code${COLORS.reset}\n`);
|
|
99
|
+
console.log(`${COLORS.dim}Note: Policy files in ${CLAUDE_HOOKS_DIR} were preserved.${COLORS.reset}\n`);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Python validator script that runs as a Claude Code PreToolUse hook.
|
|
103
|
+
* Uses Python for maximum cross-platform compatibility.
|
|
104
|
+
*/
|
|
105
|
+
const VALIDATOR_SCRIPT = `#!/usr/bin/env python3
|
|
106
|
+
"""
|
|
107
|
+
veto-leash validator for Claude Code PreToolUse hooks.
|
|
108
|
+
Checks tool inputs against configured policies.
|
|
109
|
+
|
|
110
|
+
Exit codes:
|
|
111
|
+
0 = allow
|
|
112
|
+
2 = block (stderr shown to Claude)
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
import json
|
|
116
|
+
import sys
|
|
117
|
+
import os
|
|
118
|
+
import re
|
|
119
|
+
from pathlib import Path
|
|
120
|
+
from fnmatch import fnmatch
|
|
121
|
+
|
|
122
|
+
POLICIES_DIR = Path(__file__).parent / "policies"
|
|
123
|
+
|
|
124
|
+
def load_policies():
|
|
125
|
+
"""Load all policy files from the policies directory."""
|
|
126
|
+
policies = []
|
|
127
|
+
if POLICIES_DIR.exists():
|
|
128
|
+
for f in POLICIES_DIR.glob("*.json"):
|
|
129
|
+
try:
|
|
130
|
+
policies.append(json.loads(f.read_text()))
|
|
131
|
+
except:
|
|
132
|
+
pass
|
|
133
|
+
return policies
|
|
134
|
+
|
|
135
|
+
def normalize_path(p):
|
|
136
|
+
"""Normalize path for pattern matching."""
|
|
137
|
+
# Convert to forward slashes for consistent matching
|
|
138
|
+
return str(p).replace("\\\\", "/")
|
|
139
|
+
|
|
140
|
+
def matches_pattern(target, pattern):
|
|
141
|
+
"""Check if target matches a glob pattern."""
|
|
142
|
+
target = normalize_path(target)
|
|
143
|
+
pattern = normalize_path(pattern)
|
|
144
|
+
|
|
145
|
+
# Also try matching just the basename
|
|
146
|
+
basename = os.path.basename(target)
|
|
147
|
+
|
|
148
|
+
return fnmatch(target, pattern) or fnmatch(basename, pattern)
|
|
149
|
+
|
|
150
|
+
def is_protected(target, policy):
|
|
151
|
+
"""Check if target is protected by policy."""
|
|
152
|
+
# Must match at least one include pattern
|
|
153
|
+
matches_include = any(
|
|
154
|
+
matches_pattern(target, p) for p in policy.get("include", [])
|
|
155
|
+
)
|
|
156
|
+
if not matches_include:
|
|
157
|
+
return False
|
|
158
|
+
|
|
159
|
+
# Must not match any exclude pattern
|
|
160
|
+
matches_exclude = any(
|
|
161
|
+
matches_pattern(target, p) for p in policy.get("exclude", [])
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return not matches_exclude
|
|
165
|
+
|
|
166
|
+
def parse_bash_targets(command, action):
|
|
167
|
+
"""Extract file targets from bash commands."""
|
|
168
|
+
targets = []
|
|
169
|
+
|
|
170
|
+
# rm command patterns
|
|
171
|
+
if action == "delete":
|
|
172
|
+
# Match: rm, rm -rf, rm -f, etc.
|
|
173
|
+
rm_match = re.search(r'\\brm\\s+(?:-[rfiv]+\\s+)*(.+)', command)
|
|
174
|
+
if rm_match:
|
|
175
|
+
args = rm_match.group(1)
|
|
176
|
+
# Split on spaces, filter out flags
|
|
177
|
+
for arg in args.split():
|
|
178
|
+
if not arg.startswith('-'):
|
|
179
|
+
targets.append(arg)
|
|
180
|
+
|
|
181
|
+
# git rm
|
|
182
|
+
git_rm_match = re.search(r'\\bgit\\s+rm\\s+(?:-[rf]+\\s+)*(.+)', command)
|
|
183
|
+
if git_rm_match:
|
|
184
|
+
for arg in git_rm_match.group(1).split():
|
|
185
|
+
if not arg.startswith('-'):
|
|
186
|
+
targets.append(arg)
|
|
187
|
+
|
|
188
|
+
# mv/cp for modify action
|
|
189
|
+
elif action == "modify":
|
|
190
|
+
mv_match = re.search(r'\\b(mv|cp)\\s+(?:-[a-z]+\\s+)*(.+)', command)
|
|
191
|
+
if mv_match:
|
|
192
|
+
args = mv_match.group(2).split()
|
|
193
|
+
# First non-flag arg is source
|
|
194
|
+
for arg in args:
|
|
195
|
+
if not arg.startswith('-'):
|
|
196
|
+
targets.append(arg)
|
|
197
|
+
break
|
|
198
|
+
|
|
199
|
+
return targets
|
|
200
|
+
|
|
201
|
+
def get_action_for_tool(tool_name):
|
|
202
|
+
"""Map Claude Code tool names to veto-leash actions."""
|
|
203
|
+
mapping = {
|
|
204
|
+
"Bash": ["delete", "modify", "execute"],
|
|
205
|
+
"Write": ["modify"],
|
|
206
|
+
"Edit": ["modify"],
|
|
207
|
+
"MultiEdit": ["modify"],
|
|
208
|
+
"Read": ["read"],
|
|
209
|
+
}
|
|
210
|
+
return mapping.get(tool_name, [])
|
|
211
|
+
|
|
212
|
+
def main():
|
|
213
|
+
try:
|
|
214
|
+
input_data = json.load(sys.stdin)
|
|
215
|
+
except json.JSONDecodeError:
|
|
216
|
+
sys.exit(0) # Allow if can't parse
|
|
217
|
+
|
|
218
|
+
tool_name = input_data.get("tool_name", "")
|
|
219
|
+
tool_input = input_data.get("tool_input", {})
|
|
220
|
+
cwd = input_data.get("cwd", os.getcwd())
|
|
221
|
+
|
|
222
|
+
policies = load_policies()
|
|
223
|
+
if not policies:
|
|
224
|
+
sys.exit(0) # No policies = allow all
|
|
225
|
+
|
|
226
|
+
# Extract targets based on tool
|
|
227
|
+
targets = []
|
|
228
|
+
|
|
229
|
+
if tool_name == "Bash":
|
|
230
|
+
command = tool_input.get("command", "")
|
|
231
|
+
for policy in policies:
|
|
232
|
+
action = policy.get("action", "modify")
|
|
233
|
+
targets.extend(parse_bash_targets(command, action))
|
|
234
|
+
|
|
235
|
+
elif tool_name in ("Write", "Edit", "MultiEdit"):
|
|
236
|
+
file_path = tool_input.get("file_path", "")
|
|
237
|
+
if file_path:
|
|
238
|
+
targets.append(file_path)
|
|
239
|
+
|
|
240
|
+
if not targets:
|
|
241
|
+
sys.exit(0) # No targets = allow
|
|
242
|
+
|
|
243
|
+
# Check each target against policies
|
|
244
|
+
for target in targets:
|
|
245
|
+
# Make relative to cwd if absolute
|
|
246
|
+
try:
|
|
247
|
+
target_path = Path(target)
|
|
248
|
+
if not target_path.is_absolute():
|
|
249
|
+
target_path = Path(cwd) / target
|
|
250
|
+
rel_target = str(target_path.relative_to(cwd))
|
|
251
|
+
except:
|
|
252
|
+
rel_target = target
|
|
253
|
+
|
|
254
|
+
for policy in policies:
|
|
255
|
+
tool_actions = get_action_for_tool(tool_name)
|
|
256
|
+
policy_action = policy.get("action", "modify")
|
|
257
|
+
|
|
258
|
+
if policy_action in tool_actions:
|
|
259
|
+
if is_protected(rel_target, policy):
|
|
260
|
+
# Block and report to Claude
|
|
261
|
+
desc = policy.get("description", "Protected file")
|
|
262
|
+
print(f"veto-leash: BLOCKED {policy_action}", file=sys.stderr)
|
|
263
|
+
print(f" Target: {rel_target}", file=sys.stderr)
|
|
264
|
+
print(f" Policy: {desc}", file=sys.stderr)
|
|
265
|
+
print(f" Filesystem unchanged.", file=sys.stderr)
|
|
266
|
+
sys.exit(2)
|
|
267
|
+
|
|
268
|
+
sys.exit(0) # Allow
|
|
269
|
+
|
|
270
|
+
if __name__ == "__main__":
|
|
271
|
+
main()
|
|
272
|
+
`;
|
|
273
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/native/claude-code.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sCAAsC;AACtC,0FAA0F;AAE1F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACrD,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AACxE,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;AAetE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,2CAA2C,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAEzF,yBAAyB;IACzB,SAAS,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,SAAS,CAAC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnE,uEAAuE;IACvE,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IAC7D,aAAa,CAAC,aAAa,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,uBAAuB,aAAa,EAAE,CAAC,CAAC;IAExG,yBAAyB;IACzB,IAAI,QAAQ,GAAmB,EAAE,CAAC;IAClC,IAAI,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QAC/B,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC;IACjC,CAAC;IAED,0CAA0C;IAC1C,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CACvD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CACjE,CAAC;IAEF,MAAM,SAAS,GAAG;QAChB,OAAO,EAAE,2BAA2B;QACpC,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,YAAY,aAAa,GAAG;aACtC;SACF;KACF,CAAC;IAEF,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,SAAS,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,2BAA2B,CAAC,CAAC;IAC/F,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,yBAAyB,CAAC,CAAC;IAC7F,CAAC;IAED,sBAAsB;IACtB,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,aAAa,oBAAoB,EAAE,CAAC,CAAC;IAErG,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,wCAAwC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAC3G,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,sCAAsC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,qBAAqB,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,IAAY;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IACvD,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IACrD,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,kBAAkB,UAAU,EAAE,CAAC,CAAC;AAChG,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,0CAA0C,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAExF,uBAAuB;IACvB,IAAI,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAmB,IAAI,CAAC,KAAK,CACzC,YAAY,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAC5C,CAAC;YAEF,IAAI,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;gBAC/B,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAC1D,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAClE,CAAC;gBACF,aAAa,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvE,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,6BAA6B,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,gCAAgC,CAAC,CAAC;QACpG,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,uCAAuC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAC1G,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,yBAAyB,gBAAgB,mBAAmB,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;AACzG,CAAC;AAED;;;GAGG;AACH,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuKxB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install veto-leash instructions into .cursorrules
|
|
3
|
+
* Note: This only provides AI guidance, not enforcement.
|
|
4
|
+
* For actual enforcement, use wrapper mode: leash cursor "..."
|
|
5
|
+
*/
|
|
6
|
+
export declare function installCursorRules(): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Uninstall veto-leash from .cursorrules
|
|
9
|
+
*/
|
|
10
|
+
export declare function uninstallCursorRules(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/native/cursor.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqCxD;AAkCD;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAoB1D"}
|