fastgrc-openclaw 1.0.23 → 1.0.25

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 (3) hide show
  1. package/dist/bin.js +98 -139
  2. package/dist/bin.mjs +98 -145
  3. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -91,64 +91,6 @@ function readConfig() {
91
91
  function writeConfig(data) {
92
92
  fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 384 });
93
93
  }
94
- var [, , cmd, arg] = process.argv;
95
- if (cmd === "set-key") {
96
- if (!arg) {
97
- process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
98
- process.exit(1);
99
- }
100
- writeConfig({ ...readConfig(), apiKey: arg });
101
- process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
102
- `);
103
- process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
104
- process.exit(0);
105
- }
106
- if (cmd === "get-key") {
107
- const key = readConfig().apiKey;
108
- if (!key) {
109
- process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
110
- } else {
111
- process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
112
- `);
113
- }
114
- process.exit(0);
115
- }
116
- if (cmd === "unset-key") {
117
- const cfg = readConfig();
118
- delete cfg.apiKey;
119
- writeConfig(cfg);
120
- process.stdout.write("FastGRC API key removed.\n");
121
- process.exit(0);
122
- }
123
- if (cmd === "set-policy") {
124
- if (!arg) {
125
- process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
126
- process.exit(1);
127
- }
128
- writeConfig({ ...readConfig(), policyId: arg });
129
- process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
130
- `);
131
- process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
132
- process.exit(0);
133
- }
134
- if (cmd === "get-policy") {
135
- const id = readConfig().policyId;
136
- if (!id) {
137
- process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
138
- process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
139
- } else {
140
- process.stdout.write(`${id}
141
- `);
142
- }
143
- process.exit(0);
144
- }
145
- if (cmd === "unset-policy") {
146
- const cfg = readConfig();
147
- delete cfg.policyId;
148
- writeConfig(cfg);
149
- process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
150
- process.exit(0);
151
- }
152
94
  function computeHandler() {
153
95
  const binPath = process.argv[1];
154
96
  const homeDir = os.homedir();
@@ -164,30 +106,7 @@ Test it directly (bypasses OpenClaw):
164
106
  `
165
107
  );
166
108
  }
167
- if (cmd === "restart-openclaw") {
168
- const { spawn, execSync } = require("child_process");
169
- try {
170
- execSync("pkill -x openclaw", { stdio: "ignore" });
171
- process.stdout.write("Stopped existing openclaw process(es).\n");
172
- } catch {
173
- process.stdout.write("No openclaw process was running.\n");
174
- }
175
- const logPath = process.env.OPENCLAW_LOG ?? "/tmp/openclaw.log";
176
- const workDir = arg || process.cwd();
177
- const out = fs.openSync(logPath, "a");
178
- const child = spawn("openclaw", [], {
179
- detached: true,
180
- stdio: ["ignore", out, out],
181
- cwd: workDir
182
- });
183
- child.unref();
184
- process.stdout.write(`\u2713 OpenClaw started (PID: ${child.pid}, cwd: ${workDir})
185
- Logs: tail -f ${logPath}
186
- `);
187
- process.exit(0);
188
- }
189
- if (cmd === "install-hook") {
190
- const targetDir = arg || process.cwd();
109
+ function doInstallHook(targetDir) {
191
110
  const hookMdPath = path.join(targetDir, "HOOK.md");
192
111
  const { handlerStr } = computeHandler();
193
112
  const HOOK_ENTRY = ` - matcher: PreToolUse
@@ -206,7 +125,7 @@ if (cmd === "install-hook") {
206
125
  Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
207
126
  `);
208
127
  printTestSnippet(handlerStr);
209
- process.exit(0);
128
+ return;
210
129
  }
211
130
  const existing = fs.readFileSync(hookMdPath, "utf8");
