@golproductions/check 1.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.
Files changed (3) hide show
  1. package/LICENSE +27 -0
  2. package/package.json +35 -0
  3. package/src/index.js +154 -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/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@golproductions/check",
3
+ "version": "1.1.0",
4
+ "description": "Pre-execution firewall hook for AI agents. Validates every command before it reaches the shell. Supports Claude Code, Gemini CLI, Antigravity, and Cursor.",
5
+ "bin": {
6
+ "check": "src/index.js"
7
+ },
8
+ "type": "module",
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "files": [
13
+ "src/",
14
+ "LICENSE"
15
+ ],
16
+ "keywords": [
17
+ "claude-code",
18
+ "gemini-cli",
19
+ "antigravity",
20
+ "cursor",
21
+ "hooks",
22
+ "pretooluse",
23
+ "beforetool",
24
+ "beforeshellexecution",
25
+ "command-validation",
26
+ "firewall",
27
+ "ai-agents"
28
+ ],
29
+ "license": "SEE LICENSE IN LICENSE",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/golproductions/check.git"
33
+ },
34
+ "homepage": "https://www.golproductions.com/check.html"
35
+ }
package/src/index.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ // Copyright (c) 2026 GOL Productions. All rights reserved. Proprietary and confidential.
3
+
4
+ import { execFileSync } from "node:child_process";
5
+
6
+ const API = "https://triage.golproductions.com/preflight";
7
+ const CLIENT_ID = process.env.GOL_CLIENT_ID || "";
8
+ const TIMEOUT_MS = 5000;
9
+ const IS_WIN = process.platform === "win32";
10
+
11
+ const SKIP = new Set(["cd", "ls", "dir", "pwd", "echo", "cat", "head", "tail", "wc", "mkdir", "test", "true", "false", "exit"]);
12
+ const PREFIXES = new Set(["sudo", "nohup", "nice", "time", "timeout", "env"]);
13
+
14
+ function detectPlatform(parsed) {
15
+ if (typeof parsed.command === "string" && !parsed.tool_input) return "cursor";
16
+ if (parsed.hook_event_name === "BeforeTool") return "gemini";
17
+ return "claude";
18
+ }
19
+
20
+ function extractCommand(parsed, platform) {
21
+ if (platform === "cursor") return parsed.command;
22
+ return parsed.tool_input?.command;
23
+ }
24
+
25
+ function getBaseCommand(cmd) {
26
+ const cleaned = cmd.replace(/\\\s*\n/g, " ").trim();
27
+ const tokens = [];
28
+ let i = 0;
29
+ while (i < cleaned.length) {
30
+ while (i < cleaned.length && /\s/.test(cleaned[i])) i++;
31
+ if (i >= cleaned.length) break;
32
+ let token = "";
33
+ if (cleaned[i] === "'" || cleaned[i] === '"') {
34
+ const q = cleaned[i++];
35
+ while (i < cleaned.length && cleaned[i] !== q) {
36
+ if (cleaned[i] === "\\" && q === '"' && i + 1 < cleaned.length) { token += cleaned[++i]; i++; }
37
+ else token += cleaned[i++];
38
+ }
39
+ if (i < cleaned.length) i++;
40
+ } else {
41
+ while (i < cleaned.length && !/\s/.test(cleaned[i])) token += cleaned[i++];
42
+ }
43
+ if (token.length > 0) tokens.push(token);
44
+ }
45
+ let idx = 0;
46
+ while (idx < tokens.length) {
47
+ const t = tokens[idx];
48
+ if (t === "sudo" || t === "nohup") { idx++; continue; }
49
+ if (t === "env") { idx++; if (idx < tokens.length && tokens[idx].includes("=")) idx++; continue; }
50
+ if (t === "nice") { idx++; if (idx < tokens.length && tokens[idx] === "-n") { idx++; if (idx < tokens.length) idx++; } continue; }
51
+ if (t === "time") { idx++; continue; }
52
+ if (t === "timeout") { idx++; if (idx < tokens.length) idx++; continue; }
53
+ if (t.includes("=") && !t.startsWith("-")) { idx++; continue; }
54
+ if (t === "|" || t === "||" || t === "&&" || t === ";") break;
55
+ return t.includes("/") ? t.split("/").pop() : t;
56
+ }
57
+ return null;
58
+ }
59
+
60
+ function binaryExists(base) {
61
+ if (!base || PREFIXES.has(base)) return null;
62
+ try {
63
+ execFileSync(IS_WIN ? "where" : "which", [base], { timeout: 2000, stdio: "pipe" });
64
+ return true;
65
+ } catch { return false; }
66
+ }
67
+
68
+ function respond(platform, allowed, reason) {
69
+ if (allowed) {
70
+ const out = {
71
+ cursor: { permission: "allow" },
72
+ gemini: { decision: "allow" },
73
+ claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow" } }
74
+ };
75
+ process.stdout.write(JSON.stringify(out[platform]));
76
+ process.exit(0);
77
+ }
78
+ if (platform === "gemini") {
79
+ process.stderr.write(reason + "\n");
80
+ process.exit(2);
81
+ }
82
+ const out = {
83
+ cursor: { permission: "deny", user_message: reason, agent_message: reason },
84
+ claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } }
85
+ };
86
+ process.stdout.write(JSON.stringify(out[platform]));
87
+ process.exit(0);
88
+ }
89
+
90
+ async function main() {
91
+ let platform = "claude";
92
+ try {
93
+ let input = "";
94
+ for await (const chunk of process.stdin) input += chunk;
95
+
96
+ let parsed;
97
+ try { parsed = JSON.parse(input); } catch { respond("claude", true); return; }
98
+
99
+ platform = detectPlatform(parsed);
100
+ const command = extractCommand(parsed, platform);
101
+ if (!command) { respond(platform, true); return; }
102
+
103
+ const toolName = parsed.tool_name;
104
+ const trimmed = command.trim();
105
+ const first = trimmed.split(/\s+/)[0];
106
+
107
+ if (SKIP.has(first)) { respond(platform, true); return; }
108
+ if (platform === "claude" && toolName === "PowerShell") { respond(platform, true); return; }
109
+
110
+ if (!CLIENT_ID) {
111
+ process.stderr.write("check: GOL_CLIENT_ID not set. Get your key at https://www.golproductions.com/check.html\n");
112
+ respond(platform, true);
113
+ return;
114
+ }
115
+
116
+ const base = getBaseCommand(command);
117
+ const exists = binaryExists(base);
118
+
119
+ if (exists === false) {
120
+ respond(platform, false, "Check: '" + base + "' is not installed on this machine");
121
+ return;
122
+ }
123
+
124
+ const payload = { command };
125
+ if (exists !== null) payload.binary_exists = exists;
126
+
127
+ const controller = new AbortController();
128
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
129
+
130
+ const res = await fetch(API, {
131
+ method: "POST",
132
+ headers: {
133
+ "Content-Type": "application/json",
134
+ "X-GOL-CLIENT-ID": CLIENT_ID,
135
+ "User-Agent": "check/1.1.0",
136
+ },
137
+ body: JSON.stringify(payload),
138
+ signal: controller.signal,
139
+ });
140
+ clearTimeout(timer);
141
+
142
+ const data = await res.json();
143
+
144
+ if (data.verdict === "runnable") {
145
+ respond(platform, true);
146
+ } else {
147
+ respond(platform, false, "Check: command is invalid");
148
+ }
149
+ } catch {
150
+ respond(platform, true);
151
+ }
152
+ }
153
+
154
+ main();