Skip to content

Commit ca31525

Browse files
committed
feat: git pre-commit hook blocks commits on main/master
Added .git/hooks/pre-commit locally and .hooks/pre-commit in the scaffolder template. webjs create now runs git init + configures core.hooksPath to .hooks/ so the hook is tracked in the repo and works for everyone who clones it. This is git-level enforcement — no AI agent, editor, or human can commit to main. Feature branches only.
1 parent 4c5746e commit ca31525

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

packages/cli/lib/create.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ export async function scaffoldApp(name, cwd) {
9494
'test/unit/example.test.ts',
9595
'test/browser/example.test.js',
9696
'web-test-runner.config.js',
97+
// Git hooks (blocks commits on main)
98+
'.hooks/pre-commit',
9799
// Claude Code config + hooks
98100
'.claude.json',
99101
'.claude/settings.json',
@@ -122,6 +124,9 @@ export async function scaffoldApp(name, cwd) {
122124
const hookPath = join(appDir, '.claude', 'hooks', hook);
123125
if (existsSync(hookPath)) await chmod(hookPath, 0o755);
124126
}
127+
// Make git pre-commit hook executable
128+
const preCommitPath = join(appDir, '.hooks', 'pre-commit');
129+
if (existsSync(preCommitPath)) await chmod(preCommitPath, 0o755);
125130

126131
// --- App files ---
127132

@@ -263,6 +268,14 @@ export class ThemeToggle extends WebComponent {
263268
ThemeToggle.register(import.meta.url);
264269
`);
265270

271+
// --- Git init + configure hooks directory ---
272+
const { execSync } = await import('node:child_process');
273+
try {
274+
execSync('git init', { cwd: appDir, stdio: 'pipe' });
275+
// Tell git to use .hooks/ as the hooks directory (tracked in the repo)
276+
execSync('git config core.hooksPath .hooks', { cwd: appDir, stdio: 'pipe' });
277+
} catch { /* git not available — skip */ }
278+
266279
// --- Print success ---
267280

268281
console.log(` ${name}/
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
#
3+
# pre-commit hook — blocks commits on main/master.
4+
#
5+
# No AI agent, no editor, no human can commit to main directly.
6+
# Create a feature branch first. This is git-level enforcement.
7+
#
8+
# To bypass in emergencies: git commit --no-verify
9+
10+
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
11+
12+
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
13+
echo ""
14+
echo "ERROR: Cannot commit directly to '$BRANCH'."
15+
echo ""
16+
echo "Create a feature branch first:"
17+
echo " git checkout -b feature/<name>"
18+
echo ""
19+
echo "To bypass (emergencies only): git commit --no-verify"
20+
echo ""
21+
exit 1
22+
fi
23+
24+
exit 0

0 commit comments

Comments
 (0)