Back to catalogue
WorkflowCwdChangedCwdChangedWhen working directory changes· non-blocking
Reload direnv on directory change
Automatically reloads environment variables via direnv when Claude changes its working directory, ensuring Bash commands use the right environment for the current directory.
Use cases
- Mono-repo projects with different environments per subfolder
- Automatic .envrc management with direnv
- Sync CLAUDE_ENV_FILE with the current directory's environment
Providers & tags
Claude Code
#direnv#environment#cwd#monorepo
settings.json fragment
{
"hooks": {
"CwdChanged": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/reload-direnv.mjs",
"type": "command"
}
],
"matcher": ""
}
],
"SessionStart": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/reload-direnv.mjs",
"type": "command"
}
],
"matcher": ""
}
]
}
}Script · .claude/hooks/reload-direnv.mjs
#!/usr/bin/env node
// Recharge direnv quand le répertoire de travail change (CwdChanged)
import { readFileSync, existsSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
function defaultExec(cmd, cwd) {
execSync(cmd, { cwd, stdio: 'ignore', timeout: 5_000 });
}
export function run(input, { exec = defaultExec, exists = existsSync } = {}) {
const newCwd = input.cwd ?? input.new_cwd ?? process.cwd();
const envrc = `${newCwd}/.envrc`;
if (!exists(envrc)) return null;
try {
exec('direnv allow .', newCwd);
return { message: `[reload-direnv] direnv rechargé dans ${newCwd}\n` };
} catch {
// direnv absent — non bloquant
return null;
}
}
/* 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);
}