Back to catalogue
SecurityPreToolUse· Write|EditPreToolUseBefore tool execution · can block⚡ blocking
Block file writes on main branch
Blocks any Write or Edit tool call when the current branch is main/master and the working directory is the principal repo (not a worktree). Forces the agent to create a branch or worktree before making file changes.
Use cases
- Accidental main commits prevention
- Branch discipline enforcement
- Pair with worktree auto-create hook
- Strict repository governance
Providers & tags
Claude Code
#git#safety#main-branch#write-guard#branch-discipline
settings.json fragment
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-write-main-guard.mjs",
"type": "command"
}
],
"matcher": "Write|Edit"
}
]
}
}Script · .claude/hooks/pre-write-main-guard.mjs
#!/usr/bin/env node
// PreToolUse Write|Edit: bloque la première écriture sur main si aucun worktree n'est actif
import { readFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
function defaultExec(cmd) {
try { return execSync(cmd, { encoding: 'utf8', timeout: 5_000 }).trim(); } catch { return ''; }
}
export function run(input, { exec = defaultExec } = {}) {
const branch = exec('git branch --show-current') || exec('git rev-parse --abbrev-ref HEAD');
if (!branch || !/^(main|master)$/.test(branch)) return null;
const worktreeList = exec('git worktree list');
const currentRoot = exec('git rev-parse --show-toplevel');
const mainRoot = worktreeList.split('\n')[0]?.split(/\s+/)[0] ?? '';
if (mainRoot !== currentRoot) return null;
const filePath = input.tool_input?.file_path ?? '(fichier inconnu)';
// Autoriser les écritures vers des fichiers dans un worktree (hors du repo principal)
if (filePath !== '(fichier inconnu)' && !filePath.startsWith(mainRoot + '/')) return null;
return {
decision: 'block',
reason: `Écriture sur \`${branch}\` bloquée : vous êtes sur la branche principale.\nCréez un worktree (\`git worktree add ../mon-fix -b feat/mon-fix\`) ou changez de branche avant de modifier \`${filePath}\`.`,
};
}
/* 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) process.stdout.write(JSON.stringify(result));
}