#!/usr/bin/env node /** * Install git pre-push hook. * Zero dependencies — just writes a shell script to .git/hooks/pre-push. * Runs on `bun install` via postinstall. */ import { writeFileSync, readFileSync, chmodSync, existsSync } from 'node:fs'; import { join } from 'node:path'; const hookPath = join(process.cwd(), '.git', 'hooks', 'pre-push'); // Don't overwrite if user has a custom hook if (existsSync(hookPath)) { let content = ''; try { content = readFileSync(hookPath, 'utf-8'); } catch {} if (content && !content.includes('pulse-auto-hook')) { console.log('[hooks] pre-push hook already exists (custom), skipping'); process.exit(0); } } const hook = `#!/bin/sh # pulse-auto-hook — installed by scripts/install-hooks.mjs # Runs lint + type-check + tests before pushing. Delete this file to disable. set -e ROOT=$(git rev-parse --show-toplevel) echo "[pre-push] Running lint..." bun x @biomejs/biome check packages/ || { echo "\\\\n❌ Lint failed. Fix with: bun run lint:fix" exit 1 } echo "[pre-push] Type checking..." for pkg in pulse upulse pulse-hermes pulse-cursor pulse-openclaw; do if [ -f "$ROOT/packages/$pkg/tsconfig.json" ]; then echo " tsc: $pkg" (cd "$ROOT/packages/$pkg" && bun x tsc --noEmit) || { echo "\\\\n❌ Type check failed ($pkg)" exit 1 } fi done echo "[pre-push] Running tests..." for pkg in pulse pulse-hermes pulse-cursor pulse-openclaw; do echo " test: $pkg" (cd "$ROOT/packages/$pkg" && bun test) || { echo "\\\\n❌ Tests failed ($pkg)" exit 1 } done echo " test: upulse" (cd "$ROOT/packages/upulse" && bun test src/config.test.ts) || { echo "\\\\n❌ Tests failed (upulse)" exit 1 } echo "✅ All checks passed" `; try { writeFileSync(hookPath, hook); chmodSync(hookPath, 0o755); console.log('[hooks] pre-push hook installed'); } catch (err) { // Non-fatal — CI and shallow clones may not have .git/hooks console.log('[hooks] Could not install pre-push hook (non-fatal):', err.message); }