<p>There's a moment in every local setup's life where it graduates from "serves my sites" to "runs my whole day." Grove 0.6 is that graduation. Two features, both born from the same nagging feeling: why am I still doing this by hand?</p><p>The first lets you finally uninstall Herd and Valet for good. The second lets you run a scary migration without that little knot in your stomach. Let's take them in turn.</p><h2>grove path — your toolchain, on your PATH, automatically</h2><p>Grove has always bundled everything: PHP, Node, Composer, databases. But there was a gap. Grove used those bundled binaries to serve your sites — yet when you dropped into a terminal and typed <code>php artisan</code>, <code>composer install</code>, or <code>npm run build</code>, you were still leaning on whatever <code>php</code> some other tool had put on your PATH. Usually Herd's.</p><p>So Herd stayed installed. Not because you used its UI — just because it owned <code>php</code> and <code>composer</code> in your shell.</p><p>Grove 0.6 closes that gap:</p><pre><code class="language-text">$ grove path install
✓ Installed shims for php, composer, node, npm, npx, laravel.

Provisioning the bundled toolchain (php, composer, node)…
✓ provisioned toolchain: PHP 8.4 CLI, Composer, Node 22

Add Grove's toolchain to your PATH, then restart your shell:

    echo 'export PATH="$HOME/Library/Application Support/Grove/shims:$PATH"' &gt;&gt; ~/.zshrc
</code></pre><p>Add that line, restart your shell, and now <code>php</code>, <code>composer</code>, <code>node</code>, <code>npm</code>, <code>npx</code> and <code>laravel</code> all come from Grove.</p><h3>The clever bit: per-directory version switching</h3><p>Here's what makes it more than a symlink. The shims are directory-aware. When you run <code>php</code> inside a project, Grove resolves the exact version that project pins — the one you set with <code>grove isolate</code> or <code>grove node use</code> — and falls back to your default everywhere else:</p><pre><code class="language-text">$ cd ~/Code/legacy-app        # pinned to PHP 8.1
$ php -v
PHP 8.1.29 (cli) ...

$ cd ~/Code/elyra-web         # pinned to PHP 8.4
$ php -v
PHP 8.4.10 (cli) ...
</code></pre><p>No <code>.tool-versions</code>, no <code>mise activate</code>, no shell hooks. Grove already knows which version each site runs, so the terminal just matches. It's the asdf experience with zero configuration, because the answer was already in Grove's registry.</p><h3>How it stays safe</h3><p>One architectural note, because it's the interesting part. Grove's daemon runs as root (it binds ports 80/443/53). So the runtimes it downloads live in a root-owned directory. The shims, though, run as you.</p><p>Rather than have your shell try to write into root-owned dirs (and fail), provisioning goes through the daemon — root downloads PHP, Composer and Node into the shared runtimes dir — and the shims are strictly read-only resolvers. They find what's there and exec it, replacing themselves so there's zero overhead and signals/exit codes pass through cleanly. Clean separation, no sudo in your daily loop.</p><p>And with that, Herd and Valet can go:</p><pre><code class="language-text">$ grove path install
$ # ...uninstall Herd / valet uninstall...
$ sudo grove install     # re-assert Grove's resolver + CA, just in case
</code></pre><hr><h2>grove db — snapshots, or: migrations without the knot</h2><p>You know the feeling. You've written a migration that drops a column, or backfills a table, or renames something load-bearing. You run it on your local database — the one with three weeks of hand-crafted test data you'll never reproduce — and you hope.</p><p>Grove owns your database service. So it can do something no standalone CLI can do well: snapshot it, instantly, and roll back.</p><pre><code class="language-text">$ grove db snapshot --db myapp --note "before the big migration"
✓ snapshot 20260707-164708 created (mysql, myapp, 2173 bytes)
</code></pre><p>Now run the scary thing. If it goes sideways:</p><pre><code class="language-text">$ grove db restore 20260707-164708
✓ restored snapshot 20260707-164708 into mysql (myapp)
</code></pre><p>And your three weeks of data are back, exactly as they were. Here's the full loop, start to finish:</p><pre><code class="language-text">$ grove db snapshot --db myapp --note "pre-migrate"
✓ snapshot 20260707-164708 created (mysql, myapp, 2173 bytes)

$ php artisan migrate          # ...and it eats your data...

$ grove db list
20260707-164708  mysql   myapp   2 KB  2026-07-07 16:47:08 UTC  — pre-migrate

$ grove db restore 20260707-164708
✓ restored snapshot 20260707-164708 into mysql (myapp)
</code></pre><p>It works for PostgreSQL too (<code>--engine postgres --db myapp</code>), and for MySQL you can omit <code>--db</code> to snapshot everything at once. Snapshots are plain SQL dumps under <code>$GROVE_HOME/snapshots/</code> with a small JSON index — nothing proprietary, nothing you can't read or grep. When you're done, <code>grove db rm &lt;id&gt;</code> cleans up.</p><p>Because Grove is the database supervisor, none of this needs connection strings or credentials. It knows where MySQL lives and which port it's on. You just say "snapshot," and it does.</p><h2>The theme, again</h2><p>If Grove 0.5 was about getting out of your way while you build (serving Vite over HTTPS, running your dev processes), 0.6 is about the two moments around building: setting up your terminal, and taking risks with your data.</p><p>Both used to involve another tool, a bit of ceremony, or a small prayer. Now they're one command each.</p><pre><code class="language-text">$ grove path install     # your toolchain, everywhere, auto-versioned
$ grove db snapshot      # a save point, whenever you want one
</code></pre><p>Grove auto-updates — after it relaunches, hit Tools → Restart daemon and both are live. Go delete Herd. Go run that migration. 🌱🌳</p><p>Next on the workbench: a zero-config request timeline (every request Grove proxies, with timings), and <code>grove.toml</code> + <code>grove up</code> for reproducible, one-command team environments.</p>