CM

cm-identity-guard

A mandatory check to ensure the correct GitHub or cloud account is active before pushing code.

Install

mkdir -p .claude/skills/cm-identity-guard && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18669" && unzip -o skill.zip -d .claude/skills/cm-identity-guard && rm skill.zip

Installs to .claude/skills/cm-identity-guard

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Verify and lock project identity before ANY git push, Cloudflare deploy, or Supabase operation. Essential when working with multiple GitHub accounts (personal + work), multiple Cloudflare accounts, or multiple Supabase/Neon projects. Prevents wrong-account deploys, cross-project secret leaks, and git history contamination.
324 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Beginner

Key capabilities

  • Verify GitHub account identity
  • Verify Cloudflare account identity
  • Verify Supabase project identity
  • Prevent wrong-account deploys
  • Prevent cross-project secret leaks

How it works

The skill enforces an identity verification step before critical operations by checking current GitHub, Cloudflare, and Supabase configurations against expected values defined in a `.project-identity.json` file.

Inputs & outputs

You give it
A project with a `.project-identity.json` file
You get back
Verification status of GitHub, Cloudflare, and Supabase identities, or instructions to fix wrong identities

When to use cm-identity-guard

  • Checking git identity
  • Verifying cloud deployment target
  • Ensuring safe git pushes

About this skill

Identity Guard — Multi-Account Safety Protocol

TL;DR

  • Use before any git push, Cloudflare deploy, or Supabase op
  • Verifies: GitHub account, CF account, Supabase project match expected
  • Prevents: wrong-account deploys, cross-project secret leaks

Overview

Working across multiple projects, clients, and platforms means one wrong git push or wrangler deploy can publish work to the wrong account. This skill establishes a mandatory identity check before any operation that touches external services.

