diff --git a/skills/flags-sdk/SKILL.md b/skills/flags-sdk/SKILL.md index 686454d7..51a31445 100644 --- a/skills/flags-sdk/SKILL.md +++ b/skills/flags-sdk/SKILL.md @@ -2,15 +2,14 @@ name: flags-sdk description: > Set up and use feature flags and A/B tests with the Flags SDK (`flags` npm package) and Vercel Flags. - Use when installing or configuring the SDK, adding a flag, wiring `vercelAdapter` / FLAGS env vars, - declaring flags with `flag()`, using `vercel flags` CLI (create, list, enable, disable, inspect, - archive, rm, sdk-keys), setting up providers/adapters (Vercel, Statsig, LaunchDarkly, PostHog, - GrowthBook, Global Config, OpenFeature, Split, Flagsmith, Reflag, Optimizely, or custom), - precompute, `identify`/`dedupe`, Flags Explorer/Toolbar, Next.js or SvelteKit, custom adapters, - or encrypting/decrypting flag values. - Triggers: set up feature flags, install Flags SDK, add a feature flag, feature flags, - A/B testing, experimentation, flags SDK, flag adapters, precompute, Flags Explorer, - feature gates, flag overrides, Vercel Flags, vercel flags CLI, vercel flags create/list/enable/disable, + Use when installing or configuring the SDK, adding a new or existing flag, wiring `vercelAdapter` + (OIDC or SDK keys), declaring flags with `flag()`, using the `vercel flags` CLI (create, inspect, list, + enable, disable, set, update, split, rollout, rules, segments, use-targeting, evaluations, versions, + open, archive, unarchive, rm, sdk-keys, override, prepare), setting up providers/adapters (Vercel, Statsig, LaunchDarkly, + PostHog, GrowthBook, Global Config, OpenFeature, Split, Flagsmith, Reflag, Optimizely, or custom), + precompute, `identify`/`dedupe`, Flags Explorer/Toolbar, Next.js or SvelteKit, or encrypting flag values. + Triggers: feature flags, feature gates, A/B testing, experimentation, gradual rollout, traffic split, + targeting rules, flag overrides, precompute, Flags Explorer, Vercel Flags, vercel flags CLI, `flags/next`, `flags/sveltekit`, `flags/react`, `@flags-sdk/*`. --- @@ -21,7 +20,7 @@ The Flags SDK (`flags` npm package) is a feature flags toolkit for Next.js and S - Docs: https://flags-sdk.dev - Repo: https://github.com/vercel/flags -When the user asks to install, configure, or set up feature flags, follow [Set up the SDK](#set-up-the-sdk) (including `vercel env pull` when `FLAGS` is missing). When they ask to create or add a flag, follow [Create a flag](#create-a-flag). Do not leave CLI steps as "next steps" for the user — execute them yourself. +When the user asks to install, configure, or set up feature flags, follow [Set up the SDK](#set-up-the-sdk) (including `vercel env pull` when `.env.local` is missing). When they ask to create or add a flag, follow [Create a flag](#create-a-flag). Do not leave CLI steps as "next steps" for the user — execute them yourself. ## Core concepts @@ -62,7 +61,7 @@ export const exampleFlag = flag({ ## Set up the SDK -One-time project setup. Run this when the Flags SDK is not installed yet, or when Toolbar / Flags Explorer / `FLAGS` env are missing. Skip any step that is already done. +One-time project setup. Run this when the Flags SDK is not installed yet, or when Toolbar / Flags Explorer / `.env.local` are missing. Skip any step that is already done. ### Before you start @@ -71,7 +70,7 @@ Check the project state to adapt commands and decide which steps you can skip: - Which lockfile is present (`pnpm-lock.yaml`, `package-lock.json`, `yarn.lock`, `bun.lockb`)? → Adapt all package manager commands accordingly (`pnpm add`, `npm install`, `yarn add`, `bun add`). - Is `flags` in `package.json`? → Skip install (step 1) - Does `.vercel/` directory exist? → Project is linked, skip `vercel link` in step 2 -- Does `.env.local` contain `FLAGS=`? → Env vars already pulled, skip step 3 +- Does `.env.local` contain `VERCEL_OIDC_TOKEN=` (or a `FLAGS=` SDK key)? → Env vars already pulled, skip step 3 - Is `@vercel/toolbar` in `package.json`? → Skip toolbar setup (step 4) - Does `flags.ts` (or `lib/flags.ts`, `src/flags.ts`) exist? → Skip creating it (step 5) - Does `app/.well-known/vercel/flags/route.ts` exist? → Flags Explorer already set up, skip step 6 @@ -88,7 +87,7 @@ Check the project state to adapt commands and decide which steps you can skip: Check for a `.vercel` directory in the project root. If it doesn't exist, run `vercel link`. -3. **Pull environment variables**: If `.env.local` lacks `FLAGS=`, run `vercel env pull`. Required for `vercelAdapter` when flags already exist on Vercel (fresh clone / configure). If no flags exist on Vercel yet, skip — `FLAGS` is written when you create a flag (see [Create a flag](#create-a-flag)). Setup-only still needs `FLAGS_SECRET` for Flags Explorer / overrides — generate it per [FLAGS_SECRET](#flags_secret) if missing after pull. +3. **Pull environment variables**: If `.env.local` lacks `VERCEL_OIDC_TOKEN=`, follow [Pull environment variables](#pull-environment-variables). 4. **Set up the Vercel Toolbar** (if not already present): - Run `pnpm i @vercel/toolbar` @@ -100,14 +99,24 @@ Check the project state to adapt commands and decide which steps you can skip: 6. **Set up Flags Explorer** (if not already present): Create `app/.well-known/vercel/flags/route.ts` — see [Flags Explorer setup](#flags-explorer-setup). Do this only after `flags.ts` exists. Point the import at the real flags file path (the snippet assumes root `flags.ts`). +## Pull environment variables + +`vercel env pull` writes the Development credentials to `.env.local`: the Vercel OIDC token that `vercelAdapter` uses locally (deployments receive it automatically, [Getting started](https://vercel.com/docs/flags/vercel-flags/quickstart#pull-local-openid-connect-credentials)) and the Development `FLAGS_SECRET` for Flags Explorer and overrides. Run it when: + +- `.env.local` lacks `VERCEL_OIDC_TOKEN=` (or a `FLAGS=` SDK key) +- you created the project's first flag; activating Vercel Flags creates a `FLAGS_SECRET` per environment +- local evaluation fails with an authentication error; the SDK refreshes an expired token through the linked project, re-pulling is the fallback + +SDK keys (`FLAGS`) are only for apps outside Vercel, custom environments, or flags of another project ([SDK Keys](https://vercel.com/docs/flags/vercel-flags/dashboard/sdk-keys)). If `FLAGS_SECRET` is still missing after the pull, generate it per [FLAGS_SECRET](#flags_secret). + ## Create a flag -When a user asks you to create or add a feature flag, follow these steps in order. +When a user asks you to create or add a feature flag that does not exist on Vercel yet, follow these steps in order. If the flag was already created in the dashboard (the prompt says so, or `vercel flags create` reports the key exists), follow [Add a flag that already exists on Vercel](#add-a-flag-that-already-exists-on-vercel) instead. ### Before you start -- Complete [Set up the SDK](#set-up-the-sdk) first if packages, Vercel link, `FLAGS` env, Toolbar, `flags.ts`, or Flags Explorer are missing. Skip steps that are already done. -- Does `.env.local` contain `FLAGS=`? → Env vars already pulled; still re-pull after creating a new flag if evaluation fails. +- Complete [Set up the SDK](#set-up-the-sdk) first if packages, Vercel link, `.env.local`, Toolbar, `flags.ts`, or Flags Explorer are missing. Skip steps that are already done. +- Does `.env.local` contain `VERCEL_OIDC_TOKEN=`? → Env vars already pulled; see [Pull environment variables](#pull-environment-variables) if local evaluation fails with an authentication error. - Does `flags.ts` (or `lib/flags.ts`, `src/flags.ts`) exist? → Add to it rather than creating from scratch. ### Steps @@ -118,7 +127,7 @@ When a user asks you to create or add a feature flag, follow these steps in orde Before running `vercel flags create`, verify the project is linked (`.vercel` directory). If missing, run `vercel link` first. -3. **Pull environment variables**: Run `vercel env pull` to write `FLAGS` and `FLAGS_SECRET` to `.env.local`. Without these environment variables, `vercelAdapter` will not be able to evaluate flags. This step is **mandatory** after creating a flag. +3. **Pull environment variables**: If this is the project's first flag, follow [Pull environment variables](#pull-environment-variables) again; activation created the `FLAGS_SECRET`. 4. **Declare the flag in code**: Add it to `flags.ts` (or create the file if it doesn't exist) using `vercelAdapter`: ```ts @@ -141,13 +150,39 @@ When a user asks you to create or add a feature flag, follow these steps in orde } ``` +## Add a flag that already exists on Vercel + +Use this flow when the flag was created in the dashboard or by someone else, for example when the prompt says the flag "has already been created" or asks you to run `vercel flags inspect`. Do not run `vercel flags create` for an existing key. + +1. **Ensure the SDK is set up**: Follow [Set up the SDK](#set-up-the-sdk) if needed. +2. **Read the definition**: Run `vercel flags inspect `. Note the kind, the variants (value and label), the description, and what each environment serves. +3. **Pull environment variables**: If `.env.local` lacks `VERCEL_OIDC_TOKEN=`, follow [Pull environment variables](#pull-environment-variables). +4. **Declare the flag**: Add it to `flags.ts` with `vercelAdapter`. Map the `inspect` output: + - `key`: the flag key exactly as printed + - kind → type parameter: `boolean` → `flag`, `string` → `flag`, `number` → `flag`, `json` → `flag` + - `description`: copy from `inspect` + - `defaultValue`: the value to serve when the flag is archived or evaluation fails (usually what production serves today) + - `options`: optional; mirror the variants when you use precompute or want them listed in Flags Explorer + - `identify`: add or reuse one when the flag has targeting, using the entity attributes configured in the dashboard (see [Flag with evaluation context](#flag-with-evaluation-context)) + ```ts + export const welcomeMessage = flag({ + key: 'welcome-message', + description: 'Copy shown on the landing page', + defaultValue: 'control', + adapter: vercelAdapter, + }); + ``` +5. **Use the flag** as in [Create a flag](#create-a-flag) step 5. + ## Vercel Flags -Vercel Flags is Vercel's feature flags platform. You create and manage flags from the Vercel dashboard or the `vercel flags` CLI, then connect them to your code with the `@flags-sdk/vercel` adapter. When you create a flag in Vercel, the `FLAGS` and `FLAGS_SECRET` environment variables are configured automatically. +Vercel Flags is Vercel's feature flags platform. You create and manage flags from the Vercel dashboard or the `vercel flags` CLI, then connect them to your code with the `@flags-sdk/vercel` adapter. `vercelAdapter()` authenticates with the project's Vercel OIDC token and evaluates the configuration of the current environment; SDK keys (`FLAGS`) are for manual authentication only ([SDK Keys](https://vercel.com/docs/flags/vercel-flags/dashboard/sdk-keys)). Activating Vercel Flags creates a `FLAGS_SECRET` per environment for Flags Explorer. + +To install the SDK, follow [Set up the SDK](#set-up-the-sdk). To create a flag end-to-end, follow [Create a flag](#create-a-flag). For a flag that already exists on Vercel, follow [Add a flag that already exists on Vercel](#add-a-flag-that-already-exists-on-vercel). -To install the SDK, follow [Set up the SDK](#set-up-the-sdk). To create a flag end-to-end, follow [Create a flag](#create-a-flag). +For the full Vercel provider reference — user targeting, how the CLI maps to the SDK (keys, kinds, targeting attributes, SDK keys, overrides, `prepare`), lifecycle and safety, custom adapter configuration, and Flags Explorer setup — see [references/providers.md](references/providers.md#vercel). -For the full Vercel provider reference — user targeting, `vercel flags` CLI subcommands, custom adapter configuration, and Flags Explorer setup — see [references/providers.md](references/providers.md#vercel). +For the current `vercel flags` subcommands and options (targeting, splits, rollouts, rules, segments, evaluations, versions, and more), run `vercel flags --help` or `vercel flags --help`. For CLI-wide contracts (linking, non-interactive mode, output parsing), use the `vercel-cli` skill. ## Declaring flags @@ -199,6 +234,8 @@ export const dashboardFlag = flag({ }); ``` +With `vercelAdapter`, the entity and attribute names in the returned object (`user.id` here) are what dashboard rules and `vercel flags split|rollout|rules --by` target. They must match the entities configured in the dashboard. See [references/providers.md — User targeting](references/providers.md#user-targeting). + ### Flag with another adapter Adapters connect flags to third-party providers. Each adapter replaces `decide` and `origin`: diff --git a/skills/flags-sdk/references/providers.md b/skills/flags-sdk/references/providers.md index cf5dbc27..525499f7 100644 --- a/skills/flags-sdk/references/providers.md +++ b/skills/flags-sdk/references/providers.md @@ -32,7 +32,7 @@ pnpm i flags @flags-sdk/vercel Before running any `vercel flags` command, verify the project is linked to Vercel. Check for a `.vercel` directory in the project root. If it doesn't exist, run `vercel link` first. 1. Create a flag in the Vercel dashboard or via CLI: `vercel flags create --kind boolean --description ""` -2. Pull env vars: you **must** run `vercel env pull` to write `FLAGS` and `FLAGS_SECRET` to `.env.local`. Without these environment variables, `vercelAdapter` will not be able to evaluate flags. +2. Pull env vars: run `vercel env pull` to write the Vercel OIDC token and the Development `FLAGS_SECRET` to `.env.local` ([Pull environment variables](../SKILL.md#pull-environment-variables)). See [Authentication](#how-the-cli-connects-to-the-sdk) for SDK keys. 3. Declare the flag: ```ts @@ -68,6 +68,8 @@ export const exampleFlag = flag({ }); ``` +Define the entities and attributes under Flags → Entities in the dashboard before you use them in rules or segments, and return the same names from `identify` ([Entities](https://vercel.com/docs/flags/vercel-flags/dashboard/entities)). The example above allows `--by user.id` / `--by team.id` in `vercel flags split`, `rollout`, and `rules add`, and the matching conditions in dashboard rules. Entities are evaluated fresh on every call; a rule whose attribute is missing from the context is skipped. See [How the CLI connects to the SDK](#how-the-cli-connects-to-the-sdk). + ### Flags Explorer ```ts @@ -101,7 +103,7 @@ If the app also uses `@vercel/flags-core` directly, create the client once and p import { createClient } from '@vercel/flags-core'; import { createVercelAdapter } from '@flags-sdk/vercel'; -const vercelFlagsClient = createClient(process.env.FLAGS); +const vercelFlagsClient = createClient(); // Vercel OIDC token, on deployments and after `vercel env pull` const vercelAdapter = createVercelAdapter(vercelFlagsClient); export const exampleFlag = flag({ @@ -110,84 +112,37 @@ export const exampleFlag = flag({ }); ``` -### `vercel flags` CLI - -Manage Vercel Flags from the terminal. Requires the [Vercel CLI](https://vercel.com/docs/cli) and a linked project. - -> **Prerequisite**: The Vercel CLI must be installed (`pnpm i -g vercel`) and the project must be linked (`vercel link` — check for a `.vercel` directory). For authentication issues, read and follow the `vercel-cli` skill. - -#### Subcommands - -| Subcommand | Description | -| ------------ | ----------------------------------------------------- | -| `list` | List all flags in the project | -| `create` | Create a new flag | -| `inspect` | Show details, status, and targeting rules of a flag | -| `enable` | Enable a boolean flag for a specific environment | -| `disable` | Disable a boolean flag for a specific environment | -| `archive` | Archive a flag (required before deleting) | -| `rm` | Delete an archived flag | -| `sdk-keys` | Manage SDK keys (subcommands: `ls`, `add`, `rm`) | - -#### Create and toggle a flag - -```bash -# Create a boolean flag with a description -vercel flags create my-feature --kind boolean --description "New onboarding flow" - -# Enable in development first -vercel flags enable my-feature --environment development - -# Promote to production -vercel flags enable my-feature --environment production - -# Disable in production -vercel flags disable my-feature --environment production - -# Change string variant in production -vercel flags set my-feature -e production --variant my-variant -``` +Outside Vercel, pass the SDK key: `createClient(process.env.FLAGS)`. Unlike `vercelAdapter()`, `createClient()` does not read `FLAGS` on its own. -`enable` and `disable` only work with boolean flags. For changing the state of other flag types, use the `set` command. Use the vercel-cli skill for full reference. - - -#### Inspect and list flags - -```bash -# Show details of a specific flag (status, environments, targeting rules) -vercel flags inspect my-feature - -# List all flags in the project -vercel flags list -``` - -#### Archive and delete a flag - -A flag must be archived before it can be deleted: +### `vercel flags` CLI -```bash -vercel flags archive my-feature -vercel flags rm my-feature -``` +Manage Vercel Flags from the terminal. Install, link, and `vercel env pull` requirements are in [Setup](#setup) above. -#### Manage SDK keys +For the current subcommand list and options, run `vercel flags --help` or `vercel flags --help`. For CLI-wide contracts (linking, `--non-interactive`, `--yes`, parsing stdout) follow the `vercel-cli` skill. This section covers only what `--help` cannot tell you. -SDK keys connect your application to Vercel Flags. The `FLAGS` environment variable contains an SDK key. +#### How the CLI connects to the SDK -```bash -# List SDK keys for the project -vercel flags sdk-keys ls +- **Key**: the flag slug you pass to the CLI is the `key` in `flag()`. The flag returns one of the variants you created on Vercel ([Run an A/B test](https://vercel.com/docs/flags/vercel-flags/cli/run-ab-test)). +- **Kind → type**: `inspect ` prints the kind and variants. `boolean` → `flag()`, `string` → `flag()`, `number` → `flag()`, `json` → `flag()`. The kind is fixed at creation and cannot be changed ([Flag types](https://vercel.com/docs/flags/vercel-flags/dashboard/feature-flag#flag-types)). +- **Variants → `options`**: `options` on the declaration are optional. They give Flags Explorer a dropdown, pre-fill the dashboard when a draft is promoted, and let precompute serialize values and `generatePermutations` enumerate them ([Declaring options](https://vercel.com/docs/flags/vercel-flags/sdks/flags-sdk#declaring-options)). When you declare them, keep them equal to the variants `inspect` shows. +- **`defaultValue`**: a flag that is archived, or declared in code but not created on Vercel (a draft), evaluates to `defaultValue`. Without `defaultValue`, evaluation throws ([Archive](https://vercel.com/docs/flags/vercel-flags/dashboard/archive#what-happens-when-you-archive), [Drafts](https://vercel.com/docs/flags/vercel-flags/dashboard/drafts#draft-behavior)). +- **Targeting attributes**: `split`, `rollout`, and `rules add` take `--by .` (and `--condition .::`). Define the entity and attribute under Flags → Entities first, and return the same names from `identify()`; the docs use a `User` entity with an `id` attribute and `--by user.id` ([Roll out a feature](https://vercel.com/docs/flags/vercel-flags/cli/roll-out-feature), [Entities](https://vercel.com/docs/flags/vercel-flags/dashboard/entities)). When the attribute is missing from the context, a split or rollout serves its fallback variant (`--default-variant` in the CLI) and a rule that references it is skipped. Verify with `evaluations`. +- **Authentication**: on Vercel, `vercelAdapter()` authenticates with the project's OIDC token and uses the configuration of the current environment; `vercel env pull` brings that credential to `.env.local` for local development. SDK keys (`FLAGS`) are for manual authentication: apps outside Vercel, custom environments, or flags owned by another project. Each SDK key is scoped to one environment and its full value is shown once, at creation ([Getting started](https://vercel.com/docs/flags/vercel-flags/quickstart#pull-local-openid-connect-credentials), [SDK Keys](https://vercel.com/docs/flags/vercel-flags/dashboard/sdk-keys)). +- **Overrides**: Flags Explorer stores overrides in a cookie signed with `FLAGS_SECRET`; flags declared with the SDK honour it automatically ([Handling overrides](https://vercel.com/docs/flags/flags-explorer/getting-started#handling-overrides)). `vercel flags override =` produces the same token for the `vercel-flag-overrides` cookie and reads `FLAGS_SECRET` from the environment or `.env.local`, so use the secret of the environment you test against (see [FLAGS_SECRET](../SKILL.md#flags_secret)). +- **Embedded definitions**: Vercel builds fetch the flag definitions once and bundle them into the deployment when the project uses `@flags-sdk/vercel` or `@vercel/flags-core` and the build can authenticate. This keeps every function on one snapshot and serves as the runtime fallback when the service is unreachable; opt out with `VERCEL_FLAGS_DISABLE_DEFINITION_EMBEDDING=1` ([Embedded definitions](https://vercel.com/docs/flags/vercel-flags/sdks/core#embedded-definitions)). `vercel flags prepare` is the same step for builds that run outside Vercel. -# Create a new SDK key -vercel flags sdk-keys add +#### Lifecycle and safety -# Remove an SDK key -vercel flags sdk-keys rm -``` +The docs describe these flows end to end: [Roll out a feature](https://vercel.com/docs/flags/vercel-flags/cli/roll-out-feature), [Run an A/B test](https://vercel.com/docs/flags/vercel-flags/cli/run-ab-test), [Clean up after rollout](https://vercel.com/docs/flags/vercel-flags/cli/clean-up-after-rollout). Follow them; the notes below are the parts an agent gets wrong. -These examples cover common flag operations. For the full `vercel flags` reference and other Vercel CLI commands, see the `vercel-cli` skill. If it isn't installed, suggest the user install it with `npx skills add vercel/vercel@vercel-cli`. +- **Promote**: deploy the code to preview, `enable` or `set` the flag in preview, verify on the preview URL, deploy to production, then change production (`enable`, `set`, `split`, or `rollout`). Each environment keeps its own configuration; preview stays on its current value until you change it. +- **Serve vs define**: `enable` / `disable` work on boolean flags only. `set` changes the served variant for any kind. `update` adds, removes, or renames variants and does not change what is served. A variant can only be removed when no environment configuration or rule references it, including rules that are stored but not active ([Deleting a variant](https://vercel.com/docs/flags/vercel-flags/dashboard/feature-flag#deleting-a-variant)). +- **Static value vs targeting**: `set` / `enable` / `disable` put the environment in static value mode; its split, rollout, and rules are preserved in the background. `use-targeting` switches back to targets and rules mode ([Switching between static and rules modes](https://vercel.com/docs/flags/vercel-flags/dashboard/feature-flag#switching-between-static-and-rules-modes)). Run `inspect` first so you know what the environment serves today. +- **Confirm a change**: `inspect` for the served state, `versions` for the change history (the dashboard can restore any earlier configuration), `evaluations` to confirm traffic reaches the new variant or to check whether a flag is still evaluated before archiving ([Evaluation metrics](https://vercel.com/docs/flags/vercel-flags/evaluation-metrics)). Local development evaluates the Development environment configuration. +- **Archive before delete**: archive after the flag is no longer used in code. Search the code for the key and its camelCase name, remove the declaration and the conditionals, deploy to preview, then `archive`; `unarchive` restores it with configuration and history intact. `rm` requires an archived flag and is permanent ([Clean up after rollout](https://vercel.com/docs/flags/vercel-flags/cli/clean-up-after-rollout), [Archive](https://vercel.com/docs/flags/vercel-flags/dashboard/archive)). +- **Agent runs**: `archive`, `unarchive`, `rm`, and `update --remove-variant` prompt for confirmation. Pass `--yes` when the user has approved the action. -Full CLI reference: https://vercel.com/docs/cli/flags +CLI reference: https://vercel.com/docs/cli/flags ---