From growthbook
Stop a running GrowthBook experiment via the REST API, optionally declaring a winning variation and rolling it out to 100% of eligible traffic. Use when the user says "stop this experiment", "end the A/B test", "declare a winner for X", "ship the winning variation", "roll back the test", or "we're done with this experiment". For interpreting results before deciding, use experiment-analyze first.
How this skill is triggered — by the user, by Claude, or both
Slash command
/growthbook:experiment-stopThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Stop a running experiment, optionally declaring a winning variation and ramping it to all eligible traffic via a temporary rollout. The endpoint is `POST /api/v1/experiments/<id>/stop` (a dedicated endpoint, not the generic update). All variation references are **variation ID strings** like `var_abc123`, not 0-based integer indexes.
Stop a running experiment, optionally declaring a winning variation and ramping it to all eligible traffic via a temporary rollout. The endpoint is POST /api/v1/experiments/<id>/stop (a dedicated endpoint, not the generic update). All variation references are variation ID strings like var_abc123, not 0-based integer indexes.
All API calls go through the bundled helper: ${CLAUDE_PLUGIN_ROOT}/scripts/gb-call. It needs GB_API_KEY — set in your shell, or written to ~/.config/growthbook/.env by /growthbook:gb-setup. If unset or invalid, gb-call's error message points back at /growthbook:gb-setup.
Fetch the current experiment.
gb-call GET /api/v1/experiments/<experiment-id>
Check the status field. Only running experiments should be stopped via this skill. If status === "draft", the experiment hasn't started — the user wants to delete it, not stop it (different operation). If status === "stopped", it's already done.
Also capture the type field. If type === "multi-armed-bandit", halt and tell the user this skill targets standard A/B tests; bandits have their own lifecycle (stop is similar but interpretation and rollout differ — recommend they review in the UI before scripting).
Show the user the variations table. Surface the variations as the API records them — capture each one's variationId (the string ID, e.g. var_treatment_a) and name. The user picks by the variation ID string, not by index:
The experiment has these variations:
var_control 0: Control — <description> (lift: baseline, users: N)
var_treatment_a 1: Treatment A — <description> (lift: +2.3%, users: N)
var_treatment_b 2: Treatment B — <description> (lift: -0.8%, users: N)
Which variation should ship? Reply with the variation ID (e.g. var_treatment_a),
or say "no winner" to stop without declaring.
If the user has not already run experiment-analyze, suggest doing that first so the decision is informed.
Decide on temporary rollout. If the user has a winner and wants to ship now, offer the temporary-rollout path:
"Want me to also enable a temporary rollout? That keeps this experiment in the SDK payload and forces 100% of eligible traffic to
<winnerVariationId>. It's the cleanest 'ship the winner' option — the linked feature flag's rule stays in place but routes everyone to the winner. You can toggle it off later withmodify-temporary-rolloutor clean up the rule viaflag-targeting."
If yes, set enableTemporaryRollout: true and releasedVariationId: <winner ID> in the payload. If no, the experiment stops but you leave the flag alone — surface that the user will need to clean up the experiment-ref rule manually.
Confirm intent. Restate the action in plain English:
"Stopping experiment '', declaring variation
var_treatment_a(Treatment A) as the winner, and enabling temporary rollout to ship it to 100% of eligible traffic."
Get explicit confirmation before posting. Stopping itself is reversible (you can restart), but declaring a winner and enabling a rollout produces downstream signals — don't do it on a hunch.
Build the payload. The body is flat; there is no nested resultSummary.
Stop without a declared winner:
{ "results": "inconclusive" }
Stop with a declared winner, no rollout:
{
"results": "won",
"winnerVariationId": "<winner variation ID>",
"analysis": "<one-paragraph markdown summary of the decision>"
}
Stop with a declared winner and ship via temporary rollout:
{
"results": "won",
"winnerVariationId": "<winner variation ID>",
"releasedVariationId": "<winner variation ID>",
"enableTemporaryRollout": true,
"analysis": "<one-paragraph markdown summary of the decision>"
}
Field reference:
results — required. One of "won", "lost", "inconclusive", "dnf" (did not finish).winnerVariationId — string variation ID (e.g. var_abc123). Required when results === "won" and the experiment has multiple test variations.releasedVariationId — string variation ID. Required when enableTemporaryRollout: true. Usually equals winnerVariationId.enableTemporaryRollout — boolean. Keeps the stopped experiment in the SDK payload and forces traffic to the releasedVariationId.analysis — markdown summary shown on the experiment results page.reason — optional reason text stored on the latest phase metadata.dateEnded — optional ISO datetime; defaults to now.Post the update.
echo '<payload-json>' | gb-call POST /api/v1/experiments/<experiment-id>/stop -
State what happens next, and link to the experiment. Tell the user:
analysis, and the rollout status:
<host>/experiment/<experiment-id>
Derive <host> from GB_API_URL by swapping api. → app. (matches experiment-launch's convention; on the default cloud host this produces https://app.growthbook.io).
What happens to the flag? Surface the disposition clearly based on what was sent:With temporary rollout (enableTemporaryRollout: true): the winner is live — traffic is already routed to it via the existing experiment-ref rule. No further action required until the team decides to clean up the flag (which can happen days or weeks later). When ready:
flag-rules, add a permanent force rule for the winner via flag-targeting.flag-cleanup to walk through code cleanup and archive/delete the flag.echo '{"enableTemporaryRollout": false}' | gb-call POST /api/v1/experiments/<experiment-id>/modify-temporary-rollout -), then remove the experiment-ref rule via flag-rules.Without temporary rollout: the experiment-ref rule is still on the flag, routing traffic to a stopped experiment (users will get the control value). The flag needs attention:
defaultValue to the winner's value via flag-default-value, then remove the experiment-ref rule via flag-rules. Or use flag-targeting to add a permanent force rule serving the winner, then remove the experiment-ref rule.flag-rules and the flag returns to its pre-experiment state.flag-cleanup to inline the value in code and archive/delete the flag.winnerVariationId is a variation ID string (e.g. var_abc123), not an integer index, not a name, not the variation's key. Get this wrong and the request 400s or the wrong variation is recorded as the winner.POST /api/v1/experiments/<id>/stop, not POST /api/v1/experiments/<id>. The body shape is flat — there is no resultSummary wrapper. The generic update endpoint exists but takes different fields; use the dedicated stop endpoint here.winnerVariationId; the safety is enforced here, not server-side.draft experiment isn't running — what the user wants there is DELETE /api/v1/experiments/<id> (separate skill, not covered here). Surface the confusion if they ask to stop a draft.results / winnerVariationId / analysis.type === "multi-armed-bandit" experiments need different handling — halt and tell the user.releasedVariationId is required when enableTemporaryRollout: true. The API rejects the combination otherwise. They're usually the same as winnerVariationId but don't have to be — e.g., a "lost" result that rolls everyone back to control would set releasedVariationId: <control variation ID> with results: "lost".experiment-ref rule from the linked flag. Without a temporary rollout, the flag keeps routing to a stale experiment until the user cleans the rule up.analysis should explain the decision in plain English (markdown). Future readers (including future-self) will want context. Don't leave it blank when declaring a winner.experiment-analyze first if the user hasn't. Stopping based on a glance at the dashboard is a common mistake — interim numbers can flip, and the data-quality checks in experiment-analyze can flag results that look conclusive but aren't.GET /api/v1/experiments/<id> — fetch state, variations, and typePOST /api/v1/experiments/<id>/stop — stop and optionally declare a winner + temporary rolloutPOST /api/v1/experiments/<id>/modify-temporary-rollout — toggle the temporary rollout off (or on) after stopping, without re-running this skillexperiment-analyze — run first if the user wants to interpret results before deciding.flag-rules — remove the experiment-ref rule after stopping (always needed eventually).flag-targeting — add a permanent force rule serving the winner value (replaces the experiment-ref rule).flag-default-value — set the flag's default to the winner value when shipping without a targeting rule.flag-cleanup — if the feature is fully shipped and the flag should be removed from code and archived.experiment-design and experiment-launch — for the next test if this one informed a follow-up.npx claudepluginhub growthbook/skills --plugin growthbookLaunch a GrowthBook A/B test end-to-end via the REST API — create the experiment, prep the feature flag, wire the experiment-ref rule, and start the experiment. Use when the user says "launch this experiment", "create the experiment", "wire up the A/B test", "kick off the test", "set up X as an experiment in GrowthBook", "start the experiment for flag Y", or "I already have a flag and want to run an experiment on it". Works for both experiment-first (creates the flag) and flag-first (detects the existing flag via the reuse path and wires the experiment to it). For designing the spec first, use experiment-design. For stopping a running experiment, use experiment-stop. For interpreting results, use experiment-analyze.
Guides you through designing, creating, and running A/B experiments in LaunchDarkly—configuring metrics, treatments, flag rules, starting iterations, swapping treatments, and declaring a winner.
Audits PostHog A/B experiments for validity threats (SRM, contamination, exposure stalls, flag mutations) and lifecycle drift (zombies, decided-but-running), filing validated reports.