Sets up git worktrees for Laravel projects served by Laravel Herd, creating isolated feature branches with dedicated site URLs and Vite configuration.
npx claudepluginhub harris21/laravel-herd-worktree --plugin laravel-herd-worktreeThis skill uses the workspace's default tool permissions.
Sets up a git worktree for Laravel projects served by Laravel Herd, ensuring the worktree has its own site URL and properly configured environment.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Sets up a git worktree for Laravel projects served by Laravel Herd, ensuring the worktree has its own site URL and properly configured environment.
Announce at start: "I'm using the laravel-herd-worktree skill to set up an isolated Laravel workspace with Herd."
ALWAYS use the AskUserQuestion tool for ALL user interactions. Never stop and wait for user reply. The AskUserQuestion tool allows the workflow to continue seamlessly.
All question blocks in this skill (shown in YAML-like format) should be implemented using the AskUserQuestion tool with the specified options.
git worktree listFirst, detect the project name (used for the Herd site URL to avoid conflicts between projects with the same branch name):
# Get project name from the directory name
PROJECT_NAME=$(basename "$PWD")
Use AskUserQuestion to confirm or customize the project name:
AskUserQuestion:
question: "Project name detected as '$PROJECT_NAME'. This will be used for the Herd URL (e.g., projectname-branchname.test). Is this correct?"
header: "Project"
options:
- label: "Yes, use '$PROJECT_NAME'"
description: "Use the detected project name"
- label: "Use a different name"
description: "I'll provide a custom project name"
Then use AskUserQuestion to get the branch name:
AskUserQuestion:
question: "What branch name would you like to use for this worktree?"
header: "Branch Name"
options:
- label: "feature/new-feature"
description: "Generic feature branch - you can provide a custom name"
- label: "bugfix/fix-issue"
description: "Bugfix branch pattern"
- label: "experiment/test"
description: "Experimental/testing branch"
Note: Both project name and branch name will be sanitized for the Herd link (slashes replaced with dashes, spaces removed). For example, project my-app with branch feature/new-feature becomes my-app-feature-new-feature.test.
Construct the site name:
SANITIZED_BRANCH_NAME=$(echo "$BRANCH_NAME" | tr '/' '-')
SITE_NAME="$PROJECT_NAME-$SANITIZED_BRANCH_NAME"
# Check if worktree exists
git worktree list | grep "$BRANCH_NAME"
# If not, create it
git worktree add .worktrees/$SITE_NAME -b $BRANCH_NAME
cd /path/to/project/.worktrees/$SITE_NAME
herd link $SITE_NAME
This creates a site at http://$SITE_NAME.test (e.g., http://myproject-feature-branch.test)
Note: Do NOT run herd secure - the site should use HTTP to match the Vite dev server.
Why include project name? This prevents conflicts when multiple projects have the same branch name (e.g., both project-a and project-b have a feature/login branch).
# Copy .env from main project
cp /path/to/main/project/.env /path/to/worktree/.env
# Update APP_URL to match Herd site (use HTTP, not HTTPS)
sed -i '' "s|APP_URL=.*|APP_URL=http://$SITE_NAME.test|" /path/to/worktree/.env
# Update SESSION_DOMAIN to match the worktree domain
sed -i '' "s|SESSION_DOMAIN=.*|SESSION_DOMAIN=$SITE_NAME.test|" /path/to/worktree/.env
# Add worktree domain to SANCTUM_STATEFUL_DOMAINS (for API auth, if using Sanctum)
sed -i '' "s|SANCTUM_STATEFUL_DOMAINS=\(.*\)|SANCTUM_STATEFUL_DOMAINS=\1,$SITE_NAME.test|" /path/to/worktree/.env
# Ensure secure cookies are disabled for HTTP
echo "SESSION_SECURE_COOKIE=false" >> /path/to/worktree/.env
CRITICAL: Worktrees do NOT share vendor/ or node_modules/ with the main project.
Use AskUserQuestion before running composer install:
AskUserQuestion:
question: "Would you like to add any flags to composer install?"
header: "Composer"
options:
- label: "No flags needed (Recommended)"
description: "Run 'composer install --no-interaction' with no additional flags"
- label: "Add --ignore-platform-req=ext-mailparse"
description: "Ignore the mailparse extension requirement (common issue)"
- label: "Add custom flags"
description: "I'll provide specific flags"
If user selects "Add custom flags", ask them to provide the flags they want to use.
# Install PHP dependencies (add user-provided flags if any)
composer install --no-interaction # Append user's custom flags here if provided
# Install Node.js dependencies
npm install
# Clear Laravel caches
php artisan config:clear
php artisan cache:clear
Ask user if composer/npm install fails: "The dependency installation failed. Would you like me to:
--ignore-platform-reqsIMPORTANT: To avoid Cross-Origin Request Blocked errors, ensure vite.config.js includes:
export default defineConfig(() => {
return {
server: {
host: 'localhost',
cors: true,
},
plugins: [
// ... your plugins
]
}
});
Key settings:
host: 'localhost' - Prevents CORS issues (do NOT use 0.0.0.0)cors: true - Enables CORS for cross-origin requestsIMPORTANT: If Vite is already running from the main project, it will occupy port 5173. You must kill it first to ensure the worktree's Vite uses the correct port and serves the correct assets.
# Kill any existing Vite processes
pkill -f "node.*vite" 2>/dev/null
# Remove stale hot file
rm -f public/hot
# Start Vite dev server (will use APP_URL from .env)
npm run dev
Why this matters: Vite reads APP_URL from .env to configure hot module replacement. If the wrong Vite instance is running, assets will fail to load or point to the wrong domain.
When development is complete and you want to integrate the worktree changes, immediately use AskUserQuestion to ask how they want to proceed:
AskUserQuestion:
question: "How would you like to finish your worktree changes?"
header: "Finish Work"
options:
- label: "Create PR from worktree (Recommended)"
description: "Commit, push, and create a PR directly from the worktree branch"
- label: "Transfer to main directory"
description: "Merge changes into the main project directory, then clean up the worktree"
- label: "Abandon changes"
description: "Discard all changes and remove the worktree"
After setup completes, tell the user: "When you're ready to finish your work, run /laravel-herd-worktree again and I'll help you integrate or clean up your changes."
Use this when you want to keep changes isolated and create a PR directly from the worktree.
Use AskUserQuestion to gather information (can ask multiple questions at once):
AskUserQuestion:
questions:
- question: "Do you have a task/issue number for this work?"
header: "Task ID"
options:
- label: "No task number"
description: "Skip adding a task identifier to the branch and commit"
- label: "Enter task number"
description: "I'll provide a task/issue number to include in the branch name and commit"
- question: "How would you like to handle the PR description?"
header: "PR Body"
options:
- label: "I'll write it"
description: "Create PR with empty body - I'll fill in the description on GitHub"
- label: "Generate for me"
description: "Analyze the changes and generate a PR description automatically"
- label: "Leave empty"
description: "Create PR with no description"
cd /path/to/project/.worktrees/$BRANCH_NAME
git add -A
git commit -m "Your commit message (#TASK_NUMBER)" # Omit (#TASK_NUMBER) if none provided
If a task number was provided and the branch doesn't include it:
git branch -m old-branch-name TASK_NUMBER-descriptive-name
Note: The base branch defaults to develop. Adjust to your project's default branch (e.g., main or master) if different. You can detect the default branch with:
git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
git push -u origin BRANCH_NAME
# Based on user's PR description preference:
# - "I'll write it" or "Leave empty": gh pr create --base $DEFAULT_BRANCH --title "Title" --body ""
# - "Generate for me": Generate description from git diff, then use --body "$DESCRIPTION"
gh pr create --base $DEFAULT_BRANCH --title "Description (#TASK_NUMBER)" --body "$BODY"
After the PR is merged, clean up the worktree:
# Stop Vite if running
pkill -f "node.*vite" 2>/dev/null
# From main project directory
cd /path/to/main/project
herd unlink $SITE_NAME
git worktree remove .worktrees/$SITE_NAME
git branch -d TASK_NUMBER-branch-name # Delete local branch
Use this when you want to bring your worktree changes back into the main project directory, review them there, and then commit/push from the main directory.
Use AskUserQuestion to confirm:
AskUserQuestion:
question: "This will merge your worktree branch into the main directory. Continue?"
header: "Confirm"
options:
- label: "Yes, transfer changes"
description: "Merge the worktree branch into the main project and clean up"
- label: "Cancel"
description: "Go back without transferring"
# Stop Vite if running in worktree
pkill -f "node.*vite" 2>/dev/null
# Navigate to main project directory
cd /path/to/main/project
# Fetch and merge the worktree branch into current branch
git merge $BRANCH_NAME --no-commit --no-ff
The --no-commit flag stages the changes without committing, allowing the user to review and commit manually. The --no-ff ensures a merge commit is created for clarity.
If merge conflicts occur:
After the merge is staged:
# Unlink from Herd
herd unlink $SITE_NAME
# Remove the worktree
git worktree remove .worktrees/$SITE_NAME
# Delete the worktree branch (it's now merged)
git branch -D $BRANCH_NAME
Inform the user: "Your changes have been merged into the main directory and are staged for commit. The worktree has been cleaned up.
You can now:
git status and git diff --cachedgit commitgit reset HEAD <file>"When abandoning a worktree without merging:
# Stop Vite if running
pkill -f "node.*vite" 2>/dev/null
# Unlink from Herd
herd unlink $SITE_NAME
# Remove worktree
git worktree remove .worktrees/$SITE_NAME
# Delete branch if not needed
git branch -D $BRANCH_NAME
Variables:
$PROJECT_NAME - The project directory name (e.g., my-laravel-app)$BRANCH_NAME - The git branch name (e.g., feature/login)$SANITIZED_BRANCH_NAME - Branch name with slashes replaced by dashes (e.g., feature-login)$SITE_NAME - Combined name for Herd: $PROJECT_NAME-$SANITIZED_BRANCH_NAME (e.g., my-laravel-app-feature-login)| Step | Command |
|---|---|
| Create worktree | git worktree add .worktrees/$SITE_NAME -b $BRANCH_NAME |
| Link to Herd | herd link $SITE_NAME |
| Copy .env | cp ../../../.env .env |
| Update APP_URL | sed -i '' "s|APP_URL=.*|APP_URL=http://$SITE_NAME.test|" .env |
| Install PHP deps | composer install --no-interaction |
| Install Node deps | npm install |
| Clear cache | php artisan config:clear && php artisan cache:clear |
| Kill old Vite | pkill -f "node.*vite" |
| Start dev | npm run dev |
| Unlink | herd unlink $SITE_NAME |
| Remove worktree | git worktree remove .worktrees/$SITE_NAME |
$SITE_NAME.test)php artisan config:clearSESSION_DOMAIN=$SITE_NAME.testSESSION_SECURE_COOKIE=false for HTTP sitesphp artisan config:clearhost: '0.0.0.0' instead of localhosthost: 'localhost' and cors: truenpm run devherd unsecure $SITE_NAMEhttp:// instead of https://php artisan config:clearpkill -f "node.*vite"rm -f public/hotnpm run devcomposer install in worktreenpm install in worktreepkill -f "node.*vite"Before considering setup complete, verify:
.worktrees/$SITE_NAMEherd link $SITE_NAME)host: 'localhost' and cors: truehttp://$SITE_NAME.test$SITE_NAME.testcomposer install completed successfullynpm install completed successfullynpm run dev running from worktree directoryhttp://$SITE_NAME.test (no white page)After worktree setup is complete, ALL subsequent work MUST use the worktree path.
The worktree is a separate copy of the codebase. Using the main repo path will edit the wrong files.
/path/to/project/.worktrees/$SITE_NAME//path/to/project/.worktrees/$SITE_NAME/app/...)After setup, remind the user and any subsequent agents: "All work for this task should use the worktree at /path/to/project/.worktrees/$SITE_NAME/. The site is accessible at http://$SITE_NAME.test. Do not modify files in the main project directory."
Pairs with: