vercel-environment-sync — хук для Claude Code: синхронизация .env
Хук проверяет переменные окружения после правки .env и подсказывает, как перенести их в Vercel. Пригодится, если локальные и деплойные значения расходятся.
npx claude-code-templates@latest --hook automation/vercel-environment-syncЧто делает vercel-environment-sync
Хук висит на событие PostToolUse и срабатывает, когда Claude записал или отредактировал файл, чьё имя содержит .env. Сначала он смотрит на тип окружения: .env.production — production, .env.preview или .env.staging — preview, остальное считается development.
Дальше файл разбирается построчно. Строки вида VAR=value проверяются на формат, значения в кавычках отмечаются отдельно, короткие секреты (меньше 16 символов в переменных с SECRET, PRIVATE, KEY или TOKEN) и заглушки вроде your-, change-me или replace- вызывают предупреждение. Если нашлись ошибки, хук возвращает код 2 и блокирует синхронизацию. При чистом файле он печатает число переменных и команды vercel env pull .env.local и vercel env add [name] [environment].
Для работы нужен токен: export VERCEL_TOKEN=your_token, получить его можно на vercel.com/account/tokens. Без токена хук не падает, а просто сообщает, что синхронизация выключена — это повод проверить, что переменная действительно попала в окружение сессии, а не только в .env. На старте сессии второй хук проверяет наличие Vercel CLI, привязанный проект и список .env-файлов с количеством переменных в каждом.
Какие задачи решает
- поймать короткий или заглушечный секрет в
.envдо коммита - понять, к какому окружению Vercel относится отредактированный файл
- увидеть, сколько переменных лежит в каждом
.envпри старте сессии - получить готовые команды для выгрузки и добавления переменных в Vercel
- проверить, что проект привязан к Vercel и CLI установлен
Примеры запросов агенту
- я поправил .env.production, проверь переменные и скажи, что делать с Vercel
- добавь переменную DATABASE_URL в .env.local и синхронизируй с Vercel
- проверь, не осталось ли в .env заглушек вместо ключей
Как установить vercel-environment-sync
1Через claude-code-templates
npx claude-code-templates@latest --hook automation/vercel-environment-sync2Вручную: положить файлы
.claude/settings.jsonБлок hooks: событие (PreToolUse, PostToolUse, Stop…) → команда. Личные — ~/.claude/settings.json
По шагам, с командами для каждой платформы: Хуки Claude Code: что это, где настраивать и как запретить опасную команду
Вопросы о vercel-environment-sync
Как установить vercel-environment-sync в Claude?
Через шаблоны: npx claude-code-templates@latest --hook automation/vercel-environment-sync. Настройки хука прописываются в .claude/settings.json.
Что делает vercel-environment-sync?
Следит за изменениями .env-файлов, проверяет формат переменных и наличие заглушек, определяет окружение Vercel и подсказывает команды для синхронизации значений.
Что нужно для работы хука?
Токен Vercel в переменной окружения: export VERCEL_TOKEN=your_token. Для проверок на старте сессии понадобится ещё Vercel CLI и привязанный к каталогу проект.
Исходный текст
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