@golproductions/check 3.0.4 → 3.0.6
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 +61 -24
- package/package.json +8 -2
- package/src/index.js +84 -22
package/README.md
CHANGED
|
@@ -11,12 +11,12 @@ No AI inside. Deterministic. Same input, same output. Every time.
|
|
|
11
11
|
One command. Every IDE.
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
npx @golproductions/check --install
|
|
14
|
+
npx @golproductions/check --install YOUR_KEY
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Auto-detects **Claude Code**, **Cursor**,
|
|
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
18
|
|
|
19
|
-
Get your free API key (120 free checks) at [golproductions.com](https://www.golproductions.com/check.html)
|
|
19
|
+
Get your free API key (120 free checks) at [golproductions.com/check](https://www.golproductions.com/check.html)
|
|
20
20
|
|
|
21
21
|
## What it catches
|
|
22
22
|
|
|
@@ -28,12 +28,64 @@ Get your free API key (120 free checks) at [golproductions.com](https://www.golp
|
|
|
28
28
|
| **Broken syntax** | AI writes a file with mismatched brackets. **Flagged.** |
|
|
29
29
|
| **Post-write integrity** | After the AI writes a file, imports and function calls are re-verified. **Two checkpoints.** |
|
|
30
30
|
|
|
31
|
+
## Supported environments
|
|
32
|
+
|
|
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
|
+
|
|
31
83
|
## How it works
|
|
32
84
|
|
|
33
85
|
```
|
|
34
|
-
AI
|
|
86
|
+
AI generates code
|
|
35
87
|
↓
|
|
36
|
-
Check intercepts (pre-execution
|
|
88
|
+
Check intercepts (pre-execution)
|
|
37
89
|
↓
|
|
38
90
|
Verifies against your actual project
|
|
39
91
|
↓
|
|
@@ -42,18 +94,18 @@ Real → allowed | Not real → blocked
|
|
|
42
94
|
After file write → second verification pass
|
|
43
95
|
```
|
|
44
96
|
|
|
45
|
-
|
|
97
|
+
Sub-100ms. Your AI never knows it's there.
|
|
46
98
|
|
|
47
99
|
## Why not just use another guardrail?
|
|
48
100
|
|
|
49
|
-
| | Check | Security firewalls
|
|
101
|
+
| | Check | Security firewalls | LLM guardrails | Eval platforms |
|
|
50
102
|
|---|---|---|---|---|
|
|
51
103
|
| **Checks code correctness** | Yes | No — checks safety | No — checks format | No — scores after |
|
|
52
104
|
| **Knows your project** | Yes | No | No | No |
|
|
53
105
|
| **Pre-execution** | Yes | Yes | Varies | No |
|
|
54
106
|
| **Post-write verification** | Yes | No | No | No |
|
|
55
107
|
| **No AI inside** | Yes | Varies | Uses LLMs | Uses LLMs |
|
|
56
|
-
| **Per-check pricing** | $0.0068 AUD | Free (self-hosted) | Enterprise
|
|
108
|
+
| **Per-check pricing** | $0.0068 AUD | Free (self-hosted) | Enterprise | SaaS |
|
|
57
109
|
|
|
58
110
|
Every other tool checks the AI. **Check checks the code.**
|
|
59
111
|
|
|
@@ -69,27 +121,12 @@ Every other tool checks the AI. **Check checks the code.**
|
|
|
69
121
|
| $25 | ~3,676 | $0.0068 |
|
|
70
122
|
| $50 | ~7,352 | $0.0068 |
|
|
71
123
|
|
|
72
|
-
## MCP Server
|
|
73
|
-
|
|
74
|
-
Check also runs as an MCP (Model Context Protocol) server for direct integration:
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
check-mcp
|
|
78
|
-
```
|
|
79
|
-
|
|
80
124
|
## Links
|
|
81
125
|
|
|
82
126
|
- [Product page](https://www.golproductions.com/check.html)
|
|
83
127
|
- [Pricing](https://www.golproductions.com/pricing.html)
|
|
84
128
|
- [Updates](https://www.golproductions.com/updates.html)
|
|
85
|
-
|
|
86
|
-
## Supported IDEs
|
|
87
|
-
|
|
88
|
-
- Claude Code
|
|
89
|
-
- Cursor
|
|
90
|
-
- Antigravity
|
|
91
|
-
|
|
92
|
-
More coming: Windsurf, Cline, Continue, Zed, Aider, JetBrains, GitHub Copilot.
|
|
129
|
+
- [Blog](https://www.golproductions.com/blog/)
|
|
93
130
|
|
|
94
131
|
## License
|
|
95
132
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golproductions/check",
|
|
3
|
-
"version": "3.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.6",
|
|
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.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"check": "src/index.js",
|
|
7
7
|
"check-mcp": "src/mcp.js"
|
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
"cursor",
|
|
33
33
|
"antigravity",
|
|
34
34
|
"windsurf",
|
|
35
|
+
"devin-desktop",
|
|
36
|
+
"gemini-cli",
|
|
37
|
+
"amazon-q",
|
|
38
|
+
"continue-dev",
|
|
39
|
+
"roo-code",
|
|
40
|
+
"cline",
|
|
35
41
|
"ai-guardrails",
|
|
36
42
|
"llm-validation",
|
|
37
43
|
"mcp",
|
package/src/index.js
CHANGED
|
@@ -37,6 +37,8 @@ async function install() {
|
|
|
37
37
|
const binaryPath = join(hooksDir, "truth-gate" + ext);
|
|
38
38
|
await downloadBinary(binaryPath);
|
|
39
39
|
|
|
40
|
+
const mcpEntry = { command: "npx", args: ["@golproductions/check", "--mcp"], env: { GOL_CLIENT_ID: key } };
|
|
41
|
+
|
|
40
42
|
const targets = [
|
|
41
43
|
{
|
|
42
44
|
name: "Claude Code",
|
|
@@ -58,17 +60,19 @@ async function install() {
|
|
|
58
60
|
}
|
|
59
61
|
},
|
|
60
62
|
{
|
|
61
|
-
name: "Antigravity
|
|
62
|
-
dir: join(home, ".gemini"
|
|
63
|
-
file: "
|
|
63
|
+
name: "Gemini CLI / Antigravity",
|
|
64
|
+
dir: join(home, ".gemini"),
|
|
65
|
+
file: "settings.json",
|
|
64
66
|
config: (existing) => {
|
|
65
|
-
existing
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
existing.hooks = existing.hooks || {};
|
|
68
|
+
existing.hooks.BeforeTool = existing.hooks.BeforeTool || [];
|
|
69
|
+
const hooks = existing.hooks.BeforeTool;
|
|
70
|
+
if (!hooks.find(h => h.hooks?.some(hh => hh.name === "check-gate"))) {
|
|
71
|
+
hooks.push({
|
|
72
|
+
matcher: ".*",
|
|
73
|
+
hooks: [{ type: "command", command: "node " + scriptPath, name: "check-gate" }]
|
|
74
|
+
});
|
|
75
|
+
}
|
|
72
76
|
return existing;
|
|
73
77
|
}
|
|
74
78
|
},
|
|
@@ -102,12 +106,64 @@ async function install() {
|
|
|
102
106
|
existing.env.GOL_CLIENT_ID = key;
|
|
103
107
|
return existing;
|
|
104
108
|
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "Windsurf (MCP)",
|
|
112
|
+
dir: join(home, ".codeium", "windsurf"),
|
|
113
|
+
file: "mcp_config.json",
|
|
114
|
+
config: (existing) => {
|
|
115
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
116
|
+
existing.mcpServers.Check = mcpEntry;
|
|
117
|
+
return existing;
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "Continue (MCP)",
|
|
122
|
+
dir: join(process.cwd(), ".continue", "mcpServers"),
|
|
123
|
+
file: "check.json",
|
|
124
|
+
config: () => {
|
|
125
|
+
return { mcpServers: { Check: mcpEntry } };
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "Amazon Q Developer (MCP)",
|
|
130
|
+
dir: join(home, ".aws", "amazonq"),
|
|
131
|
+
file: "mcp.json",
|
|
132
|
+
config: (existing) => {
|
|
133
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
134
|
+
existing.mcpServers.Check = { type: "stdio", ...mcpEntry };
|
|
135
|
+
return existing;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "Roo Code (project MCP)",
|
|
140
|
+
dir: join(process.cwd(), ".roo"),
|
|
141
|
+
file: "mcp.json",
|
|
142
|
+
config: (existing) => {
|
|
143
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
144
|
+
existing.mcpServers.Check = mcpEntry;
|
|
145
|
+
return existing;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "Project MCP (shared)",
|
|
150
|
+
dir: process.cwd(),
|
|
151
|
+
file: ".mcp.json",
|
|
152
|
+
config: (existing) => {
|
|
153
|
+
existing.mcpServers = existing.mcpServers || {};
|
|
154
|
+
existing.mcpServers.Check = mcpEntry;
|
|
155
|
+
return existing;
|
|
156
|
+
}
|
|
105
157
|
}
|
|
106
158
|
];
|
|
107
159
|
|
|
160
|
+
const mcpTargets = ["Windsurf (MCP)", "Continue (MCP)", "Amazon Q Developer (MCP)", "Roo Code (project MCP)", "Project MCP (shared)"];
|
|
161
|
+
|
|
108
162
|
let hasClaude = false;
|
|
109
163
|
for (const t of targets) {
|
|
110
|
-
|
|
164
|
+
const isMcp = mcpTargets.includes(t.name);
|
|
165
|
+
if (!isMcp && !existsSync(t.dir)) continue;
|
|
166
|
+
if (isMcp) mkdirSync(t.dir, { recursive: true });
|
|
111
167
|
const filepath = join(t.dir, t.file);
|
|
112
168
|
let existing = {};
|
|
113
169
|
try { existing = JSON.parse(readFileSync(filepath, "utf8")); } catch {}
|
|
@@ -147,31 +203,37 @@ if (process.argv.includes("--mcp")) { await import("./mcp.js"); process.exit(0);
|
|
|
147
203
|
|
|
148
204
|
function detect(p) {
|
|
149
205
|
if (typeof p.command === "string" && !p.tool_input) return "cursor";
|
|
150
|
-
if (p.hook_event_name === "BeforeTool") return "gemini";
|
|
151
|
-
if (p.toolCall?.argumentsJson) return "antigravity";
|
|
206
|
+
if (p.hook_event_name === "BeforeTool" || p.toolCall?.argumentsJson) return "gemini";
|
|
152
207
|
return "claude";
|
|
153
208
|
}
|
|
154
209
|
|
|
155
210
|
function cmd(p, f) {
|
|
156
211
|
if (f === "cursor") return p.command;
|
|
157
|
-
if (f === "
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
212
|
+
if (f === "gemini") {
|
|
213
|
+
if (p.tool_input?.command) return p.tool_input.command;
|
|
214
|
+
if (p.toolCall?.argumentsJson) {
|
|
215
|
+
try {
|
|
216
|
+
const a = typeof p.toolCall.argumentsJson === "string" ? JSON.parse(p.toolCall.argumentsJson) : p.toolCall.argumentsJson;
|
|
217
|
+
return a.command || a.CommandLine || a.command_line;
|
|
218
|
+
} catch { return null; }
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
162
221
|
}
|
|
163
222
|
return p.tool_input?.command;
|
|
164
223
|
}
|
|
165
224
|
|
|
166
225
|
function out(f, ok, reason) {
|
|
167
226
|
if (ok) {
|
|
168
|
-
const r = { cursor: { permission: "allow" }, gemini: { decision: "allow" },
|
|
169
|
-
process.stdout.write(JSON.stringify(r[f]));
|
|
227
|
+
const r = { cursor: { permission: "allow" }, gemini: { decision: "allow" }, claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow" } } };
|
|
228
|
+
process.stdout.write(JSON.stringify(r[f] || r.claude));
|
|
170
229
|
process.exit(0);
|
|
171
230
|
}
|
|
172
|
-
if (f === "gemini"
|
|
231
|
+
if (f === "gemini") {
|
|
232
|
+
process.stdout.write(JSON.stringify({ decision: "deny", reason }));
|
|
233
|
+
process.exit(2);
|
|
234
|
+
}
|
|
173
235
|
const r = { cursor: { permission: "deny", user_message: reason, agent_message: reason }, claude: { hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } } };
|
|
174
|
-
process.stdout.write(JSON.stringify(r[f]));
|
|
236
|
+
process.stdout.write(JSON.stringify(r[f] || r.claude));
|
|
175
237
|
process.exit(0);
|
|
176
238
|
}
|
|
177
239
|
|