@golproductions/check 2.4.1
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/LICENSE +27 -0
- package/README.md +31 -0
- package/package.json +47 -0
- package/src/index.js +161 -0
- package/src/mcp.js +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
GOL Productions Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GOL Productions. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is the proprietary product of GOL Productions
|
|
6
|
+
("GOL"). It is licensed, not sold.
|
|
7
|
+
|
|
8
|
+
GRANT OF LICENSE. GOL grants you a limited, non-exclusive,
|
|
9
|
+
non-transferable, revocable licence to use this software
|
|
10
|
+
exclusively with GOL's Check API service.
|
|
11
|
+
|
|
12
|
+
RESTRICTIONS. You may not:
|
|
13
|
+
1. Copy, modify, or create derivative works of this software.
|
|
14
|
+
2. Redistribute, sublicense, sell, or otherwise transfer this
|
|
15
|
+
software to any third party.
|
|
16
|
+
3. Use this software with any competing command-validation or
|
|
17
|
+
preflight service.
|
|
18
|
+
4. Reverse-engineer, decompile, or disassemble this software.
|
|
19
|
+
|
|
20
|
+
TERMINATION. This licence terminates immediately if you breach
|
|
21
|
+
any of its terms or if GOL revokes it at its discretion.
|
|
22
|
+
|
|
23
|
+
DISCLAIMER. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
|
|
24
|
+
OF ANY KIND. GOL DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED.
|
|
25
|
+
|
|
26
|
+
GOVERNING LAW. This licence is governed by the laws of the
|
|
27
|
+
State of Victoria, Australia.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Check — The Anti-Hallucination Layer for AI Agents
|
|
2
|
+
|
|
3
|
+
Your AI says "done" when it isn't. Check stops that.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
One command. Every IDE.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npx @golproductions/check --install your_key
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Auto-detects Claude Code, Gemini CLI, Antigravity, and Cursor. Writes the hook config, sets your key, done. Restart your IDE to activate.
|
|
14
|
+
|
|
15
|
+
Get your free API key at [golproductions.com/check.html](https://www.golproductions.com/check.html)
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
Check sits between your AI and the shell. Every command is verified before execution. If something is wrong, the AI knows before it speaks. No more hallucinated success, no more blind retries.
|
|
20
|
+
|
|
21
|
+
## Pricing
|
|
22
|
+
|
|
23
|
+
$0.0068 AUD per check. 120 free checks on signup. Credits never expire.
|
|
24
|
+
|
|
25
|
+
## Links
|
|
26
|
+
|
|
27
|
+
- [Documentation](https://www.golproductions.com/docs-triage-gate.html)
|
|
28
|
+
- [Pricing](https://www.golproductions.com/pricing.html)
|
|
29
|
+
- [VS Code extension](https://open-vsx.org/extension/golproductions/gol-check)
|
|
30
|
+
|
|
31
|
+
Copyright (c) 2026 GOL Productions. All rights reserved.
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@golproductions/check",
|
|
3
|
+
"version": "2.4.1",
|
|
4
|
+
"description": "The anti-hallucination layer for AI agents. Your AI says done when it isn't. Check stops that. Supports Claude Code, Gemini CLI, Antigravity, and Cursor.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"check": "src/index.js",
|
|
7
|
+
"check-mcp": "src/mcp.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src/",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"claude-code",
|
|
20
|
+
"gemini-cli",
|
|
21
|
+
"antigravity",
|
|
22
|
+
"cursor",
|
|
23
|
+
"hooks",
|
|
24
|
+
"pretooluse",
|
|
25
|
+
"beforetool",
|
|
26
|
+
"beforeshellexecution",
|
|
27
|
+
"command-validation",
|
|
28
|
+
"anti-hallucination",
|
|
29
|
+
"firewall",
|
|
30
|
+
"ai-agents",
|
|
31
|
+
"vscode",
|
|
32
|
+
"openvsx",
|
|
33
|
+
"windsurf",
|
|
34
|
+
"mcp",
|
|
35
|
+
"model-context-protocol"
|
|
36
|
+
],
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
39
|
+
"zod": "^3.24.0"
|
|
40
|
+
},
|
|
41
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/golproductions/check.git"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://www.golproductions.com/check.html"
|
|
47
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
|
|
6
|
+
const VERSION = "2.4.0";
|
|
7
|
+
const API = "https://triage.golproductions.com/preflight";
|
|
8
|
+
const CLIENT_ID = process.env.GOL_CLIENT_ID || "";
|
|
9
|
+
|
|
10
|
+
function install() {
|
|
11
|
+
const key = process.argv[3] || process.env.GOL_CLIENT_ID || "your_key";
|
|
12
|
+
const home = homedir();
|
|
13
|
+
let installed = 0;
|
|
14
|
+
|
|
15
|
+
const scriptSrc = readFileSync(new URL(import.meta.url), "utf8");
|
|
16
|
+
const hooksDir = join(home, ".check");
|
|
17
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
18
|
+
const scriptPath = join(hooksDir, "check.mjs");
|
|
19
|
+
writeFileSync(scriptPath, scriptSrc, "utf8");
|
|
20
|
+
|
|
21
|
+
const targets = [
|
|
22
|
+
{
|
|
23
|
+
name: "Claude Code",
|
|
24
|
+
dir: join(home, ".claude"),
|
|
25
|
+
file: "settings.json",
|
|
26
|
+
config: (existing) => {
|
|
27
|
+
existing.hooks = existing.hooks || {};
|
|
28
|
+
existing.hooks.PreToolUse = [{
|
|
29
|
+
matcher: "Bash|PowerShell",
|
|
30
|
+
hooks: [{ type: "command", command: "node", args: [scriptPath] }]
|
|
31
|
+
}];
|
|
32
|
+
existing.env = existing.env || {};
|
|
33
|
+
existing.env.GOL_CLIENT_ID = key;
|
|
34
|
+
return existing;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "Antigravity IDE",
|
|
39
|
+
dir: join(home, ".gemini", "config"),
|
|
40
|
+
file: "hooks.json",
|
|
41
|
+
config: (existing) => {
|
|
42
|
+
existing["check-gate"] = {
|
|
43
|
+
enabled: true,
|
|
44
|
+
PreToolUse: [{
|
|
45
|
+
matcher: "run_command",
|
|
46
|
+
hooks: [{ type: "command", command: "node " + scriptPath }]
|
|
47
|
+
}]
|
|
48
|
+
};
|
|
49
|
+
return existing;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "Cursor",
|
|
54
|
+
dir: join(home, ".cursor"),
|
|
55
|
+
file: "hooks.json",
|
|
56
|
+
config: (existing) => {
|
|
57
|
+
existing.version = existing.version || 1;
|
|
58
|
+
existing.hooks = existing.hooks || {};
|
|
59
|
+
existing.hooks.beforeShellExecution = [{
|
|
60
|
+
command: "node " + scriptPath
|
|
61
|
+
}];
|
|
62
|
+
return existing;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
for (const t of targets) {
|
|
68
|
+
if (!existsSync(t.dir)) continue;
|
|
69
|
+
const filepath = join(t.dir, t.file);
|
|
70
|
+
let existing = {};
|
|
71
|
+
try { existing = JSON.parse(readFileSync(filepath, "utf8")); } catch {}
|
|
72
|
+
const updated = t.config(existing);
|
|
73
|
+
writeFileSync(filepath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
74
|
+
installed++;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (installed === 0) {
|
|
78
|
+
mkdirSync(join(home, ".claude"), { recursive: true });
|
|
79
|
+
const filepath = join(home, ".claude", "settings.json");
|
|
80
|
+
let existing = {};
|
|
81
|
+
try { existing = JSON.parse(readFileSync(filepath, "utf8")); } catch {}
|
|
82
|
+
const updated = targets[0].config(existing);
|
|
83
|
+
writeFileSync(filepath, JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const agentsMd = join(process.cwd(), "AGENTS.md");
|
|
87
|
+
const checkRule = "Never fabricate, hallucinate, or invent values. If you don't have it, say you don't have it. No fake keys, no fake IDs, no fake paths, no fake URLs. If unsure, ask. Never guess and present it as fact.";
|
|
88
|
+
try {
|
|
89
|
+
const existing = existsSync(agentsMd) ? readFileSync(agentsMd, "utf8") : "";
|
|
90
|
+
if (!existing.includes("Never fabricate")) {
|
|
91
|
+
const prefix = existing.length > 0 ? existing.trimEnd() + "\n\n" : "";
|
|
92
|
+
writeFileSync(agentsMd, prefix + checkRule + "\n", "utf8");
|
|
93
|
+
}
|
|
94
|
+
} catch {}
|
|
95
|
+
|
|
96
|
+
console.log(`\nSafe travels wanderer..\n`);
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (process.argv.includes("--install")) { install(); }
|
|
101
|
+
if (process.argv.includes("--mcp")) { await import("./mcp.js"); process.exit(0); }
|
|
102
|
+
|
|
103
|
+
function detect(p) {
|
|
104
|
+
if (typeof p.command === "string" && !p.tool_input) return "cursor";
|
|
105
|
+
if (p.hook_event_name === "BeforeTool") return "gemini";
|
|
106
|
+
if (p.toolCall?.argumentsJson) return "antigravity";
|
|
107
|
+
return "claude";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function cmd(p, f) {
|
|
111
|
+
if (f === "cursor") return p.command;
|
|
112
|
+
if (f === "antigravity") {
|
|
113
|
+
try {
|
|
114
|
+
const a = typeof p.toolCall.argumentsJson === "string" ? JSON.parse(p.toolCall.argumentsJson) : p.toolCall.argumentsJson;
|
|
115
|
+
return a.command || a.CommandLine || a.command_line;
|
|
116
|
+
} catch { return null; }
|
|
117
|
+
}
|
|
118
|
+
return p.tool_input?.command;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function out(f, ok, reason) {
|
|
122
|
+
if (ok) {
|
|
123
|
+
const r = { cursor: { permission: "allow" }, gemini: { decision: "allow" }, antigravity: { decision: "allow" }, claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow" } } };
|
|
124
|
+
process.stdout.write(JSON.stringify(r[f]));
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
if (f === "gemini" || f === "antigravity") { process.stderr.write(reason + "\n"); process.exit(2); }
|
|
128
|
+
const r = { cursor: { permission: "deny", user_message: reason, agent_message: reason }, claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } } };
|
|
129
|
+
process.stdout.write(JSON.stringify(r[f]));
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function main() {
|
|
134
|
+
let f = "claude";
|
|
135
|
+
try {
|
|
136
|
+
let input = "";
|
|
137
|
+
for await (const chunk of process.stdin) input += chunk;
|
|
138
|
+
input = input.replace(/^/, "").trim();
|
|
139
|
+
let p;
|
|
140
|
+
try { p = JSON.parse(input); } catch { out("claude", true); return; }
|
|
141
|
+
if (p.hook_event_name === "PostToolUse") { process.exit(0); return; }
|
|
142
|
+
f = detect(p);
|
|
143
|
+
const c = cmd(p, f);
|
|
144
|
+
if (!c) { out(f, true); return; }
|
|
145
|
+
if (!CLIENT_ID) { process.stderr.write("check: GOL_CLIENT_ID not set. Get your key at https://www.golproductions.com/check.html\n"); out(f, true); return; }
|
|
146
|
+
const controller = new AbortController();
|
|
147
|
+
const timer = setTimeout(() => controller.abort(), 5000);
|
|
148
|
+
const res = await fetch(API, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: { "Content-Type": "application/json", "X-GOL-CLIENT-ID": CLIENT_ID, "User-Agent": "c/" + VERSION },
|
|
151
|
+
body: JSON.stringify({ command: c, cwd: p.cwd || process.cwd(), platform: f, tool_name: p.tool_name, transcript_path: p.transcript_path, v: VERSION }),
|
|
152
|
+
signal: controller.signal
|
|
153
|
+
});
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
const d = await res.json();
|
|
156
|
+
if (d.verdict === "runnable") { out(f, true); }
|
|
157
|
+
else { out(f, false, d.reason || "denied — address the issue before continuing"); }
|
|
158
|
+
} catch { out(f, true); }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
main();
|
package/src/mcp.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const VERSION = "2.4.0";
|
|
10
|
+
const API = "https://triage.golproductions.com/preflight";
|
|
11
|
+
const CLIENT_ID = process.env.GOL_CLIENT_ID;
|
|
12
|
+
const IS_WIN = process.platform === "win32";
|
|
13
|
+
|
|
14
|
+
if (!CLIENT_ID) {
|
|
15
|
+
process.stderr.write("check: GOL_CLIENT_ID environment variable is required.\nGet your key at https://www.golproductions.com/check.html\n");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function validate(command) {
|
|
20
|
+
const res = await fetch(API, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: { "Content-Type": "application/json", "X-GOL-CLIENT-ID": CLIENT_ID, "User-Agent": "c/" + VERSION },
|
|
23
|
+
body: JSON.stringify({ command, v: VERSION })
|
|
24
|
+
});
|
|
25
|
+
return res.json();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const server = new McpServer({ name: "check", version: VERSION });
|
|
29
|
+
|
|
30
|
+
server.tool(
|
|
31
|
+
"Check",
|
|
32
|
+
"Know if a command will work before running it. Returns 'runnable' or 'invalid'. $0.0068 AUD per Check.",
|
|
33
|
+
{ command: z.string().max(10000).describe("The shell command to validate before execution") },
|
|
34
|
+
async ({ command }) => {
|
|
35
|
+
try {
|
|
36
|
+
const d = await validate(command);
|
|
37
|
+
if (!d.verdict) return { content: [{ type: "text", text: `Error: ${d.error || "unknown"}` }], isError: true };
|
|
38
|
+
return { content: [{ type: "text", text: `Verdict: ${d.verdict === "runnable" ? "RUNNABLE" : "INVALID"}` }] };
|
|
39
|
+
} catch (err) {
|
|
40
|
+
return { content: [{ type: "text", text: `Check API error: ${err.message}` }], isError: true };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
server.tool(
|
|
46
|
+
"CheckAndExecute",
|
|
47
|
+
"Validate a command with Check, then execute it if runnable. Returns the command output if valid, or blocks it.",
|
|
48
|
+
{ command: z.string().max(10000).describe("The shell command to validate and execute") },
|
|
49
|
+
async ({ command }) => {
|
|
50
|
+
try {
|
|
51
|
+
const d = await validate(command);
|
|
52
|
+
if (d.verdict !== "runnable") return { content: [{ type: "text", text: "BLOCKED: " + (d.reason || "command is invalid") }] };
|
|
53
|
+
const { stdout, stderr } = await execFileAsync(IS_WIN ? "cmd" : "bash", IS_WIN ? ["/c", command] : ["-c", command], { timeout: 30000 });
|
|
54
|
+
return { content: [{ type: "text", text: (stdout || "") + (stderr ? "\nSTDERR: " + stderr : "") || "(no output)" }] };
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err.stdout || err.stderr) return { content: [{ type: "text", text: `Exit ${err.code || 1}:\n${(err.stdout || "") + (err.stderr ? "\nSTDERR: " + err.stderr : "")}` }] };
|
|
57
|
+
return { content: [{ type: "text", text: `Error: ${err.message}` }], isError: true };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const transport = new StdioServerTransport();
|
|
63
|
+
await server.connect(transport);
|