HookStackGitHub
Back to catalogue
WorkflowPreToolUse· BashPreToolUseBefore tool execution · can block⚡ blocking

Block push on closed PR

Intercepts git push commands and checks via gh CLI if the current branch has a closed or merged PR. Blocks the push with a message pointing to create a new branch from main.

Use cases

  • Prevent pushing fixes on a branch whose PR was already merged or closed
  • Guide the agent to always branch from an up-to-date main

Providers & tags

Claude Code
#git#github#safety#pr

settings.json fragment

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/block-push-closed-pr.mjs"
          }
        ]
      }
    ]
  }
}

Script · .claude/hooks/block-push-closed-pr.mjs

import { readFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';

const defaultExec = (cmd) => execSync(cmd, { encoding: 'utf8', timeout: 5000 });

export function run(input, { exec = defaultExec } = {}) {
  const command = input?.tool_input?.command ?? '';
  if (!/\bgit\s+push\b/.test(command)) return null;

  let branch;
  try {
    branch = exec('git rev-parse --abbrev-ref HEAD').trim();
  } catch {
    return null;
  }

  if (!branch || branch === 'HEAD' || branch === 'main' || branch === 'master') return null;

  let state;
  try {
    state = exec(`gh pr view "${branch}" --json state --jq '.state'`).trim();
  } catch {
    return null;
  }

  if (state === 'CLOSED' || state === 'MERGED') {
    const label = state === 'MERGED' ? 'mergée' : 'fermée';
    return {
      decision: 'block',
      reason: `La PR de la branche '${branch}' est ${label}. Créez une nouvelle branche depuis main : git checkout -b fix/... origin/main`,
    };
  }

  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) process.stdout.write(JSON.stringify(result));
}