AgenticCLI

──[ ▮ ]── 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 — read recommendation in the JSON for the verdict. exit 1 = blocked under --strict: fix findings where blocking:true, or re-run if the scan was degraded or the verdict is DO_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 or shipguard telemetry disable.
$npx @agenticcli/shipguard scan --changed --strict --json
full docs →

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.
Copy sentence
  1. Step 1 · Install

    npm i -g @agenticcli/shipguard

    Installs the shipguard command. Runs on your machine.

  2. Step 2 · Sign in (one approval)

    shipguard login

    Prints 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.

  3. Step 3 · First scan

    shipguard scan

    Runs locally. The report is saved on your machine in .shipguard/reports/ (.shipguard/reports/latest.md and .shipguard/reports/latest.json).

  4. Step 4 · Add the policy file

    shipguard init

    Creates shipguard.policy.yml and the reports folder in this repo.

  5. Step 5 · Hook: git

    shipguard hook

    Installs pre-push and pre-merge-commit hooks. They run shipguard scan --json --strict before every push and merge.

  6. Step 6 · Hook: Claude Code

    shipguard hook --target claude

    Adds 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.
Copy block

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


Claude Code
$npx @agenticcli/shipguard scan --changed --strict --json

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.

Cursor / Codex CLI
$npx @agenticcli/shipguard scan --changed --strict --json

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.

GitHub Actions
$- name: ShipGuard gate run: npx @agenticcli/shipguard scan --strict --json

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).

Pre-push hook
$npx @agenticcli/shipguard scan --strict --json

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:

system-prompt snippet — copy this
Before declaring any task done, run: npx @agenticcli/shipguard scan --changed --strict --json If exit code is 1, read findings[].fix for each item where blocking:true, apply the fix, and re-scan until exit 0.
Copy snippet

why --strict matters

Without --strict, exit 1 is never emitted.

If you omit --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?
exit 0 = scan completed — read the JSON 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?
A JSON object with: findings[] (array of findings, may be empty), riskScore (object with score 0–100, recommendation, totalFindings, criticalCount, highCount, mediumCount, lowCount, infoCount, blockingCount), filesScanned (number), timestamp (ISO 8601), policyUsed (string), recommendation ("SAFE_TO_SHIP"|"REVIEW_BEFORE_SHIP"|"DO_NOT_SHIP"), and schemaVersion. Each finding has: id (rule identifier), title, severity, category, file, line, explanation (why it is a risk), recommendation (how to fix), blocking (boolean), and optional fix (code snippet).
How does the agent fix loop work?
Run scan --changed --strict --json. Parse JSON. For each finding where blocking:true, read fix, apply it. Re-scan. Repeat until exit 0, then commit and deploy.
Does my code leave my machine?
Never. Every scan runs locally in your terminal. No code, file contents, or paths are transmitted to any server. Pro rules are loaded into memory for the duration of the scan and discarded after. 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 or shipguard telemetry disable.
What does --strict do?
--strict is required for exit 1 to be emitted. Without it, blocking findings are reported in the output but the process exits 0, which means the fix loop never triggers. Always pass --strict in agentic CI contexts.
Why not use --changed in CI?
--changed limits the scan to the files that differ from your last git commit in the working tree (staged, unstaged and untracked). It is for local runs, pre-commit hooks and agent loops. It never compares against a base branch, so on a fresh CI checkout it finds nothing to scan. In CI, omit --changed and run a full scan: scan --strict.

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.

