@staff0rd/assist 0.166.0 → 0.167.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/README.md +1 -1
- package/{assist.cli-reads → allowed.cli-reads} +0 -13
- package/allowed.cli-writes +15 -0
- package/dist/index.js +47 -24
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ After installation, the `assist` command will be available globally. You can als
|
|
|
119
119
|
- `assist devlog repos` - Show which github.com/staff0rd repos are missing devlog entries
|
|
120
120
|
- `assist devlog skip <date>` - Add a date to the skip list
|
|
121
121
|
- `assist devlog version` - Show current repo name and version info
|
|
122
|
-
- `assist cli-hook` - PreToolUse hook for auto-approving
|
|
122
|
+
- `assist cli-hook` - PreToolUse hook for auto-approving CLI commands (reads from `allowed.cli-reads` and `allowed.cli-writes`, also auto-approves read-only `gh api` calls). Supports compound commands (`|`, `&&`, `||`, `;`) by checking each sub-command independently
|
|
123
123
|
- `assist cli-hook add <cli>` - Discover a CLI's commands and auto-permit read-only ones
|
|
124
124
|
- `assist cli-hook check <command> [--tool <tool>]` - Check whether a command would be auto-approved by `cli-hook` (tool defaults to `Bash`)
|
|
125
125
|
- `assist cli-hook deny` - List all deny rules
|
|
@@ -19,27 +19,18 @@ acli jira workitem link list
|
|
|
19
19
|
acli jira workitem search
|
|
20
20
|
acli jira workitem view
|
|
21
21
|
acli jira workitem watcher list
|
|
22
|
-
assist backlog add
|
|
23
|
-
assist backlog comment
|
|
24
22
|
assist backlog comments
|
|
25
|
-
assist backlog done
|
|
26
23
|
assist backlog list
|
|
27
|
-
assist backlog phase-done
|
|
28
|
-
assist backlog plan
|
|
29
24
|
assist backlog show
|
|
30
|
-
assist backlog start
|
|
31
25
|
assist backlog view
|
|
32
26
|
assist cli-hook
|
|
33
|
-
assist commit
|
|
34
27
|
assist complexity
|
|
35
28
|
assist coverage
|
|
36
|
-
assist devlog
|
|
37
29
|
assist dotnet
|
|
38
30
|
assist jira ac
|
|
39
31
|
assist jira auth
|
|
40
32
|
assist jira view
|
|
41
33
|
assist news
|
|
42
|
-
assist notify
|
|
43
34
|
assist prs list-comments
|
|
44
35
|
assist ravendb auth list
|
|
45
36
|
assist ravendb collections
|
|
@@ -49,11 +40,7 @@ assist roam show-claude-code-icon
|
|
|
49
40
|
assist screenshot
|
|
50
41
|
assist seq auth list
|
|
51
42
|
assist seq query
|
|
52
|
-
assist signal next
|
|
53
43
|
assist status-line
|
|
54
|
-
assist sync
|
|
55
|
-
assist transcript format
|
|
56
|
-
assist transcript summarise
|
|
57
44
|
assist verify
|
|
58
45
|
assist voice
|
|
59
46
|
az account list
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
assist backlog add
|
|
2
|
+
assist backlog comment
|
|
3
|
+
assist backlog done
|
|
4
|
+
assist backlog link
|
|
5
|
+
assist backlog phase-done
|
|
6
|
+
assist backlog plan
|
|
7
|
+
assist backlog unlink
|
|
8
|
+
assist backlog start
|
|
9
|
+
assist commit
|
|
10
|
+
assist devlog
|
|
11
|
+
assist notify
|
|
12
|
+
assist signal next
|
|
13
|
+
assist sync
|
|
14
|
+
assist transcript format
|
|
15
|
+
assist transcript summarise
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.167.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -17,7 +17,8 @@ var package_default = {
|
|
|
17
17
|
files: [
|
|
18
18
|
"dist",
|
|
19
19
|
"claude",
|
|
20
|
-
"
|
|
20
|
+
"allowed.cli-reads",
|
|
21
|
+
"allowed.cli-writes"
|
|
21
22
|
],
|
|
22
23
|
publishConfig: {
|
|
23
24
|
access: "public"
|
|
@@ -3721,32 +3722,41 @@ import { dirname as dirname14, resolve as resolve2 } from "path";
|
|
|
3721
3722
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3722
3723
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
3723
3724
|
var __dirname4 = dirname14(__filename2);
|
|
3724
|
-
function
|
|
3725
|
-
return resolve2(__dirname4, ".."
|
|
3725
|
+
function packageRoot() {
|
|
3726
|
+
return resolve2(__dirname4, "..");
|
|
3726
3727
|
}
|
|
3727
|
-
|
|
3728
|
+
function readLines(path50) {
|
|
3729
|
+
if (!existsSync21(path50)) return [];
|
|
3730
|
+
return readFileSync16(path50, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
3731
|
+
}
|
|
3732
|
+
var cachedReads;
|
|
3733
|
+
var cachedWrites;
|
|
3728
3734
|
function getCliReadsLines() {
|
|
3729
|
-
if (
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3735
|
+
if (!cachedReads) {
|
|
3736
|
+
cachedReads = readLines(resolve2(packageRoot(), "allowed.cli-reads"));
|
|
3737
|
+
}
|
|
3738
|
+
return cachedReads;
|
|
3739
|
+
}
|
|
3740
|
+
function getCliWritesLines() {
|
|
3741
|
+
if (!cachedWrites) {
|
|
3742
|
+
cachedWrites = readLines(resolve2(packageRoot(), "allowed.cli-writes"));
|
|
3734
3743
|
}
|
|
3735
|
-
|
|
3736
|
-
return cachedLines;
|
|
3744
|
+
return cachedWrites;
|
|
3737
3745
|
}
|
|
3738
3746
|
function loadCliReads() {
|
|
3739
3747
|
return getCliReadsLines();
|
|
3740
3748
|
}
|
|
3741
3749
|
function saveCliReads(commands) {
|
|
3742
|
-
writeFileSync15(
|
|
3743
|
-
|
|
3744
|
-
|
|
3750
|
+
writeFileSync15(
|
|
3751
|
+
resolve2(packageRoot(), "allowed.cli-reads"),
|
|
3752
|
+
`${commands.join("\n")}
|
|
3753
|
+
`
|
|
3754
|
+
);
|
|
3755
|
+
cachedReads = void 0;
|
|
3745
3756
|
}
|
|
3746
|
-
function
|
|
3757
|
+
function findMatch(command, lines) {
|
|
3747
3758
|
const words = command.split(/\s+/);
|
|
3748
3759
|
if (words.length === 0) return void 0;
|
|
3749
|
-
const lines = getCliReadsLines();
|
|
3750
3760
|
if (lines.includes(words[0])) return words[0];
|
|
3751
3761
|
if (words.length < 2) return void 0;
|
|
3752
3762
|
const prefix2 = `${words[0]} ${words[1]}`;
|
|
@@ -3755,6 +3765,12 @@ function findCliRead(command) {
|
|
|
3755
3765
|
);
|
|
3756
3766
|
return candidates.sort((a, b) => b.length - a.length).find((rc) => command === rc || command.startsWith(`${rc} `));
|
|
3757
3767
|
}
|
|
3768
|
+
function findCliRead(command) {
|
|
3769
|
+
return findMatch(command, getCliReadsLines());
|
|
3770
|
+
}
|
|
3771
|
+
function findCliWrite(command) {
|
|
3772
|
+
return findMatch(command, getCliWritesLines());
|
|
3773
|
+
}
|
|
3758
3774
|
|
|
3759
3775
|
// src/shared/readSettingsPerms.ts
|
|
3760
3776
|
import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
|
|
@@ -3788,6 +3804,7 @@ var allowCache;
|
|
|
3788
3804
|
var denyCache;
|
|
3789
3805
|
var TOOL_RE = /^(Bash|PowerShell)\((.+?)(:.*)?\)$/;
|
|
3790
3806
|
var SHELL_TOOLS = ["Bash", "PowerShell"];
|
|
3807
|
+
var DOTSLASH_RE = /^\.[\\/]/;
|
|
3791
3808
|
function loadPerms(key) {
|
|
3792
3809
|
return parsePerms(readSettingsPerms(key));
|
|
3793
3810
|
}
|
|
@@ -3797,18 +3814,22 @@ function shellEntries(map, toolName) {
|
|
|
3797
3814
|
}
|
|
3798
3815
|
return map.get(toolName) ?? [];
|
|
3799
3816
|
}
|
|
3800
|
-
function
|
|
3817
|
+
function normCmd(cmd) {
|
|
3818
|
+
return cmd.replace(DOTSLASH_RE, "");
|
|
3819
|
+
}
|
|
3820
|
+
function findMatch2(entries, command) {
|
|
3821
|
+
const norm = normCmd(command);
|
|
3801
3822
|
return entries.find(
|
|
3802
|
-
(e) => e.wildcard ?
|
|
3823
|
+
(e) => e.wildcard ? norm === e.command || norm.startsWith(`${e.command} `) : norm === e.command
|
|
3803
3824
|
)?.command;
|
|
3804
3825
|
}
|
|
3805
3826
|
function matchesAllow(toolName, command) {
|
|
3806
3827
|
if (!allowCache) allowCache = loadPerms("allow");
|
|
3807
|
-
return
|
|
3828
|
+
return findMatch2(shellEntries(allowCache, toolName), command);
|
|
3808
3829
|
}
|
|
3809
3830
|
function matchesDeny(toolName, command) {
|
|
3810
3831
|
if (!denyCache) denyCache = loadPerms("deny");
|
|
3811
|
-
return
|
|
3832
|
+
return findMatch2(shellEntries(denyCache, toolName), command);
|
|
3812
3833
|
}
|
|
3813
3834
|
function parsePerms(entries) {
|
|
3814
3835
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -3816,7 +3837,7 @@ function parsePerms(entries) {
|
|
|
3816
3837
|
const m = entry.match(TOOL_RE);
|
|
3817
3838
|
if (m) {
|
|
3818
3839
|
const tool = m[1];
|
|
3819
|
-
const command = m[2];
|
|
3840
|
+
const command = normCmd(m[2]);
|
|
3820
3841
|
const wildcard = m[3] !== void 0;
|
|
3821
3842
|
const list4 = map.get(tool) ?? [];
|
|
3822
3843
|
list4.push({ command, wildcard });
|
|
@@ -3829,8 +3850,10 @@ function parsePerms(entries) {
|
|
|
3829
3850
|
// src/shared/isApprovedRead.ts
|
|
3830
3851
|
function isApprovedRead(command, toolName = "Bash") {
|
|
3831
3852
|
if (isCdToCwd(command)) return "cd to current directory";
|
|
3832
|
-
const
|
|
3833
|
-
if (
|
|
3853
|
+
const matchedRead = findCliRead(command);
|
|
3854
|
+
if (matchedRead) return `Read-only CLI command: ${matchedRead}`;
|
|
3855
|
+
const matchedWrite = findCliWrite(command);
|
|
3856
|
+
if (matchedWrite) return `Allowed CLI write: ${matchedWrite}`;
|
|
3834
3857
|
if (isGhApiRead(command)) return "Read-only gh api command";
|
|
3835
3858
|
const allowMatch = matchesAllow(toolName, command);
|
|
3836
3859
|
if (allowMatch) return `Allowed by settings: ${allowMatch}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staff0rd/assist",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.167.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
13
|
"claude",
|
|
14
|
-
"
|
|
14
|
+
"allowed.cli-reads",
|
|
15
|
+
"allowed.cli-writes"
|
|
15
16
|
],
|
|
16
17
|
"publishConfig": {
|
|
17
18
|
"access": "public"
|