The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Gatetest listing page.
AI-powered code quality. Pay per scan via Stripe.
GateTest is a single CLI plus a composite GitHub Action that runs 121 static-analysis modules against any codebase, then uses an AI fix engine to repair the findings it can. It replaces SonarQube, Snyk, ESLint, Cypress, Lighthouse, axe, pa11y, and twenty-plus other tools with one config, one gate decision, and one report.
It is different because the cost trends to zero. Deterministic AST and rule-based layers run first — these are free and ship the fix in milliseconds. The AI layer only runs on patterns nothing else has seen. Every AI win is distilled into a reusable recipe, so the next time the same pattern appears anywhere in the network it is handled for free. The longer you run GateTest, the less of it is paid work.
What you get depends on the tier. A pull request with the fixes, regression tests pinned to each fix, an architecture-shape critique, a cross-finding attack-chain analysis, and a CTO-readable executive summary — in whichever combination the tier you bought includes. One-time payment per scan via Stripe at checkout. No subscription, no auto-renew.
Drop this in .github/workflows/gatetest.yml:
The action is a composite — no Docker pull, no container build. It installs GateTest, runs the gate, and if auto-fix: true and ANTHROPIC_API_KEY is set, runs the AI repair loop on a blocking gate. See action.yml for every input.
The action authenticates with the workflow's own token by default (github-token input, ${{ github.token }}), so the permissions: block above is all it needs: without pull-requests: write the summary comment and suggestions are skipped, with a warning in the log. Add issues: write if you turn on track-non-fixable: true, and security-events: write (plus actions: read) if you upload the --sarif report to the Security tab with github/codeql-action/upload-sarif (see Wire it into CI below).
Your first full run passes. Turning a gate on against an existing codebase would otherwise fail on years of backlog nobody wrote this week, so a full-repo run that finds no .gatetest/baseline.json snapshots what is already there and exits green. Commit that file and every run after it fails on new findings only — pull requests are judged on the files they change from the very first run. Details under baseline mode.
The whole engine in your Problems panel, before you commit. Every finding lands on the line that caused it, with the fix. Free, no account, and nothing leaves your machine.
Source and the full command reference: vscode-extension/.
Run the full pre-merge sweep locally in one command:
This runs the same seven checks that block a merge in CI. Verdict is green or red. Exit code is 0 or 1, matching CI exactly.
Fast path during iteration:
See gatetest sweep --help for every flag.
Every scanner gets it wrong sometimes. When GateTest flags something you've judged safe, add one line to a .gatetestignore file at your repo root:
Suppressed findings are excluded from the gate decision and every failure count, but stay visible in a suppressedChecks list — nothing is silently hidden. Two more controls:
gatetest --noise — ranks your noisiest modules and prints the exact ignore line to copy. The same signal, aggregated across every opted-in scan, is published rule by rule at gatetest.io/noise.The policy is reviewed as policy. .gatetest.json and .gatetestignore are what
every later PR is judged by, so a PR that changes them says so: a suppression added
to .gatetestignore, a module disabled, the gate set to report-only or the block
threshold raised in .gatetest.json each produce a Gate policy changed warning on
that PR — reported, never blocking, quiet on comments and on tightening. Every
signed report records the SHA-256 of both files (gatetest verify-report prints
them), so two reports that disagree can be told apart by policy, not only by
engine.
Project-wide options live in .gatetest.json (suites, per-module config, severity overrides) — run gatetest --init to scaffold one.
Turning a scanner on against a large existing codebase usually means drowning in a backlog you didn't write. GateTest's baseline mode grandfathers everything that exists today so the gate only ever fails on new findings — "clean as you code."
Fix a baselined finding and it's gone for good; the count is tracked per file, so adding a second secret to a file that already had one baselined re-blocks the gate (you can't sneak a new problem in behind an old one). Refresh the snapshot after paying down debt with gatetest --baseline; delete .gatetest/baseline.json to see everything again.
The live crawler can carry a session so it reaches authed areas (/dashboard/*, account pages) instead of bouncing off the login redirect:
Session material is only ever sent to the target's own origin — never to third-party links, assets, or cross-origin redirects. Without a session, a crawl that hits a login wall tells you exactly which flag to add rather than silently skipping the protected pages. The hosted scanner at gatetest.io accepts the same session auth.
Connect GateTest directly to Claude Code (or any MCP-compatible AI) in one command:
24 tools across five families:
| Family | Tools | What it gives the agent |
|---|---|---|
| Engine | scan_local, run_module, fix_issue, verify_fix, … | Scan + fix local code |
| 👁 Eyes | capture_screenshot, get_visual_diff | See the rendered page as a real image |
| 👂 Ears | get_production_errors, run_live_checks | Hear Sentry/Datadog/Rollbar errors + localhost runtime failures |
| 🤝 Hands | verify_fix | Hard ✅/❌ — prove the fix actually worked |
| 🔬 Root Cause | resolve_stack_trace, blame_regression | Resolve a minified stack trace to original file:line via source maps; find the git commit that introduced a specific line. Same engines are also CLI subcommands (gatetest trace, gatetest blame) — one implementation, both entry points |
Works with Claude Code, Cursor, Windsurf, Continue, and Cline. See packages/mcp-server/ for the full tool reference and example prompts.
Visit gatetest.io/web and paste any URL. You get a free preview and a paid full report. For WordPress sites use gatetest.io/wp.
Don't hand-write the pipeline. One command scaffolds a complete, conventional config:
Each generated config gates the right thing at the right time rather than running
everything everywhere: a quick, diff-scoped scan on merge requests and pull
requests, a full scan on the main branch, and a separate security stage. JUnit
and SARIF are emitted to .gatetest/reports/ and wired into the platform's native
test-reporting and artifact storage, so failures show up in the UI instead of only
in the log.
On any other CI — Jenkins, Buildkite, Bitbucket, Drone — the CLI is the whole integration:
Onboarding an existing codebase? Pair this with baseline mode above so the gate only fails on new findings.
Merge queues. The GitHub Action and the drop-in workflow handle the merge_group
event: each group is scanned diff-scoped against the queue's base (the event
payload's base_sha, which the engine resolves through one shared base resolver —
the same one --pr, prSize and the fake-fix detector use, so no module measures a
different diff from another). Add merge_group: under on: in your workflow and
nothing else changes.
Path filters. In a monorepo, scope the gate to the packages it owns in
.gatetest.json:
A bare directory means everything under it; * is one segment, ** any depth;
exclude wins. The filter applies at the one file walk every module shares, findings
from modules with their own lookups are dropped at the runner, and every report says
so — Scope: .gatetest.json paths — include packages/api (3 finding(s) outside it not shown) — and carries it in the signed provenance. No paths key, no filter.
Reproduce any failing GitHub Actions run on your laptop in seconds:
This fetches the run, identifies which steps failed, and runs them locally against your current working tree. Output tells you whether the failure reproduces, doesn't reproduce (flaky CI), or hits a different error.
Authentication is optional — if you have a GITHUB_TOKEN set or gh CLI
installed, replay can read private repo runs. Otherwise it uses the
unauthenticated rate limit (60 req/hour, fine for a few replays).
When a gate is blocked inside GitHub Actions, the log and the checks tab already carry this command with the run's URL filled in.
The engine is an npm package with four runtime dependencies that reads your tree and
writes to .gatetest/. By default the only thing that leaves the machine is the
anonymized telemetry flush (module and rule ids with integer counts; opt out with
GATETEST_NO_TELEMETRY=1); the AI-backed fix paths are opt-in and need
ANTHROPIC_API_KEY. For an air-gapped runner, make that a stated promise:
Under --offline nothing leaves the machine: no telemetry upload, no AI calls
(--fix / --auto-pr are refused with a message, gatetest fix exits 2), no live
API ping from --doctor. The console prints the mode, the summary carries
offline: true, and the signed provenance records it — so a report produced inside
the perimeter can be verified outside it with gatetest verify-report and the key.
There is no licence server and no account; nothing expires.
Every release tag and every push to main publishes an image to GitHub Container
Registry: ghcr.io/crclabs-hq/gatetest (1.61.1, 1.61, 1, latest for
releases; main and sha-<short> for main). It is primarily the gatetest.io
website plus the sandbox worker — the image docker compose up runs — but the
scan engine ships in the same image at /app, so docker run with CLI-flag
arguments (anything starting with -) runs a scan instead: no npm install, no
second image. With no arguments it falls through to its default command, which
serves the site on port 3000:
The container runs as an unprivileged user, so the mounted repo must be readable
by it (it writes the report to .gatetest/ in the mount). For day-to-day use the
npm package is smaller and faster: npx -p @gatetest/cli gatetest --suite quick.
Build it yourself with docker compose up --build; everything the image reads is
listed in docs/ops/docker.md.
Every JSON report (.gatetest/reports/gatetest-report-latest.json) carries a
provenance block — engine version, runtime, which modules ran, which were
skipped or deferred, the suppression state, and a SHA-256 digest of the
findings — and, when GATETEST_REPORT_SIGNING_KEY is set where the scan runs,
an HMAC-SHA256 signature over it.
VERIFIED means the signature matches the provenance and the findings still
match the digest — neither block can be edited without the other noticing.
Without a key the report says signature.unsigned explicitly rather than
carrying a decorative field.
Writes .gatetest/reports/gatetest-compliance-<timestamp>.json and .md: every
finding filed under OWASP Top 10 2021, SOC 2 Trust Services Criteria and
CIS Controls v8, control by control, with the raw results behind the tables
and the same provenance + signature as the JSON report, so gatetest verify-report
proves the pack was not edited after the scan. Three states, never two: a control is
PASS only when a module mapped to it ran and found nothing; NOT CHECKED
when no mapped module ran in that suite (and the report names which, and why);
NO MODULE when nothing in the engine maps to it. Modules without a framework
mapping are listed as unattributed rather than filed under a catch-all.
Both subcommands share the exact same engine as the MCP resolve_stack_trace
and blame_regression tools — run them by hand or let your agent call them
mid-fix-loop; the answer is identical either way. Run gatetest trace --help
or gatetest blame --help for the full option list.
First time we see a pattern: the AI layer. Every time after: free. The longer you run GateTest, the cheaper it gets.
One config, one bill, one gate decision. Twelve-plus tools dissolve into single CLI flags.
| Their tool | GateTest module |
|---|---|
| Snyk Code, Dependabot, npm audit | security, dependencies |
| SonarQube | codeQuality + every other module |
| ESLint, Stylelint | lint |
| Cypress, BrowserStack, Sauce Labs | e2e |
| Lighthouse | performance |
| axe, pa11y | accessibility |
| Percy, Chromatic | visual |
| git-secrets, TruffleHog | secrets, secretRotation |
| hadolint, dockle | dockerfile |
| actionlint, zizmor, StepSecurity | ciSecurity |
| tfsec, Checkov, Terrascan | terraform |
| kube-score, kubeaudit, Polaris | kubernetes |
| Stryker, Pitest | mutation |
| broken-link-checker | links |
| (none — fragmented across ESLint rules) | errorSwallow, nPlusOne, flakyTests |
| (none — no static tool exists) | redos, moneyFloat, logPii, tlsSecurity |
| (none — runtime profilers only) | resourceLeak, raceCondition, retryHygiene |
Twelve-plus tools. One config. One bill. Full module catalogue: run node bin/gatetest.js --list or read it on gatetest.io.
Scan tiers are one-time payments via Stripe at checkout — no auto-renew. Continuous and MCP are monthly subscriptions; manage or cancel them yourself at gatetest.io/billing (enter your checkout email, get a secure Stripe portal link by email — update your card, view invoices, change plan, or cancel). Refunds only at our discretion for scans that failed to start or crashed mid-way without producing a report (contact support@gatetest.io).
| Tier | Price | What you get |
|---|---|---|
| Quick Scan | $29 | 4 modules — syntax, linting, secrets, code quality. Fastest path to a first signal. Scan-only — no auto-fix. |
| Full Scan | $99 | The full engine suite (88 modules; mutation + chaos run via the GitHub Action or a nightly instead — they need a CI runner to execute your test suite, and mutation re-runs it once per mutant). Every scan prints what it deferred and where that work runs. SARIF + JUnit reports via the CLI / GitHub Action. Scan-only — auto-fix ships at the Scan + Fix tier. |
| Scan + Fix | $199 | Everything in Full, plus a second-AI pair-review critique on every fix and an architecture-shape design-observations report. |
| Forensic Scan | $399 | Everything in Scan + Fix, plus real AI diagnosis on every finding, cross-finding attack-chain correlation, board-ready CISO report (OWASP / SOC2 / CIS v8 / 30-60-90), and a CTO-readable executive summary. Mutation testing and chaos / fuzz pass are also available via the GitHub Action (mutation: true / chaos: true) — they need a CI runner to execute your test suite and a headless browser, so they ship with the Action rather than the website-only scan. |
| Continuous | $49/mo | Scan every push via the GitHub App. Unlimited deterministic push scans plus a monthly AI-review allowance. Fix PRs are a per-scan upsell. |
| MCP | $29/mo | The hosted remote MCP endpoint — use GateTest from web/mobile AI clients or locked-down machines, plus hosted scan history (gtmcp_ key delivered by email after checkout). The local MCP server (npx @gatetest/mcp-server) is 100% free — every tool runs on your machine with your keys. |
Live prices and Stripe checkout at gatetest.io.
GateTest is not magic. The things it does not yet do, said out loud:
liveCrawler, runtimeErrors, explorer, chaos) do not run inside the hosted web request. The hosted URL scan runs its static probes inline and hands the headless runtime pass to the platform worker tier, best effort — if that dispatch fails the report says so and the rest of the scan continues. Full power requires the CLI, the GitHub Action, or local dev.The full Known Issues table (with severity and status) lives in CLAUDE.md — that file is the project's source of truth.
Static engine. 121 modules, every one extending BaseModule. Each module is a self-contained scanner that emits checks at three severity levels (error blocks the gate, warning reports, info is informational). The runner is EventEmitter-based, supports parallel execution, diff-mode (--diff scans only git-changed files), watch mode, and five output formats (Console, JSON, HTML, SARIF for the GitHub Security tab, JUnit XML for any CI). The gate has four small runtime dependencies (acorn, pngjs, pixelmatch, and the MCP SDK) — node bin/gatetest.js --list runs anywhere Node 20+ runs.
Website and payments. gatetest.io is Next.js 16 with the App Router, Tailwind 4, and Stripe in per-scan upfront-charge mode. One-time payment per scan at checkout — no subscription, no auto-renew, no hold-then-capture flow. All scan state is persisted in Stripe metadata so the request handlers stay stateless across requests — there is no shared in-memory state and no webhook is required for the critical user flow. The scan executes inside the request and reports back directly.
AI layer. On the GitHub Action the customer brings their own ANTHROPIC_API_KEY and pays the provider directly. On the website the key is managed and the cost is folded into the tier price. Every AI success is distilled into a recipe by the flywheel orchestrator (see lib/ and the AI CI-fixer at scripts/ai-ci-fixer.js) so subsequent runs on the same pattern are deterministic and free.
The codebase ships under MIT, the gate runs locally with no external calls, and every architectural decision is documented inline in CLAUDE.md.
GateTest is dogfooded against itself on every push, and the team runs the full Forensic pipeline against external production codebases before shipping changes that touch the deeper tiers. The reports below are reproducible artifacts in this repo:
src/runtime/alerts.js, 8.5 seconds wall time, syntax gate green: docs/proofs/phase-1-self-fix-real.mdThe Bible — CLAUDE.md — is required reading for contributors. It defines the architecture, the quality bar, the forbidden list, the protected platforms, and the authorization rules that apply to anything touching money, user data, or public-facing communication.
Bug reports and feature requests are welcome via GitHub Issues. Small PRs that fix one thing and add a test are merged fastest. The pre-commit and pre-push hooks under src/hooks/ run the gate locally — running them before pushing keeps CI green.
MIT — see LICENSE.