Skip to content

Commit af2b7b4

Browse files
committed
feat: add local dev setup with Claude symlink and improve git hooks (#405)
# Improve local development workflow with automated hooks This PR enhances the developer experience with several improvements: 1. Added a post-checkout hook that: - Automatically runs `pnpm install` when dependencies change between branches - Supports symlink creation for Claude skills via a configurable script 2. Improved the pre-push hook that prevents pushing to main: - Fixed stdin handling to avoid hanging - Added better error handling and logging - Made the script more robust with proper exit codes 3. Added documentation and configuration: - Created `LOCAL_DEV.md` with instructions for setting up Claude symlinks - Added `.envrc.local.example` with configuration for the Claude symlink script - Added NX affected checks to run lint and build on pre-push These changes make the development workflow more seamless by automating dependency installation when switching branches and providing better protection against accidental pushes to main.
1 parent b59c014 commit af2b7b4

File tree

4 files changed

+77
-11
lines changed

4 files changed

+77
-11
lines changed

.envrc.local.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Local environment variables (copy to .envrc.local and customize)
2+
3+
# Path to Claude symlink script (runs on git checkout)
4+
# Claude skills are in pgflow-dev/claude private repo
5+
# See LOCAL_DEV.md for details
6+
# export CLAUDE_SYMLINK_SCRIPT="/path/to/your/claude/symlink.sh"
Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
#!/bin/bash
2+
set -e
23

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

1011
# Check destination branch (handles: git push origin feature:main)
1112
# Git hook receives: <local_ref> <local_sha> <remote_ref> <remote_sha> per line
12-
# Note: Using timeout because lefthook's script execution may keep stdin open
13-
while read -r -t 0.5 local_ref local_sha remote_ref remote_sha || [ -n "$local_ref" ]; do
14-
[ -z "$remote_ref" ] && break
15-
remote_branch=$(echo "$remote_ref" | sed 's#^refs/heads/##')
16-
if [ "$remote_branch" = "main" ]; then
17-
echo "ERROR: Pushing to remote main branch is not allowed!"
18-
echo "Attempted: $local_ref -> $remote_ref"
19-
exit 1
20-
fi
21-
done
13+
# Only read if stdin is available (not a tty)
14+
if [ ! -t 0 ]; then
15+
while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
16+
# Skip empty lines
17+
[ -z "$remote_ref" ] && continue
18+
19+
# Extract branch name from ref
20+
remote_branch="${remote_ref#refs/heads/}"
21+
22+
if [ "$remote_branch" = "main" ]; then
23+
echo "ERROR: Pushing to remote main branch is not allowed!"
24+
echo "Attempted: $local_ref -> $remote_ref"
25+
exit 1
26+
fi
27+
done
28+
fi
2229

2330
exit 0

LOCAL_DEV.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Local Development Setup
2+
3+
This document contains setup instructions specific to local development environments.
4+
5+
> **Note**: This is a starting point and will be expanded with more comprehensive setup instructions in the future.
6+
7+
## Claude Symlink Hook
8+
9+
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:
10+
11+
1. Add to your `.envrc.local`:
12+
```bash
13+
export CLAUDE_SYMLINK_SCRIPT="/path/to/your/claude/symlink.sh"
14+
```
15+
16+
2. Run `direnv allow` to reload the environment
17+
18+
The `post-checkout` hook in `lefthook.yml` will automatically run this script whenever you switch branches.

lefthook.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,42 @@ pre-commit:
2121
run: |
2222
./scripts/validate-json-files.sh
2323
24+
post-checkout:
25+
commands:
26+
'pnpm-install-on-deps-change':
27+
run: |
28+
# Only run if pnpm is available
29+
if ! command -v pnpm &> /dev/null; then
30+
echo "\033[33mWarning: pnpm not available, skipping dependency installation.\033[0m"
31+
exit 0
32+
fi
33+
34+
# Only run for branch checkouts (not file checkouts)
35+
if [ "{3}" = "1" ]; then
36+
# Always install if node_modules doesn't exist (new worktree case)
37+
if [ ! -d "node_modules" ]; then
38+
echo "📦 node_modules not found, running pnpm install --frozen-lockfile..."
39+
pnpm install --frozen-lockfile
40+
# Otherwise, only install if dependencies changed
41+
elif git diff --name-only {1} {2} | grep -qE '^(package\.json|pnpm-lock\.yaml|pnpm-workspace\.yaml)$'; then
42+
echo "📦 Dependencies changed, running pnpm install --frozen-lockfile..."
43+
pnpm install --frozen-lockfile
44+
fi
45+
fi
46+
'claude-symlink':
47+
run: |
48+
if [ -n "$CLAUDE_SYMLINK_SCRIPT" ] && [ -f "$CLAUDE_SYMLINK_SCRIPT" ]; then
49+
"$CLAUDE_SYMLINK_SCRIPT" "$PWD"
50+
elif [ -z "$CLAUDE_SYMLINK_SCRIPT" ]; then
51+
echo "\033[33mWarning: CLAUDE_SYMLINK_SCRIPT not set. See LOCAL_DEV.md for setup instructions.\033[0m"
52+
fi
53+
2454
pre-push:
55+
commands:
56+
'nx-affected-checks':
57+
run: pnpm nx affected --target=lint,build --base=origin/main --head=HEAD
2558
scripts:
2659
'prevent-push-to-main.sh':
2760
runner: bash
61+
skip_output:
62+
- meta

0 commit comments

Comments
 (0)