[!CAUTION] Real incidents this skill prevents:

  • Pushed client code to personal GitHub repo
  • Deployed to wrong Cloudflare account (different org's Pages project, billing confusion)
  • Used personal Supabase ANON_KEY in a client project (wrong DB entirely)
  • git config user.email was personal email → commits show wrong author in client repo

The Iron Law

NEVER push, deploy, or use secrets WITHOUT verifying identity first.
ASK: Which account? Which project? Which database?
ONE command verifies all three. Run it. Always.

When to Use

ALWAYS before:

  • git push or git commit in a project with multiple account contexts
  • wrangler pages deploy or any Cloudflare operation
  • Creating or accessing a Supabase/Neon client
  • Setting up a new project from scratch
  • Resuming work after switching between personal and work projects

Account Registry (Your Known Accounts)

Maintain this table in your head (or in .project-identity.json):

GitHub Accounts

AccountPurposeEmailWhen to Use
my-personalPersonal projects, experimentspersonal emailPersonal repos, side projects
my-work-orgClient work[email protected]All client projects

Cloudflare Accounts

Account IDPurposeProjects
abc123def456ghi789jkl012mno345pqrClient A / Orgproject-1, project-2, app
(personal)Personal experimentspersonal side projects

Database Accounts

ServiceAccountPurpose
Supabase (Org)org accountAll Client A apps
Supabase (personal)personal accountExperiments
Neonper projectIf used

Phase 0: Project Identity File

Every project MUST have a .project-identity.json in the project root:

{
  "name": "my-awesome-project",
  "description": "An awesome internal tool",
  "github": {
    "account": "my-work-org",
    "org": "my-work-org",
    "repo": "my_project_repo",
    "remoteUrl": "https://github.com/my-work-org/my_project_repo.git",
    "userEmail": "[email protected]"
  },
  "cloudflare": {
    "accountId": "abc123def456ghi789jkl012mno345pqr",
    "projectName": "my-frontend-app",
    "stagingUrl": "https://my-app-staging.pages.dev",
    "productionUrl": "https://myapp.workdomain.com",
    "productionBranch": "production"
  },
  "database": {
    "provider": "supabase",
    "projectName": "my-database-project",
    "urlVar": "SUPABASE_URL",
    "anonKeyVar": "SUPABASE_ANON_KEY",
    "serviceKeyVar": "SUPABASE_SERVICE_KEY",
    "secretsStore": "cloudflare-secrets"
  },
  "i18n": {
    "primary": "vi",
    "languages": ["vi", "en", "th", "ph"],
    "dir": "public/static/i18n"
  }
}

[!IMPORTANT] Add .project-identity.json to git but NEVER put actual secrets in it — only variable NAMES and account IDs. Secrets live in .dev.vars (local) or Cloudflare Secrets (production).


Phase 1: Identity Verification

The One-Liner Check

Run this before any push or deploy:

# Full identity check — GitHub + Git user + CF account + DB config
echo "=== GitHub CLI ===" && gh auth status 2>&1 | grep -E "Logged in|github.com" && \
echo "=== Git Remote ===" && git remote get-url origin && \
echo "=== Git User ===" && git config user.name && git config user.email && \
echo "=== Cloudflare ===" && cat wrangler.jsonc | grep -E "account_id|project|name" | head -5 && \
echo "=== DB Config ===" && cat .dev.vars 2>/dev/null | grep -E "URL|SUPABASE" | sed 's/=.*/=***/' && \
echo "=== Expected ===" && cat .project-identity.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('GitHub:', d['github']['account'], '| CF:', d['cloudflare']['accountId'][:8]+'...', '| DB:', d['database']['provider'])"

What to Verify (Checklist)

☐ GitHub CLI: logged in as <EXPECTED ACCOUNT>
☐ git remote origin: points to <EXPECTED REPO URL>
☐ git config user.email: matches <EXPECTED EMAIL>
☐ wrangler.jsonc: account_id matches <EXPECTED CF ACCOUNT ID>
☐ .dev.vars: SUPABASE_URL points to <EXPECTED SUPABASE PROJECT>

Phase 2: Fix Wrong Identity

Wrong GitHub Account

# Check current
gh auth status

# Switch to work account
gh auth logout
gh auth login
# → Login with web browser → select my-work-org

# Fix git user for THIS repo (not global)
git config user.name "my-work-org"
git config user.email "[email protected]"

# Fix remote URL
git remote set-url origin https://github.com/my-work-org/REPO_NAME.git

Wrong Cloudflare Account

# Check current CF account
wrangler whoami

# Look for account_id in wrangler.jsonc
grep account_id wrangler.jsonc

# Expected for Your Project: abc123def456ghi789jkl012mno345pqr
# Fix: update account_id in wrangler.jsonc

Wrong Supabase Project

# Check which Supabase URL is in .dev.vars
grep SUPABASE_URL .dev.vars

# The URL pattern reveals the project: https://<PROJECT_ID>.supabase.co
# Compare with the project in .project-identity.json

# Fix: update .dev.vars with correct values
# Then restart wrangler dev

Wrong git author on recent commits

# See who authored the last few commits
git log --format="%h %an <%ae>" -5

# If wrong — amend last commit's author (before push only!)
git commit --amend --author="my-work-org <[email protected]>" --no-edit

# For multiple commits: rebase and re-author
git rebase -i HEAD~N  # Then for each commit: edit → amend author → continue

Phase 3: Project Setup (New Projects)

When starting a new project, answer these questions FIRST:

Before writing any code or creating any repo, I need to lock identity:

1. **GitHub account**: Personal (my-personal) or Work (my-work-org)?
2. **Cloudflare account**: Which account ID?
3. **Database**: Which Supabase org? New project or existing?
4. **Languages**: Single locale or multi-language from day 1?
   → If multi-language: list all target languages now

Then create .project-identity.json BEFORE the first commit:

# Lock git identity to this project immediately
git config user.name "my-work-org"
git config user.email "[email protected]"
git remote set-url origin https://github.com/my-work-org/NEW_REPO.git

# Verify before first push
git config user.email  # Must match expected
git remote get-url origin  # Must match expected
gh auth status  # Must show correct account

Phase 4: Multi-Account Git Setup (OS Level)

Using SSH Keys per Account

# Generate separate keys for each account
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_my_work_org
ssh-keygen -t ed25519 -C "personal@..." -f ~/.ssh/id_personal

# ~/.ssh/config — route by host alias
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_my_work_org

Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_personal

Using SSH, reference by alias in project:

# For work projects:
git remote set-url origin git@github-work:my-work-org/REPO.git

# For personal projects:
git remote set-url origin git@github-personal:my-personal/REPO.git

Global vs Local git config

# Global: personal (default for new repos)
git config --global user.name "my-personal"
git config --global user.email "[email protected]"

# Per-repo override for work projects (run inside each work repo):
git config user.name "my-work-org"
git config user.email "[email protected]"

[!TIP] Use includeIf in ~/.gitconfig to auto-apply work identity for repos in specific directories:

[includeIf "gitdir:~/Builder/ClientA/"]
    path = ~/.gitconfig-work

~/.gitconfig-work:

[user]
    name = my-work-org
    email = [email protected]

Phase 5: Token Lifecycle Management 🔄

NEW — Secrets don't just need to be hidden. They need to be ROTATED. Full rotation playbooks now live in cm-safe-deploy.

Rotation Schedule

PlatformToken TypeMax LifetimeWhere to Rotate
Supabaseanon_key90 daysDashboard → Settings → API
Supabaseservice_role_key30 daysDashboard → Settings → API
CloudflareAPI Token90 daysDashboard → My Profile → API Tokens
GitHubPersonal Access Token90 daysSettings → Developer Settings → PAT
OpenAI/GeminiAPI Key90 daysPlatform dashboard

After Rotation

# 1. Update Cloudflare Secrets with new values
wrangler secret put SUPABASE_ANON_KEY
wrangler secret put SUPABASE_SERVICE_KEY

# 2. Update local .dev.vars
# 3. Redeploy
npm run deploy:staging

# 4. Verify: test staging URL

For emergency rotation (leaked secret), see the emergency rotation guidance in cm-safe-deploy.


Red Flags — Identity Confusion

❌ git push and see "Repository not found" or "Permission denied"
   → Wrong account. Run identity check.

❌ wrangler deploy succeeded but can't find it in your CF dashboard
   → Deployed to wrong CF account. Check wrangler.jsonc account_id.

❌ Authentication fails with correct password
   → `gh auth status` shows wrong account. Logout and login to correct one.

❌ Production app shows the wrong data / can't connect to DB
   → Wrong SUPABASE_URL or key. Check Cloudflare Secrets for the project.

❌ git log shows wrong author email on commits
  

---

*Content truncated.*

When not to use it

  • When the user is not performing a git push, Cloudflare deploy, or Supabase operation
  • When the user is working on a project with only one account context for all services

Limitations

  • Requires a `.project-identity.json` file in the project root
  • Does not prevent all types of security incidents, only identity-related ones
  • Relies on external CLI tools like `gh` and `wrangler` for status checks

How it compares

This skill provides a mandatory, automated identity check across multiple services, preventing accidental deployments or leaks, unlike relying on manual checks or memory.

Compared to similar skills

cm-identity-guard side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
cm-identity-guard (this skill)02moReviewBeginner
release-sidecar15moReviewAdvanced
realmfall-devops02moNo flagsIntermediate
secrets-manager16moCautionBeginner

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry