The Terminal Follows the Project
Your sites are served by the right PHP. Your terminal is not: it
still runs whatever is first on your PATH, which is how
php artisan ends up on a different version from the
site it belongs to. This chapter fixes that, and it is the point
where the old tools can go.
The problem
There are two PHPs in your life and they are not the same
one. The server PHP runs your site;
chapter 5 made that per-project. The
terminal PHP runs
php artisan migrate, composer
install, vendor/bin/pest — and it
is whatever your PATH finds first, globally, regardless of
which directory you are standing in.
The failure is quiet and confusing. A site served on 8.1 whose migrations run on 8.5 will mostly work, until a dependency resolves differently, or a composer install writes a lock file for the wrong platform, or a test passes locally and fails in CI. The cause is never where the symptom is.
Shims
grove path install
✓ Installed shims for php, composer, cpx, node, npm, npx, laravel.
✓ provisioned toolchain: PHP 8.5 CLI, Composer, cpx, Node 22
echo 'export PATH="$HOME/Library/Application Support/Grove/shims:$PATH"' >> ~/.zshrc
Add the line, restart your shell, and the commands you type are Grove's. A shim is a tiny program that asks one question before it runs anything: which project am I in, and what does it pin? Then it executes that version.
cd ~/Code/legacy-client && php -v # PHP 8.1
cd ~/Code/freddy && php -v # PHP 8.5
No switching, no ceremony, no remembering. The same
mechanism covers composer, node,
npm, npx and the
laravel installer, so an npm install in a
project pinned to Node 20 uses Node 20.
cpx, while we are here
Grove also installs cpx, a Composer
package executor — npx for PHP. It runs
a Composer package without installing it into your
project:
cpx friendsofphp/php-cs-fixer fix src/
Useful for the tools you want occasionally and do not want
in composer.json forever, where they will
constrain your dependency resolution for years for the
sake of something you ran twice.
Removing Herd and Valet
This is the moment. Everything the old tool did is now done: DNS, the proxy, certificates, PHP versions, the database, the terminal toolchain. Three chapters of evidence that the replacement works, rather than a leap.
- Copy the databases first if you have not — chapter 6, with the source untouched.
- Uninstall the old tool its own way.
-
Run
sudo grove installonce more. Uninstalling Herd or Valet removes resolver files and trust-store entries on the way out, including, sometimes, ones that were not theirs. This re-asserts Grove's resolver and CA. If.teststops resolving after you remove something, this is the command. -
grove doctorto confirm the ports, the resolver and the CA are all where they should be.
What you learned
- Two PHPs: the one serving the site and the one in your terminal. Only the first was per-project until now.
- Shims ask which project you are in before running php, composer, node, npm, npx or laravel.
- cpx runs a Composer package without installing it, keeping occasional tools out of composer.json forever.
- Remove the old tool after the evidence, not before — and copy the databases first.
- Run
sudo grove installafter uninstalling Herd or Valet. They take resolver and trust entries with them.