212
131
  if (existing.includes(handlerStr)) {
@@ -214,7 +133,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
214
133
  Handler: ${handlerStr}
215
134
  `);
216
135
  printTestSnippet(handlerStr);
217
- process.exit(0);
136
+ return;
218
137
  }
219
138
  if (existing.includes("fastgrc-hook") || existing.includes("fastgrc-openclaw")) {
220
139
  const patched = existing.replace(
@@ -228,7 +147,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
228
147
  Restart OpenClaw to activate.
229
148
  `);
230
149
  printTestSnippet(handlerStr);
231
- process.exit(0);
150
+ return;
232
151
  }
233
152
  const fmEnd = existing.indexOf("\n---", 3);
234
153
  let updated;
@@ -247,10 +166,93 @@ ${HOOK_ENTRY}`;
247
166
  Restart OpenClaw to activate.
248
167
  `);
249
168
  printTestSnippet(handlerStr);
169
+ }
170
+ function doUninstallHook(targetDir) {
171
+ const hookMdPath = path.join(targetDir, "HOOK.md");
172
+ if (!fs.existsSync(hookMdPath)) {
173
+ process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
174
+ return;
175
+ }
176
+ const existing = fs.readFileSync(hookMdPath, "utf8");
177
+ const patched = existing.replace(
178
+ /[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
179
+ ""
180
+ );
181
+ if (patched === existing) {
182
+ process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
183
+ } else {
184
+ fs.writeFileSync(hookMdPath, patched, "utf8");
185
+ process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
186
+ `);
187
+ }
188
+ }
189
+ var [, , cmd, arg] = process.argv;
190
+ if (cmd === "set-key") {
191
+ if (!arg) {
192
+ process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
193
+ process.exit(1);
194
+ }
195
+ writeConfig({ ...readConfig(), apiKey: arg });
196
+ process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
197
+ `);
198
+ process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
199
+ process.exit(0);
200
+ }
201
+ if (cmd === "get-key") {
202
+ const key = readConfig().apiKey;
203
+ if (!key) {
204
+ process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
205
+ } else {
206
+ process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
207
+ `);
208
+ }
209
+ process.exit(0);
210
+ }
211
+ if (cmd === "unset-key") {
212
+ const cfg = readConfig();
213
+ delete cfg.apiKey;
214
+ writeConfig(cfg);
215
+ process.stdout.write("FastGRC API key removed.\n");
216
+ process.exit(0);
217
+ }
218
+ if (cmd === "set-policy") {
219
+ if (!arg) {
220
+ process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
221
+ process.exit(1);
222
+ }
223
+ writeConfig({ ...readConfig(), policyId: arg });
224
+ process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
225
+ `);
226
+ process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
227
+ process.exit(0);
228
+ }
229
+ if (cmd === "get-policy") {
230
+ const id = readConfig().policyId;
231
+ if (!id) {
232
+ process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
233
+ process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
234
+ } else {
235
+ process.stdout.write(`${id}
236
+ `);
237
+ }
238
+ process.exit(0);
239
+ }
240
+ if (cmd === "unset-policy") {
241
+ const cfg = readConfig();
242
+ delete cfg.policyId;
243
+ writeConfig(cfg);
244
+ process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
245
+ process.exit(0);
246
+ }
247
+ if (cmd === "install-hook") {
248
+ doInstallHook(arg || process.cwd());
249
+ process.exit(0);
250
+ }
251
+ if (cmd === "uninstall-hook") {
252
+ doUninstallHook(arg || process.cwd());
250
253
  process.exit(0);
251
254
  }
252
255
  if (cmd === "setup") {
253
- const { execSync } = require("child_process");
254
256
  const rest = process.argv.slice(3);
255
257
  let apiKeyArg;
256
258
  let policyIdArg;
@@ -269,71 +271,29 @@ if (cmd === "setup") {
269
271
  process.stderr.write("Usage: fastgrc-hook setup --api-key <key> [--policy-id <id>]\n");
270
272
  process.exit(1);
271
273
  }
272
- const selfBin = process.argv[1];
273
- process.stdout.write("Step 1/4: Installing OpenClaw plugin as root...\n");
274
- try {
275
- execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "ignore" });
276
- } catch {
277
- }
278
- execSync("sudo openclaw plugins install fastgrc-openclaw", { stdio: "inherit" });
279
274
  writeConfig({ ...readConfig(), apiKey: apiKeyArg });
280
- process.stdout.write("Step 2/4: API key saved to ~/.fastgrc.json\n");
275
+ process.stdout.write("\u2713 API key saved to ~/.fastgrc.json\n");
281
276
  if (policyIdArg) {
282
277
  writeConfig({ ...readConfig(), policyId: policyIdArg });
283
- process.stdout.write("Step 3/4: Policy ID saved to ~/.fastgrc.json\n");
284
- } else {
285
- process.stdout.write("Step 3/4: No policy ID provided \u2014 org-wide default will be used.\n");
286
- }
287
- process.stdout.write("Step 4/4: Wiring up HOOK.md and restarting OpenClaw...\n");
288
- execSync(`node "${selfBin}" install-hook`, { stdio: "inherit" });
289
- execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
290
- process.stdout.write('\n\u2713 FastGRC setup complete. Run "fastgrc-hook test" to verify.\n');
291
- process.exit(0);
292
- }
293
- if (cmd === "uninstall-hook") {
294
- const targetDir = arg || process.cwd();
295
- const hookMdPath = path.join(targetDir, "HOOK.md");
296
- if (!fs.existsSync(hookMdPath)) {
297
- process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
298
- process.exit(0);
299
- }
300
- const existing = fs.readFileSync(hookMdPath, "utf8");
301
- const patched = existing.replace(
302
- /[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
303
- ""
304
- );
305
- if (patched === existing) {
306
- process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
278
+ process.stdout.write("\u2713 Policy ID saved to ~/.fastgrc.json\n");
307
279
  } else {
308
- fs.writeFileSync(hookMdPath, patched, "utf8");
309
- process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
310
- `);
280
+ process.stdout.write(" (no policy ID \u2014 org-wide default will be used)\n");
311
281
  }
282
+ doInstallHook(process.cwd());
283
+ process.stdout.write("\n\u2713 Config and HOOK.md done.\n");
284
+ process.stdout.write('Run "fastgrc-hook test" to verify the hook.\n');
312
285
  process.exit(0);
313
286
  }
314
287
  if (cmd === "uninstall") {
315
- const { execSync } = require("child_process");
316
- const selfBin = process.argv[1];
317
288
  const targetDir = arg || process.cwd();
318
- process.stdout.write("Removing FastGRC from this OpenClaw deployment...\n\n");
319
- process.stdout.write("1. Removing OpenClaw plugin...\n");
320
- try {
321
- execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "inherit" });
322
- } catch {
323
- process.stdout.write(" (plugin was not installed \u2014 skipped)\n");
324
- }
325
- process.stdout.write("2. Clearing config...\n");
326
289
  const cfg = readConfig();
327
290
  delete cfg.apiKey;
328
291
  delete cfg.policyId;
329
292
  writeConfig(cfg);
330
- process.stdout.write(" API key and policy ID removed from ~/.fastgrc.json\n");
331
- process.stdout.write("3. Removing hook from HOOK.md...\n");
332
- execSync(`node "${selfBin}" uninstall-hook "${targetDir}"`, { stdio: "inherit" });
333
- process.stdout.write("4. Restarting OpenClaw...\n");
334
- execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
293
+ process.stdout.write("\u2713 API key and policy ID removed from ~/.fastgrc.json\n");
294
+ doUninstallHook(targetDir);
335
295
  process.stdout.write(
336
- "\n\u2713 FastGRC removed.\nTo fully remove the CLI: npm uninstall -g fastgrc-openclaw\n"
296
+ "\n\u2713 Config and HOOK.md cleaned up.\nComplete removal \u2014 run these two commands:\n rm -rf ~/.openclaw/npm/node_modules/fastgrc-openclaw\n npm uninstall -g fastgrc-openclaw\n"
337
297
  );
338
298
  process.exit(0);
339
299
  }
@@ -390,7 +350,7 @@ if (cmd === "test") {
390
350
  `);
391
351
  process.exit(0);
392
352
  }
393
- if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restart-openclaw" || cmd === "setup" || cmd === "uninstall" || cmd === "uninstall-hook") {
353
+ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "setup" || cmd === "uninstall" || cmd === "install-hook" || cmd === "uninstall-hook") {
394
354
  } else {
395
355
  const apiKey = process.env.FASTGRC_API_KEY ?? readConfig().apiKey;
396
356
  if (!apiKey) {
@@ -431,7 +391,6 @@ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restar
431
391
  args,
432
392
  agentId,
433
393
  apiKey,
434
- // narrowed at module level via early-exit guard above
435
394
  policyId,
436
395
  baseUrl
437
396
  });
package/dist/bin.mjs CHANGED
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
- }) : x)(function(x) {
5
- if (typeof require !== "undefined") return require.apply(this, arguments);
6
- throw Error('Dynamic require of "' + x + '" is not supported');
7
- });
8
2
 
9
3
  // src/bin.ts
10
4
  import * as fs from "fs";
@@ -74,64 +68,6 @@ function readConfig() {
74
68
  function writeConfig(data) {
75
69
  fs.writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 384 });
76
70
  }
77
- var [, , cmd, arg] = process.argv;
78
- if (cmd === "set-key") {
79
- if (!arg) {
80
- process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
81
- process.exit(1);
82
- }
83
- writeConfig({ ...readConfig(), apiKey: arg });
84
- process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
85
- `);
86
- process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
87
- process.exit(0);
88
- }
89
- if (cmd === "get-key") {
90
- const key = readConfig().apiKey;
91
- if (!key) {
92
- process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
93
- } else {
94
- process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
95
- `);
96
- }
97
- process.exit(0);
98
- }
99
- if (cmd === "unset-key") {
100
- const cfg = readConfig();
101
- delete cfg.apiKey;
102
- writeConfig(cfg);
103
- process.stdout.write("FastGRC API key removed.\n");
104
- process.exit(0);
105
- }
106
- if (cmd === "set-policy") {
107
- if (!arg) {
108
- process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
109
- process.exit(1);
110
- }
111
- writeConfig({ ...readConfig(), policyId: arg });
112
- process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
113
- `);
114
- process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
115
- process.exit(0);
116
- }
117
- if (cmd === "get-policy") {
118
- const id = readConfig().policyId;
119
- if (!id) {
120
- process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
121
- process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
122
- } else {
123
- process.stdout.write(`${id}
124
- `);
125
- }
126
- process.exit(0);
127
- }
128
- if (cmd === "unset-policy") {
129
- const cfg = readConfig();
130
- delete cfg.policyId;
131
- writeConfig(cfg);
132
- process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
133
- process.exit(0);
134
- }
135
71
  function computeHandler() {
136
72
  const binPath = process.argv[1];
137
73
  const homeDir = os.homedir();
@@ -147,30 +83,7 @@ Test it directly (bypasses OpenClaw):
147
83
  `
148
84
  );
149
85
  }
