<h2>0.12 — Replay, reproduce, and a splash of color in your SQL</h2><h3>Why: a failing request shouldn't be a one-time event</h3><p>You know the loop. Something posts to your app, it 500s, and by the time you've added a dd() the moment is gone — you're re-triggering the flow by hand, re-filling the form, re-clicking the button. Because Grove sees every request, it can just keep them. So now it does.</p><h3>How: expand it, replay it</h3><p>The Requests timeline (and grove requests) now shows a stable id for every request, and you can expand any one to see its full headers and body. Then you replay it:</p><pre><code class="language-text">grove requests
# #142   14:03:21.882   500   POST     18ms   myapp   /checkout

grove replay 142
# replayed → 500 in 16ms (see it in `grove requests`)
</code></pre><p>Replay re-sends the captured request through Grove's whole pipeline, so it hits your app exactly as the original did — same method, headers, body — while you edit the code. Fix, replay, fix, replay. No clicking through the UI again. It's a zero-config, framework-agnostic Telescope that works for Laravel, WordPress, a raw PHP file, or a Node container all the same.</p><h3>Why: "works on my machine" should be a file you can hand someone</h3><p>A grove.toml already captured your PHP/Node versions and services. But a teammate cloning your repo still needed your data to see what you see. So we made the whole environment portable.</p><h3>How: bundle it, ship it</h3><pre><code class="language-text">grove bundle export
# wrote myapp.grovebundle — share it; restore with `grove bundle import &lt;file&gt;`
</code></pre><p>That single file contains the grove.toml, the .env, and the database — a SQLite file copied in, or a MySQL/Postgres dump taken through Grove's bundled tools. On the other end:</p><pre><code class="language-text">grove bundle import myapp.grovebundle
# unpacks → brings the environment up → loads the database
# restored to ./myapp — live at https://myapp.test
</code></pre><p>Reproducible dev environments, no Docker required. It's the fastest onboarding story we know: hand someone a file, they run one command, they're looking at the same running app with the same data.</p><h3>And a small joy: SQL that isn't a wall of gray</h3><p>The built-in Database panel's query editor now highlights your SQL — keywords, strings, numbers, comments — with a tiny, dependency-free highlighter. Small thing. Makes writing a quick select feel a lot nicer.</p><h2>0.13 — Grove catches webhooks (and writes your tests)</h2><h3>Why: everyone can catch mail; nobody catches webhooks</h3><p>Herd popularized the local mail-catcher, and it's genuinely great. But the modern pain isn't just email — it's webhooks. Stripe, GitHub, Slack, all POSTing to endpoints you can't easily see or re-run locally. You end up on <a target="_blank" rel="noopener noreferrer nofollow" href="http://webhook.site">webhook.site</a>, copying payloads by hand. Grove already owns your DNS, TLS, and tunnels — so it can be the catcher.</p><h3>How: point, capture, re-deliver</h3><p>Any request to <code>/__grove/hooks/&lt;bucket&gt;</code> on a site is captured and answered 200 — it never touches your app. Expose it publicly with the tunnel you already have:</p><pre><code class="language-text">grove share myapp
# https://calm-otter-1234.grove.li  →  myapp.test
</code></pre><p>Point Stripe at <a target="_blank" rel="noopener noreferrer nofollow" href="https://calm-otter-1234.grove.li/__grove/hooks/stripe">https://calm-otter-1234.grove.li/__grove/hooks/stripe</a>, trigger an event, and it lands in the Webhooks panel (and grove hooks) with its full payload. Now the good part — re-deliver it to your real handler while you work:</p><pre><code class="language-text">grove hooks
# #7   15:22:01   POST   stripe   /__grove/hooks/stripe

grove hooks replay 7 --to https://myapp.test/stripe/webhook
# delivered → 200 in 24ms
</code></pre><p>Trigger the real event once in Stripe. Replay it into your handler a hundred times. No more "let me make another test payment."</p><h3>Why: the best test is the request that just broke</h3><p>You captured the exact request that failed. That is your test case — you shouldn't have to retype it.</p><h3>How: copy it as a test</h3><p>From any request or webhook, copy it as a curl command, a .http file, or a Pest feature test:</p><pre><code class="language-text">grove request 142 --as pest
</code></pre><pre><code class="language-php">&lt;?php

it('POST /checkout responds', function () {
    $response = $this-&gt;postJson('/checkout', [
        'sku' =&gt; 'A1',
        'qty' =&gt; 2,
    ]);

    $response-&gt;assertStatus(500);
});
</code></pre><p>Grove reads the captured JSON body and renders it as a PHP array, sets the method and path, and asserts the status. Turn a bug you just saw into a regression test in one click — or grab the same request as curl to share in an issue. (The buttons are right there in the app, too.)</p><h3>And yes — it's lime now</h3><p>The app icon traded its orange for a bright lime. Small, cosmetic, and honestly kind of cheerful sitting in the menu bar. 🍋‍🟩</p><h2>The throughline</h2><p>Every one of these features exists because Grove sits at a layer bolted-on tools don't reach. It's the proxy, so it can remember and replay requests. It owns your config, secrets, and databases, so it can bundle a whole environment. It runs the tunnel, so it can be your webhook catcher. It captured the request, so it can write the test.</p><p>None of this gates the free core — serving sites, HTTPS, PHP/Node, databases, mail, tunnels, the request timeline, webhooks, replay, bundles, test-gen: all free and open source, forever.</p><pre><code class="language-text"># already installed? you're on your way here automatically
grove requests        # what just happened
grove replay &lt;id&gt;     # make it happen again
grove bundle export   # hand it to a teammate
grove hooks           # what the internet just sent you
</code></pre><p>Update the app (it does that itself), and go poke around. Expand a request and hit Replay. Point a webhook at Grove. Copy something as a Pest test. It's the same local dev environment you had yesterday — it just remembers a lot more now. 🌱🌳</p><p>Grove is free and open source. Try it at elyracode.com/grove.</p>