engineering· May 5, 2026· 6 min read

How to CI-Validate Your CLAUDE.md Across Every Repo

CLAUDE.md drifts silently across repos. A 30-line bash CI check catches it before policy gets quietly deleted.

How to CI-Validate Your CLAUDE.md Across Every Repo

If your team uses Claude Code, Cursor, or another AI assistant that reads a CLAUDE.md (or .cursorrules, AGENTS.md, .github/copilot-instructions.md), you've probably noticed the file drifts.

One repo has it pristine. Another deletes the security section to fit an unrelated change. A third has it but with a typo that's quietly been wrong for months. New repos copy from whichever sibling repo someone happened to clone first, propagating the inconsistency.

The fix is the same as for any other team-wide standard: a CI check.

Why drift is inevitable without enforcement

CLAUDE.md files are unusual in a few ways:

Side-by-side diff showing two repos' CLAUDE.md files with subtle drift

Drift is rarely a deletion. It's the section that quietly disappeared during an unrelated change two months ago.

  • They're read by tools, not by humans (mostly), so the immediate consequences of breaking them are invisible.
  • They're not "code" in the traditional sense, so reviewers skim them.
  • They're not "docs" in the traditional sense, so doc-style review processes don't apply.
  • They're often template-like, so people delete sections they don't understand.

Combine those four properties and you get the perfect storm for silent drift.

What's worth enforcing

Not everything in a CLAUDE.md should be team-wide standardised. Some sections are repo-specific (architecture, testing commands). Others should be team-wide:

  • Security policy ("never commit secrets, never disable auth in tests")
  • License/copyright handling
  • Branch naming and PR rules
  • Forbidden actions (force-push to main, --no-verify, etc.)
  • The list of approved AI agents and their authorisation level
  • Privacy / data-handling policies (especially for regulated industries)

A reasonable rule: anything that's a cross-repo policy should be enforceable; anything that's repo-specific shouldn't be.

The minimal CI check

Below is a pattern that works. It can be a GitHub Action, a pre-commit hook, or a Make target — the mechanism doesn't matter.

CI pipeline diagram for validating CLAUDE.md: parse, required-sections check, schema-style lint, fail or pass

Each stage catches a different failure mode. Parse fails on broken markdown; sections fails on deletions; lint fails on subtle drift.

#!/usr/bin/env bash
# .github/scripts/validate-claude-md.sh
set -euo pipefail

CLAUDE_MD="${1:-CLAUDE.md}"

if [ ! -f "$CLAUDE_MD" ]; then
  echo "FAIL: $CLAUDE_MD not found"
  exit 1
fi

required_sections=(
  "## Security policy"
  "## Branch & PR rules"
  "## Forbidden actions"
  "## Authorised agents"
)

required_phrases=(
  "Never commit secrets"
  "No --no-verify"
  "No force-push to main"
)

fail=0

for section in "${required_sections[@]}"; do
  if ! grep -qF "$section" "$CLAUDE_MD"; then
    echo "FAIL: missing section: $section"
    fail=1
  fi
done

for phrase in "${required_phrases[@]}"; do
  if ! grep -qF "$phrase" "$CLAUDE_MD"; then
    echo "FAIL: missing required phrase: $phrase"
    fail=1
  fi
done

[ $fail -eq 0 ] && echo "OK: $CLAUDE_MD has all required sections and phrases" || exit 1

Wire this into a GitHub Action that runs on every PR:

# .github/workflows/validate-claude-md.yml
name: validate-claude-md
on: [pull_request, push]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: bash .github/scripts/validate-claude-md.sh CLAUDE.md

For pre-commit, drop a hook into .pre-commit-config.yaml that runs the same script.

Going further: structured CLAUDE.md

For teams managing 10+ repos, the bash check breaks down because the required sections evolve and you don't want to push a script update to every repo.

Better pattern: keep the required parts in a separate version-controlled file in a central repo (your DevOps or platform repo), and have the CI script fetch and compare:

#!/usr/bin/env bash
# .github/scripts/validate-claude-md.sh
set -euo pipefail

CLAUDE_MD="${1:-CLAUDE.md}"
RULES_URL="https://raw.githubusercontent.com/yourorg/policies/main/claude-md/required-sections.txt"

required=$(curl -fsSL "$RULES_URL")

while IFS= read -r line; do
  [ -z "$line" ] && continue
  if ! grep -qF "$line" "$CLAUDE_MD"; then
    echo "FAIL: missing required entry: $line"
    exit 1
  fi
done <<< "$required"

echo "OK: $CLAUDE_MD passes central policy v$(curl -fsSL https://raw.githubusercontent.com/yourorg/policies/main/claude-md/version.txt)"

Now updating the policy is a single PR in the central repo. All other repos pick it up on their next CI run.

The alternative: precommit-style auto-fix

Some teams prefer auto-fixing to validation. A script that appends missing required sections rather than failing the build.

That works for straightforward sections like "Forbidden actions" — the boilerplate is the same everywhere. It doesn't work for sections that need repo-specific content (like architecture or testing notes).

For most teams, fail-on-missing is the right default. Auto-fix is a polish for non-policy boilerplate later.

What to put in the central required list

Be conservative. Every entry in the required list is a forcing function on every repo. Two rules:

  1. Only add things that are wrong if missing. If a repo is functional without the section, it shouldn't be required.
  2. Only add things you'll actually enforce. If you're not going to read the FAILs and act on them, dropping the requirement is more honest.

A starter list of high-leverage requirements:

  • ## Security policy
  • ## Forbidden actions containing at least: "Never commit secrets", "No --no-verify", "No force-push to main"
  • ## Branch & PR rules
  • ## Authorised AI agents (list of allowed tools and any per-tool guardrails)

That's enough to catch real drift without becoming a paperwork burden.

Why this matters more for AI assistants than for humans

Humans skim a CLAUDE.md. They might miss a section. AI assistants read it cover-to-cover and treat every line as authoritative.

If the security section is missing, an assistant won't know to refuse a "commit this with my AWS credentials embedded" request. If "no --no-verify" is missing, the assistant will gladly bypass pre-commit hooks when something fails.

The CI check isn't about formatting consistency. It's about ensuring the AI tools your team uses have the same policy across every repo, regardless of who set up the repo or when.

A 30-line bash script in a CI workflow is the cheapest team-wide AI policy enforcement you can buy.

claude-mdcipolicy-driftteam-workflow