Skip to main content
hook

vercel-environment-sync — Claude Code hook: sync .env with Vercel

A hook that inspects environment variables after an .env edit and points you to the right Vercel sync commands. Useful when local and deployed values drift apart.

Install into Claude Code · claude-code-templates All methods and platforms ↓
npx claude-code-templates@latest --hook automation/vercel-environment-sync
Open on GitHub

What vercel-environment-sync does

The hook listens on PostToolUse and fires when Claude writes or edits a file whose name contains .env. It first works out the target environment: .env.production maps to production, .env.preview and .env.staging to preview, anything else to development.

Then it walks the file line by line. Entries shaped like VAR=value get a format check, quoted values are flagged, and short secrets (under 16 characters in names containing SECRET, PRIVATE, KEY or TOKEN) or placeholders such as your-, change-me and replace- raise warnings. Any issue makes the hook exit with code 2 and blocks the sync. On a clean file it prints the variable count plus the vercel env pull .env.local and vercel env add [name] [environment] commands.

A token is required: export VERCEL_TOKEN=your_token, issued at vercel.com/account/tokens. Without it the hook does not fail — it just reports that sync is off, which is worth checking if you expected it to run. A second hook on session start verifies the Vercel CLI, whether a project is linked, and lists each .env file with its variable count.

What it helps with

  • catch a short or placeholder secret in .env before it gets committed
  • tell which Vercel environment an edited file belongs to
  • see how many variables each .env file holds at session start
  • get ready-made commands for pulling and adding Vercel env vars
  • check that the Vercel CLI is installed and a project is linked

Example prompts for the agent

  • I edited .env.production, validate the variables and tell me what to do about Vercel
  • add DATABASE_URL to .env.local and sync it with Vercel
  • check whether any placeholders are still sitting in .env instead of real keys

How to install vercel-environment-sync

1claude-code-templates

npx claude-code-templates@latest --hook automation/vercel-environment-sync

2Manually: put the files in place

.claude/settings.json

The hooks block: event (PreToolUse, PostToolUse, Stop…) → command. Personal ones go to ~/.claude/settings.json

Step by step, with commands for each platform: Claude Code hooks: what they are, where to configure them, how to block a risky command

Questions about vercel-environment-sync

How do I install vercel-environment-sync in Claude?

Through the templates CLI: npx claude-code-templates@latest --hook automation/vercel-environment-sync. The hook config lands in .claude/settings.json.

What does vercel-environment-sync do?

It watches .env file changes, validates variable format and placeholder values, detects the Vercel environment, and suggests commands for syncing values.

What does the hook need to run?

A Vercel token in an environment variable: export VERCEL_TOKEN=your_token. The session-start checks also want the Vercel CLI and a project linked to the current directory.

Source text