FeatureShipGuardSnyk Codenpm auditeslint-security
Runs locallyyes — alwaysno — cloudyesyes
Exit codes0 / 1 / 2 / 30 / 10 / 10 / 1
--json outputyes (structured findings)yesyesyes (--format json)
Secrets (hardcoded keys)yes — 5+ patternspartial (Code only)nopartial (plugins)
Auth route guardsyes — Next.js, Express, Fastifynonono
Payment webhook sigsyes — Stripe, Razorpaynonono
Dependency / SCAno — first gate onlyyes — primary focusyesno
Pricefree forever (core)free tier / paidfree (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

- const client = new OpenAI({ apiKey: "sk-proj-abc123def456…" }) // ↑ ShipGuard: id=hardcoded_secret · critical · blocking:true

2. The --json output (exit code 1)

$ npx @agenticcli/shipguard scan --changed --strict --json
{ "findings": [ { "id": "hardcoded_secret", "title": "Hardcoded OpenAI API Key", "severity": "critical", "category": "secrets", "file": "src/lib/openai.ts", "line": 4, "explanation": "A hardcoded API key (\"sk-proj-…\") will be committed to source control and exposed to anyone with repo access.", "recommendation": "Use process.env.OPENAI_API_KEY and ensure the key is set in .env.local (git-ignored).", "blocking": true, "fix": "const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })" } ], "riskScore": { "score": 82, "recommendation": "DO_NOT_SHIP", "totalFindings": 1, "criticalCount": 1, "highCount": 0, "mediumCount": 0, "lowCount": 0, "infoCount": 0, "blockingCount": 1 }, "filesScanned": 14, "timestamp": "2026-06-26T10:42:00.000Z", "policyUsed": "default", "recommendation": "DO_NOT_SHIP", "schemaVersion": "6", "runId": "3f0c9a52-7d1e-4b86-9a3c-5e2b8d14f6a0", "treeDigest": "9b1e4c7a2f60d83a5c19e7b04d2f8a6c3e51b9d7a0f4c28e6b35d1a97c40e8f2", "cliVersion": "0.10.0" }

3. Apply the fix from findings[].fix

- const client = new OpenAI({ apiKey: "sk-proj-abc123def456…" })+ const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }) // ensure OPENAI_API_KEY is set in .env.local (never committed)

4. Re-scan — exit 0

$ npx @agenticcli/shipguard scan --changed --strict --json
{ "findings": [], "riskScore": { "score": 0, "recommendation": "SAFE_TO_SHIP", "totalFindings": 0, "criticalCount": 0, "highCount": 0, "mediumCount": 0, "lowCount": 0, "infoCount": 0, "blockingCount": 0 }, "filesScanned": 14, "timestamp": "2026-06-26T10:42:31.000Z", "policyUsed": "default", "recommendation": "SAFE_TO_SHIP", "schemaVersion": "6", "runId": "a71d2e90-4c3b-4f58-8e6d-0b9c1a7f3d25", "treeDigest": "c4a8f1e6b03d7295e1a6c84b0f3d97a25e6c1b8d40a7f39e2c5b6d18a4e07f93", "cliVersion": "0.10.0" }

exit 0 → no blocking findings remain — ship it.

Machine-readable contract


Exit codes

CodeMeaning
exit 0Scan completed — verdict is in the JSON recommendation field (returned even if degraded)
exit 1Blocked — --strict AND at least one finding with blocking:true
exit 2Config error — bad policy file, bad flags, or non-project directory
exit 3Runtime 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.

secret-api-key-leaks
Pre-Commit Secret Scanner vs CI: What Each Place Missed

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

agentic-agent-security
AI Agent Security Risks: 7 Checks No Scanner Answers

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

mcp-security
MCP Security Best Practices: What 4 Scanners Miss

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

mcp-security
MCP Security Scanner: Four Found Nothing, One Read It

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

agentic-agent-security
Vetting an AI Agent Framework: We Probed 4 SDKs

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

ai-supply-chain-slopsquatting
Slopsquatting: Four Scanners, Two Phantom Dependencies

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

ai-supply-chain-slopsquatting
AI Supply Chain Security: 0 Advisories, Then 46

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

secret-api-key-leaks
Detect Hardcoded Secrets: 6 Shapes, 4 Scanners

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

secret-api-key-leaks
GitLab Secret Detection: 1 Finding, Then 0, Then 2

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

security-harness-ai-tools
Is Cursor's AI Output Secure? We Scanned a Seeded Diff

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

agentic-agent-security
AI Agent Security: Two Agents, One Identical Scan

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

supabase-firebase-security
Supabase RLS: The Security Check Every AI-Built App Skips

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

supabase-firebase-security
Firebase Security Rules: The Test-Mode Trap That Exposes Your Database

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

secret-api-key-leaks
What a Real Secret Scan Found in a Vibe-Coded App

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

secret-api-key-leaks
GitHub Secret Scanner vs CLI Tools: gitleaks, TruffleHog, and ShipGuard Compared

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

security-harness-ai-tools
Is Claude Code's Output Secure? I Audited What It Generates

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

secret-api-key-leaks
Secret Scanner for Next.js + Supabase Apps: Scan Before You Deploy

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

vibe-security
Vibe Coding Security: 12 Checks Before You Ship

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

Claude Code hardcoded a Stripe key. Here's how it happens.

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

▮freshness

Last updated 2026-11-06

▮

start free

Gate your next deploy in 30 seconds.

Free, unlimited, local. Code never leaves your machine. No account needed. Pseudonymous usage pings, opt-out.
npx @agenticcli/shipguard scan
▮ shipguardfor-ai-agentsexit 0 → ship itby AgenticCLI · agenticcli.dev