From levered
End-to-end optimization setup. Claude proposes a design, prototypes the variants in your app so you can preview and iterate in the browser, and only wires up the Levered backend once you approve.
How this skill is triggered — by the user, by Claude, or both
Slash command
/levered:growth-engineerThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
The user wants to optimize something. You own the whole flow. Be opinionated about the design, but work in two phases: **prototype first, wire up second.**
The user wants to optimize something. You own the whole flow. Be opinionated about the design, but work in two phases: prototype first, wire up second.
useVariant, and set up exposure logging.Creating the optimization in the backend and wiring useVariant too early wastes the user's time: once an optimization is live, changing factors or levels means archiving and recreating. The preview loop is where design decisions get made.
Take "$ARGUMENTS" and make it happen. The user should not need to touch the terminal or make decisions unless truly ambiguous.
Confirm the CLI is installed, silently:
levered --version
If the CLI is not found, install it:
curl -fsSL https://cli.levered.dev/install.sh | bash
Then source the user's shell profile or use ~/.levered/bin/levered so the command is available in the current session.
Do not check auth or environment yet. Login and warehouse/metric checks are deferred to the wire-up phase (step 6) — there's no point interrupting the user with a login prompt just to prototype in the browser.
Read the user's codebase. Find the component, page, or feature they want to optimize. Look at:
Reward first — always. Factors only make sense in the context of a specific goal metric. "Optimize for trial started" implies very different variants than "optimize for D7 retention" or "optimize for revenue per user." So before drafting any factor table:
Never pick the reward metric silently via name-matching against levered metrics list. Metric selection — including whether to reuse an existing metric or create a new one — happens in step 6, but the semantic reward ("what event counts as a win") must be user-confirmed before you propose any factors.
Once the reward is locked:
Design factors: What has the highest potential to move the reward metric? Pick the biggest levers available, not the safest ones. Copy is one lever — often not the strongest. Consider the full space:
Pick 1–3 factors that plausibly swing the metric by meaningful amounts. Don't pad the design with factors you don't believe in — each extra factor spreads traffic thinner. And don't restrict yourself to copy swaps just because they're easy to implement; if removing a step is the highest-leverage change, propose removing the step.
Design factors so every combination is coherent. This is the core rule: a user must never be served a variant whose factor levels contradict each other. Coherence is a property of how you cut the factors — make incoherent variants impossible by construction, rather than producing them and cleaning up afterward.
message: "trust headline + security line" / "speed headline + benefit line" — so an incoherent pairing can't be produced. This also cuts the variant count (faster learning) and keeps every variant shippable.The test, applied to the whole grid: as you settle on factors, mentally expand the full cross-product and read each cell as a real screen. If any cell would be incoherent, the factor design is wrong — compose the offending dimensions, merge levels, or redefine them until every combination tells a coherent story. Within that constraint, keep factors as independent as you can: don't over-compose. The mistakes aren't symmetric — an over-factored design just learns a bit slower and you can recompose next round (visible, recoverable), whereas wrongly merging dimensions hard-codes your guess about which pairings win and silently forfeits discovering the combination that would have won (invisible loss). So compose exactly enough to guarantee coherence, and no more.
Suppressing individual variant combinations is a last resort for rare extreme cases where no clean factor cut avoids a clash — not the normal tool. The default is to make incoherence impossible by construction; reach for per-combination suppression only when restructuring genuinely can't. When you truly must, pass --excluded-combinations to levered optimizations create with a JSON array of factor→level maps (partial maps allowed — e.g. [{"visual":"family_photo","message":"tax_complexity"}]); every variant matching a map is then never served. The baseline (all first-level factors) can't be excluded, and at least two variants must remain servable. Variants can also be disabled after they appear in results. Both are escape hatches — prefer designing the clash away.
Exclude colors. Colors are not a real lever — they almost never move conversion meaningfully. Don't propose them.
Don't invent content, period. Variants must test presentation of what exists — not introduce claims, features, or content the app doesn't actually have. This is broader than commercial terms; it applies to everything:
Every invented element makes the variant un-shippable — if it wins, the business still can't deploy it. If you don't know whether something is real, stop and ask the user. Don't assume and don't fabricate plausible-looking placeholders. Reframing, re-ordering, or showing/hiding real content is fine; inventing new assertions is not.
When you present the plan, briefly explain why you chose these factors — the hypothesis about why they'll move the metric.
Before creating anything or touching code, present the proposed reward, factors, and hypothesis in a short message. Keep it to one short paragraph plus a factor table — not a menu of alternatives to pick from, but a concrete plan the user can approve or redirect. End with a single closing question like "Want me to prototype these in the app so you can click through them?"
Factor table format. Use a markdown table with two columns: Factor and Levels. Render each level on its own row inside the Levels cell (use <br> to break lines). Never inline levels with " · " separators on a single line, and never prefix them with L1: / L2: / L3: — the position in the list already conveys order, and inline forms are hard to scan.
Don't narrate the rules you're following. Present factors, levels, and the positive hypothesis for why they'll move the metric. Then stop. Do not add trailing lines like "no invented content / no fabricated stats" or "excluding colors since they don't move the metric" — these read as defensive and waste the user's attention on the obvious. Just follow the rule; don't announce that you're following it. If the user later asks why something is missing, explain then.
Example:
| Factor | Levels |
|---|---|
| `onboarding_length` | 2 questions (goal + frequency)<br>1 question (goal only) |
| `plan_screen_emphasis` | Plan-first headline<br>Trial-first headline |
Do not edit application code yet. If they push back on a factor, revise and re-propose rather than starting the prototype.
Once the user approves the design, implement the variants locally so they can click through every level in the browser — without creating anything in Levered's backend. This is the design-review phase.
For React apps, the preview tool is LeveredAdminMenu from @levered_dev/sdk/react. It's a floating admin pill that lets the user override factor values at runtime. Set it up like this:
Install the SDK if not already present and wrap the app root in LeveredProvider — no optimizationId is needed for preview; you just need the provider so the menu component works. Pull the API URL from an env var using whichever style the app already uses, so the same build works against local / testing / prod. Default to prod only so the provider mounts — during prototype the admin menu overrides the variant, no API call is needed.
Vite apps (import.meta.env is Vite-only — VITE_ prefix):
import { LeveredProvider } from '@levered_dev/sdk/react';
const LEVERED_API_URL =
import.meta.env.VITE_LEVERED_API_URL ?? 'https://api.levered.dev';
<LeveredProvider apiUrl={LEVERED_API_URL} anonymousId={anonymousId}>
<App />
</LeveredProvider>
Next.js apps (NEXT_PUBLIC_ prefix required for client-side reads):
import { LeveredProvider } from '@levered_dev/sdk/react';
const LEVERED_API_URL =
process.env.NEXT_PUBLIC_LEVERED_API_URL ?? 'https://api.levered.dev';
<LeveredProvider apiUrl={LEVERED_API_URL} anonymousId={anonymousId}>
<App />
</LeveredProvider>
For other setups, match the framework's own convention (CRA: REACT_APP_, etc.). Using the wrong prefix silently falls back to prod, so make sure the env var actually reaches the client bundle.
Define factors as local state, with fallback values matching today's UI (so the baseline is the current experience):
const FALLBACK = {
results_reveal: 'none',
plan_price_framing: 'free_trial_first',
social_proof_placement: 'plan_only',
}
const ADMIN_VARIANTS = [
{ name: 'results_reveal', label: 'Results Reveal',
options: [{ value: 'none' }, { value: 'analyzing_only' }, { value: 'analyzing_plus_projection' }] },
// ...
]
const [override, setOverride] = useState<Record<string, string | number | boolean>>(FALLBACK)
const active = { ...FALLBACK, ...override }
Render the admin menu near the app root:
<LeveredAdminMenu
enabled
variants={ADMIN_VARIANTS}
currentValues={active}
onOverride={(o) => setOverride(o as Record<string, string>)}
onReset={() => setOverride(FALLBACK)}
/>
Branch the UI on active.<factor> to implement each level. Structural/flow/layout factors may require new components or altered step sequences — that's expected, and why we do this before wire-up.
Guide the user to preview. After you implement, tell them exactly how to try it:
results_reveal = analyzing_plus_projection with plan_price_framing = anchored_price — that's the boldest cell").For non-React apps, fall back to a query-param switch or feature-flag toggle and document it for the user in the same way.
Expect multiple rounds. The user will look at variants and want to change things: reword a level, add/remove a level, drop a factor, rethink the structural change. Each time:
FALLBACK / ADMIN_VARIANTS definitions if factors/levels changed).Only enter this step once the user has explicitly approved the prototype.
levered whoami
levered env
levered warehouse status
levered metrics list
levered login (requires a browser) and stop.levered env use <prod|testing> based on what the app's apiUrl points at.levered-platform skill for the endpoints + fields, and have the user create an API key at Settings > API Keys.levered metrics list along with what each one's SQL actually captures, and confirm which to use (or offer to create a new one). Never pick by name-matching alone — a metric called "Purchase" may not track what the user actually wants rewarded. Only proceed once the user confirms the metric ID to bind to the optimization.levered optimizations create \
--name "..." \
--design-factors '[...]' \
--reward-metric-id <uuid> \
--model-type cmab \
--reward-name reward \
--reward-type bool
The --design-factors JSON must match the factors and levels the user just approved in the prototype. Choose a clear, descriptive name. Don't ask the user what to name it.
useVariant (swap the preview scaffold)Now replace the local-override scaffolding with a real useVariant hook bound to the optimization you just created. The fallback must stay the same — it's already the current UI.
Add the onExposure callback to the provider. Without it, Levered has no data to train on. Keep the env-driven apiUrl from the prototype step. For a connected warehouse, log the exposure into the customer's own warehouse (via their analytics pipeline):
<LeveredProvider
apiUrl={LEVERED_API_URL}
anonymousId={anonymousId}
onExposure={(exposure) => {
analytics.track('levered_exposure', {
optimization_id: exposure.optimizationId,
anonymous_id: exposure.anonymousId,
variant: exposure.variant,
timestamp: new Date().toISOString(),
});
}}
>
...
</LeveredProvider>
If the org is on the Managed Warehouse (from step 6), don't log to a customer warehouse — POST the exposure to Levered's ingestion API instead, and send the reward at the conversion point. Both use the API key from an env var (e.g. LEVERED_API_KEY):
onExposure={(exposure) =>
fetch(`${LEVERED_API_URL}/api/v2/ingest/exposures`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.LEVERED_API_KEY}`,
},
body: JSON.stringify({
events: [{
anonymous_id: exposure.anonymousId,
optimization_id: exposure.optimizationId,
variant: exposure.variant,
}],
}),
})
}
At the conversion point, POST /api/v2/ingest/rewards with { events: [{ anonymous_id, name: '<reward-name>', value: 1 }] }. See the Managed Warehouse section of the levered-platform skill for all fields and response codes.
Swap override state for useVariant in the target component:
import { useVariant } from '@levered_dev/sdk/react';
const { variant } = useVariant({
optimizationId: '<the-uuid-you-just-created>',
fallback: FALLBACK, // same object used in the prototype
});
const active = variant ?? FALLBACK
Keep LeveredAdminMenu for internal QA — pass enabled={process.env.NODE_ENV !== 'production'} so it disappears in prod.
Handle anonymous ID — use whatever the app already has (cookies, session IDs, analytics IDs). If nothing exists, generate a UUID in localStorage.
Set up exposure logging — use whatever pipeline the app already has (Segment, Rudderstack, PostHog, direct warehouse inserts). The exposure must land in the warehouse with anonymous_id, optimization_id, variant, and timestamp columns.
For non-React apps, use LeveredClient directly instead of the hook.
Docs: Integrate the SDK.
Tell the user what you did in 3-4 sentences:
Don't dump CLI output. Don't over-explain. Be brief and confident.
levered optimizations create or swap in useVariant before the user has seen the variants in the browser and explicitly approved them. The preview loop is where design decisions get made — once the optimization exists in the backend, changing factors means archiving and recreating.FALLBACK object during prototyping (and useVariant fallback during wire-up) is always the current live experience, so the baseline is an unchanged user journey.Provides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.
npx claudepluginhub levered-hq/claude-plugin --plugin levered