@melihmucuk/leash 1.0.10 → 1.0.11
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/README.md +13 -6
- package/dist/cli/leash.js +48 -81
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ Links:
|
|
|
29
29
|
|
|
30
30
|
## Quick Start
|
|
31
31
|
|
|
32
|
+
**All platforms except Pi:**
|
|
33
|
+
|
|
32
34
|
```bash
|
|
33
35
|
# Install leash globally
|
|
34
36
|
npm install -g @melihmucuk/leash
|
|
@@ -43,12 +45,17 @@ leash --remove <platform>
|
|
|
43
45
|
leash --update
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
| Platform
|
|
47
|
-
|
|
|
48
|
-
| OpenCode
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
48
|
+
| Platform | Command |
|
|
49
|
+
| ------------- | --------------------------- |
|
|
50
|
+
| OpenCode | `leash --setup opencode` |
|
|
51
|
+
| Claude Code | `leash --setup claude-code` |
|
|
52
|
+
| Factory Droid | `leash --setup factory` |
|
|
53
|
+
|
|
54
|
+
**Pi Coding Agent:**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pi install npm:@melihmucuk/leash
|
|
58
|
+
```
|
|
52
59
|
|
|
53
60
|
Restart your agent. Done!
|
|
54
61
|
|
package/dist/cli/leash.js
CHANGED
|
@@ -1384,44 +1384,11 @@ function applyEdits(text, edits) {
|
|
|
1384
1384
|
}
|
|
1385
1385
|
|
|
1386
1386
|
// packages/cli/lib.ts
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
name:
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
".config/opencode/opencode.json"
|
|
1393
|
-
],
|
|
1394
|
-
distPath: "opencode/leash.js",
|
|
1395
|
-
remove: (config) => {
|
|
1396
|
-
if (!config.plugin) return false;
|
|
1397
|
-
const before = config.plugin.length;
|
|
1398
|
-
config.plugin = config.plugin.filter((p) => !p.includes("leash"));
|
|
1399
|
-
return config.plugin.length < before;
|
|
1400
|
-
}
|
|
1401
|
-
},
|
|
1402
|
-
pi: {
|
|
1403
|
-
name: "Pi",
|
|
1404
|
-
configPath: ".pi/agent/settings.json",
|
|
1405
|
-
distPath: "pi/leash.js",
|
|
1406
|
-
setup: (config, leashPath) => {
|
|
1407
|
-
config.extensions = config.extensions || [];
|
|
1408
|
-
if (config.extensions.some((e) => e.includes("leash"))) {
|
|
1409
|
-
return { skipped: true };
|
|
1410
|
-
}
|
|
1411
|
-
config.extensions.push(leashPath);
|
|
1412
|
-
return { skipped: false };
|
|
1413
|
-
},
|
|
1414
|
-
remove: (config) => {
|
|
1415
|
-
if (!config.extensions) return false;
|
|
1416
|
-
const before = config.extensions.length;
|
|
1417
|
-
config.extensions = config.extensions.filter((e) => !e.includes("leash"));
|
|
1418
|
-
return config.extensions.length < before;
|
|
1419
|
-
}
|
|
1420
|
-
},
|
|
1421
|
-
"claude-code": {
|
|
1422
|
-
name: "Claude Code",
|
|
1423
|
-
configPath: ".claude/settings.json",
|
|
1424
|
-
distPath: "claude-code/leash.js",
|
|
1387
|
+
function createHookPlatform(opts) {
|
|
1388
|
+
return {
|
|
1389
|
+
name: opts.name,
|
|
1390
|
+
configPath: opts.configPath,
|
|
1391
|
+
distPath: opts.distPath,
|
|
1425
1392
|
setup: (config, leashPath) => {
|
|
1426
1393
|
config.hooks = config.hooks || {};
|
|
1427
1394
|
const hookCommand = { type: "command", command: `node ${leashPath}` };
|
|
@@ -1441,7 +1408,7 @@ var PLATFORMS = {
|
|
|
1441
1408
|
if (!inPreToolUse) {
|
|
1442
1409
|
config.hooks.PreToolUse = config.hooks.PreToolUse || [];
|
|
1443
1410
|
config.hooks.PreToolUse.push({
|
|
1444
|
-
matcher:
|
|
1411
|
+
matcher: opts.preToolUseMatcher,
|
|
1445
1412
|
hooks: [hookCommand]
|
|
1446
1413
|
});
|
|
1447
1414
|
}
|
|
@@ -1466,56 +1433,50 @@ var PLATFORMS = {
|
|
|
1466
1433
|
}
|
|
1467
1434
|
return removed;
|
|
1468
1435
|
}
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
var PLATFORMS = {
|
|
1439
|
+
opencode: {
|
|
1440
|
+
name: "OpenCode",
|
|
1441
|
+
configPaths: [
|
|
1442
|
+
".config/opencode/opencode.jsonc",
|
|
1443
|
+
".config/opencode/opencode.json"
|
|
1444
|
+
],
|
|
1445
|
+
distPath: "opencode/leash.js"
|
|
1446
|
+
// opencode config is JSONC (supports comments). Generic readConfig/writeConfig use JSON.stringify
|
|
1447
|
+
// which strips comments. setupOpenCode/removeOpenCode handle this via jsonc-parser instead.
|
|
1469
1448
|
},
|
|
1470
|
-
|
|
1471
|
-
name: "
|
|
1472
|
-
configPath: ".
|
|
1473
|
-
distPath: "
|
|
1449
|
+
pi: {
|
|
1450
|
+
name: "Pi",
|
|
1451
|
+
configPath: ".pi/agent/settings.json",
|
|
1452
|
+
distPath: "pi/leash.js",
|
|
1474
1453
|
setup: (config, leashPath) => {
|
|
1475
|
-
config.
|
|
1476
|
-
|
|
1477
|
-
const inSessionStart = config.hooks.SessionStart?.some(
|
|
1478
|
-
(entry) => entry.hooks?.some((h) => h.command?.includes("leash"))
|
|
1479
|
-
);
|
|
1480
|
-
const inPreToolUse = config.hooks.PreToolUse?.some(
|
|
1481
|
-
(entry) => entry.hooks?.some((h) => h.command?.includes("leash"))
|
|
1482
|
-
);
|
|
1483
|
-
if (inSessionStart && inPreToolUse) {
|
|
1454
|
+
config.extensions = config.extensions || [];
|
|
1455
|
+
if (config.extensions.some((e) => e.includes("leash"))) {
|
|
1484
1456
|
return { skipped: true };
|
|
1485
1457
|
}
|
|
1486
|
-
|
|
1487
|
-
config.hooks.SessionStart = config.hooks.SessionStart || [];
|
|
1488
|
-
config.hooks.SessionStart.push({ hooks: [hookCommand] });
|
|
1489
|
-
}
|
|
1490
|
-
if (!inPreToolUse) {
|
|
1491
|
-
config.hooks.PreToolUse = config.hooks.PreToolUse || [];
|
|
1492
|
-
config.hooks.PreToolUse.push({
|
|
1493
|
-
matcher: "Execute|Write|Edit",
|
|
1494
|
-
hooks: [hookCommand]
|
|
1495
|
-
});
|
|
1496
|
-
}
|
|
1458
|
+
config.extensions.push(leashPath);
|
|
1497
1459
|
return { skipped: false };
|
|
1498
1460
|
},
|
|
1499
1461
|
remove: (config) => {
|
|
1500
|
-
if (!config.
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
config.hooks.SessionStart = config.hooks.SessionStart.filter(
|
|
1505
|
-
(entry) => !entry.hooks?.some((h) => h.command?.includes("leash"))
|
|
1506
|
-
);
|
|
1507
|
-
if (config.hooks.SessionStart.length < before) removed = true;
|
|
1508
|
-
}
|
|
1509
|
-
if (config.hooks.PreToolUse) {
|
|
1510
|
-
const before = config.hooks.PreToolUse.length;
|
|
1511
|
-
config.hooks.PreToolUse = config.hooks.PreToolUse.filter(
|
|
1512
|
-
(entry) => !entry.hooks?.some((h) => h.command?.includes("leash"))
|
|
1513
|
-
);
|
|
1514
|
-
if (config.hooks.PreToolUse.length < before) removed = true;
|
|
1515
|
-
}
|
|
1516
|
-
return removed;
|
|
1462
|
+
if (!config.extensions) return false;
|
|
1463
|
+
const before = config.extensions.length;
|
|
1464
|
+
config.extensions = config.extensions.filter((e) => !e.includes("leash"));
|
|
1465
|
+
return config.extensions.length < before;
|
|
1517
1466
|
}
|
|
1518
|
-
}
|
|
1467
|
+
},
|
|
1468
|
+
"claude-code": createHookPlatform({
|
|
1469
|
+
name: "Claude Code",
|
|
1470
|
+
configPath: ".claude/settings.json",
|
|
1471
|
+
distPath: "claude-code/leash.js",
|
|
1472
|
+
preToolUseMatcher: "Bash|Write|Edit"
|
|
1473
|
+
}),
|
|
1474
|
+
factory: createHookPlatform({
|
|
1475
|
+
name: "Factory",
|
|
1476
|
+
configPath: ".factory/settings.json",
|
|
1477
|
+
distPath: "factory/leash.js",
|
|
1478
|
+
preToolUseMatcher: "Execute|Write|Edit"
|
|
1479
|
+
})
|
|
1519
1480
|
};
|
|
1520
1481
|
function readConfig(configPath) {
|
|
1521
1482
|
if (!existsSync(configPath)) {
|
|
@@ -1597,6 +1558,9 @@ function setupPlatform(platformKey, configPath, leashPath) {
|
|
|
1597
1558
|
return setupOpenCode(configPath, leashPath);
|
|
1598
1559
|
}
|
|
1599
1560
|
const config = readConfig(configPath);
|
|
1561
|
+
if (!platform2.setup) {
|
|
1562
|
+
return { error: `Platform ${platformKey} has no setup handler` };
|
|
1563
|
+
}
|
|
1600
1564
|
const result = platform2.setup(config, leashPath);
|
|
1601
1565
|
if (result.skipped) {
|
|
1602
1566
|
return { skipped: true, platform: platform2.name };
|
|
@@ -1616,6 +1580,9 @@ function removePlatform(platformKey, configPath) {
|
|
|
1616
1580
|
return { notFound: true, platform: platform2.name };
|
|
1617
1581
|
}
|
|
1618
1582
|
const config = readConfig(configPath);
|
|
1583
|
+
if (!platform2.remove) {
|
|
1584
|
+
return { error: `Platform ${platformKey} has no remove handler` };
|
|
1585
|
+
}
|
|
1619
1586
|
const removed = platform2.remove(config);
|
|
1620
1587
|
if (!removed) {
|
|
1621
1588
|
return { notInstalled: true, platform: platform2.name };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@melihmucuk/leash",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Security guardrails for AI coding agents",
|
|
6
6
|
"bin": {
|
|
7
|
-
"leash": "
|
|
7
|
+
"leash": "dist/cli/leash.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist/"
|
|
@@ -25,15 +25,21 @@
|
|
|
25
25
|
"plugin",
|
|
26
26
|
"hooks",
|
|
27
27
|
"file-system",
|
|
28
|
-
"protection"
|
|
28
|
+
"protection",
|
|
29
|
+
"pi-package"
|
|
29
30
|
],
|
|
31
|
+
"pi": {
|
|
32
|
+
"extensions": [
|
|
33
|
+
"./dist/pi/leash.js"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
30
36
|
"homepage": "https://github.com/melihmucuk/leash",
|
|
31
37
|
"bugs": {
|
|
32
38
|
"url": "https://github.com/melihmucuk/leash/issues"
|
|
33
39
|
},
|
|
34
40
|
"repository": {
|
|
35
41
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/melihmucuk/leash.git"
|
|
42
|
+
"url": "git+https://github.com/melihmucuk/leash.git"
|
|
37
43
|
},
|
|
38
44
|
"scripts": {
|
|
39
45
|
"test": "npm run build:core && npm run build:cli-lib && node --test 'packages/core/test/*.test.js' 'packages/cli/test/*.test.js'",
|
|
@@ -47,6 +53,9 @@
|
|
|
47
53
|
"build:claude-code": "esbuild packages/claude-code/leash.ts --bundle --outfile=dist/claude-code/leash.js --platform=node --format=esm",
|
|
48
54
|
"build:factory": "esbuild packages/factory/leash.ts --bundle --outfile=dist/factory/leash.js --platform=node --format=esm"
|
|
49
55
|
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@mariozechner/pi-coding-agent": "*"
|
|
58
|
+
},
|
|
50
59
|
"devDependencies": {
|
|
51
60
|
"@mariozechner/pi-coding-agent": "^0.37.8",
|
|
52
61
|
"@opencode-ai/plugin": "^1.1.4",
|