HookStackGitHub
Back to catalogue
WorkflowFileChanged· .env|.env.local|.envrc

Reload .env on file change

Edit .env and Bash picks it up instantly

Watches .env, .env.local and .envrc files and writes updated KEY=VALUE pairs to CLAUDE_ENV_FILE when any of them change on disk. Subsequent Bash commands automatically pick up the new values without restarting the session.

What does the Reload .env on file change hook do?

Reload .env on file change is a Claude Code FileChanged hook matching .env|.env.local|.envrc. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Edit .env and Bash picks it up instantly.

Use cases

  • Reload environment variables after editing .env without restarting Claude Code
  • Sync .env.local overrides into Claude's Bash environment on the fly
  • Keep API keys and feature flags up to date during active development

Tags

#env#environment#reload#dotenv#file-watch

settings.json fragment

{
  "hooks": {
    "FileChanged": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/file-changed-reload-env.mjs",
            "type": "command"
          }
        ],
        "matcher": ".env|.env.local|.envrc"
      }
    ]
  }
}

Script · .claude/hooks/file-changed-reload-env.mjs

#!/usr/bin/env node
// Recharge les variables d'env d'un fichier modifié dans CLAUDE_ENV_FILE (FileChanged)
import { readFileSync, appendFileSync } from 'fs';
import { fileURLToPath } from 'url';

export function run(
  input,
  {
    readFile = readFileSync,
    append = appendFileSync,
    envFile = process.env.CLAUDE_ENV_FILE,
  } = {},
) {
  if (!envFile || input.event === 'unlink') return null;

  try {
    const content = readFile(input.file_path, 'utf8');
    const lines = content
      .split('\n')
      .filter((l) => /^[A-Z_a-z][A-Z_a-z0-9]*=/.test(l) && !l.startsWith('#'));
    for (const line of lines) {
      append(envFile, `export ${line.trim()}\n`);
    }
    return { count: lines.length, message: `[file-changed-reload-env] reloaded ${lines.length} vars from ${input.file_path}\n` };
  } catch (e) {
    return { error: e.message, message: `[file-changed-reload-env] ${e.message}\n` };
  }
}

/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const input = JSON.parse(readFileSync(0, 'utf8'));
  const result = run(input);
  if (result?.message) process.stderr.write(result.message);
}