Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .envrc.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Local environment variables (copy to .envrc.local and customize)

# Path to Claude symlink script (runs on git checkout)
# Claude skills are in pgflow-dev/claude private repo
# See LOCAL_DEV.md for details
# export CLAUDE_SYMLINK_SCRIPT="/path/to/your/claude/symlink.sh"
29 changes: 18 additions & 11 deletions .lefthook/pre-push/prevent-push-to-main.sh
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
#!/bin/bash
set -e

# Check current branch
branch=$(git rev-parse --abbrev-ref HEAD)
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
if [ "$branch" = "main" ]; then
echo "ERROR: Direct pushes from main branch are not allowed!"
exit 1
fi

# Check destination branch (handles: git push origin feature:main)
# Git hook receives: <local_ref> <local_sha> <remote_ref> <remote_sha> per line
# Note: Using timeout because lefthook's script execution may keep stdin open
while read -r -t 0.5 local_ref local_sha remote_ref remote_sha || [ -n "$local_ref" ]; do
[ -z "$remote_ref" ] && break
remote_branch=$(echo "$remote_ref" | sed 's#^refs/heads/##')
if [ "$remote_branch" = "main" ]; then
echo "ERROR: Pushing to remote main branch is not allowed!"
echo "Attempted: $local_ref -> $remote_ref"
exit 1
fi
done
# Only read if stdin is available (not a tty)
if [ ! -t 0 ]; then
while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
# Skip empty lines
[ -z "$remote_ref" ] && continue

# Extract branch name from ref
remote_branch="${remote_ref#refs/heads/}"

if [ "$remote_branch" = "main" ]; then
echo "ERROR: Pushing to remote main branch is not allowed!"
echo "Attempted: $local_ref -> $remote_ref"
exit 1
fi
done
fi

exit 0
18 changes: 18 additions & 0 deletions LOCAL_DEV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Local Development Setup

This document contains setup instructions specific to local development environments.

> **Note**: This is a starting point and will be expanded with more comprehensive setup instructions in the future.

## Claude Symlink Hook

Claude Code skills and configuration are stored in a separate private repository (`pgflow-dev/claude`). If you have access to this repository and need the `.claude/` directory to be symlinked on branch changes, configure the following:

1. Add to your `.envrc.local`:
```bash
export CLAUDE_SYMLINK_SCRIPT="/path/to/your/claude/symlink.sh"
```

2. Run `direnv allow` to reload the environment

The `post-checkout` hook in `lefthook.yml` will automatically run this script whenever you switch branches.
35 changes: 35 additions & 0 deletions lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,42 @@ pre-commit:
run: |
./scripts/validate-json-files.sh

post-checkout:
commands:
'pnpm-install-on-deps-change':
run: |
# Only run if pnpm is available
if ! command -v pnpm &> /dev/null; then
echo "\033[33mWarning: pnpm not available, skipping dependency installation.\033[0m"
exit 0
fi

# Only run for branch checkouts (not file checkouts)
if [ "{3}" = "1" ]; then
# Always install if node_modules doesn't exist (new worktree case)
if [ ! -d "node_modules" ]; then
echo "📦 node_modules not found, running pnpm install --frozen-lockfile..."
pnpm install --frozen-lockfile
# Otherwise, only install if dependencies changed
elif git diff --name-only {1} {2} | grep -qE '^(package\.json|pnpm-lock\.yaml|pnpm-workspace\.yaml)$'; then
echo "📦 Dependencies changed, running pnpm install --frozen-lockfile..."
pnpm install --frozen-lockfile
fi
fi
'claude-symlink':
run: |
if [ -n "$CLAUDE_SYMLINK_SCRIPT" ] && [ -f "$CLAUDE_SYMLINK_SCRIPT" ]; then
"$CLAUDE_SYMLINK_SCRIPT" "$PWD"
elif [ -z "$CLAUDE_SYMLINK_SCRIPT" ]; then
echo "\033[33mWarning: CLAUDE_SYMLINK_SCRIPT not set. See LOCAL_DEV.md for setup instructions.\033[0m"
fi

pre-push:
commands:
'nx-affected-checks':
run: pnpm nx affected --target=lint,build --base=origin/main --head=HEAD
scripts:
'prevent-push-to-main.sh':
runner: bash
skip_output:
- meta