Skip to content

How-to: gate AI-generated code (Claude / Cursor / Copilot)

Prerequisites

  • A running Meridian instance (Docker Compose)
  • An AI coding tool (Claude Code, Cursor, GitHub Copilot, etc.)
  • CRA_API_TOKEN if auth is enabled

What you'll have after

A loop where AI-generated diffs are checked by Meridian before they reach your remote, with the agent fixing what gets blocked.

The core idea

AI assistants produce volume. The win is to put Meridian as close to the agent as possible so blocks become immediate feedback the agent can act on, not a surprise at push time.

flowchart LR
    A[AI generates change] --> B[Submit staged diff to Meridian]
    B --> C{RFC}
    C -->|BLOCKED| D[Feed findings back to the agent]
    D --> A
    C -->|APPROVED| E[Commit & push]

Step 1 — A pre-commit check script

Add scripts/meridian-check.sh to your repo:

#!/usr/bin/env bash
set -euo pipefail
MERIDIAN_URL="${MERIDIAN_URL:-http://localhost:3011}"
TOKEN="${CRA_API_TOKEN:-}"

DIFF="$(git diff --cached --no-color)"
[ -z "$DIFF" ] && { echo "No staged changes."; exit 0; }
MSG="$(git log -1 --format=%s 2>/dev/null || echo 'wip')"

RESP="$(curl -s -X POST "$MERIDIAN_URL/api/cra/analyze" \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $TOKEN" \
  --data "$(jq -nc --arg m "$MSG" --arg d "$DIFF" \
    '{repo_name:"local",branch:"local",commit_message:$m,diff:$d}')")"

RFC_ID="$(echo "$RESP" | jq -r '.rfc_id')"
STATUS="$(echo "$RESP" | jq -r '.overall_status')"
for _ in $(seq 1 30); do
  [ "$STATUS" = "DRAFT" ] || break; sleep 1
  STATUS="$(curl -s "$MERIDIAN_URL/api/cra/rfc/$RFC_ID" -H "Authorization: Bearer $TOKEN" | jq -r '.overall_status')"
done

if [ "$STATUS" = "APPROVED" ] || [ "$STATUS" = "OVERRIDDEN" ]; then
  echo "Meridian: $STATUS ($RFC_ID)"; exit 0
fi
echo "Meridian: $STATUS ($RFC_ID) — findings:" >&2
echo "$RESP" | jq -r '.gates | to_entries[] | .value.findings[]? | "  [\(.severity)] \(.id): \(.message // "")"' >&2
exit 1

Wire it as a Git pre-commit hook (.git/hooks/pre-commit → call the script) or run it manually.

Step 2 — Make the findings agent-readable

When blocked, the script prints findings like:

Meridian: BLOCKED (rfc_01HZ...) — findings:
  [critical] secret-aws-access-key: Hardcoded AWS access key
  [high] vuln-command-injection: Possible command injection via interpolated child_process call

Paste that straight back to Claude/Cursor: "Meridian blocked this with the following findings, fix them." Agents handle these well because each finding names the exact problem.

Step 3 — Tool-specific notes

Add the check to the agent's task loop or as a pre-commit hook. The agent runs the change, the hook blocks, the agent reads the findings and iterates. This is the highest-leverage setup — the agent self-corrects before anything leaves the machine.

Copilot doesn't run a loop, so rely on the pre-commit hook plus the CI gate. The hook catches it locally; the GitHub Actions gate is the backstop for whatever slips through.

Step 4 — Backstop with a server-side gate

Local hooks can be skipped (git commit --no-verify). Always pair the local loop with a server-side pre-receive or CI gate so a skipped local check still cannot ship.

Troubleshooting

Symptom Likely cause Fix
Hook not running Not executable / wrong path chmod +x .git/hooks/pre-commit
Agent ignores findings Findings not surfaced Print findings to the agent's context as in step 2
Everything blocks Over-broad custom rule Review rules
Slow on every commit Gate 3 latency Use Ollama for local checks; full tiers in CI

Next: Block and override