I've been running multiple Claude Code sessions in parallel. One agent is refactoring the booking flow, another is building a new integration, and I need to push a hotfix to production. All at the same time. All on the same codebase.
If you've ever tried this with git stash and branch switching, you know the pain. Uncommitted changes, shared databases getting corrupted by competing migrations. It's a mess.
Git worktrees fixed all of that for me.
What are git worktrees?
A worktree is a separate checkout of your repository in a different directory, linked to the same .git history. Each worktree has its own branch, its own working tree, its own node_modules, its own .env. But they share the same git history, so commits, branches, and remotes are all in sync.
git worktree add .claude/worktrees/feature-billing feature-billing
That's it. You now have a full copy of your project in .claude/worktrees/feature-billing, checked out on the feature-billing branch. Your main directory stays exactly where it was.
No stashing. No context switching. No "wait, which branch am I on?"
Why this matters for AI coding agents
Claude Code (and similar tools) work best when they have a stable, isolated environment. An agent planning a database migration shouldn't accidentally break the working directory where another agent is running tests.
With worktrees, each Claude session gets its own sandbox. They can't step on each other's toes. One agent can be mid-migration on a feature branch while another is writing tests on main, and neither knows the other exists.
But here's the thing: a raw git worktree add only gives you the files. For a Laravel project, you also need:
- Composer and npm dependencies installed
- Its own database (not the one your main app is using)
- Its own
.envwith the rightAPP_URLandDB_DATABASE - A working local domain (if you're using Laravel Herd)
- A Vite dev server on a port that doesn't conflict
Setting all of that up manually every time would defeat the purpose.
One command to create everything
I wrote a setup script that does the whole thing. Create a worktree, and within a minute you have a fully functional Laravel environment:
./claude-worktree.sh feature-billing
What happens behind the scenes:
- Creates the git worktree with a new branch
- Copies
.envfrom the main project and adjusts it (newAPP_URL,DB_DATABASE,VITE_PORT) - Finds a free port for Vite (scans 5100–5199, checks both
.envfiles andlsof) - Runs
composer installandpnpm install - Creates a fresh database
- Runs migrations and seeders
- Links the worktree to Laravel Herd with HTTPS
- Starts Claude Code in the new directory
The result:
Branch: feature-billing
Path: /project/.claude/worktrees/feature-billing
URL: https://feature-billing.myapp.test
Database: myapp_feature_billing
Vite port: 5101
A completely isolated environment. Its own database, its own domain, its own port. You can open it in a browser alongside your main app and they don't interfere at all.
One command to tear it down
When you're done:
./claude-worktree-remove.sh feature-billing
This drops the database, removes the Herd link and TLS certificate, deletes the worktree, and cleans up the branch. Gone. No leftover databases, no phantom Herd domains.
The Vite port problem
This one was surprisingly annoying. Vite defaults to port 5173, and if you have three worktrees all trying to run dev servers, they'll either fight over the port or silently pick random ones.
The setup script assigns each worktree a unique port from a reserved range (5100–5199). It checks both existing worktree .env files and active listeners to avoid conflicts. Then it patches the package.json dev script directly:
"dev": "vite --port 5101"
No config file gymnastics. The port is baked into the command. It works every time.
On the Laravel side, the Blade directive that loads Vite assets reads the port from .env:
$port = Env::get('VITE_PORT', '5173');
return '<script type="module" src="https://127.0.0.1:' . $port . '/resources/js/app.ts"></script>';
This only runs in development. Production uses the CDN build, completely unaffected.
Hooks for safety
If you're using Claude Code, you can add hooks that automatically handle worktree setup and cleanup. A PreToolUse hook on the Bash tool can detect when Claude enters an unconfigured worktree and run the setup script. Another hook can detect git worktree remove commands and run cleanup before the directory is deleted.
This means even if Claude creates or removes worktrees on its own (which it does with its built-in worktree support), everything gets set up and torn down properly.
Being honest about parallel sessions
I'll be honest. I can't effectively run more than 2–3 Claude sessions at once. I've tried. It's like playing StarCraft 2 and trying to manage 10 bases simultaneously. You end up switching between them so frantically that you play worse than if you'd just focused on one.
But for me, that's not really the point. Maybe you're better at juggling than I am, and if so, go for it. But the real value for me isn't just in running five agents at the same time. It's in isolation and persistence.
You can start a feature branch, let Claude plan and scaffold for an hour, then pause it. Switch to your main branch, push a hotfix, deal with a support ticket. Come back to the feature worktree later and everything is exactly where you left it. The database has the right migrations, the dependencies are installed, the branch is untouched.
No stash popping. No "where was I?" No accidentally running migrations on the wrong database.
Set it up in your project
I packaged the whole thing as a Claude Code skill. Install it, run /setup-worktrees, and Claude will generate everything — the create script, the remove script, the cleanup logic, the hooks, all of it.
It detects your package manager, reads your .env for database credentials, derives Herd subdomains from your app name. Works with MySQL, PostgreSQL, and SQLite. You don't need to configure anything upfront.
What you'll need:
- A Laravel project served by Laravel Herd
- A database (MySQL, PostgreSQL, or SQLite)
- A git repository
What you'll get:
-
claude-worktree.sh— one command to create a fully isolated environment -
claude-worktree-remove.sh— one command to tear it all down - Claude Code hooks for automatic setup/cleanup
- Each worktree gets its own database, Herd domain, and Vite port
Install the skill:
/plugin marketplace add gausejakub/claude-skills
/plugin install laravel-worktrees@gause-claude-skills
Then run /setup-worktrees in Claude Code. That's it. One slash command, fully configured worktree system.
If you're using a different stack, the principle is the same. Each worktree needs its own isolated runtime: its own database, its own dev server port, its own local URL. Automate the setup, automate the teardown, and branch switching becomes a non-issue.
Top comments (0)