@golproductions/check 3.2.24 → 3.2.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.
- package/dist/index.js +1 -1
- package/dist/mcp.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as e,writeFileSync as o,mkdirSync as s,existsSync as n,createWriteStream as t,chmodSync as c,unlinkSync as r,rmSync as i}from"node:fs";import{spawnSync as l}from"node:child_process";import{join as a}from"node:path";import{homedir as h,platform as d,arch as u}from"node:os";import{pipeline as m}from"node:stream/promises";import{Readable as p}from"node:stream";const f="3.2.24",k="https://triage.golproductions.com/preflight",g=process.env.GOL_CLIENT_ID||"";function y(){if(g)return g;try{const o=e(a(h(),".check","key"),"utf8").trim();if(o)return o}catch{}try{const o=JSON.parse(e(a(h(),".claude","settings.json"),"utf8"));return o.env?.GOL_CLIENT_ID||""}catch{return""}}function v(e){return e&&(e.includes(".check")||e.includes("truth-gate"))}function C(e){return!!v(e.command)||!!e.args?.some(e=>v(e))}function w(){console.log(`\n Check v${f}: Anti-hallucination layer for AI coding agents\n\n Usage:\n\n npx @golproductions/check --install <key> Install Check with your Client ID\n npx @golproductions/check --uninstall Remove Check from all tools\n npx @golproductions/check --status Show what is installed and active\n npx @golproductions/check --credits Check your usage and balance\n npx @golproductions/check --docs View documentation\n npx @golproductions/check --help Show this help\n\n Get your key: https://golproductions.com/check\n Pricing: 120 free/day, then $0.0068 AUD per check\n`),process.exit(0)}const T=process.argv.slice(2);function P(e,o){try{const s=x();if(!s)return null;const n=l(s,["-c",'type -- "$1"',"check",e],{timeout:4e3,encoding:"utf8",cwd:o});if(n.error)return null;if(0===n.status)return{exists:!0};const t=(n.stderr||"").split("\n").find(o=>o.includes(e))||"";return{exists:!1,why:t.slice(t.indexOf(e)).trim()||e+": not found"}}catch{return null}}function S(e,o,s){if(o){const o={cursor:{permission:"allow"},gemini:{decision:"allow"},claude:{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}};process.stdout.write(JSON.stringify(o[e]||o.claude)),process.exit(0)}"gemini"===e&&(process.stdout.write(JSON.stringify({decision:"deny",reason:s})),process.exit(2));const n={cursor:{permission:"deny",agent_message:s},claude:{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:s}}};process.stdout.write(JSON.stringify(n[e]||n.claude)),process.exit(0)}function b(e,t){let c=!0;try{const e=a(h(),".check","credits-warned-"+(new Date).toISOString().slice(0,10));c=n(e),c||(s(a(h(),".check"),{recursive:!0}),o(e,"1"))}catch{c=!1}const r=c?void 0:t;if("gemini"===e&&(process.stdout.write(JSON.stringify({decision:"allow"})),r&&process.stderr.write(r),process.exit(0)),"cursor"===e){const e={permission:"allow"};r&&(e.user_message=r),process.stdout.write(JSON.stringify(e)),process.exit(0)}const i={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};r&&(i.systemMessage=r),process.stdout.write(JSON.stringify(i)),process.exit(0)}function x(){if("win32"!==d())return"bash";const e=[process.env.CLAUDE_CODE_GIT_BASH_PATH,"C:/Program Files/Git/bin/bash.exe","C:/Program Files/Git/usr/bin/bash.exe","C:/Program Files (x86)/Git/bin/bash.exe"].filter(Boolean);for(const o of e)try{if(n(o))return o}catch{}return null}T.includes("--install")&&await async function(){let r=process.argv[3]||process.env.GOL_CLIENT_ID||"";r&&"your_key"!==r||(console.log("\n Activating Check (free, no signup)...\n"),r=await async function(){try{const e=await async function(){const{createHash:e}=await import("node:crypto"),{hostname:o,userInfo:s}=await import("node:os");let n="";try{n=s().username||""}catch{}const t=[o(),d(),u(),n].join("|");return e("sha256").update(t).digest("hex")}(),o=await fetch(k.replace("/preflight","/instant-key"),{method:"POST",headers:{"Content-Type":"application/json","User-Agent":"c/"+f},body:JSON.stringify({fingerprint:e,channel:"npm"}),signal:AbortSignal.timeout(1e4)});if(!o.ok)return null;const s=await o.json();return s&&s.client_id?s.client_id:null}catch{return null}}(),r||(console.log(" Could not activate automatically (offline, or this network hit its daily limit).\n"),console.log(" Get a key the manual way: https://golproductions.com/check\n"),console.log(" Then run: npx @golproductions/check --install YOUR_KEY\n"),process.exit(1)),console.log(" Activated. 120 free checks per day.\n"));const i=await async function(e){try{const o=await fetch(k,{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":e,"User-Agent":"c/"+f},body:JSON.stringify({command:"echo check-install-verify",cwd:process.cwd(),v:f}),signal:AbortSignal.timeout(1e4)});if(o.ok)return{valid:!0,expired:!1};let s={};try{s=await o.json()}catch{}return{valid:!1,expired:/expir/i.test(s.reason||s.error||s.message||"")}}catch{return{valid:!1,expired:!1}}}(r);i.valid||(i.expired?(console.log("\n Your Client ID has expired: "+r),console.log("\n Renew your key at: https://golproductions.com/check\n")):(console.log("\n Invalid Client ID: "+r),console.log("\n Get a valid key at: https://golproductions.com/check\n")),process.exit(1)),console.log("\n Key verified. Installing Check...\n");const l=h();let g=0;const y=e(new URL(import.meta.url),"utf8"),w=a(l,".check");s(w,{recursive:!0});const T=a(w,"check.mjs").replace(/\\/g,"/");o(T,y,"utf8"),o(a(w,"key"),r,"utf8");const P="win32"===d()?".exe":"",S=a(w,"truth-gate"+P).replace(/\\/g,"/");await async function(e){const o="win32"===d()?"win":"darwin"===d()?"macos":"linux",s=`https://pub-e55366a7f5994be9be04f0e205179f4a.r2.dev/releases/truth-gate-v3.0.0-${o}-${"arm64"===u()?"arm64":"x64"}${"win"===o?".exe":""}`,n=await fetch(s);if(!n.ok)throw new Error(`Download failed: ${n.status}`);if(await m(p.fromWeb(n.body),t(e)),"win"!==o)try{c(e,493)}catch{}}(S);const b={command:"npx",args:["@golproductions/check","--mcp"],env:{GOL_CLIENT_ID:r}},x=[{name:"Claude Code",dir:a(l,".claude"),file:"settings.json",config:e=>(e.hooks=e.hooks||{},e.hooks.PreToolUse=(e.hooks.PreToolUse||[]).filter(e=>!e.hooks?.some(C)),e.hooks.PreToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:"node",args:[T]}]}),e.hooks.PostToolUse=(e.hooks.PostToolUse||[]).filter(e=>!e.hooks?.some(C)),e.hooks.PostToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:S}]},{matcher:"Edit|Write|NotebookEdit",hooks:[{type:"command",command:S}]}),e.env=e.env||{},e.env.GOL_CLIENT_ID=r,e)},{name:"Gemini CLI / Antigravity",dir:a(l,".gemini"),file:"settings.json",config:e=>{e.hooks=e.hooks||{},e.hooks.BeforeTool=e.hooks.BeforeTool||[];const o=e.hooks.BeforeTool;return o.find(e=>e.hooks?.some(e=>"check-gate"===e.name))||o.push({matcher:".*",hooks:[{type:"command",command:"node "+T,name:"check-gate"}]}),e}},{name:"Cursor",dir:a(l,".cursor"),file:"hooks.json",config:e=>(e.version=e.version||1,e.hooks=e.hooks||{},e.hooks.beforeShellExecution=(e.hooks.beforeShellExecution||[]).filter(e=>!v(e.command)),e.hooks.beforeShellExecution.push({command:"node "+T}),e)},{name:"Homebase",dir:a(l,".homebase"),file:"hooks.json",config:e=>(e.hooks=e.hooks||{},e.hooks.PreToolUse=(e.hooks.PreToolUse||[]).filter(e=>!e.hooks?.some(C)),e.hooks.PreToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:"node",args:[T]}]}),e.hooks.PostToolUse=(e.hooks.PostToolUse||[]).filter(e=>!e.hooks?.some(C)),e.hooks.PostToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:S}]}),e.env=e.env||{},e.env.GOL_CLIENT_ID=r,e)},{name:"Windsurf (MCP)",dir:a(l,".codeium","windsurf"),file:"mcp_config.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)},{name:"Continue (MCP)",dir:a(process.cwd(),".continue","mcpServers"),file:"check.json",config:()=>({mcpServers:{Check:b}})},{name:"Amazon Q Developer (MCP)",dir:a(l,".aws","amazonq"),file:"mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check={type:"stdio",...b},e)},{name:"Roo Code (project MCP)",dir:a(process.cwd(),".roo"),file:"mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)},{name:"Project MCP (shared)",dir:process.cwd(),file:".mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)}],U=["Windsurf (MCP)","Continue (MCP)","Amazon Q Developer (MCP)","Roo Code (project MCP)","Project MCP (shared)"];let j=!1;for(const t of x){const c=U.includes(t.name);if(!c&&!n(t.dir))continue;c&&s(t.dir,{recursive:!0});const r=a(t.dir,t.file);let i={};try{i=JSON.parse(e(r,"utf8"))}catch{}const l=t.config(i);o(r,JSON.stringify(l,null,2)+"\n","utf8"),g++,"Claude Code"===t.name&&(j=!0)}if(0===g){s(a(l,".claude"),{recursive:!0});const n=a(l,".claude","settings.json");let t={};try{t=JSON.parse(e(n,"utf8"))}catch{}const c=x[0].config(t);o(n,JSON.stringify(c,null,2)+"\n","utf8"),j=!0}const O=j?"CLAUDE.md":"AGENTS.md",_=a(process.cwd(),O);try{const s=n(_)?e(_,"utf8"):"";if(!s.includes("Never fabricate")){const e=s.length>0?s.trimEnd()+"\n\n":"";o(_,e+"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.\n","utf8")}}catch{}console.log(`\n Your free GOL Client ID (this machine): ${r}`),console.log(" Shared by every editor on this machine. 120 free checks/day."),console.log(" Need more? Get a GOL API Key (paid, prepaid balance) at"),console.log(" https://www.golproductions.com/console"),console.log("\n By using Check you agree to the Terms and Privacy Policy:"),console.log(" golproductions.com/terms | golproductions.com/privacy"),console.log("\nSafe travels wanderer..\n"),process.exit(0)}(),T.includes("--uninstall")&&await async function(){const s=h();let t=0;console.log("\n Removing Check...\n");let c=Promise.resolve();try{const e=y();e&&(c=fetch(k.replace("/preflight","/log"),{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":e,"User-Agent":"c/"+f},body:JSON.stringify({verdict:"uninstall",channel:"npm",os:d(),arch:u(),version:f}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}))}catch{}const l=[{name:"Claude Code",path:a(s,".claude","settings.json"),clean:e=>(e.hooks?.PreToolUse&&(e.hooks.PreToolUse=e.hooks.PreToolUse.filter(e=>!e.hooks?.some(C)),0===e.hooks.PreToolUse.length&&delete e.hooks.PreToolUse),e.hooks?.PostToolUse&&(e.hooks.PostToolUse=e.hooks.PostToolUse.filter(e=>!e.hooks?.some(C)),0===e.hooks.PostToolUse.length&&delete e.hooks.PostToolUse),e.hooks&&0===Object.keys(e.hooks).length&&delete e.hooks,e.env&&(delete e.env.GOL_CLIENT_ID,0===Object.keys(e.env).length&&delete e.env),e)},{name:"Gemini CLI",path:a(s,".gemini","settings.json"),clean:e=>(e.hooks?.BeforeTool&&(e.hooks.BeforeTool=e.hooks.BeforeTool.filter(e=>!e.hooks?.some(e=>"check-gate"===e.name)),0===e.hooks.BeforeTool.length&&delete e.hooks.BeforeTool,0===Object.keys(e.hooks).length&&delete e.hooks),e)},{name:"Cursor",path:a(s,".cursor","hooks.json"),clean:e=>(e.hooks?.beforeShellExecution&&(e.hooks.beforeShellExecution=e.hooks.beforeShellExecution.filter(e=>!v(e.command)),0===e.hooks.beforeShellExecution.length&&delete e.hooks.beforeShellExecution,0===Object.keys(e.hooks).length&&delete e.hooks),e)},{name:"Homebase",path:a(s,".homebase","hooks.json"),clean:e=>(e.hooks?.PreToolUse&&(e.hooks.PreToolUse=e.hooks.PreToolUse.filter(e=>!e.hooks?.some(C)),0===e.hooks.PreToolUse.length&&delete e.hooks.PreToolUse),e.hooks?.PostToolUse&&(e.hooks.PostToolUse=e.hooks.PostToolUse.filter(e=>!e.hooks?.some(C)),0===e.hooks.PostToolUse.length&&delete e.hooks.PostToolUse),e.hooks&&0===Object.keys(e.hooks).length&&delete e.hooks,e.env&&(delete e.env.GOL_CLIENT_ID,0===Object.keys(e.env).length&&delete e.env),e)}],m=[{name:"Windsurf",path:a(s,".codeium","windsurf","mcp_config.json")},{name:"Amazon Q",path:a(s,".aws","amazonq","mcp.json")}],p=[{name:"Continue",path:a(process.cwd(),".continue","mcpServers","check.json"),deleteFile:!0},{name:"Roo Code",path:a(process.cwd(),".roo","mcp.json")},{name:"Project MCP",path:a(process.cwd(),".mcp.json")}];for(const s of l)if(n(s.path))try{const n=JSON.parse(e(s.path,"utf8")),c=s.clean(n);o(s.path,JSON.stringify(c,null,2)+"\n","utf8"),console.log(" removed "+s.name),t++}catch{}for(const s of[...m,...p])if(n(s.path))try{if(s.deleteFile)r(s.path),console.log(" removed "+s.name),t++;else{const n=JSON.parse(e(s.path,"utf8"));n.mcpServers?.Check&&(delete n.mcpServers.Check,0===Object.keys(n.mcpServers).length&&delete n.mcpServers,o(s.path,JSON.stringify(n,null,2)+"\n","utf8"),console.log(" removed "+s.name),t++)}}catch{}const g=a(s,".check");if(n(g))try{i(g,{recursive:!0,force:!0}),console.log(" removed ~/.check/")}catch{}0===t?console.log(" No Check installations found.\n"):(console.log(`\n Removed from ${t} tool${1!==t?"s":""}.`),console.log(" CLAUDE.md / AGENTS.md rules were left in place.\n"));try{await c}catch{}process.exit(0)}(),T.includes("--status")&&await async function(){const o=h(),s=a(o,".check"),t="win32"===d()?".exe":"",c=y();if(console.log(`\n Check v${f}\n`),c){const e=c.length>12?c.slice(0,8)+"..."+c.slice(-4):c;console.log(" Client ID: "+e)}else console.log(" Client ID: not set");const r=a(s,"truth-gate"+t);console.log(" Binary: "+(n(r)?"installed":"not found"));const i=a(s,"check.mjs");console.log(" Script: "+(n(i)?"installed":"not found")),console.log("\n Integrations:\n");const l=[{name:"Claude Code",path:a(o,".claude","settings.json"),test:e=>e.hooks?.PreToolUse?.some(e=>e.hooks?.some(C))||e.hooks?.PostToolUse?.some(e=>e.hooks?.some(C)),detail:e=>{const o=[];return e.hooks?.PreToolUse?.some(e=>e.hooks?.some(C))&&o.push("PreToolUse"),e.hooks?.PostToolUse?.some(e=>e.hooks?.some(C))&&o.push("PostToolUse"),o.join(", ")}},{name:"Gemini CLI",path:a(o,".gemini","settings.json"),test:e=>e.hooks?.BeforeTool?.some(e=>e.hooks?.some(e=>"check-gate"===e.name)),detail:()=>"BeforeTool"},{name:"Cursor",path:a(o,".cursor","hooks.json"),test:e=>e.hooks?.beforeShellExecution?.some(e=>v(e.command)),detail:()=>"beforeShellExecution"},{name:"Homebase",path:a(o,".homebase","hooks.json"),test:e=>e.hooks?.PreToolUse?.some(e=>e.hooks?.some(C))||e.hooks?.PostToolUse?.some(e=>e.hooks?.some(C)),detail:e=>{const o=[];return e.hooks?.PreToolUse?.some(e=>e.hooks?.some(C))&&o.push("PreToolUse"),e.hooks?.PostToolUse?.some(e=>e.hooks?.some(C))&&o.push("PostToolUse"),o.join(", ")}},{name:"Windsurf",path:a(o,".codeium","windsurf","mcp_config.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP"},{name:"Continue",path:a(process.cwd(),".continue","mcpServers","check.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"},{name:"Amazon Q",path:a(o,".aws","amazonq","mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP"},{name:"Roo Code",path:a(process.cwd(),".roo","mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"},{name:"Project MCP",path:a(process.cwd(),".mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"}];for(const o of l)if(n(o.path))try{const s=JSON.parse(e(o.path,"utf8"));o.test(s)?console.log(" + "+o.name.padEnd(14)+" active ("+o.detail(s)+")"):console.log(" - "+o.name.padEnd(14)+" tool installed, Check not configured")}catch{console.log(" ? "+o.name.padEnd(14)+" config unreadable")}else console.log(" - "+o.name.padEnd(14)+" not detected");console.log(""),process.exit(0)}(),T.includes("--credits")&&await async function(){const e=y();e||(console.log("\n No Client ID found. Set GOL_CLIENT_ID or run --install first.\n"),process.exit(1));try{const o=await fetch(k.replace("/preflight","/credits"),{method:"GET",headers:{"X-GOL-CLIENT-ID":e,"User-Agent":"c/"+f},signal:AbortSignal.timeout(1e4)});o.ok||(console.log("\n Could not fetch credits (HTTP "+o.status+").\n"),process.exit(1));const s=await o.json();console.log(`\n Check v${f}: Credits\n`),void 0!==s.free_remaining&&console.log(" Free today: "+s.free_remaining+" / "+(s.free_daily||120)),void 0!==s.calls_today&&console.log(" Calls today: "+s.calls_today),void 0!==s.balance&&console.log(" Balance: $"+s.balance+" AUD"),void 0!==s.total_calls&&console.log(" Total calls: "+s.total_calls),s.plan&&console.log(" Plan: "+s.plan),0===Object.keys(s).length&&console.log(" "+JSON.stringify(s)),console.log("")}catch(e){console.log("\n Could not reach API: "+e.message+"\n")}process.exit(0)}(),T.includes("--docs")&&await async function(){console.log(`\n Check v${f}: Documentation\n\n Install: npx @golproductions/check --install <key>\n Uninstall: npx @golproductions/check --uninstall\n Status: npx @golproductions/check --status\n Credits: npx @golproductions/check --credits\n\n How it works:\n\n Check installs hooks into your AI coding tools. Every time\n the AI runs a command or edits a file, Check verifies it\n before or after execution.\n\n PreToolUse Validates commands before they run.\n PostToolUse Verifies results after execution.\n MCP Server Provides Check and CheckAndExecute tools.\n CLAUDE.md Adds anti-fabrication instructions.\n\n Supported tools:\n\n Claude Code, Gemini CLI, Cursor, Windsurf, Continue,\n Amazon Q Developer, Roo Code, Homebase\n\n Pricing:\n\n 120 free checks per day. Then $0.0068 AUD per check.\n Credits never expire. Pay as you go.\n\n Links:\n\n Website: https://golproductions.com/check\n Docs: https://github.com/golproductions/check\n Support: support@golproductions.com\n`);try{const{execSync:e}=await import("node:child_process"),o="https://github.com/golproductions/check";"win32"===d()?e(`start "" "${o}"`,{stdio:"ignore",shell:!0}):"darwin"===d()?e(`open "${o}"`,{stdio:"ignore"}):e(`xdg-open "${o}"`,{stdio:"ignore"})}catch{}process.exit(0)}(),(T.includes("--help")||T.includes("-h"))&&w(),T.includes("--mcp")&&(await import("./mcp.js"),process.exit(0)),!T.some(e=>e.startsWith("-"))&&process.stdin.isTTY&&w(),async function(){let e="claude";try{let o,s="";for await(const e of process.stdin)s+=e;s=s.replace(/^/,"").trim(),s||(process.stderr.write("check: no hook input on stdin. This entrypoint is for tool hooks; run --help for CLI usage.\n"),process.exit(1));try{o=JSON.parse(s)}catch{return void S("claude",!1,"check: unreadable hook input (not JSON), command blocked")}if("PostToolUse"===o.hook_event_name)return void process.exit(0);e=function(e){return"string"!=typeof e.command||e.tool_input?"BeforeTool"===e.hook_event_name||e.toolCall?.argumentsJson?"gemini":"claude":"cursor"}(o);const n=function(e,o){if("cursor"===o)return e.command;if("gemini"===o){if(e.tool_input?.command)return e.tool_input.command;if(e.toolCall?.argumentsJson)try{const o="string"==typeof e.toolCall.argumentsJson?JSON.parse(e.toolCall.argumentsJson):e.toolCall.argumentsJson;return o.command||o.CommandLine||o.command_line}catch{return null}return null}return e.tool_input?.command}(o,e);if(!n)return void S(e,!0);const t=y();if(!t)return void S(e,!1,"check: GOL_CLIENT_ID not set. Get your key at https://golproductions.com/check");if("Bash"===o.tool_name){const o=await async function(e){try{const o=x();if(!o)return null;const s=l(o,["-n"],{input:e,timeout:4e3,encoding:"utf8"});if(s.error)return null;if(0===s.status){const e=(s.stderr||"").split("\n").find(e=>/here-document.*end-of-file/i.test(e));return!!e&&e.replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}return((s.stderr||"").split("\n").find(e=>e.trim())||"syntax error").replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}catch{return null}}(n);if("string"==typeof o)return void S(e,!1,`check: syntax error. ${o}`)}const c=async e=>{const o=new AbortController,s=setTimeout(()=>o.abort(),5e3),n=await fetch(k,{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":t,"User-Agent":"c/"+f},body:JSON.stringify(e),signal:o.signal});return clearTimeout(s),{res:n,d:await n.json()}},r={command:n,cwd:o.cwd||process.cwd(),platform:e,channel:"npm",tool_name:o.tool_name,v:f,probe_ok:1};let{res:i,d:a}=await c(r);if(i.ok&&"probe"===a.verdict&&Array.isArray(a.probe)){const e={},s={};for(const n of a.probe.slice(0,8)){if("string"!=typeof n||!n||n.length>200)continue;const t=P(n,o.cwd||process.cwd());null!==t&&(e[n]=t.exists,!t.exists&&t.why&&(s[n]=t.why))}({res:i,d:a}=await c({...r,probe:e,probe_why:s}))}if(!i.ok){if(429===i.status||/rate limit/i.test(a.reason||a.error||""))return void b(e,"check: rate limited (60 checks/min), command ran unverified. Check resumes automatically.");if(i.status>=500)return void b(e,"check: validation service error (HTTP "+i.status+"), command ran unverified. Check resumes automatically.");if(402===i.status){return void b(e,`check: you've used all ${a.daily_free||120} free checks for today and your balance is empty. Check is off until tomorrow, commands run unverified. Credits you buy never expire. ${a.upgrade||"Top up at https://www.golproductions.com/console.html"}`)}return void S(e,!1,a.reason||a.error||"check: request not authorized, command blocked")}"runnable"===a.verdict?S(e,!0):S(e,!1,a.reason||"denied. Address the issue before continuing.")}catch{b(e,"check: validation service unreachable, command ran unverified. Check resumes automatically.")}}();
|
|
2
|
+
import{readFileSync as e,writeFileSync as o,mkdirSync as s,existsSync as n,createWriteStream as t,chmodSync as c,unlinkSync as r,rmSync as i}from"node:fs";import{spawnSync as l,spawn as a}from"node:child_process";import{join as h}from"node:path";import{homedir as d,platform as u,arch as m}from"node:os";import{pipeline as p}from"node:stream/promises";import{Readable as f}from"node:stream";const k="3.2.25",g="https://triage.golproductions.com/preflight",y=process.env.GOL_CLIENT_ID||"";function v(){if(y)return y;try{const o=e(h(d(),".check","key"),"utf8").trim();if(o)return o}catch{}try{const o=JSON.parse(e(h(d(),".claude","settings.json"),"utf8"));return o.env?.GOL_CLIENT_ID||""}catch{return""}}function C(e){return e&&(e.includes(".check")||e.includes("truth-gate"))}function w(e){return!!C(e.command)||!!e.args?.some(e=>C(e))}function T(){console.log(`\n Check v${k}: Anti-hallucination layer for AI coding agents\n\n Usage:\n\n npx @golproductions/check --install <key> Install Check with your Client ID\n npx @golproductions/check --uninstall Remove Check from all tools\n npx @golproductions/check --status Show what is installed and active\n npx @golproductions/check --credits Check your usage and balance\n npx @golproductions/check --docs View documentation\n npx @golproductions/check --help Show this help\n\n Get your key: https://golproductions.com/check\n Pricing: 120 free/day, then $0.0068 AUD per check\n`),process.exit(0)}const P=process.argv.slice(2);function S(e,{input:o,cwd:s}={}){return new Promise(t=>{try{const c=function(){if("win32"!==u())return"bash";const e=[process.env.CLAUDE_CODE_GIT_BASH_PATH,"C:/Program Files/Git/bin/bash.exe","C:/Program Files/Git/usr/bin/bash.exe","C:/Program Files (x86)/Git/bin/bash.exe"].filter(Boolean);for(const o of e)try{if(n(o))return o}catch{}return null}();if(!c)return t(null);const r=a(c,e,{cwd:s,windowsHide:!0});let i="";const l=setTimeout(()=>{try{r.kill()}catch{}t(null)},4e3);r.stderr.on("data",e=>{i+=e}),r.on("error",()=>{clearTimeout(l),t(null)}),r.on("close",e=>{clearTimeout(l),t({status:e,stderr:i})}),void 0!==o&&r.stdin.write(o),r.stdin.end()}catch{t(null)}})}function b(e,o,s){if(o){const o={cursor:{permission:"allow"},gemini:{decision:"allow"},claude:{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}};process.stdout.write(JSON.stringify(o[e]||o.claude)),process.exit(0)}"gemini"===e&&(process.stdout.write(JSON.stringify({decision:"deny",reason:s})),process.exit(2));const n={cursor:{permission:"deny",agent_message:s},claude:{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:s}}};process.stdout.write(JSON.stringify(n[e]||n.claude)),process.exit(0)}function x(e,t){let c=!0;try{const e=h(d(),".check","credits-warned-"+(new Date).toISOString().slice(0,10));c=n(e),c||(s(h(d(),".check"),{recursive:!0}),o(e,"1"))}catch{c=!1}const r=c?void 0:t;if("gemini"===e&&(process.stdout.write(JSON.stringify({decision:"allow"})),r&&process.stderr.write(r),process.exit(0)),"cursor"===e){const e={permission:"allow"};r&&(e.user_message=r),process.stdout.write(JSON.stringify(e)),process.exit(0)}const i={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};r&&(i.systemMessage=r),process.stdout.write(JSON.stringify(i)),process.exit(0)}P.includes("--install")&&await async function(){let r=process.argv[3]||process.env.GOL_CLIENT_ID||"";r&&"your_key"!==r||(console.log("\n Activating Check (free, no signup)...\n"),r=await async function(){try{const e=await async function(){const{createHash:e}=await import("node:crypto"),{hostname:o,userInfo:s}=await import("node:os");let n="";try{n=s().username||""}catch{}const t=[o(),u(),m(),n].join("|");return e("sha256").update(t).digest("hex")}(),o=await fetch(g.replace("/preflight","/instant-key"),{method:"POST",headers:{"Content-Type":"application/json","User-Agent":"c/"+k},body:JSON.stringify({fingerprint:e,channel:"npm"}),signal:AbortSignal.timeout(1e4)});if(!o.ok)return null;const s=await o.json();return s&&s.client_id?s.client_id:null}catch{return null}}(),r||(console.log(" Could not activate automatically (offline, or this network hit its daily limit).\n"),console.log(" Get a key the manual way: https://golproductions.com/check\n"),console.log(" Then run: npx @golproductions/check --install YOUR_KEY\n"),process.exit(1)),console.log(" Activated. 120 free checks per day.\n"));const i=await async function(e){try{const o=await fetch(g,{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":e,"User-Agent":"c/"+k},body:JSON.stringify({command:"echo check-install-verify",cwd:process.cwd(),v:k}),signal:AbortSignal.timeout(1e4)});if(o.ok)return{valid:!0,expired:!1};let s={};try{s=await o.json()}catch{}return{valid:!1,expired:/expir/i.test(s.reason||s.error||s.message||"")}}catch{return{valid:!1,expired:!1}}}(r);i.valid||(i.expired?(console.log("\n Your Client ID has expired: "+r),console.log("\n Renew your key at: https://golproductions.com/check\n")):(console.log("\n Invalid Client ID: "+r),console.log("\n Get a valid key at: https://golproductions.com/check\n")),process.exit(1)),console.log("\n Key verified. Installing Check...\n");const l=d();let a=0;const y=e(new URL(import.meta.url),"utf8"),v=h(l,".check");s(v,{recursive:!0});const T=h(v,"check.mjs").replace(/\\/g,"/");o(T,y,"utf8"),o(h(v,"key"),r,"utf8");const P="win32"===u()?".exe":"",S=h(v,"truth-gate"+P).replace(/\\/g,"/");await async function(e){const o="win32"===u()?"win":"darwin"===u()?"macos":"linux",s=`https://pub-e55366a7f5994be9be04f0e205179f4a.r2.dev/releases/truth-gate-v3.0.0-${o}-${"arm64"===m()?"arm64":"x64"}${"win"===o?".exe":""}`,n=await fetch(s);if(!n.ok)throw new Error(`Download failed: ${n.status}`);if(await p(f.fromWeb(n.body),t(e)),"win"!==o)try{c(e,493)}catch{}}(S);const b={command:"npx",args:["@golproductions/check","--mcp"],env:{GOL_CLIENT_ID:r}},x=[{name:"Claude Code",dir:h(l,".claude"),file:"settings.json",config:e=>(e.hooks=e.hooks||{},e.hooks.PreToolUse=(e.hooks.PreToolUse||[]).filter(e=>!e.hooks?.some(w)),e.hooks.PreToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:"node",args:[T]}]}),e.hooks.PostToolUse=(e.hooks.PostToolUse||[]).filter(e=>!e.hooks?.some(w)),e.hooks.PostToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:S}]},{matcher:"Edit|Write|NotebookEdit",hooks:[{type:"command",command:S}]}),e.env=e.env||{},e.env.GOL_CLIENT_ID=r,e)},{name:"Gemini CLI / Antigravity",dir:h(l,".gemini"),file:"settings.json",config:e=>{e.hooks=e.hooks||{},e.hooks.BeforeTool=e.hooks.BeforeTool||[];const o=e.hooks.BeforeTool;return o.find(e=>e.hooks?.some(e=>"check-gate"===e.name))||o.push({matcher:".*",hooks:[{type:"command",command:"node "+T,name:"check-gate"}]}),e}},{name:"Cursor",dir:h(l,".cursor"),file:"hooks.json",config:e=>(e.version=e.version||1,e.hooks=e.hooks||{},e.hooks.beforeShellExecution=(e.hooks.beforeShellExecution||[]).filter(e=>!C(e.command)),e.hooks.beforeShellExecution.push({command:"node "+T}),e)},{name:"Homebase",dir:h(l,".homebase"),file:"hooks.json",config:e=>(e.hooks=e.hooks||{},e.hooks.PreToolUse=(e.hooks.PreToolUse||[]).filter(e=>!e.hooks?.some(w)),e.hooks.PreToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:"node",args:[T]}]}),e.hooks.PostToolUse=(e.hooks.PostToolUse||[]).filter(e=>!e.hooks?.some(w)),e.hooks.PostToolUse.push({matcher:"Bash|PowerShell",hooks:[{type:"command",command:S}]}),e.env=e.env||{},e.env.GOL_CLIENT_ID=r,e)},{name:"Windsurf (MCP)",dir:h(l,".codeium","windsurf"),file:"mcp_config.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)},{name:"Continue (MCP)",dir:h(process.cwd(),".continue","mcpServers"),file:"check.json",config:()=>({mcpServers:{Check:b}})},{name:"Amazon Q Developer (MCP)",dir:h(l,".aws","amazonq"),file:"mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check={type:"stdio",...b},e)},{name:"Roo Code (project MCP)",dir:h(process.cwd(),".roo"),file:"mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)},{name:"Project MCP (shared)",dir:process.cwd(),file:".mcp.json",config:e=>(e.mcpServers=e.mcpServers||{},e.mcpServers.Check=b,e)}],U=["Windsurf (MCP)","Continue (MCP)","Amazon Q Developer (MCP)","Roo Code (project MCP)","Project MCP (shared)"];let j=!1;for(const t of x){const c=U.includes(t.name);if(!c&&!n(t.dir))continue;c&&s(t.dir,{recursive:!0});const r=h(t.dir,t.file);let i={};try{i=JSON.parse(e(r,"utf8"))}catch{}const l=t.config(i);o(r,JSON.stringify(l,null,2)+"\n","utf8"),a++,"Claude Code"===t.name&&(j=!0)}if(0===a){s(h(l,".claude"),{recursive:!0});const n=h(l,".claude","settings.json");let t={};try{t=JSON.parse(e(n,"utf8"))}catch{}const c=x[0].config(t);o(n,JSON.stringify(c,null,2)+"\n","utf8"),j=!0}const O=j?"CLAUDE.md":"AGENTS.md",_=h(process.cwd(),O);try{const s=n(_)?e(_,"utf8"):"";if(!s.includes("Never fabricate")){const e=s.length>0?s.trimEnd()+"\n\n":"";o(_,e+"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.\n","utf8")}}catch{}console.log(`\n Your free GOL Client ID (this machine): ${r}`),console.log(" Shared by every editor on this machine. 120 free checks/day."),console.log(" Need more? Get a GOL API Key (paid, prepaid balance) at"),console.log(" https://www.golproductions.com/console"),console.log("\n By using Check you agree to the Terms and Privacy Policy:"),console.log(" golproductions.com/terms | golproductions.com/privacy"),console.log("\nSafe travels wanderer..\n"),process.exit(0)}(),P.includes("--uninstall")&&await async function(){const s=d();let t=0;console.log("\n Removing Check...\n");let c=Promise.resolve();try{const e=v();e&&(c=fetch(g.replace("/preflight","/log"),{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":e,"User-Agent":"c/"+k},body:JSON.stringify({verdict:"uninstall",channel:"npm",os:u(),arch:m(),version:k}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}))}catch{}const l=[{name:"Claude Code",path:h(s,".claude","settings.json"),clean:e=>(e.hooks?.PreToolUse&&(e.hooks.PreToolUse=e.hooks.PreToolUse.filter(e=>!e.hooks?.some(w)),0===e.hooks.PreToolUse.length&&delete e.hooks.PreToolUse),e.hooks?.PostToolUse&&(e.hooks.PostToolUse=e.hooks.PostToolUse.filter(e=>!e.hooks?.some(w)),0===e.hooks.PostToolUse.length&&delete e.hooks.PostToolUse),e.hooks&&0===Object.keys(e.hooks).length&&delete e.hooks,e.env&&(delete e.env.GOL_CLIENT_ID,0===Object.keys(e.env).length&&delete e.env),e)},{name:"Gemini CLI",path:h(s,".gemini","settings.json"),clean:e=>(e.hooks?.BeforeTool&&(e.hooks.BeforeTool=e.hooks.BeforeTool.filter(e=>!e.hooks?.some(e=>"check-gate"===e.name)),0===e.hooks.BeforeTool.length&&delete e.hooks.BeforeTool,0===Object.keys(e.hooks).length&&delete e.hooks),e)},{name:"Cursor",path:h(s,".cursor","hooks.json"),clean:e=>(e.hooks?.beforeShellExecution&&(e.hooks.beforeShellExecution=e.hooks.beforeShellExecution.filter(e=>!C(e.command)),0===e.hooks.beforeShellExecution.length&&delete e.hooks.beforeShellExecution,0===Object.keys(e.hooks).length&&delete e.hooks),e)},{name:"Homebase",path:h(s,".homebase","hooks.json"),clean:e=>(e.hooks?.PreToolUse&&(e.hooks.PreToolUse=e.hooks.PreToolUse.filter(e=>!e.hooks?.some(w)),0===e.hooks.PreToolUse.length&&delete e.hooks.PreToolUse),e.hooks?.PostToolUse&&(e.hooks.PostToolUse=e.hooks.PostToolUse.filter(e=>!e.hooks?.some(w)),0===e.hooks.PostToolUse.length&&delete e.hooks.PostToolUse),e.hooks&&0===Object.keys(e.hooks).length&&delete e.hooks,e.env&&(delete e.env.GOL_CLIENT_ID,0===Object.keys(e.env).length&&delete e.env),e)}],a=[{name:"Windsurf",path:h(s,".codeium","windsurf","mcp_config.json")},{name:"Amazon Q",path:h(s,".aws","amazonq","mcp.json")}],p=[{name:"Continue",path:h(process.cwd(),".continue","mcpServers","check.json"),deleteFile:!0},{name:"Roo Code",path:h(process.cwd(),".roo","mcp.json")},{name:"Project MCP",path:h(process.cwd(),".mcp.json")}];for(const s of l)if(n(s.path))try{const n=JSON.parse(e(s.path,"utf8")),c=s.clean(n);o(s.path,JSON.stringify(c,null,2)+"\n","utf8"),console.log(" removed "+s.name),t++}catch{}for(const s of[...a,...p])if(n(s.path))try{if(s.deleteFile)r(s.path),console.log(" removed "+s.name),t++;else{const n=JSON.parse(e(s.path,"utf8"));n.mcpServers?.Check&&(delete n.mcpServers.Check,0===Object.keys(n.mcpServers).length&&delete n.mcpServers,o(s.path,JSON.stringify(n,null,2)+"\n","utf8"),console.log(" removed "+s.name),t++)}}catch{}const f=h(s,".check");if(n(f))try{i(f,{recursive:!0,force:!0}),console.log(" removed ~/.check/")}catch{}0===t?console.log(" No Check installations found.\n"):(console.log(`\n Removed from ${t} tool${1!==t?"s":""}.`),console.log(" CLAUDE.md / AGENTS.md rules were left in place.\n"));try{await c}catch{}process.exit(0)}(),P.includes("--status")&&await async function(){const o=d(),s=h(o,".check"),t="win32"===u()?".exe":"",c=v();if(console.log(`\n Check v${k}\n`),c){const e=c.length>12?c.slice(0,8)+"..."+c.slice(-4):c;console.log(" Client ID: "+e)}else console.log(" Client ID: not set");const r=h(s,"truth-gate"+t);console.log(" Binary: "+(n(r)?"installed":"not found"));const i=h(s,"check.mjs");console.log(" Script: "+(n(i)?"installed":"not found")),console.log("\n Integrations:\n");const l=[{name:"Claude Code",path:h(o,".claude","settings.json"),test:e=>e.hooks?.PreToolUse?.some(e=>e.hooks?.some(w))||e.hooks?.PostToolUse?.some(e=>e.hooks?.some(w)),detail:e=>{const o=[];return e.hooks?.PreToolUse?.some(e=>e.hooks?.some(w))&&o.push("PreToolUse"),e.hooks?.PostToolUse?.some(e=>e.hooks?.some(w))&&o.push("PostToolUse"),o.join(", ")}},{name:"Gemini CLI",path:h(o,".gemini","settings.json"),test:e=>e.hooks?.BeforeTool?.some(e=>e.hooks?.some(e=>"check-gate"===e.name)),detail:()=>"BeforeTool"},{name:"Cursor",path:h(o,".cursor","hooks.json"),test:e=>e.hooks?.beforeShellExecution?.some(e=>C(e.command)),detail:()=>"beforeShellExecution"},{name:"Homebase",path:h(o,".homebase","hooks.json"),test:e=>e.hooks?.PreToolUse?.some(e=>e.hooks?.some(w))||e.hooks?.PostToolUse?.some(e=>e.hooks?.some(w)),detail:e=>{const o=[];return e.hooks?.PreToolUse?.some(e=>e.hooks?.some(w))&&o.push("PreToolUse"),e.hooks?.PostToolUse?.some(e=>e.hooks?.some(w))&&o.push("PostToolUse"),o.join(", ")}},{name:"Windsurf",path:h(o,".codeium","windsurf","mcp_config.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP"},{name:"Continue",path:h(process.cwd(),".continue","mcpServers","check.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"},{name:"Amazon Q",path:h(o,".aws","amazonq","mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP"},{name:"Roo Code",path:h(process.cwd(),".roo","mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"},{name:"Project MCP",path:h(process.cwd(),".mcp.json"),test:e=>!!e.mcpServers?.Check,detail:()=>"MCP (project)"}];for(const o of l)if(n(o.path))try{const s=JSON.parse(e(o.path,"utf8"));o.test(s)?console.log(" + "+o.name.padEnd(14)+" active ("+o.detail(s)+")"):console.log(" - "+o.name.padEnd(14)+" tool installed, Check not configured")}catch{console.log(" ? "+o.name.padEnd(14)+" config unreadable")}else console.log(" - "+o.name.padEnd(14)+" not detected");console.log(""),process.exit(0)}(),P.includes("--credits")&&await async function(){const e=v();e||(console.log("\n No Client ID found. Set GOL_CLIENT_ID or run --install first.\n"),process.exit(1));try{const o=await fetch(g.replace("/preflight","/credits"),{method:"GET",headers:{"X-GOL-CLIENT-ID":e,"User-Agent":"c/"+k},signal:AbortSignal.timeout(1e4)});o.ok||(console.log("\n Could not fetch credits (HTTP "+o.status+").\n"),process.exit(1));const s=await o.json();console.log(`\n Check v${k}: Credits\n`),void 0!==s.free_remaining&&console.log(" Free today: "+s.free_remaining+" / "+(s.free_daily||120)),void 0!==s.calls_today&&console.log(" Calls today: "+s.calls_today),void 0!==s.balance&&console.log(" Balance: $"+s.balance+" AUD"),void 0!==s.total_calls&&console.log(" Total calls: "+s.total_calls),s.plan&&console.log(" Plan: "+s.plan),0===Object.keys(s).length&&console.log(" "+JSON.stringify(s)),console.log("")}catch(e){console.log("\n Could not reach API: "+e.message+"\n")}process.exit(0)}(),P.includes("--docs")&&await async function(){console.log(`\n Check v${k}: Documentation\n\n Install: npx @golproductions/check --install <key>\n Uninstall: npx @golproductions/check --uninstall\n Status: npx @golproductions/check --status\n Credits: npx @golproductions/check --credits\n\n How it works:\n\n Check installs hooks into your AI coding tools. Every time\n the AI runs a command or edits a file, Check verifies it\n before or after execution.\n\n PreToolUse Validates commands before they run.\n PostToolUse Verifies results after execution.\n MCP Server Provides Check and CheckAndExecute tools.\n CLAUDE.md Adds anti-fabrication instructions.\n\n Supported tools:\n\n Claude Code, Gemini CLI, Cursor, Windsurf, Continue,\n Amazon Q Developer, Roo Code, Homebase\n\n Pricing:\n\n 120 free checks per day. Then $0.0068 AUD per check.\n Credits never expire. Pay as you go.\n\n Links:\n\n Website: https://golproductions.com/check\n Docs: https://github.com/golproductions/check\n Support: support@golproductions.com\n`);try{const{execSync:e}=await import("node:child_process"),o="https://github.com/golproductions/check";"win32"===u()?e(`start "" "${o}"`,{stdio:"ignore",shell:!0}):"darwin"===u()?e(`open "${o}"`,{stdio:"ignore"}):e(`xdg-open "${o}"`,{stdio:"ignore"})}catch{}process.exit(0)}(),(P.includes("--help")||P.includes("-h"))&&T(),P.includes("--mcp")&&(await import("./mcp.js"),process.exit(0)),!P.some(e=>e.startsWith("-"))&&process.stdin.isTTY&&T(),async function(){let e="claude";try{let o,s="";for await(const e of process.stdin)s+=e;s=s.replace(/^/,"").trim(),s||(process.stderr.write("check: no hook input on stdin. This entrypoint is for tool hooks; run --help for CLI usage.\n"),process.exit(1));try{o=JSON.parse(s)}catch{return void b("claude",!1,"check: unreadable hook input (not JSON), command blocked")}if("PostToolUse"===o.hook_event_name)return void process.exit(0);e=function(e){return"string"!=typeof e.command||e.tool_input?"BeforeTool"===e.hook_event_name||e.toolCall?.argumentsJson?"gemini":"claude":"cursor"}(o);const n=function(e,o){if("cursor"===o)return e.command;if("gemini"===o){if(e.tool_input?.command)return e.tool_input.command;if(e.toolCall?.argumentsJson)try{const o="string"==typeof e.toolCall.argumentsJson?JSON.parse(e.toolCall.argumentsJson):e.toolCall.argumentsJson;return o.command||o.CommandLine||o.command_line}catch{return null}return null}return e.tool_input?.command}(o,e);if(!n)return void b(e,!0);const t=v();if(!t)return void b(e,!1,"check: GOL_CLIENT_ID not set. Get your key at https://golproductions.com/check");const c=async e=>{const o=new AbortController,s=setTimeout(()=>o.abort(),5e3),n=await fetch(g,{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":t,"User-Agent":"c/"+k},body:JSON.stringify(e),signal:o.signal});return clearTimeout(s),{res:n,d:await n.json()}},r={command:n,cwd:o.cwd||process.cwd(),platform:e,channel:"npm",tool_name:o.tool_name,v:k,probe_ok:1},i="Bash"===o.tool_name?async function(e){try{const o=await S(["-n"],{input:e});if(null===o)return null;if(0===o.status){const e=(o.stderr||"").split("\n").find(e=>/here-document.*end-of-file/i.test(e));return!!e&&e.replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}return((o.stderr||"").split("\n").find(e=>e.trim())||"syntax error").replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}catch{return null}}(n):Promise.resolve(null),l=c(r).catch(e=>{throw e});l.catch(()=>{});const a=await i;if("string"==typeof a)return void b(e,!1,`check: syntax error. ${a}`);let{res:h,d:d}=await l;if(h.ok&&"probe"===d.verdict&&Array.isArray(d.probe)){const e=d.probe.slice(0,8).filter(e=>"string"==typeof e&&e&&e.length<=200),s=await Promise.all(e.map(e=>async function(e,o){try{const s=await S(["-c",'type -- "$1"',"check",e],{cwd:o});if(null===s)return null;if(0===s.status)return{exists:!0};const n=(s.stderr||"").split("\n").find(o=>o.includes(e))||"";return{exists:!1,why:n.slice(n.indexOf(e)).trim()||e+": not found"}}catch{return null}}(e,o.cwd||process.cwd()))),n={},t={};e.forEach((e,o)=>{const c=s[o];null!==c&&(n[e]=c.exists,!c.exists&&c.why&&(t[e]=c.why))}),({res:h,d:d}=await c({...r,probe:n,probe_why:t}))}if(!h.ok){if(429===h.status||/rate limit/i.test(d.reason||d.error||""))return void x(e,"check: rate limited (60 checks/min), command ran unverified. Check resumes automatically.");if(h.status>=500)return void x(e,"check: validation service error (HTTP "+h.status+"), command ran unverified. Check resumes automatically.");if(402===h.status){return void x(e,`check: you've used all ${d.daily_free||120} free checks for today and your balance is empty. Check is off until tomorrow, commands run unverified. Credits you buy never expire. ${d.upgrade||"Top up at https://www.golproductions.com/console.html"}`)}return void b(e,!1,d.reason||d.error||"check: request not authorized, command blocked")}"runnable"===d.verdict?b(e,!0):b(e,!1,d.reason||"denied. Address the issue before continuing.")}catch{x(e,"check: validation service unreachable, command ran unverified. Check resumes automatically.")}}();
|
package/dist/mcp.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{McpServer as t}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as e}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as r}from"zod";import{execFile as n,
|
|
2
|
+
import{McpServer as t}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as e}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as r}from"zod";import{execFile as n,spawn as o}from"node:child_process";import{existsSync as s}from"node:fs";import{platform as i}from"node:os";import{promisify as c}from"node:util";const a=c(n),l="3.2.25",d=process.env.GOL_CLIENT_ID,u="win32"===process.platform;function m(t,e){return new Promise(r=>{try{const n=function(){if("win32"!==i())return"bash";const t=[process.env.CLAUDE_CODE_GIT_BASH_PATH,"C:/Program Files/Git/bin/bash.exe","C:/Program Files/Git/usr/bin/bash.exe","C:/Program Files (x86)/Git/bin/bash.exe"].filter(Boolean);for(const e of t)try{if(s(e))return e}catch{}return null}();if(!n)return r(null);const c=o(n,t,{windowsHide:!0});let a="";const l=setTimeout(()=>{try{c.kill()}catch{}r(null)},4e3);c.stderr.on("data",t=>{a+=t}),c.on("error",()=>{clearTimeout(l),r(null)}),c.on("close",t=>{clearTimeout(l),r({status:t,stderr:a})}),void 0!==e&&c.stdin.write(e),c.stdin.end()}catch{r(null)}})}async function p(t){const e=async t=>{const e=await fetch("https://triage.golproductions.com/preflight",{method:"POST",headers:{"Content-Type":"application/json","X-GOL-CLIENT-ID":d,"User-Agent":"c/"+l},body:JSON.stringify(t)}),r=await e.json();return r._status=e.status,r},r={command:t,v:l,channel:"mcp",platform:"mcp",probe_ok:1},n=async function(t){try{const e=await m(["-n"],t);if(null===e)return null;if(0===e.status){const t=(e.stderr||"").split("\n").find(t=>/here-document.*end-of-file/i.test(t));return!!t&&t.replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}return((e.stderr||"").split("\n").find(t=>t.trim())||"syntax error").replace(/^[^:]*bash[^:]*:\s*/i,"").trim()}catch{return null}}(t),o=e(r);o.catch(()=>{});const s=await n;if("string"==typeof s)return{verdict:"invalid",reason:`syntax error. ${s}`,_status:200};let i=await o;if(200===i._status&&"probe"===i.verdict&&Array.isArray(i.probe)){const t=i.probe.slice(0,8).filter(t=>"string"==typeof t&&t&&t.length<=200),n=await Promise.all(t.map(t=>async function(t){try{const e=await m(["-c",'type -- "$1"',"check",t]);if(null===e)return null;if(0===e.status)return{exists:!0};const r=(e.stderr||"").split("\n").find(e=>e.includes(t))||"";return{exists:!1,why:r.slice(r.indexOf(t)).trim()||t+": not found"}}catch{return null}}(t))),o={},s={};t.forEach((t,e)=>{const r=n[e];null!==r&&(o[t]=r.exists,!r.exists&&r.why&&(s[t]=r.why))}),i=await e({...r,probe:o,probe_why:s})}return i}d||(process.stderr.write("check: GOL_CLIENT_ID environment variable is required.\nGet your key at https://www.golproductions.com/check.html\n"),process.exit(1));const h=new t({name:"check",version:l});h.tool("Check","Know if a command will work before running it. Returns 'runnable' or 'invalid'. $0.0068 AUD per Check.",{command:r.string().max(1e4).describe("The shell command to validate before execution")},async({command:t})=>{try{const e=await p(t);return 402===e._status?{content:[{type:"text",text:"Verdict: RUNNABLE (unverified). Check: daily free checks used and balance is empty. Command NOT verified. Check resumes tomorrow or after a top-up at https://www.golproductions.com/console.html"}]}:e.verdict?"runnable"===e.verdict?{content:[{type:"text",text:"Verdict: RUNNABLE"}]}:{content:[{type:"text",text:"Verdict: INVALID"+(e.reason?". "+e.reason:"")}]}:{content:[{type:"text",text:`Error: ${e.error||"unknown"}`}],isError:!0}}catch(t){return{content:[{type:"text",text:`Check API error: ${t.message}`}],isError:!0}}}),h.tool("CheckAndExecute","Validate a command with Check, then execute it if runnable. Returns the command output if valid, or blocks it.",{command:r.string().max(1e4).describe("The shell command to validate and execute")},async({command:t})=>{try{const e=await p(t);if(402!==e._status&&"runnable"!==e.verdict)return{content:[{type:"text",text:"BLOCKED: "+(e.reason||"command is invalid")}]};const{stdout:r,stderr:n}=await a(u?"cmd":"bash",u?["/c",t]:["-c",t],{timeout:3e4});return{content:[{type:"text",text:(r||"")+(n?"\nSTDERR: "+n:"")||"(no output)"}]}}catch(t){return t.stdout||t.stderr?{content:[{type:"text",text:`Exit ${t.code||1}:\n${(t.stdout||"")+(t.stderr?"\nSTDERR: "+t.stderr:"")}`}]}:{content:[{type:"text",text:`Error: ${t.message}`}],isError:!0}}});const f=new e;await h.connect(f);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golproductions/check",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.25",
|
|
4
4
|
"description": "Less hallucinations. A command firewall for AI agents: validates every shell command before execution, so fabricated commands are denied before they run.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"check": "dist/index.js",
|