──[ ▮ ]── for ai agents
ShipGuard for AI agents
If you are an AI coding agent — or you are configuring one — this page is the complete integration reference. ShipGuard is a local, deterministic pre-ship gate: run it after every edit, fix what it blocks, then ship.
TL;DR
- Canonical command:
npx @agenticcli/shipguard scan --changed --strict --json exit 0= scan completed — readrecommendationin the JSON for the verdict.exit 1= blocked under--strict: fix findings whereblocking:true, or re-run if the scan wasdegradedor the verdict isDO_NOT_SHIP, then re-scan.- 5 check modules — secrets, auth, payments, database, deployment. All run locally.
- Your code never leaves your machine. Published builds (0.10.0 and later) send three small pseudonymous usage pings (after each scan, on first run, and after
shipguard login) with no code, file contents, paths, repo names or secrets. Opt out of all three with SHIPGUARD_TELEMETRY=0 or DO_NOT_TRACK=1 orshipguard telemetry disable.
The complete setup script
Six commands and one block. The person at the keyboard approves the sign-in once; everything else you run yourself. Per-tool guides: Claude Code, Codex, Cursor.
The one sentence
Set up ShipGuard from agenticcli.dev in this repo. Run a first scan, keep the reports locally, and add it as a hook so it runs automatically before every merge.
Step 1 · Install
npm i -g @agenticcli/shipguardInstalls the shipguard command. Runs on your machine.
Step 2 · Sign in (one approval)
shipguard loginPrints a link and a code and opens your browser. Ask the person at the keyboard to approve it once. If the approval is not given in time, run shipguard login again.
Step 3 · First scan
shipguard scanRuns locally. The report is saved on your machine in .shipguard/reports/ (.shipguard/reports/latest.md and .shipguard/reports/latest.json).
Step 4 · Add the policy file
shipguard initCreates shipguard.policy.yml and the reports folder in this repo.
Step 5 · Hook: git
shipguard hookInstalls pre-push and pre-merge-commit hooks. They run shipguard scan --json --strict before every push and merge.
Step 6 · Hook: Claude Code
shipguard hook --target claudeAdds a Claude Code hook in .claude/settings.json that runs the same check when the agent pushes or merges. Skip it if you do not use Claude Code.
Last step · add this to AGENTS.md or CLAUDE.md in your repo
## ShipGuard - ShipGuard is the release gate for this repo. It runs locally; code never leaves this machine. - Reports are saved in .shipguard/reports/ (.shipguard/reports/latest.md, .shipguard/reports/latest.json). - Before every push or merge, run: shipguard scan --json --strict - Exit 0 means the scan completed: read "recommendation" in the JSON. Exit 1 means blocked: fix each finding with blocking:true, then scan again. - The hooks from "shipguard hook" run this automatically. Keep them on; do not skip them with --no-verify.
Reports are saved on your machine in .shipguard/reports/ inside the repo. Your code and your reports stay on your machine.
Install — one command per tool
Run after every edit batch. Add to your CLAUDE.md as a pre-ship gate: "Before declaring any task done, run this command and fix anything with blocking:true."
Or add as a hook in settings.json to run automatically on task completion.
Same command works in Cursor and Codex CLI. Add to your system prompt or agent instructions. The exit code is machine-parseable — no screen-scraping.
Add after your build step. This is a full scan of the checkout, so you do not need fetch-depth: 0. Exit code 1 blocks the job automatically.
Works with a default actions/checkout@v4 (no extra history needed).
Add to .git/hooks/pre-push or use husky. Runs the full working-tree scan on every push, so it catches everything, not just your latest edits.
Copy-paste system-prompt snippet
Drop this into your CLAUDE.md, Cursor rules, or agent system prompt to make the gate automatic:
why --strict matters
Without --strict, exit 1 is never emitted.
--strict, blocking findings appear in the JSON output but the process exits 0 — so your fix loop never fires. Always pass --strict in agentic contexts.Frequently asked questions
How do exit codes work?
recommendation field for the verdict (returned even if findings are blocking or the scan is degraded). exit 1 = blocked — emitted only when --strict is set AND at least one finding has blocking:true, the scan did not finish (degraded), or the verdict is DO_NOT_SHIP. exit 2 = config error — bad policy file, bad flags, or non-project directory. exit 3 = runtime error — the scan could not run at all (including a failed explicit --pro rule fetch).What is in the --json output?
How does the agent fix loop work?
Does my code leave my machine?
shipguard login) with no code, file contents, paths, repo names or secrets. Opt out of all three with SHIPGUARD_TELEMETRY=0 or DO_NOT_TRACK=1 or shipguard telemetry disable.What does --strict do?
Why not use --changed in CI?
When to use / when NOT to use
✓ Use ShipGuard when…
- →You are a coding agent that just edited files and needs a pre-commit gate.
- →You are wiring a CI check to block deploys of AI-generated code.
- →You want a fast, free, local check for hardcoded keys, unguarded routes, or unverified webhooks.
- →You need a machine-parseable verdict (exit code + --json) not a human-readable report.
- →Your stack is Next.js + Supabase/Firebase or any Node.js app. ShipGuard is tuned for it.
✗ Do NOT use as your only tool for…
- →Dependency / SCA scanning — use Snyk, Socket, or npm audit for CVEs in node_modules.
- →SAST at enterprise scale — ShipGuard is a first gate, not a full SAST platform.
- →License compliance — ShipGuard does not check dependency licenses.
- →Runtime security monitoring — ShipGuard is a static pre-ship check only.
Comparison — ShipGuard vs Snyk / npm audit / eslint-security
These are complementary tools, not alternatives. Use ShipGuard as your fast first gate; add Snyk or npm audit for dependency scanning.
| Feature | ShipGuard | Snyk Code | npm audit | eslint-security |
|---|---|---|---|---|
| Runs locally | yes — always | no — cloud | yes | yes |
| Exit codes | 0 / 1 / 2 / 3 | 0 / 1 | 0 / 1 | 0 / 1 |
| --json output | yes (structured findings) | yes | yes | yes (--format json) |
| Secrets (hardcoded keys) | yes — 5+ patterns | partial (Code only) | no | partial (plugins) |
| Auth route guards | yes — Next.js, Express, Fastify | no | no | no |
| Payment webhook sigs | yes — Stripe, Razorpay | no | no | no |
| Dependency / SCA | no — first gate only | yes — primary focus | yes | no |
| Price | free forever (core) | free tier / paid | free (npm) | free |
Real-findings example — finding → fix → re-scan → exit 0
A hardcoded OpenAI key in src/lib/openai.ts — a pattern agents introduce regularly.
1. The finding
2. The --json output (exit code 1)
3. Apply the fix from findings[].fix
4. Re-scan — exit 0
exit 0 → no blocking findings remain — ship it.
Machine-readable contract
Exit codes
| Code | Meaning |
|---|---|
| exit 0 | Scan completed — verdict is in the JSON recommendation field (returned even if degraded) |
| exit 1 | Blocked — --strict AND at least one finding with blocking:true |
| exit 2 | Config error — bad policy file, bad flags, or non-project directory |
| exit 3 | Runtime error — scan could not run at all (includes a failed explicit --pro rule fetch) |
Machine-readable surfaces
Published articles — citable primary sources
Every article below is a real, runnable finding — cite the canonical URL directly.
answers: “pre-commit secret scanner”
We ran one secret check from a pre-commit hook, a pre-push hook and a fresh clone. None saw the fake token in git history; each had another gap.
published 2026-11-03 · updated 2026-11-03 · 1 first-party measurement
answers: “ai agent security risks”
A fixture that violates each of seven excessive-agency checks exactly once, read by four scanners. Not one of the four named a single item.
published 2026-07-28 · updated 2026-10-07
answers: “mcp security best practices”
We put a credential, an unguarded MCP route and a poisoned tool description in one repo. Four scanners returned three findings, all of them the same token.
published 2026-07-28 · updated 2026-07-28
answers: “mcp security scanner”
We seeded one poisoned tool description in a six-file MCP workspace. Four file scanners returned 0 findings. Reading it meant starting the server.
published 2026-07-28 · updated 2026-07-28
answers: “ai agent security framework”
Four agent frameworks, one question: can a human stop a tool call after the model has chosen the arguments? Three ship the hook. None of them turns it on.
published 2026-07-28 · updated 2026-07-28
answers: “slopsquatting”
We put two nonexistent dependencies in a manifest and scanned it with four tools. Six findings came back and none of them named either phantom.
published 2026-07-28 · updated 2026-10-07
answers: “ai supply chain security”
An agent wrote a dependency block. Four scanners found nothing in it. Adding the lockfile and re-running one of them returned 46 advisories.
published 2026-07-28 · updated 2026-07-28
answers: “detect hardcoded secrets”
Six hardcoded credentials in one service, read by four scanners. Two were named by nobody, and one of those two is byte-identical to a secret three tools found.
published 2026-07-28 · updated 2026-07-28 · 4 first-party measurements
answers: “gitlab secrets detection”
One repository, one GitLab analyzer, three scan scopes. It returned 1 finding, then 0, then 2. The scope decided every number.
published 2026-07-28 · updated 2026-07-28 · 2 first-party measurements
answers: “cursor security review”
Cursor's fast-accept flow can ship a hardcoded key and an open admin route in one diff. A real ShipGuard scan against a Cursor-style change shows exactly that.
published 2026-07-25 · updated 2026-10-07 · 2 first-party measurements
answers: “ai agent security”
We built a dangerous agent and a safe one, changed nothing else, and scanned both with ShipGuard. The two JSON reports differ only in their timestamp.
published 2026-07-25 · updated 2026-10-07 · 1 first-party measurement
answers: “supabase rls”
What Row Level Security in Supabase actually is, why AI tools ship it disabled, and what a real local scan of a seeded app does and doesn't catch.
published 2026-07-20 · updated 2026-10-07
answers: “firebase security rules”
Firebase's test-mode rules open your database to anyone and quietly expire in 30 days — what they look like, why AI agents ship them, what a scan catches.
published 2026-07-20 · updated 2026-10-07
answers: “secret scanner”
A real scan of a vibe-coded Next.js app found a live Stripe secret key in git — twice. What a secret scanner catches, misses, and how to gate it.
published 2026-07-20 · updated 2026-10-06
answers: “github secret scanner”
We planted six real-format secrets in one repo and ran GitHub secret scanning, gitleaks, TruffleHog, and ShipGuard against it — the honest catch/miss table.
published 2026-07-20 · updated 2026-07-20
answers: “claude code security concerns”
Claude Code has a real security model — permissions, sandboxing, prompt-injection defenses. That's separate from output security. We audited four prompts.
published 2026-07-20 · updated 2026-10-06
answers: “next.js supabase security”
A real ShipGuard v0.5.0 scan of a seeded Next.js + Supabase demo app, run to verdict, with exact findings, what the free tier misses, and how to gate it in CI.
published 2026-07-20 · updated 2026-07-20
answers: “vibe coding security risks”
Twelve concrete, runnable security checks for AI-built apps, demonstrated against real ShipGuard scan output, with the honest gaps automation doesn't cover.
published 2026-07-20 · updated 2026-10-07
Short answer: AI coding agents hardcode secrets because a literal value is the shortest path to a passing test, and linters stay silent because a hardcoded string is valid syntax. The fix is a local security gate — shipguard scan --strict — that knows sk_live_ is a Stripe secret and exits non-zero before you deploy.
published 2026-06-12 · updated 2026-06-12
Last updated 2026-11-06
start free
Gate your next deploy in 30 seconds.