vercel-environment-sync.json · MIT
{
  "description": "Synchronize environment variables between local development and Vercel deployments, ensuring consistency across all environments. Detects changes to .env files and provides options to sync with Vercel, validates environment variable format, and ensures required variables are present. Setup: Export 'export VERCEL_TOKEN=your_token' (get from vercel.com/account/tokens).",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'input=$(cat); FILE_PATH=$(echo \"$input\" | jq -r \".tool_input.file_path // empty\"); SUCCESS=$(echo \"$input\" | jq -r \".tool_response.success // false\"); if [ \"$SUCCESS\" = \"true\" ] && [[ \"$FILE_PATH\" =~ \\.env ]]; then echo \"🔐 Environment file change detected: $FILE_PATH\"; if [ -n \"$VERCEL_TOKEN\" ]; then echo \"🔄 Environment Sync available - Vercel token configured\"; ENV_TYPE=\"development\"; if [[ \"$FILE_PATH\" =~ \\.env\\.production ]]; then ENV_TYPE=\"production\"; elif [[ \"$FILE_PATH\" =~ \\.env\\.preview ]] || [[ \"$FILE_PATH\" =~ \\.env\\.staging ]]; then ENV_TYPE=\"preview\"; fi; echo \"📋 Environment type detected: $ENV_TYPE\"; if [ -f \"$FILE_PATH\" ]; then echo \"🔍 Validating environment variables in $FILE_PATH...\"; VALIDATION_ISSUES=0; while IFS= read -r line; do if [[ \"$line\" =~ ^[A-Z_][A-Z0-9_]*= ]] && [[ ! \"$line\" =~ ^# ]]; then VAR_NAME=$(echo \"$line\" | cut -d\"=\" -f1); VAR_VALUE=$(echo \"$line\" | cut -d\"=\" -f2-); if [[ \"$VAR_VALUE\" =~ ^[\\\"\\'].*[\\\"\\']$ ]]; then echo \"💡 $VAR_NAME: Quoted value detected (quotes will be included in value)\"; fi; if [[ \"$VAR_NAME\" =~ (SECRET|PRIVATE|KEY|TOKEN) ]] && [ ${#VAR_VALUE} -lt 16 ]; then echo \"⚠️ $VAR_NAME: Secret appears to be too short (${#VAR_VALUE} chars)\" >&2; ((VALIDATION_ISSUES++)); fi; if [[ \"$VAR_VALUE\" == \"your-\"* ]] || [[ \"$VAR_VALUE\" == \"change-me\"* ]] || [[ \"$VAR_VALUE\" == \"replace-\"* ]]; then echo \"❌ $VAR_NAME: Placeholder value detected\" >&2; ((VALIDATION_ISSUES++)); fi; elif [[ \"$line\" =~ ^[A-Za-z] ]] && [[ ! \"$line\" =~ ^# ]] && [ -n \"$line\" ]; then echo \"⚠️ Invalid environment variable format: $line\" >&2; ((VALIDATION_ISSUES++)); fi; done < \"$FILE_PATH\"; if [ $VALIDATION_ISSUES -eq 0 ]; then echo \"✅ Environment validation passed\"; VAR_COUNT=$(grep -c \"^[A-Z_][A-Z0-9_]*=\" \"$FILE_PATH\" 2>/dev/null || echo \"0\"); echo \"📊 Found $VAR_COUNT environment variables\"; echo \"💡 Sync options:\"; echo \"  • Manual sync: vercel env pull .env.local\"; echo \"  • Push to Vercel: vercel env add [name] [environment]\"; echo \"  • Bulk sync: Use vercel-env-sync command if available\"; echo \"🔒 Security reminder: Never commit secrets to version control\"; else echo \"❌ Found $VALIDATION_ISSUES validation issues\" >&2; echo \"🚨 Environment sync blocked due to validation errors\" >&2; exit 2; fi; else echo \"❌ File $FILE_PATH not found\"; fi; else echo \"⚠️ VERCEL_TOKEN not configured. Set environment variable to enable sync features.\"; echo \"💡 Get token from: https://vercel.com/account/tokens\"; echo \"💡 Export with: export VERCEL_TOKEN=your_token\"; fi; else echo \"ℹ️ Environment sync skipped (not an .env file or failed operation)\"; fi'",
            "timeout": 30
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "startup|resume",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'echo \"🔐 Environment Sync Status Check...\"; if [ -n \"$VERCEL_TOKEN\" ]; then echo \"✅ Vercel token configured\"; if command -v vercel >/dev/null 2>&1; then echo \"✅ Vercel CLI available\"; PROJECT_STATUS=$(vercel project ls 2>/dev/null | head -1); if [[ \"$PROJECT_STATUS\" =~ \"No projects found\" ]]; then echo \"⚠️ No Vercel project linked to current directory\"; echo \"💡 Run: vercel link\"; else echo \"✅ Vercel project linked\"; fi; else echo \"⚠️ Vercel CLI not installed\"; echo \"💡 Install with: npm i -g vercel\"; fi; if [ -f \".env.example\" ]; then echo \"📋 .env.example found - template available\"; fi; ENV_FILES=($(ls .env* 2>/dev/null | grep -v .env.example || true)); if [ ${#ENV_FILES[@]} -gt 0 ]; then echo \"📁 Environment files found: ${ENV_FILES[*]}\"; for file in \"${ENV_FILES[@]}\"; do VAR_COUNT=$(grep -c \"^[A-Z_][A-Z0-9_]*=\" \"$file\" 2>/dev/null || echo \"0\"); echo \"  $file: $VAR_COUNT variables\"; done; else echo \"ℹ️ No .env files found\"; fi; else echo \"⚠️ VERCEL_TOKEN not configured\"; echo \"💡 Environment sync features disabled\"; fi'",
            "timeout": 15
          }
        ]
      }
    ]
  }
}

© davila7 · MIT · davila7/claude-code-templates

Similar hooks

Everything for DevOps and infrastructure →

From the same set205

The whole set →

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor