@golproductions/check 3.0.7 → 3.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/README.md CHANGED
@@ -1,125 +1,34 @@
1
- # Check — The Anti-Hallucination Firewall for AI Coding Agents
1
+ # Check -- The Universal Anti-Hallucination Engine
2
2
 
3
- **Your AI hallucinates commands, imports, and function calls. Check catches them before execution.**
3
+ AI agents hallucinate. Check catches it before it reaches your project.
4
4
 
5
- Check sits between your AI and your project. Every command is verified before it runs. Every import is checked against your actual dependencies. Every function call is matched against your real source files. What doesn't exist gets blocked.
6
-
7
- No AI inside. Deterministic. Same input, same output. Every time.
5
+ No AI inside. Deterministic. Sub-100ms.
8
6
 
9
7
  ## Install
10
8
 
11
- One command. Every IDE.
12
-
13
9
  ```
14
10
  npx @golproductions/check --install YOUR_KEY
15
11
  ```
16
12
 
17
- Auto-detects and configures **Claude Code**, **Cursor**, **Gemini CLI / Antigravity**, and MCP servers for **Windsurf / Devin Desktop**, **Continue**, **Amazon Q**, and **Roo Code**.
18
-
19
- Get your free API key (120 free checks) at [golproductions.com/check](https://www.golproductions.com/check.html)
20
-
21
- ## What it catches
13
+ One command. Auto-detects your environment and configures everything.
22
14
 
23
- | Type | What happens |
24
- |------|-------------|
25
- | **Phantom commands** | AI runs `git stash apply 3` — stash doesn't exist. **Blocked.** |
26
- | **Hallucinated imports** | AI writes `import cache from "express-session"` — not installed. **Blocked.** |
27
- | **Invented functions** | AI calls `db.findUserByEmail()` — doesn't exist in your project. **Blocked.** |
28
- | **Broken syntax** | AI writes a file with mismatched brackets. **Flagged.** |
29
- | **Post-write integrity** | After the AI writes a file, imports and function calls are re-verified. **Two checkpoints.** |
15
+ 120 free checks on signup at [golproductions.com/check](https://www.golproductions.com/check.html)
30
16
 
31
17
  ## Supported environments
32
18
 
33
- **Hooks (automatic, pre-execution)**
34
-
35
- | Environment | Integration |
36
- |-------------|-------------|
37
- | Claude Code | PreToolUse hook |
38
- | Cursor | beforeShellExecution hook |
39
- | Gemini CLI / Antigravity | BeforeTool hook |
40
-
41
- **MCP Server (agent-driven)**
42
-
43
- | Environment | Integration |
44
- |-------------|-------------|
45
- | Claude Code | MCP server |
46
- | Cursor | MCP server |
47
- | Windsurf / Devin Desktop | MCP server |
48
- | Continue | MCP server |
49
- | Amazon Q | MCP server |
50
- | Roo Code | MCP server |
51
- | Claude Desktop | MCP server |
52
- | Any MCP client | MCP server |
53
-
54
- **Editor plugins**
55
-
56
- | Editor | Install |
57
- |--------|---------|
58
- | VS Code / Cursor / Devin Desktop | [Open VSX](https://open-vsx.org/extension/golproductions/gol-check) |
59
- | JetBrains (IntelliJ, WebStorm, PyCharm, GoLand, Rider, PHPStorm, RubyMine) | [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/com.golproductions.check) |
60
- | Neovim | [check.nvim](https://github.com/golproductions/check.nvim) |
61
- | Emacs | [check.el](https://github.com/golproductions/check.el) |
62
- | Sublime Text | [GOLCheck](https://github.com/golproductions/check-sublime) |
63
- | Zed | [check-zed](https://github.com/golproductions/check-zed) |
64
-
65
- **Direct API**
66
-
67
- ```
68
- POST https://triage.golproductions.com/preflight
69
- ```
70
-
71
- ## MCP Server
72
-
73
- Run Check as an MCP server for direct agent integration:
74
-
75
- ```
76
- npx @golproductions/check check-mcp
77
- ```
78
-
79
- Exposes two tools:
80
- - **Check** — validates a command, returns `RUNNABLE` or `INVALID`
81
- - **CheckAndExecute** — validates then executes, blocking invalid commands before they reach the shell
82
-
83
- ## How it works
84
-
85
- ```
86
- AI generates code
87
- ↓
88
- Check intercepts (pre-execution)
89
- ↓
90
- Verifies against your actual project
91
- ↓
92
- Real → allowed | Not real → blocked
93
- ↓
94
- After file write → second verification pass
95
- ```
96
-
97
- Sub-100ms. Your AI never knows it's there.
98
-
99
- ## Why not just use another guardrail?
100
-
101
- | | Check | Security firewalls | LLM guardrails | Eval platforms |
102
- |---|---|---|---|---|
103
- | **Checks code correctness** | Yes | No — checks safety | No — checks format | No — scores after |
104
- | **Knows your project** | Yes | No | No | No |
105
- | **Pre-execution** | Yes | Yes | Varies | No |
106
- | **Post-write verification** | Yes | No | No | No |
107
- | **No AI inside** | Yes | Varies | Uses LLMs | Uses LLMs |
108
- | **Per-check pricing** | $0.0068 AUD | Free (self-hosted) | Enterprise | SaaS |
109
-
110
- Every other tool checks the AI. **Check checks the code.**
19
+ Claude Code, Cursor, Gemini CLI, Windsurf, Devin Desktop, Continue, Amazon Q, Roo Code, Claude Desktop, JetBrains, VS Code, Neovim, Emacs, Sublime Text, Zed, and any MCP client.
111
20
 
112
21
  ## Pricing
113
22
 
114
- **$0.0068 AUD per check.** 120 free checks on signup. Prepaid wallet — no subscription, no monthly fee. Credits never expire.
23
+ $0.0068 AUD per check. No subscription. Credits never expire.
115
24
 
116
- | Tier | Checks | Cost per check |
117
- |------|--------|---------------|
118
- | Free | 120 | $0.00 |
119
- | $5 | ~735 | $0.0068 |
120
- | $10 | ~1,470 | $0.0068 |
121
- | $25 | ~3,676 | $0.0068 |
122
- | $50 | ~7,352 | $0.0068 |
25
+ | Tier | Checks |
26
+ |------|--------|
27
+ | Free | 120 |
28
+ | $5 | ~735 |
29
+ | $10 | ~1,470 |
30
+ | $25 | ~3,676 |
31
+ | $50 | ~7,352 |
123
32
 
124
33
  ## Links
125
34
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@golproductions/check",
3
- "version": "3.0.7",
4
- "description": "Anti-hallucination firewall for AI agents. Validates commands, imports, and function calls before execution. Supports Claude Code, Cursor, Gemini CLI, Windsurf, JetBrains, Neovim, Emacs, Sublime Text, Zed, and any MCP client.",
3
+ "version": "3.1.0",
4
+ "description": "The universal anti-hallucination engine for AI coding agents. Catches what is not real before it reaches your project.",
5
5
  "bin": {
6
6
  "check": "src/index.js",
7
7
  "check-mcp": "src/mcp.js"
@@ -18,35 +18,19 @@
18
18
  "keywords": [
19
19
  "anti-hallucination",
20
20
  "ai-hallucination",
21
- "hallucination-detection",
22
- "ai-firewall",
23
21
  "ai-agents",
24
- "ai-code-validation",
25
- "command-validation",
26
- "import-validation",
27
- "function-verification",
28
- "code-integrity",
29
- "pre-execution",
30
- "deterministic-verification",
22
+ "ai-coding-agent",
31
23
  "claude-code",
32
24
  "cursor",
33
- "antigravity",
34
25
  "windsurf",
35
- "devin-desktop",
36
26
  "gemini-cli",
37
27
  "amazon-q",
38
28
  "continue-dev",
39
29
  "roo-code",
40
- "cline",
41
- "ai-guardrails",
42
- "llm-validation",
43
30
  "mcp",
44
31
  "model-context-protocol",
45
- "ai-coding-agent",
46
- "code-verification",
47
32
  "ai-safety",
48
- "developer-tools",
49
- "devtools"
33
+ "developer-tools"
50
34
  ],
51
35
  "dependencies": {
52
36
  "@modelcontextprotocol/sdk": "^1.12.0",
@@ -57,5 +41,5 @@
57
41
  "type": "git",
58
42
  "url": "git+https://github.com/golproductions/check.git"
59
43
  },
60
- "homepage": "https://www.golproductions.com/check.html"
44
+ "homepage": "https://golproductions.com/check"
61
45
  }
package/src/index.js CHANGED
@@ -1,16 +1,24 @@
1
1
  #!/usr/bin/env node
2
- import { readFileSync, writeFileSync, mkdirSync, existsSync, createWriteStream, chmodSync } from "node:fs";
2
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, createWriteStream, chmodSync, unlinkSync, rmSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { homedir, platform, arch } from "node:os";
5
5
  import { pipeline } from "node:stream/promises";
6
6
  import { Readable } from "node:stream";
7
7
 
8
- const VERSION = "3.0.7";
8
+ const VERSION = "3.1.0";
9
9
  const BINARY_VERSION = "3.0.0";
10
10
  const API = "https://triage.golproductions.com/preflight";
11
11
  const CDN = "https://pub-e55366a7f5994be9be04f0e205179f4a.r2.dev/releases";
12
12
  const CLIENT_ID = process.env.GOL_CLIENT_ID || "";
13
13
 
14
+ function getClientId() {
15
+ if (CLIENT_ID) return CLIENT_ID;
16
+ try {
17
+ const cfg = JSON.parse(readFileSync(join(homedir(), ".claude", "settings.json"), "utf8"));
18
+ return cfg.env?.GOL_CLIENT_ID || "";
19
+ } catch { return ""; }
20
+ }
21
+
14
22
  async function validateKey(key) {
15
23
  try {
16
24
  const res = await fetch(API, {
@@ -239,9 +247,347 @@ async function install() {
239
247
  process.exit(0);
240
248
  }
241
249
 
242
- if (process.argv.includes("--install")) { await install(); }
243
- if (process.argv.includes("--mcp")) { await import("./mcp.js"); process.exit(0); }
250
+ function isCheckRef(str) {
251
+ return str && (str.includes(".check") || str.includes("truth-gate"));
252
+ }
253
+
254
+ function isCheckHook(hook) {
255
+ if (isCheckRef(hook.command)) return true;
256
+ if (hook.args?.some(a => isCheckRef(a))) return true;
257
+ return false;
258
+ }
259
+
260
+ async function uninstall() {
261
+ const home = homedir();
262
+ let removed = 0;
263
+
264
+ console.log("\n Removing Check...\n");
265
+
266
+ const hookTargets = [
267
+ {
268
+ name: "Claude Code",
269
+ path: join(home, ".claude", "settings.json"),
270
+ clean: (cfg) => {
271
+ if (cfg.hooks?.PreToolUse) {
272
+ cfg.hooks.PreToolUse = cfg.hooks.PreToolUse.filter(h => !h.hooks?.some(isCheckHook));
273
+ if (cfg.hooks.PreToolUse.length === 0) delete cfg.hooks.PreToolUse;
274
+ }
275
+ if (cfg.hooks?.PostToolUse) {
276
+ cfg.hooks.PostToolUse = cfg.hooks.PostToolUse.filter(h => !h.hooks?.some(isCheckHook));
277
+ if (cfg.hooks.PostToolUse.length === 0) delete cfg.hooks.PostToolUse;
278
+ }
279
+ if (cfg.hooks && Object.keys(cfg.hooks).length === 0) delete cfg.hooks;
280
+ if (cfg.env) {
281
+ delete cfg.env.GOL_CLIENT_ID;
282
+ if (Object.keys(cfg.env).length === 0) delete cfg.env;
283
+ }
284
+ return cfg;
285
+ }
286
+ },
287
+ {
288
+ name: "Gemini CLI",
289
+ path: join(home, ".gemini", "settings.json"),
290
+ clean: (cfg) => {
291
+ if (cfg.hooks?.BeforeTool) {
292
+ cfg.hooks.BeforeTool = cfg.hooks.BeforeTool.filter(h => !h.hooks?.some(hh => hh.name === "check-gate"));
293
+ if (cfg.hooks.BeforeTool.length === 0) delete cfg.hooks.BeforeTool;
294
+ if (Object.keys(cfg.hooks).length === 0) delete cfg.hooks;
295
+ }
296
+ return cfg;
297
+ }
298
+ },
299
+ {
300
+ name: "Cursor",
301
+ path: join(home, ".cursor", "hooks.json"),
302
+ clean: (cfg) => {
303
+ if (cfg.hooks?.beforeShellExecution) {
304
+ cfg.hooks.beforeShellExecution = cfg.hooks.beforeShellExecution.filter(h => !isCheckRef(h.command));
305
+ if (cfg.hooks.beforeShellExecution.length === 0) delete cfg.hooks.beforeShellExecution;
306
+ if (Object.keys(cfg.hooks).length === 0) delete cfg.hooks;
307
+ }
308
+ return cfg;
309
+ }
310
+ },
311
+ {
312
+ name: "Homebase",
313
+ path: join(home, ".homebase", "hooks.json"),
314
+ clean: (cfg) => {
315
+ if (cfg.hooks?.PreToolUse) {
316
+ cfg.hooks.PreToolUse = cfg.hooks.PreToolUse.filter(h => !h.hooks?.some(isCheckHook));
317
+ if (cfg.hooks.PreToolUse.length === 0) delete cfg.hooks.PreToolUse;
318
+ }
319
+ if (cfg.hooks?.PostToolUse) {
320
+ cfg.hooks.PostToolUse = cfg.hooks.PostToolUse.filter(h => !h.hooks?.some(isCheckHook));
321
+ if (cfg.hooks.PostToolUse.length === 0) delete cfg.hooks.PostToolUse;
322
+ }
323
+ if (cfg.hooks && Object.keys(cfg.hooks).length === 0) delete cfg.hooks;
324
+ if (cfg.env) {
325
+ delete cfg.env.GOL_CLIENT_ID;
326
+ if (Object.keys(cfg.env).length === 0) delete cfg.env;
327
+ }
328
+ return cfg;
329
+ }
330
+ }
331
+ ];
332
+
333
+ const mcpUserTargets = [
334
+ { name: "Windsurf", path: join(home, ".codeium", "windsurf", "mcp_config.json") },
335
+ { name: "Amazon Q", path: join(home, ".aws", "amazonq", "mcp.json") },
336
+ ];
337
+
338
+ const mcpProjectTargets = [
339
+ { name: "Continue", path: join(process.cwd(), ".continue", "mcpServers", "check.json"), deleteFile: true },
340
+ { name: "Roo Code", path: join(process.cwd(), ".roo", "mcp.json") },
341
+ { name: "Project MCP", path: join(process.cwd(), ".mcp.json") },
342
+ ];
343
+
344
+ for (const t of hookTargets) {
345
+ if (!existsSync(t.path)) continue;
346
+ try {
347
+ const cfg = JSON.parse(readFileSync(t.path, "utf8"));
348
+ const cleaned = t.clean(cfg);
349
+ writeFileSync(t.path, JSON.stringify(cleaned, null, 2) + "\n", "utf8");
350
+ console.log(" removed " + t.name);
351
+ removed++;
352
+ } catch {}
353
+ }
354
+
355
+ for (const t of [...mcpUserTargets, ...mcpProjectTargets]) {
356
+ if (!existsSync(t.path)) continue;
357
+ try {
358
+ if (t.deleteFile) {
359
+ unlinkSync(t.path);
360
+ console.log(" removed " + t.name);
361
+ removed++;
362
+ } else {
363
+ const cfg = JSON.parse(readFileSync(t.path, "utf8"));
364
+ if (cfg.mcpServers?.Check) {
365
+ delete cfg.mcpServers.Check;
366
+ if (Object.keys(cfg.mcpServers).length === 0) delete cfg.mcpServers;
367
+ writeFileSync(t.path, JSON.stringify(cfg, null, 2) + "\n", "utf8");
368
+ console.log(" removed " + t.name);
369
+ removed++;
370
+ }
371
+ }
372
+ } catch {}
373
+ }
374
+
375
+ const checkDir = join(home, ".check");
376
+ if (existsSync(checkDir)) {
377
+ try {
378
+ rmSync(checkDir, { recursive: true, force: true });
379
+ console.log(" removed ~/.check/");
380
+ } catch {}
381
+ }
382
+
383
+ if (removed === 0) {
384
+ console.log(" No Check installations found.\n");
385
+ } else {
386
+ console.log(`\n Removed from ${removed} tool${removed !== 1 ? "s" : ""}.`);
387
+ console.log(" CLAUDE.md / AGENTS.md rules were left in place.\n");
388
+ }
389
+
390
+ process.exit(0);
391
+ }
392
+
393
+ async function status() {
394
+ const home = homedir();
395
+ const checkDir = join(home, ".check");
396
+ const ext = platform() === "win32" ? ".exe" : "";
397
+ const id = getClientId();
398
+
399
+ console.log(`\n Check v${VERSION}\n`);
400
+
401
+ if (id) {
402
+ const masked = id.length > 12 ? id.slice(0, 8) + "..." + id.slice(-4) : id;
403
+ console.log(" Client ID: " + masked);
404
+ } else {
405
+ console.log(" Client ID: not set");
406
+ }
407
+
408
+ const binaryPath = join(checkDir, "truth-gate" + ext);
409
+ console.log(" Binary: " + (existsSync(binaryPath) ? "installed" : "not found"));
410
+ const scriptPath = join(checkDir, "check.mjs");
411
+ console.log(" Script: " + (existsSync(scriptPath) ? "installed" : "not found"));
412
+
413
+ console.log("\n Integrations:\n");
414
+
415
+ const checks = [
416
+ {
417
+ name: "Claude Code",
418
+ path: join(home, ".claude", "settings.json"),
419
+ test: (cfg) => cfg.hooks?.PreToolUse?.some(h => h.hooks?.some(isCheckHook)) || cfg.hooks?.PostToolUse?.some(h => h.hooks?.some(isCheckHook)),
420
+ detail: (cfg) => {
421
+ const parts = [];
422
+ if (cfg.hooks?.PreToolUse?.some(h => h.hooks?.some(isCheckHook))) parts.push("PreToolUse");
423
+ if (cfg.hooks?.PostToolUse?.some(h => h.hooks?.some(isCheckHook))) parts.push("PostToolUse");
424
+ return parts.join(", ");
425
+ }
426
+ },
427
+ {
428
+ name: "Gemini CLI",
429
+ path: join(home, ".gemini", "settings.json"),
430
+ test: (cfg) => cfg.hooks?.BeforeTool?.some(h => h.hooks?.some(hh => hh.name === "check-gate")),
431
+ detail: () => "BeforeTool"
432
+ },
433
+ {
434
+ name: "Cursor",
435
+ path: join(home, ".cursor", "hooks.json"),
436
+ test: (cfg) => cfg.hooks?.beforeShellExecution?.some(h => isCheckRef(h.command)),
437
+ detail: () => "beforeShellExecution"
438
+ },
439
+ {
440
+ name: "Homebase",
441
+ path: join(home, ".homebase", "hooks.json"),
442
+ test: (cfg) => cfg.hooks?.PreToolUse?.some(h => h.hooks?.some(isCheckHook)) || cfg.hooks?.PostToolUse?.some(h => h.hooks?.some(isCheckHook)),
443
+ detail: (cfg) => {
444
+ const parts = [];
445
+ if (cfg.hooks?.PreToolUse?.some(h => h.hooks?.some(isCheckHook))) parts.push("PreToolUse");
446
+ if (cfg.hooks?.PostToolUse?.some(h => h.hooks?.some(isCheckHook))) parts.push("PostToolUse");
447
+ return parts.join(", ");
448
+ }
449
+ },
450
+ { name: "Windsurf", path: join(home, ".codeium", "windsurf", "mcp_config.json"), test: (cfg) => !!cfg.mcpServers?.Check, detail: () => "MCP" },
451
+ { name: "Continue", path: join(process.cwd(), ".continue", "mcpServers", "check.json"), test: (cfg) => !!cfg.mcpServers?.Check, detail: () => "MCP (project)" },
452
+ { name: "Amazon Q", path: join(home, ".aws", "amazonq", "mcp.json"), test: (cfg) => !!cfg.mcpServers?.Check, detail: () => "MCP" },
453
+ { name: "Roo Code", path: join(process.cwd(), ".roo", "mcp.json"), test: (cfg) => !!cfg.mcpServers?.Check, detail: () => "MCP (project)" },
454
+ { name: "Project MCP", path: join(process.cwd(), ".mcp.json"), test: (cfg) => !!cfg.mcpServers?.Check, detail: () => "MCP (project)" },
455
+ ];
456
+
457
+ for (const c of checks) {
458
+ if (!existsSync(c.path)) {
459
+ console.log(" - " + c.name.padEnd(14) + " not detected");
460
+ continue;
461
+ }
462
+ try {
463
+ const cfg = JSON.parse(readFileSync(c.path, "utf8"));
464
+ if (c.test(cfg)) {
465
+ console.log(" + " + c.name.padEnd(14) + " active (" + c.detail(cfg) + ")");
466
+ } else {
467
+ console.log(" - " + c.name.padEnd(14) + " tool installed, Check not configured");
468
+ }
469
+ } catch {
470
+ console.log(" ? " + c.name.padEnd(14) + " config unreadable");
471
+ }
472
+ }
473
+
474
+ console.log("");
475
+ process.exit(0);
476
+ }
477
+
478
+ async function credits() {
479
+ const id = getClientId();
480
+ if (!id) {
481
+ console.log("\n No Client ID found. Set GOL_CLIENT_ID or run --install first.\n");
482
+ process.exit(1);
483
+ }
484
+
485
+ try {
486
+ const res = await fetch(API.replace("/preflight", "/credits"), {
487
+ method: "GET",
488
+ headers: { "X-GOL-CLIENT-ID": id, "User-Agent": "c/" + VERSION },
489
+ signal: AbortSignal.timeout(10000),
490
+ });
491
+ if (!res.ok) {
492
+ console.log("\n Could not fetch credits (HTTP " + res.status + ").\n");
493
+ process.exit(1);
494
+ }
495
+ const d = await res.json();
496
+ console.log(`\n Check v${VERSION} — Credits\n`);
497
+ if (d.free_remaining !== undefined) console.log(" Free today: " + d.free_remaining + " / " + (d.free_daily || 120));
498
+ if (d.calls_today !== undefined) console.log(" Calls today: " + d.calls_today);
499
+ if (d.balance !== undefined) console.log(" Balance: $" + d.balance + " AUD");
500
+ if (d.total_calls !== undefined) console.log(" Total calls: " + d.total_calls);
501
+ if (d.plan) console.log(" Plan: " + d.plan);
502
+ if (Object.keys(d).length === 0) console.log(" " + JSON.stringify(d));
503
+ console.log("");
504
+ } catch (err) {
505
+ console.log("\n Could not reach API: " + err.message + "\n");
506
+ }
507
+ process.exit(0);
508
+ }
509
+
510
+ async function docs() {
511
+ console.log(`
512
+ Check v${VERSION} — Documentation
513
+
514
+ Install: npx @golproductions/check --install <key>
515
+ Uninstall: npx @golproductions/check --uninstall
516
+ Status: npx @golproductions/check --status
517
+ Credits: npx @golproductions/check --credits
518
+
519
+ How it works:
520
+
521
+ Check installs hooks into your AI coding tools. Every time
522
+ the AI runs a command or edits a file, Check verifies it
523
+ before or after execution.
524
+
525
+ PreToolUse Validates commands before they run.
526
+ PostToolUse Verifies results after execution.
527
+ MCP Server Provides Check and CheckAndExecute tools.
528
+ CLAUDE.md Adds anti-fabrication instructions.
529
+
530
+ Supported tools:
531
+
532
+ Claude Code, Gemini CLI, Cursor, Windsurf, Continue,
533
+ Amazon Q Developer, Roo Code, Homebase
534
+
535
+ Pricing:
536
+
537
+ 120 free checks per day. Then $0.0068 AUD per check.
538
+ Credits never expire. Pay as you go.
539
+
540
+ Links:
541
+
542
+ Website: https://golproductions.com/check
543
+ Docs: https://github.com/golproductions/check
544
+ Support: support@golproductions.com
545
+ `);
546
+
547
+ try {
548
+ const { execSync } = await import("node:child_process");
549
+ const url = "https://github.com/golproductions/check";
550
+ if (platform() === "win32") execSync(`start "" "${url}"`, { stdio: "ignore", shell: true });
551
+ else if (platform() === "darwin") execSync(`open "${url}"`, { stdio: "ignore" });
552
+ else execSync(`xdg-open "${url}"`, { stdio: "ignore" });
553
+ } catch {}
554
+
555
+ process.exit(0);
556
+ }
557
+
558
+ function help() {
559
+ console.log(`
560
+ Check v${VERSION} — Anti-hallucination layer for AI coding agents
561
+
562
+ Usage:
563
+
564
+ npx @golproductions/check --install <key> Install Check with your Client ID
565
+ npx @golproductions/check --uninstall Remove Check from all tools
566
+ npx @golproductions/check --status Show what is installed and active
567
+ npx @golproductions/check --credits Check your usage and balance
568
+ npx @golproductions/check --docs View documentation
569
+ npx @golproductions/check --help Show this help
570
+
571
+ Get your key: https://golproductions.com/check
572
+ Pricing: 120 free/day, then $0.0068 AUD per check
573
+ `);
574
+ process.exit(0);
575
+ }
576
+
577
+ // CLI routing
578
+ const args = process.argv.slice(2);
579
+ if (args.includes("--install")) { await install(); }
580
+ if (args.includes("--uninstall")) { await uninstall(); }
581
+ if (args.includes("--status")) { await status(); }
582
+ if (args.includes("--credits")) { await credits(); }
583
+ if (args.includes("--docs")) { await docs(); }
584
+ if (args.includes("--help") || args.includes("-h")) { help(); }
585
+ if (args.includes("--mcp")) { await import("./mcp.js"); process.exit(0); }
586
+
587
+ // No flags + interactive terminal = show help
588
+ if (!args.some(a => a.startsWith("-")) && process.stdin.isTTY) { help(); }
244
589
 
590
+ // Hook handler (invoked by tools via stdin)
245
591
  function detect(p) {
246
592
  if (typeof p.command === "string" && !p.tool_input) return "cursor";
247
593
  if (p.hook_event_name === "BeforeTool" || p.toolCall?.argumentsJson) return "gemini";
@@ -290,7 +636,7 @@ async function main() {
290
636
  f = detect(p);
291
637
  const c = cmd(p, f);
292
638
  if (!c) { out(f, true); return; }
293
- if (!CLIENT_ID) { process.stderr.write("check: GOL_CLIENT_ID not set. Get your key at https://golproductions.com/check\n"); out(f, true); return; }
639
+ if (!CLIENT_ID) { out(f, false, "check: GOL_CLIENT_ID not set. Get your key at https://golproductions.com/check"); return; }
294
640
  const controller = new AbortController();
295
641
  const timer = setTimeout(() => controller.abort(), 5000);
296
642
  const res = await fetch(API, {
@@ -303,7 +649,7 @@ async function main() {
303
649
  const d = await res.json();
304
650
  if (d.verdict === "runnable") { out(f, true); }
305
651
  else { out(f, false, d.reason || "denied — address the issue before continuing"); }
306
- } catch { out(f, true); }
652
+ } catch { out(f, false, "check: verification failed, command blocked"); }
307
653
  }
308
654
 
309
655
  main();
package/src/mcp.js CHANGED
@@ -6,7 +6,7 @@ import { execFile } from "node:child_process";
6
6
  import { promisify } from "node:util";
7
7
 
8
8
  const execFileAsync = promisify(execFile);
9
- const VERSION = "2.4.0";
9
+ const VERSION = "3.0.8";
10
10
  const API = "https://triage.golproductions.com/preflight";
11
11
  const CLIENT_ID = process.env.GOL_CLIENT_ID;
12
12
  const IS_WIN = process.platform === "win32";