@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 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 read-only CLI commands (reads from `assist.cli-reads`, also auto-approves read-only `gh api` calls). Supports compound commands (`|`, `&&`, `||`, `;`) by checking each sub-command independently
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.166.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
- "assist.cli-reads"
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 getCliReadsPath() {
3725
- return resolve2(__dirname4, "..", "assist.cli-reads");
3725
+ function packageRoot() {
3726
+ return resolve2(__dirname4, "..");
3726
3727
  }
3727
- var cachedLines;
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 (cachedLines) return cachedLines;
3730
- const path50 = getCliReadsPath();
3731
- if (!existsSync21(path50)) {
3732
- cachedLines = [];
3733
- return cachedLines;
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
- cachedLines = readFileSync16(path50, "utf-8").split("\n").filter((line) => line.trim() !== "");
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(getCliReadsPath(), `${commands.join("\n")}
3743
- `);
3744
- cachedLines = void 0;
3750
+ writeFileSync15(
3751
+ resolve2(packageRoot(), "allowed.cli-reads"),
3752
+ `${commands.join("\n")}
3753
+ `
3754
+ );
3755
+ cachedReads = void 0;
3745
3756
  }
3746
- function findCliRead(command) {
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 findMatch(entries, command) {
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 ? command === e.command || command.startsWith(`${e.command} `) : command === e.command
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 findMatch(shellEntries(allowCache, toolName), command);
3828
+ return findMatch2(shellEntries(allowCache, toolName), command);
3808
3829
  }
3809
3830
  function matchesDeny(toolName, command) {
3810
3831
  if (!denyCache) denyCache = loadPerms("deny");
3811
- return findMatch(shellEntries(denyCache, toolName), command);
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 matched = findCliRead(command);
3833
- if (matched) return `Read-only CLI command: ${matched}`;
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.166.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
- "assist.cli-reads"
14
+ "allowed.cli-reads",
15
+ "allowed.cli-writes"
15
16
  ],
16
17
  "publishConfig": {
17
18
  "access": "public"