150
- if (cmd === "restart-openclaw") {
151
- const { spawn, execSync } = __require("child_process");
152
- try {
153
- execSync("pkill -x openclaw", { stdio: "ignore" });
154
- process.stdout.write("Stopped existing openclaw process(es).\n");
155
- } catch {
156
- process.stdout.write("No openclaw process was running.\n");
157
- }
158
- const logPath = process.env.OPENCLAW_LOG ?? "/tmp/openclaw.log";
159
- const workDir = arg || process.cwd();
160
- const out = fs.openSync(logPath, "a");
161
- const child = spawn("openclaw", [], {
162
- detached: true,
163
- stdio: ["ignore", out, out],
164
- cwd: workDir
165
- });
166
- child.unref();
167
- process.stdout.write(`\u2713 OpenClaw started (PID: ${child.pid}, cwd: ${workDir})
168
- Logs: tail -f ${logPath}
169
- `);
170
- process.exit(0);
171
- }
172
- if (cmd === "install-hook") {
173
- const targetDir = arg || process.cwd();
86
+ function doInstallHook(targetDir) {
174
87
  const hookMdPath = path.join(targetDir, "HOOK.md");
175
88
  const { handlerStr } = computeHandler();
176
89
  const HOOK_ENTRY = ` - matcher: PreToolUse
@@ -189,7 +102,7 @@ if (cmd === "install-hook") {
189
102
  Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
190
103
  `);
191
104
  printTestSnippet(handlerStr);
192
- process.exit(0);
105
+ return;
193
106
  }
194
107
  const existing = fs.readFileSync(hookMdPath, "utf8");
195
108
  if (existing.includes(handlerStr)) {
@@ -197,7 +110,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
197
110
  Handler: ${handlerStr}
198
111
  `);
199
112
  printTestSnippet(handlerStr);
200
- process.exit(0);
113
+ return;
201
114
  }
202
115
  if (existing.includes("fastgrc-hook") || existing.includes("fastgrc-openclaw")) {
203
116
  const patched = existing.replace(
@@ -211,7 +124,7 @@ Restart OpenClaw \u2014 FastGRC will evaluate every tool call.
211
124
  Restart OpenClaw to activate.
212
125
  `);
213
126
  printTestSnippet(handlerStr);
214
- process.exit(0);
127
+ return;
215
128
  }
216
129
  const fmEnd = existing.indexOf("\n---", 3);
217
130
  let updated;
@@ -230,10 +143,93 @@ ${HOOK_ENTRY}`;
230
143
  Restart OpenClaw to activate.
231
144
  `);
232
145
  printTestSnippet(handlerStr);
146
+ }
147
+ function doUninstallHook(targetDir) {
148
+ const hookMdPath = path.join(targetDir, "HOOK.md");
149
+ if (!fs.existsSync(hookMdPath)) {
150
+ process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
151
+ return;
152
+ }
153
+ const existing = fs.readFileSync(hookMdPath, "utf8");
154
+ const patched = existing.replace(
155
+ /[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
156
+ ""
157
+ );
158
+ if (patched === existing) {
159
+ process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
160
+ } else {
161
+ fs.writeFileSync(hookMdPath, patched, "utf8");
162
+ process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
163
+ `);
164
+ }
165
+ }
166
+ var [, , cmd, arg] = process.argv;
167
+ if (cmd === "set-key") {
168
+ if (!arg) {
169
+ process.stderr.write("Usage: fastgrc-hook set-key fgrc_k1_...\n");
170
+ process.exit(1);
171
+ }
172
+ writeConfig({ ...readConfig(), apiKey: arg });
173
+ process.stdout.write(`\u2713 FastGRC API key saved to ${CONFIG_PATH}
174
+ `);
175
+ process.stdout.write(' Run "fastgrc-hook get-key" to verify.\n');
176
+ process.exit(0);
177
+ }
178
+ if (cmd === "get-key") {
179
+ const key = readConfig().apiKey;
180
+ if (!key) {
181
+ process.stdout.write("No key stored. Run: fastgrc-hook set-key fgrc_k1_...\n");
182
+ } else {
183
+ process.stdout.write(`${key.slice(0, 12)}${"*".repeat(Math.max(0, key.length - 12))}
184
+ `);
185
+ }
186
+ process.exit(0);
187
+ }
188
+ if (cmd === "unset-key") {
189
+ const cfg = readConfig();
190
+ delete cfg.apiKey;
191
+ writeConfig(cfg);
192
+ process.stdout.write("FastGRC API key removed.\n");
193
+ process.exit(0);
194
+ }
195
+ if (cmd === "set-policy") {
196
+ if (!arg) {
197
+ process.stderr.write("Usage: fastgrc-hook set-policy <policy-id>\n");
198
+ process.exit(1);
199
+ }
200
+ writeConfig({ ...readConfig(), policyId: arg });
201
+ process.stdout.write(`\u2713 FastGRC policy ID saved to ${CONFIG_PATH}
202
+ `);
203
+ process.stdout.write(' Run "fastgrc-hook get-policy" to verify.\n');
204
+ process.exit(0);
205
+ }
206
+ if (cmd === "get-policy") {
207
+ const id = readConfig().policyId;
208
+ if (!id) {
209
+ process.stdout.write("No policy ID stored \u2014 org-wide default will be used.\n");
210
+ process.stdout.write("Run: fastgrc-hook set-policy <policy-id>\n");
211
+ } else {
212
+ process.stdout.write(`${id}
213
+ `);
214
+ }
215
+ process.exit(0);
216
+ }
217
+ if (cmd === "unset-policy") {
218
+ const cfg = readConfig();
219
+ delete cfg.policyId;
220
+ writeConfig(cfg);
221
+ process.stdout.write("FastGRC policy ID removed \u2014 org-wide default will be used.\n");
222
+ process.exit(0);
223
+ }
224
+ if (cmd === "install-hook") {
225
+ doInstallHook(arg || process.cwd());
226
+ process.exit(0);
227
+ }
228
+ if (cmd === "uninstall-hook") {
229
+ doUninstallHook(arg || process.cwd());
233
230
  process.exit(0);
234
231
  }
235
232
  if (cmd === "setup") {
236
- const { execSync } = __require("child_process");
237
233
  const rest = process.argv.slice(3);
238
234
  let apiKeyArg;
239
235
  let policyIdArg;
@@ -252,71 +248,29 @@ if (cmd === "setup") {
252
248
  process.stderr.write("Usage: fastgrc-hook setup --api-key <key> [--policy-id <id>]\n");
253
249
  process.exit(1);
254
250
  }
255
- const selfBin = process.argv[1];
256
- process.stdout.write("Step 1/4: Installing OpenClaw plugin as root...\n");
257
- try {
258
- execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "ignore" });
259
- } catch {
260
- }
261
- execSync("sudo openclaw plugins install fastgrc-openclaw", { stdio: "inherit" });
262
251
  writeConfig({ ...readConfig(), apiKey: apiKeyArg });
263
- process.stdout.write("Step 2/4: API key saved to ~/.fastgrc.json\n");
252
+ process.stdout.write("\u2713 API key saved to ~/.fastgrc.json\n");
264
253
  if (policyIdArg) {
265
254
  writeConfig({ ...readConfig(), policyId: policyIdArg });
266
- process.stdout.write("Step 3/4: Policy ID saved to ~/.fastgrc.json\n");
267
- } else {
268
- process.stdout.write("Step 3/4: No policy ID provided \u2014 org-wide default will be used.\n");
269
- }
270
- process.stdout.write("Step 4/4: Wiring up HOOK.md and restarting OpenClaw...\n");
271
- execSync(`node "${selfBin}" install-hook`, { stdio: "inherit" });
272
- execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
273
- process.stdout.write('\n\u2713 FastGRC setup complete. Run "fastgrc-hook test" to verify.\n');
274
- process.exit(0);
275
- }
276
- if (cmd === "uninstall-hook") {
277
- const targetDir = arg || process.cwd();
278
- const hookMdPath = path.join(targetDir, "HOOK.md");
279
- if (!fs.existsSync(hookMdPath)) {
280
- process.stdout.write("No HOOK.md found \u2014 nothing to remove.\n");
281
- process.exit(0);
282
- }
283
- const existing = fs.readFileSync(hookMdPath, "utf8");
284
- const patched = existing.replace(
285
- /[ \t]*-[ \t]*matcher:[ \t]*PreToolUse\n[ \t]*handler:[ \t]*"[^"]*(?:fastgrc-hook|fastgrc-openclaw)[^"]*"\n?/,
286
- ""
287
- );
288
- if (patched === existing) {
289
- process.stdout.write("FastGRC hook not found in HOOK.md \u2014 nothing to remove.\n");
255
+ process.stdout.write("\u2713 Policy ID saved to ~/.fastgrc.json\n");
290
256
  } else {
291
- fs.writeFileSync(hookMdPath, patched, "utf8");
292
- process.stdout.write(`\u2713 FastGRC hook removed from ${hookMdPath}
293
- `);
257
+ process.stdout.write(" (no policy ID \u2014 org-wide default will be used)\n");
294
258
  }
259
+ doInstallHook(process.cwd());
260
+ process.stdout.write("\n\u2713 Config and HOOK.md done.\n");
261
+ process.stdout.write('Run "fastgrc-hook test" to verify the hook.\n');
295
262
  process.exit(0);
296
263
  }
297
264
  if (cmd === "uninstall") {
298
- const { execSync } = __require("child_process");
299
- const selfBin = process.argv[1];
300
265
  const targetDir = arg || process.cwd();
301
- process.stdout.write("Removing FastGRC from this OpenClaw deployment...\n\n");
302
- process.stdout.write("1. Removing OpenClaw plugin...\n");
303
- try {
304
- execSync("sudo openclaw plugins remove fastgrc-openclaw", { stdio: "inherit" });
305
- } catch {
306
- process.stdout.write(" (plugin was not installed \u2014 skipped)\n");
307
- }
308
- process.stdout.write("2. Clearing config...\n");
309
266
  const cfg = readConfig();
310
267
  delete cfg.apiKey;
311
268
  delete cfg.policyId;
312
269
  writeConfig(cfg);
313
- process.stdout.write(" API key and policy ID removed from ~/.fastgrc.json\n");
314
- process.stdout.write("3. Removing hook from HOOK.md...\n");
315
- execSync(`node "${selfBin}" uninstall-hook "${targetDir}"`, { stdio: "inherit" });
316
- process.stdout.write("4. Restarting OpenClaw...\n");
317
- execSync(`node "${selfBin}" restart-openclaw`, { stdio: "inherit" });
270
+ process.stdout.write("\u2713 API key and policy ID removed from ~/.fastgrc.json\n");
271
+ doUninstallHook(targetDir);
318
272
  process.stdout.write(
319
- "\n\u2713 FastGRC removed.\nTo fully remove the CLI: npm uninstall -g fastgrc-openclaw\n"
273
+ "\n\u2713 Config and HOOK.md cleaned up.\nComplete removal \u2014 run these two commands:\n rm -rf ~/.openclaw/npm/node_modules/fastgrc-openclaw\n npm uninstall -g fastgrc-openclaw\n"
320
274
  );
321
275
  process.exit(0);
322
276
  }
@@ -373,7 +327,7 @@ if (cmd === "test") {
373
327
  `);
374
328
  process.exit(0);
375
329
  }
376
- if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restart-openclaw" || cmd === "setup" || cmd === "uninstall" || cmd === "uninstall-hook") {
330
+ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "setup" || cmd === "uninstall" || cmd === "install-hook" || cmd === "uninstall-hook") {
377
331
  } else {
378
332
  const apiKey = process.env.FASTGRC_API_KEY ?? readConfig().apiKey;
379
333
  if (!apiKey) {
@@ -414,7 +368,6 @@ if (cmd === "test" || cmd === "where" || cmd === "which-hook" || cmd === "restar
414
368
  args,
415
369
  agentId,
416
370
  apiKey,
417
- // narrowed at module level via early-exit guard above
418
371
  policyId,
419
372
  baseUrl
420
373
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastgrc-openclaw",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "FastGRC agent compliance plugin for OpenClaw — evaluates every tool call against your policy before it executes",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",