[REL-12163] feature management tools (#8)

* adding feature management workflow skills, updating skill creation

* updating readme
This commit is contained in:
Ramon Niebla
2026-02-13 09:53:10 -08:00
committed by GitHub
parent dcfb2a8f43
commit 7cd1d68dcd
25 changed files with 2173 additions and 202 deletions
+16 -1
View File
@@ -12,6 +12,9 @@ Agent Skills are modular, text-based playbooks that teach an agent how to perfor
| Skill | Description |
|-------|-------------|
| `feature-flags/launchdarkly-flag-discovery` | Audit flags, find stale/launched flags, and assess removal readiness |
| `feature-flags/launchdarkly-flag-create` | Create new feature flags in a way that fits existing codebase patterns |
| `feature-flags/launchdarkly-flag-targeting` | Control targeting, rollouts, rules, and cross-environment config |
| `feature-flags/launchdarkly-flag-cleanup` | Safely remove flags from code using LaunchDarkly as the source of truth |
### AI Configs
@@ -28,7 +31,7 @@ Agent Skills are modular, text-based playbooks that teach an agent how to perfor
| Skill | Description |
|-------|-------------|
| `skill-authoring/create-skill` | Add a new skill to the LaunchDarkly agent-skills repo following conventions |
| `skill-authoring/create-skill` | Add a new skill following conventions — explore existing skills, create with workflow pattern, verify with validation scripts |
## Quick Start (Local)
@@ -46,6 +49,18 @@ cp -r skills/feature-flags/launchdarkly-flag-cleanup <your-agent-skills-dir>/
Then ask your agent something like:
```
Which feature flags are stale and should be cleaned up?
```
```
Create a feature flag for the new checkout flow
```
```
Roll out dark-mode to 25% of users in production
```
```
Remove the `new-checkout-flow` feature flag from this codebase
```
+61 -5
View File
@@ -37,19 +37,19 @@
},
{
"name": "create-skill",
"description": "Add a new skill to the LaunchDarkly agent-skills repo. Use when creating a new SKILL.md, updating the skills catalog, and aligning with repo conventions.",
"description": "Add a new skill to the LaunchDarkly agent-skills repo. Use when creating a new SKILL.md, adding a skill to the catalog, or aligning with repo conventions. Guides exploration of existing skills before creating.",
"path": "skills/skill-authoring/create-skill",
"version": "0.1.0",
"version": "0.2.0",
"license": "Apache-2.0",
"compatibility": "Works in repositories following the Agent Skills open standard"
},
{
"name": "launchdarkly-flag-cleanup",
"description": "Safely automate feature flag cleanup workflows using the LaunchDarkly MCP server. Use when removing flags from code, cleaning up stale flags, assessing removal readiness, or creating PRs that preserve production behavior.",
"description": "Safely remove a feature flag from code while preserving production behavior. Use when the user wants to remove a flag from code, delete flag references, or create a PR that hardcodes the winning variation after a rollout is complete.",
"path": "skills/feature-flags/launchdarkly-flag-cleanup",
"version": "1.0.0-alpha",
"version": "1.0.0-experimental",
"license": "Apache-2.0",
"compatibility": "Requires LaunchDarkly MCP server (@launchdarkly/mcp-server)",
"compatibility": "Requires the remotely hosted LaunchDarkly MCP server",
"tags": [
"launchdarkly",
"feature-flags",
@@ -61,6 +61,62 @@
"devops",
"mcp"
]
},
{
"name": "launchdarkly-flag-create",
"description": "Create and configure LaunchDarkly feature flags in a way that fits the existing codebase. Use when the user wants to create a new flag, wrap code in a flag, add a feature toggle, or set up an experiment. Guides exploration of existing patterns before creating.",
"path": "skills/feature-flags/launchdarkly-flag-create",
"version": "1.0.0-experimental",
"license": "Apache-2.0",
"compatibility": "Requires the remotely hosted LaunchDarkly MCP server",
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"flag-creation",
"feature-toggle",
"sdk",
"devops",
"mcp"
]
},
{
"name": "launchdarkly-flag-discovery",
"description": "Audit your LaunchDarkly feature flags to understand the landscape, find stale or launched flags, and assess removal readiness. Use when the user asks about flag debt, stale flags, cleanup candidates, flag health, or wants to understand their flag inventory.",
"path": "skills/feature-flags/launchdarkly-flag-discovery",
"version": "1.0.0-experimental",
"license": "Apache-2.0",
"compatibility": "Requires the remotely hosted LaunchDarkly MCP server",
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"flag-audit",
"flag-health",
"stale-flags",
"tech-debt",
"inventory",
"discovery",
"mcp"
]
},
{
"name": "launchdarkly-flag-targeting",
"description": "Control LaunchDarkly feature flag targeting including toggling flags on/off, percentage rollouts, targeting rules, individual targets, and copying flag configurations between environments. Use when the user wants to change who sees a flag, roll out to a percentage, add targeting rules, or promote config between environments.",
"path": "skills/feature-flags/launchdarkly-flag-targeting",
"version": "1.0.0-experimental",
"license": "Apache-2.0",
"compatibility": "Requires the remotely hosted LaunchDarkly MCP server",
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"targeting",
"rollout",
"percentage-rollout",
"devops",
"mcp"
]
}
]
}
@@ -20,39 +20,9 @@ Examples:
## Prerequisites
This skill requires the LaunchDarkly MCP server to be configured in your environment.
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. The remote server provides higher-level, agent-optimized tools that orchestrate multiple API calls and return pruned, actionable responses.
### Configure MCP Server
**Claude Code (`~/.claude/mcp.json`):**
```json
{
"mcpServers": {
"launchdarkly": {
"command": "npx",
"args": ["-y", "@launchdarkly/mcp-server", "start"],
"env": {
"LD_ACCESS_TOKEN": "your-api-key"
}
}
}
}
```
**Cursor (`.cursor/mcp.json`):**
```json
{
"mcpServers": {
"launchdarkly": {
"command": "npx",
"args": ["-y", "@launchdarkly/mcp-server", "start"],
"env": {
"LD_ACCESS_TOKEN": "your-api-key"
}
}
}
}
```
Refer to your LaunchDarkly account settings for instructions on connecting to the remotely hosted MCP server.
## Usage
@@ -1,110 +1,108 @@
---
name: launchdarkly-flag-cleanup
description: "Safely automate feature flag cleanup workflows using the LaunchDarkly MCP server. Use when removing flags from code, cleaning up stale flags, assessing removal readiness, or creating PRs that preserve production behavior."
description: "Safely remove a feature flag from code while preserving production behavior. Use when the user wants to remove a flag from code, delete flag references, or create a PR that hardcodes the winning variation after a rollout is complete."
license: Apache-2.0
compatibility: Requires LaunchDarkly MCP server (@launchdarkly/mcp-server)
compatibility: Requires the remotely hosted LaunchDarkly MCP server
metadata:
author: launchdarkly
version: "1.0.0-alpha"
version: "1.0.0-experimental"
---
# LaunchDarkly Flag Cleanup
A workflow for safely removing feature flags from codebases while preserving production behavior. This skill uses LaunchDarkly as the source of truth to determine removal readiness and the correct forward value.
You're using a skill that will guide you through safely removing a feature flag from a codebase while preserving production behavior. Your job is to explore the codebase to understand how the flag is used, query LaunchDarkly to determine the correct forward value, remove the flag code cleanly, and verify the result.
If you haven't already identified which flag to clean up, use the [flag discovery skill](../launchdarkly-flag-discovery/SKILL.md) first to audit the landscape and find candidates.
## Prerequisites
This skill requires the LaunchDarkly MCP server to be configured in your environment.
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment.
**Required MCP tools:**
- `get-environments`
- `get-feature-flag`
- `get-flag-status-across-environments`
- `get-code-references`
- `check-removal-readiness` — detailed safety check (orchestrates flag config, cross-env status, dependencies, code references, and expiring targets in parallel)
- `get-flag` — fetch flag configuration for a specific environment
**Optional MCP tools:**
- `archive-flag` — archive the flag in LaunchDarkly after code removal
- `delete-flag` — permanently delete the flag (irreversible, prefer archive)
## Core Principles
1. **Safety First**: Always preserve current production behavior.
2. **LaunchDarkly as Source of Truth**: Never guess. Query the actual configuration.
3. **Clear Communication**: Explain reasoning in PR descriptions.
4. **Follow Conventions**: Respect existing code style and structure.
2. **LaunchDarkly as Source of Truth**: Never guess the forward value. Query the actual configuration.
3. **Follow Conventions**: Respect existing code style and structure.
4. **Minimal Change**: Only remove flag-related code. No unrelated refactors.
## Flag Removal Workflow
## Workflow
### Step 1: Identify Critical Environments
### Step 1: Explore the Codebase
Use `get-environments` with the project key to find environments marked as critical (typically `production`, `staging`, or user-specified).
Before touching LaunchDarkly or removing code, understand how this flag is used in the codebase.
### Step 2: Fetch Flag Configuration
1. **Find all references to the flag key.** Search for the flag key string (e.g., `new-checkout-flow`) across the codebase. Check for:
- Direct SDK evaluation calls (`variation()`, `boolVariation()`, `useFlags()`, etc.)
- Constants/enums that reference the key
- Wrapper/service patterns that abstract the SDK
- Configuration files, tests, and documentation
- See [SDK Patterns](references/sdk-patterns.md) for the full list of patterns by language
Use `get-feature-flag` to retrieve the full configuration. Extract:
- `variations`: Possible values
- Per critical environment:
- `on`: Whether enabled
- `fallthrough.variation`: Variation index when no rules match
- `offVariation`: Variation index when flag is off
- `rules`: Targeting rules (complexity indicator)
- `targets`: Individual context targets
2. **Understand the branching.** For each reference, identify:
- What code runs when the flag is `true` (or variation A)?
- What code runs when the flag is `false` (or variation B)?
- Are there side effects, early returns, or nested conditions?
### Step 3: Determine Forward Value
3. **Note the scope.** How many files, components, or modules does this flag touch? A flag used in one `if` block is simpler than one threaded through multiple layers.
The **forward value** replaces the flag in code.
### Step 2: Run the Removal Readiness Check
Use `check-removal-readiness` to get a detailed safety assessment. This single tool call orchestrates multiple checks in parallel:
- Flag configuration and targeting state
- Cross-environment status
- Dependent flags (prerequisites)
- Expiring targets
- Code reference statistics
The tool returns a readiness verdict:
**`safe`** — No blockers or warnings. Proceed with removal.
**`caution`** — No hard blockers but warnings exist (e.g., code references in other repos, expiring targets scheduled, flag marked as permanent). Present warnings and let the user decide.
**`blocked`** — Hard blockers prevent safe removal (e.g., dependent flags, actively receiving requests, targeting is on with active rules). Present blockers — the user must resolve them first.
### Step 3: Determine the Forward Value
Use `get-flag` to fetch the flag configuration in each critical environment. The **forward value** is the variation that replaces the flag in code.
| Scenario | Forward Value |
|----------|---------------|
| All critical envs ON, same fallthrough, no rules/targets | Use `fallthrough.variation` |
| All critical envs OFF, same offVariation | Use `offVariation` |
| Critical envs differ in ON/OFF state | **NOT SAFE** - stop |
| Critical envs serve different variations | **NOT SAFE** - stop |
| Critical envs differ in ON/OFF state | **NOT SAFE** stop and inform the user |
| Critical envs serve different variations | **NOT SAFE** stop and inform the user |
### Step 4: Assess Removal Readiness
### Step 4: Remove the Flag from Code
Use `get-flag-status-across-environments` to check lifecycle status.
Now execute the removal using what you learned in Step 1.
**READY** if ALL true:
- Status is `launched` or `active` in all critical environments
- Same variation served across all critical environments
- No targeting rules or individual targets in critical environments
- Flag is not already archived/deprecated
1. **Replace flag evaluations with the forward value.**
- Preserve the code branch matching the forward value
- Remove the dead branch entirely
- If the flag value was assigned to a variable, replace the variable with the literal value or inline it
**PROCEED WITH CAUTION** if:
- Status is `inactive` (no recent traffic)
- Zero evaluations in last 7 days (confirm with user)
2. **Clean up dead code.**
- Remove imports, constants, and type definitions that only existed for the flag
- Remove functions, components, or files that only existed for the dead branch
- Check for orphaned exports, hooks, helpers, styles, and test files
- If the repo uses an unused-export tool (Knip, ts-prune, lint rules), run it and remove any flag-related orphans
**NOT READY** if:
- Status is `new` (still rolling out)
- Different variations across critical environments
- Complex targeting rules exist
- Critical environments differ in ON/OFF state
3. **Don't over-clean.**
- Only remove code directly related to the flag
- Don't refactor, optimize, or "improve" surrounding code
- Don't change formatting or style of untouched code
### Step 5: Check Code References
**Example transformation (boolean flag, forward value = `true`):**
Use `get-code-references` to identify repositories. If the current repo isn't listed, inform the user. Note the count of other repositories for awareness.
### Step 6: Remove Flag from Code
Search for all references and replace with the forward value:
1. **Find evaluation patterns:**
- `variation('flag-key', ...)`
- `boolVariation('flag-key', ...)`
- `featureFlags['flag-key']`
- SDK-specific and wrapper patterns
2. **Replace with forward value:**
- Preserve the branch matching the forward value
- Remove the dead branch and related code
- If assigned to a variable, replace with the value directly
3. **Clean up:**
- Remove unused imports/constants
- Avoid unrelated refactors
- Double-check for orphaned exports or files created solely for the flag
(unused components, hooks, helpers, styles, and test files)
- If the repo uses an unused-export tool (e.g., lint rules, Knip, ts-prune),
run it and remove any flag-related orphans it reports
**Example transformation (forward value = true):**
```typescript
// Before
const showNewCheckout = await ldClient.variation('new-checkout-flow', user, false);
@@ -118,29 +116,52 @@ if (showNewCheckout) {
return renderNewCheckout();
```
### Step 7: Create Pull Request
### Step 5: Create Pull Request
Use the template in `references/pr-template.md` for a structured PR description including removal summary, readiness assessment, and risk analysis.
Use the template in [references/pr-template.md](references/pr-template.md) for a structured PR description. The PR should clearly communicate:
- What flag was removed and why
- What the forward value is and why it's correct
- The readiness assessment results (from `check-removal-readiness`)
- What code was removed and what behavior is preserved
- Whether other repos still reference this flag
### Step 6: Verify
Before considering the job done:
1. **Code compiles and lints.** Run the project's build and lint steps.
2. **Tests pass.** If the flag was used in tests, the tests should be updated to reflect the hardcoded behavior.
3. **No remaining references.** Search the codebase one more time for the flag key to make sure nothing was missed.
4. **PR is complete.** The description covers the readiness assessment, forward value rationale, and any cross-repo coordination needed.
## Edge Cases
| Situation | Action |
|-----------|--------|
| Flag not found | Inform user, check for typos |
| Already archived | Ask if code cleanup still needed |
| Multiple SDK patterns | Search all: `variation()`, `boolVariation()`, `variationDetail()`, `allFlags()` |
| Dynamic flag keys (`flag-${id}`) | Warn that automated removal may be incomplete |
| Different default values in code | Flag as inconsistency in PR |
| Orphaned exports/files remain | Run unused-export checks and remove dead files |
| Flag not found in LaunchDarkly | Inform user, check for typos in the key |
| Flag already archived | Ask if code cleanup is still needed (flag is gone from LD but code may still reference it) |
| Multiple SDK patterns in codebase | Search all patterns: `variation()`, `boolVariation()`, `variationDetail()`, `allFlags()`, `useFlags()`, plus any wrappers |
| Dynamic flag keys (`flag-${id}`) | Warn that automated removal may be incomplete — manual review required |
| Different default values in code vs LD | Flag as inconsistency in the PR description |
| Orphaned exports/files remain after removal | Run unused-export checks and remove dead files |
## What NOT to Do
- Don't change code unrelated to flag cleanup.
- Don't refactor or optimize beyond flag removal.
- Don't remove flags still being rolled out.
- Don't guess the forward value.
- Don't remove flags still being actively rolled out.
- Don't guess the forward value — always query LaunchDarkly.
## Related Resources
## After Cleanup
- [PR Template](references/pr-template.md)
- [SDK Patterns](references/sdk-patterns.md)
Once the PR is merged and deployed:
1. **Archive the flag in LaunchDarkly** using `archive-flag`. Archival is reversible; deletion is not. Always archive first.
2. **Notify other teams** if `check-removal-readiness` reported code references in other repositories.
3. **If the flag had targeting changes pending,** they can be ignored — the flag is being removed.
## References
- [PR Template](references/pr-template.md) — Structured PR description for flag removal
- [SDK Patterns](references/sdk-patterns.md) — Flag evaluation patterns by language/framework
- [Flag Discovery](../launchdarkly-flag-discovery/SKILL.md) — Find cleanup candidates before using this skill
- [Flag Targeting](../launchdarkly-flag-targeting/SKILL.md) — If you need to change targeting instead of removing
@@ -1,7 +1,7 @@
{
"name": "launchdarkly-flag-cleanup",
"description": "Safely automate feature flag cleanup workflows using LaunchDarkly MCP server",
"version": "1.0.0-alpha",
"version": "1.0.0-experimental",
"author": "LaunchDarkly",
"repository": "https://github.com/launchdarkly/agent-skills",
"skills": ["./"],
@@ -0,0 +1,63 @@
# LaunchDarkly Flag Create Skill
An Agent Skill for introducing new feature flags into a codebase, matching existing patterns and conventions.
## Overview
This skill teaches agents how to:
- Explore a codebase to understand existing flag patterns and SDK usage
- Choose the right flag type and configuration
- Create the flag in LaunchDarkly
- Add flag evaluation code that matches codebase conventions
- Verify the flag is wired up correctly
## Installation (Local)
For now, install by placing this skill directory where your agent client loads skills.
Examples:
- **Generic**: copy `skills/feature-flags/launchdarkly-flag-create/` into your client's skills path
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. The remote server provides higher-level, agent-optimized tools that orchestrate multiple API calls and return pruned, actionable responses.
## Usage
Once installed, the skill activates automatically when you ask about creating flags:
```
Create a feature flag for the new checkout flow
```
```
Wrap the dark mode feature in a LaunchDarkly flag
```
```
Add a feature toggle for the new pricing page
```
## Structure
```
launchdarkly-flag-create/
├── SKILL.md
├── marketplace.json
├── README.md
└── references/
├── flag-types.md
└── sdk-evaluation-patterns.md
```
## Related
- [LaunchDarkly Flag Targeting](../launchdarkly-flag-targeting/) — Control targeting after creating a flag
- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/) — Remove flags when they're no longer needed
- [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server)
- [LaunchDarkly Docs](https://docs.launchdarkly.com)
## License
Apache-2.0
@@ -0,0 +1,130 @@
---
name: launchdarkly-flag-create
description: "Create and configure LaunchDarkly feature flags in a way that fits the existing codebase. Use when the user wants to create a new flag, wrap code in a flag, add a feature toggle, or set up an experiment. Guides exploration of existing patterns before creating."
license: Apache-2.0
compatibility: Requires the remotely hosted LaunchDarkly MCP server
metadata:
author: launchdarkly
version: "1.0.0-experimental"
---
# LaunchDarkly Flag Create & Configure
You're using a skill that will guide you through introducing a new feature flag into a codebase. Your job is to explore how flags are already used in this codebase, create the flag in LaunchDarkly in a way that fits, add the evaluation code matching existing patterns, and verify everything is wired up correctly.
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment.
**Required MCP tools:**
- `create-flag` — create a new feature flag in a project
- `get-flag` — verify the flag was created correctly
**Optional MCP tools (enhance workflow):**
- `list-flags` — browse existing flags to understand naming conventions and tags
- `update-flag-settings` — update flag metadata (name, description, tags, temporary/permanent status)
## Workflow
### Step 1: Explore the Codebase
Before creating anything, understand how this codebase uses feature flags.
1. **Find the SDK.** Search for LaunchDarkly SDK imports or initialization:
- Look for `launchdarkly`, `ldclient`, `ld-client`, `LDClient` in imports
- Check `package.json`, `requirements.txt`, `go.mod`, `Gemfile`, or equivalent for the SDK dependency
- Identify which SDK is in use (server-side Node, React, Python, Go, Java, etc.)
2. **Find existing flag evaluations.** Search for variation calls to understand the patterns this codebase uses:
- Direct SDK calls: `variation()`, `boolVariation()`, `useFlags()`, etc.
- Wrapper patterns: Does this codebase abstract flags behind a service or utility?
- Constant definitions: Are flag keys defined as constants somewhere?
- See [SDK Evaluation Patterns](references/sdk-evaluation-patterns.md) for patterns by language
3. **Understand conventions.** Look at existing flags to learn:
- **Naming convention**: Are keys `kebab-case`, `snake_case`, `camelCase`?
- **Organization**: Are flag keys co-located with features, or centralized in a constants file?
- **Default values**: What defaults do existing evaluations use?
- **Context/user construction**: How does this codebase build the user/context object passed to the SDK?
4. **Check LaunchDarkly project conventions.** Optionally use `list-flags` to see existing flags:
- What tags are commonly used?
- Are flags marked as temporary or permanent?
- What naming patterns exist in the project?
### Step 2: Determine the Right Flag Type
Based on what the user needs, choose the appropriate flag configuration. See [Flag Types and Patterns](references/flag-types.md) for the full guide.
**Quick decision:**
| User intent | Flag kind | Variations |
|-------------|-----------|------------|
| "Toggle a feature on/off" | `boolean` | `true` / `false` |
| "Gradually roll out a feature" | `boolean` | `true` / `false` |
| "A/B test between options" | `multivariate` (string) | User-defined values |
| "Configure a numeric threshold" | `multivariate` (number) | User-defined values |
| "Serve different config objects" | `multivariate` (JSON) | User-defined values |
**Defaults to apply:**
- Set `temporary: true` unless the user explicitly says this is a permanent/long-lived flag. Most flags are release flags that should eventually be cleaned up.
- Generate a `key` from the name if not provided (e.g., "New Checkout Flow" → `new-checkout-flow`), but match the codebase's naming convention if one exists.
- Suggest relevant tags based on the feature area, team, or context the user mentions.
### Step 3: Create the Flag in LaunchDarkly
Use `create-flag` with the configuration determined in Step 2.
After creation:
- The flag is created with **targeting OFF** in all environments.
- The flag serves the `offVariation` to everyone until targeting is turned on.
- Remind the user they'll need to use the [flag targeting skill](../launchdarkly-flag-targeting/SKILL.md) to toggle it on and optionally set up rollout rules.
### Step 4: Add Flag Evaluation to Code
Now add the code to evaluate the flag, **matching the patterns you found in Step 1**.
1. **Use the same SDK patterns** the codebase already uses. If there's a wrapper, use the wrapper. If there are constants, add the new key to the constants file.
2. **Use an appropriate default value.** The default (fallback) value in code should be the "safe" behavior — typically the existing behavior before the flag. This ensures the feature stays off if the SDK can't reach LaunchDarkly.
3. **Add the conditional logic.** Wrap the new behavior in a flag check.
4. **Handle both branches.** Make sure the code path for each variation is clear and complete.
See [SDK Evaluation Patterns](references/sdk-evaluation-patterns.md) for implementation examples by language and framework.
### Step 5: Verify
Confirm the flag is properly set up:
1. **Code compiles/passes linting.** Run the project's build or lint step.
2. **Flag exists in LaunchDarkly.** Use `get-flag` to confirm it was created with the right configuration.
3. **Both code paths work.** The flag-off path preserves existing behavior; the flag-on path enables the new feature.
4. **Default value is safe.** If LaunchDarkly is unreachable, the code falls back to the default — make sure that's the existing/safe behavior.
## Updating Flag Settings
If the user wants to change flag metadata (not targeting), use `update-flag-settings`. Supported changes:
| Change | Instruction |
|--------|-------------|
| Rename | `{kind: "updateName", value: "New Name"}` |
| Update description | `{kind: "updateDescription", value: "New description"}` |
| Add tags | `{kind: "addTags", values: ["tag1", "tag2"]}` |
| Remove tags | `{kind: "removeTags", values: ["old-tag"]}` |
| Mark as temporary | `{kind: "markTemporary"}` |
| Mark as permanent | `{kind: "markPermanent"}` |
Multiple instructions can be batched in a single call. These changes are project-wide, not environment-specific.
**Important:** Metadata updates (above) are separate from targeting changes (toggle, rollout, rules). If the user wants to change who sees what, direct them to the [flag targeting skill](../launchdarkly-flag-targeting/SKILL.md).
## Important Context
- **Flag keys are immutable.** Once created, a flag's key cannot be changed. Choose carefully.
- **Flags start OFF.** Creation never enables a flag. This is a safety feature.
- **The default value in code is your safety net.** It's what gets served when the SDK can't connect to LaunchDarkly. Always use the "safe" / existing behavior as the default.
- **Follow existing codebase conventions.** The most common mistake is introducing a flag pattern that doesn't match what the team already does. Step 1 exists to prevent this.
## References
- [Flag Types and Patterns](references/flag-types.md) — Boolean vs multivariate, naming conventions, configuration best practices
- [SDK Evaluation Patterns](references/sdk-evaluation-patterns.md) — How to evaluate flags in each SDK, including common wrapper patterns
@@ -0,0 +1,21 @@
{
"name": "launchdarkly-flag-create",
"description": "Create and configure LaunchDarkly feature flags in a way that fits the existing codebase",
"version": "1.0.0-experimental",
"author": "LaunchDarkly",
"repository": "https://github.com/launchdarkly/agent-skills",
"skills": ["./"],
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"flag-creation",
"feature-toggle",
"sdk",
"devops",
"mcp"
],
"requirements": {
"mcp-servers": ["@launchdarkly/mcp-server"]
}
}
@@ -0,0 +1,162 @@
# Flag Types and Patterns
A reference for choosing the right flag type and configuring it properly.
## Flag Kinds
### Boolean Flags
The most common type. Two variations: `true` and `false`.
**When to use:**
- Feature toggles (show/hide a feature)
- Kill switches (disable a feature in emergencies)
- Gradual rollouts (serve `true` to a percentage of traffic)
- Simple A/B tests (control vs treatment)
**Configuration:**
```json
{
"kind": "boolean",
"variations": [
{"value": true},
{"value": false}
]
}
```
**Convention:** Variation 0 is `true` (the new/enabled behavior), variation 1 is `false` (the old/disabled behavior). The `offVariation` should point to `false`.
### Multivariate Flags (String)
Multiple string values. Use for text variants, feature versions, or named configurations.
**When to use:**
- A/B/C tests with different copy or UI variants
- Feature version selection ("v1", "v2", "v3")
- Named configuration modes ("basic", "advanced", "enterprise")
**Configuration:**
```json
{
"kind": "multivariate",
"variations": [
{"value": "control", "name": "Control"},
{"value": "variant-a", "name": "Variant A"},
{"value": "variant-b", "name": "Variant B"}
]
}
```
### Multivariate Flags (Number)
Numeric values. Use for thresholds, limits, or quantities.
**When to use:**
- Rate limits
- Timeout durations
- Feature limits (max items, max size)
- Numeric configuration that varies by audience
**Configuration:**
```json
{
"kind": "multivariate",
"variations": [
{"value": 10, "name": "Default"},
{"value": 50, "name": "Increased"},
{"value": 100, "name": "Maximum"}
]
}
```
### Multivariate Flags (JSON)
Complex objects. Use for structured configuration.
**When to use:**
- Configuration objects with multiple fields
- UI layout configurations
- Feature bundles (multiple settings in one flag)
**Configuration:**
```json
{
"kind": "multivariate",
"variations": [
{"value": {"theme": "light", "density": "comfortable"}, "name": "Default"},
{"value": {"theme": "dark", "density": "compact"}, "name": "Dark Compact"}
]
}
```
## Naming Conventions
### Flag Keys
Flag keys are immutable identifiers. Choose carefully.
**Common conventions:**
| Convention | Example | When used |
|-----------|---------|-----------|
| `kebab-case` | `new-checkout-flow` | Most common, LaunchDarkly default |
| `snake_case` | `new_checkout_flow` | Common in Python/Ruby codebases |
| `camelCase` | `newCheckoutFlow` | Sometimes in JS/TS codebases |
| `dot.notation` | `checkout.new-flow` | Hierarchical organization |
**Always check the existing codebase** for which convention is in use before creating a new flag.
**Good key practices:**
- Descriptive but concise: `new-checkout-flow` not `the-new-checkout-flow-feature`
- Feature-oriented: `dark-mode` not `jira-1234`
- Avoid dates: `new-pricing` not `new-pricing-2025`
### Flag Names
The human-readable display name in the LaunchDarkly UI. Can be changed later (unlike keys).
**Good name practices:**
- Use title case: "New Checkout Flow"
- Be descriptive: "Dark Mode Toggle" not "DM"
- Include context: "Checkout V2 (Q1 Experiment)" can be helpful
## Temporary vs Permanent
### Temporary Flags (default)
- Expected to be removed after the feature is fully rolled out
- LaunchDarkly tracks these for cleanup reminders
- Most feature toggles and release flags are temporary
### Permanent Flags
- Long-lived configuration that should NOT be cleaned up
- Kill switches, ops toggles, plan-based feature gating
- Only mark as permanent when the user explicitly says the flag is long-lived
## Tags
Tags help organize flags in LaunchDarkly. Suggest tags based on:
| Category | Example tags |
|----------|-------------|
| Team | `team-checkout`, `team-platform` |
| Feature area | `payments`, `onboarding`, `search` |
| Flag purpose | `experiment`, `release`, `ops` |
| Lifecycle | `q1-2025`, `migration` |
## Best Practices for Variations
### Boolean Flags
- Name variations: `true` → "Enabled" / "New behavior", `false` → "Disabled" / "Old behavior"
- Set `offVariation` to `false` (index 1)
### Multivariate Flags
- Always include a "control" or "default" variation
- Give every variation a descriptive `name`
- Consider what the `offVariation` should be — typically the control/default
- Order variations with the default/control first
### Default Values in Code
- The default value (fallback) in your code should ALWAYS be the safe/existing behavior
- For boolean flags: default to `false` (feature off) unless the feature is already live
- For multivariate: default to the control/existing variation
- This ensures graceful degradation if LaunchDarkly is unreachable
@@ -0,0 +1,234 @@
# SDK Evaluation Patterns
How to evaluate feature flags in each LaunchDarkly SDK. Use this reference to match the patterns already in use in the codebase.
## JavaScript/TypeScript (Node.js Server SDK)
```typescript
// Standard boolean evaluation
const enabled = await ldClient.boolVariation('flag-key', context, false);
// Standard string evaluation
const variant = await ldClient.stringVariation('flag-key', context, 'default');
// Standard number evaluation
const limit = await ldClient.numberVariation('flag-key', context, 10);
// JSON evaluation
const config = await ldClient.jsonVariation('flag-key', context, {});
// Generic evaluation (returns any type)
const value = await ldClient.variation('flag-key', context, defaultValue);
// With evaluation details (includes reason for the variation served)
const detail = await ldClient.boolVariationDetail('flag-key', context, false);
// detail.value, detail.variationIndex, detail.reason
// All flags at once
const allFlags = await ldClient.allFlagsState(context);
```
## JavaScript/TypeScript (React SDK)
```tsx
// Hook-based (most common in React)
import { useFlags, useLDClient } from 'launchdarkly-react-client-sdk';
function MyComponent() {
const { flagKey } = useFlags(); // camelCase access
const flags = useFlags();
const value = flags['flag-key']; // bracket access for kebab-case keys
// Direct client access when needed
const ldClient = useLDClient();
const variant = ldClient?.variation('flag-key', 'default');
}
// HOC pattern (older codebases)
import { withLDConsumer } from 'launchdarkly-react-client-sdk';
class MyComponent extends React.Component {
render() {
const enabled = this.props.flags['flag-key'];
return enabled ? <NewFeature /> : <OldFeature />;
}
}
export default withLDConsumer()(MyComponent);
```
## Python
```python
# Standard evaluation
enabled = ld_client.variation('flag-key', context, False)
# Typed evaluations
enabled = ld_client.bool_variation('flag-key', context, False)
variant = ld_client.string_variation('flag-key', context, 'default')
limit = ld_client.int_variation('flag-key', context, 10)
ratio = ld_client.float_variation('flag-key', context, 0.0)
config = ld_client.json_variation('flag-key', context, {})
# With details
detail = ld_client.variation_detail('flag-key', context, False)
# detail.value, detail.variation_index, detail.reason
# All flags
all_flags = ld_client.all_flags_state(context)
```
## Go
```go
// Typed evaluations
enabled, err := ldClient.BoolVariation("flag-key", context, false)
variant, err := ldClient.StringVariation("flag-key", context, "default")
limit, err := ldClient.IntVariation("flag-key", context, 10)
ratio, err := ldClient.Float64Variation("flag-key", context, 0.0)
config, err := ldClient.JSONVariation("flag-key", context, ldvalue.Null())
// With details
detail, err := ldClient.BoolVariationDetail("flag-key", context, false)
// detail.Value, detail.VariationIndex, detail.Reason
// All flags
allFlags := ldClient.AllFlagsState(context)
```
## Java/Kotlin
```java
// Typed evaluations
boolean enabled = ldClient.boolVariation("flag-key", context, false);
String variant = ldClient.stringVariation("flag-key", context, "default");
int limit = ldClient.intVariation("flag-key", context, 10);
double ratio = ldClient.doubleVariation("flag-key", context, 0.0);
LDValue config = ldClient.jsonValueVariation("flag-key", context, LDValue.ofNull());
// With details
EvaluationDetail<Boolean> detail = ldClient.boolVariationDetail("flag-key", context, false);
// detail.getValue(), detail.getVariationIndex(), detail.getReason()
// All flags
FeatureFlagsState allFlags = ldClient.allFlagsState(context);
```
## Ruby
```ruby
# Standard evaluation
enabled = ld_client.variation('flag-key', context, false)
# Typed evaluations
enabled = ld_client.bool_variation('flag-key', context, false)
variant = ld_client.string_variation('flag-key', context, 'default')
limit = ld_client.number_variation('flag-key', context, 10)
config = ld_client.json_variation('flag-key', context, {})
# With details
detail = ld_client.variation_detail('flag-key', context, false)
# detail.value, detail.variation_index, detail.reason
# All flags
all_flags = ld_client.all_flags_state(context)
```
## .NET (C#)
```csharp
// Typed evaluations
bool enabled = ldClient.BoolVariation("flag-key", context, false);
string variant = ldClient.StringVariation("flag-key", context, "default");
int limit = ldClient.IntVariation("flag-key", context, 10);
float ratio = ldClient.FloatVariation("flag-key", context, 0.0f);
double precise = ldClient.DoubleVariation("flag-key", context, 0.0);
LdValue config = ldClient.JsonVariation("flag-key", context, LdValue.Null);
// With details
EvaluationDetail<bool> detail = ldClient.BoolVariationDetail("flag-key", context, false);
// detail.Value, detail.VariationIndex, detail.Reason
// All flags
FeatureFlagsState allFlags = ldClient.AllFlagsState(context);
```
## Common Wrapper Patterns
Many teams build abstraction layers over the SDK. Search for these in addition to direct SDK calls:
```typescript
// Service/utility wrappers
featureFlagService.isEnabled('flag-key');
featureFlagService.getValue('flag-key');
FeatureFlags.isEnabled('flag-key');
flagsClient.check('flag-key');
// Constants/enums for flag keys
FLAGS.NEW_CHECKOUT_FLOW
FeatureFlag.NEW_CHECKOUT_FLOW
FEATURE_FLAGS['flag-key']
const FLAG_KEY = 'flag-key';
// Decorator patterns (Python/Java)
@feature_flag('flag-key')
@FeatureFlag("flag-key")
// React context/provider patterns
<FeatureFlagProvider flags={['flag-key']}>
<ConditionalFeature flag="flag-key">
<NewFeature />
</ConditionalFeature>
</FeatureFlagProvider>
// Configuration files (YAML, JSON)
feature_flags:
flag-key: true
```
## Adding a New Flag Evaluation
When adding flag evaluation code, follow this pattern:
1. **Import/access the client** the same way existing code does
2. **Define the flag key** following the project's convention (constants file, inline, etc.)
3. **Choose the right evaluation method** based on the flag type
4. **Set a safe default value** — the behavior when LaunchDarkly is unreachable
5. **Add the conditional logic** for each variation
### Example: Adding a boolean flag (Node.js)
```typescript
// If the codebase uses constants:
// In flags.ts / constants.ts
export const NEW_CHECKOUT_FLOW = 'new-checkout-flow';
// In the feature code:
import { NEW_CHECKOUT_FLOW } from '../flags';
const showNewCheckout = await ldClient.boolVariation(
NEW_CHECKOUT_FLOW,
context,
false // default: keep old behavior if LD is unreachable
);
if (showNewCheckout) {
return renderNewCheckout();
} else {
return renderOldCheckout();
}
```
### Example: Adding a boolean flag (React)
```tsx
import { useFlags } from 'launchdarkly-react-client-sdk';
function CheckoutPage() {
const { newCheckoutFlow } = useFlags();
if (newCheckoutFlow) {
return <NewCheckout />;
}
return <OldCheckout />;
}
```
@@ -0,0 +1,63 @@
# LaunchDarkly Flag Discovery Skill
An Agent Skill for auditing and understanding your LaunchDarkly feature flag landscape.
## Overview
This skill teaches agents how to:
- Survey the full feature flag inventory in a project
- Identify stale, inactive, or fully-launched flags
- Assess whether specific flags are ready for removal
- Provide prioritized, actionable recommendations
## Installation (Local)
For now, install by placing this skill directory where your agent client loads skills.
Examples:
- **Generic**: copy `skills/feature-flags/launchdarkly-flag-discovery/` into your client's skills path
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. The remote server provides higher-level, agent-optimized tools that orchestrate multiple API calls and return pruned, actionable responses.
Refer to your LaunchDarkly account settings for instructions on connecting to the remotely hosted MCP server.
## Usage
Once installed, the skill activates automatically when you ask about flag health or inventory:
```
What's the state of our feature flags?
```
```
Which flags are stale and should be cleaned up?
```
```
Is the `dark-mode` flag ready to be removed?
```
## Structure
```
launchdarkly-flag-discovery/
├── SKILL.md
├── marketplace.json
├── README.md
└── references/
├── flag-health-signals.md
└── removal-readiness-checklist.md
```
## Related
- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/) — Remove flags from code after discovery identifies candidates
- [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server)
- [LaunchDarkly Docs](https://docs.launchdarkly.com)
## License
Apache-2.0
@@ -0,0 +1,119 @@
---
name: launchdarkly-flag-discovery
description: "Audit your LaunchDarkly feature flags to understand the landscape, find stale or launched flags, and assess removal readiness. Use when the user asks about flag debt, stale flags, cleanup candidates, flag health, or wants to understand their flag inventory."
license: Apache-2.0
compatibility: Requires the remotely hosted LaunchDarkly MCP server
metadata:
author: launchdarkly
version: "1.0.0-experimental"
---
# LaunchDarkly Flag Discovery
You're using a skill that will guide you through auditing and understanding the feature flag landscape in a LaunchDarkly project. Your job is to explore the project, assess the health of its flags, identify what needs attention, and provide actionable recommendations.
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment.
**Required MCP tools:**
- `list-flags` — search and browse flags with filtering by state, type, tags
- `get-flag` — get full configuration for a single flag in a specific environment
- `get-flag-status-across-envs` — check a flag's lifecycle status across all environments
**Optional MCP tools (enhance depth):**
- `find-stale-flags` — find flags that are candidates for cleanup, sorted by staleness
- `get-flag-health` — get combined health view for a single flag (merges status + config)
- `check-removal-readiness` — detailed safety check for a specific flag
## Workflow
### Step 1: Understand the Project
Before diving into flag data, establish context:
1. **Identify the project.** Confirm the `projectKey` with the user. If they haven't specified one, ask.
2. **Understand scope.** Ask the user what they're trying to accomplish:
- Broad audit? ("What's the state of our flags?")
- Targeted investigation? ("Is this specific flag still needed?")
- Cleanup planning? ("What flags can we remove?")
### Step 2: Explore the Flag Landscape
Adapt your approach to the user's goal:
**For a broad audit:**
- Use `list-flags` scoped to a critical environment (default to `production`).
- Note the total count — this tells you the scale of the flag surface area.
- Filter by `state` (active, inactive, launched, new) to segment the landscape.
- Filter by `type` (temporary vs permanent) — temporary flags are the primary cleanup targets.
**For cleanup planning:**
- Use `find-stale-flags` — this is the most efficient entry point. It returns a prioritized list of cleanup candidates sorted by staleness, categorized as:
- `never_requested` — created but never evaluated (possibly abandoned)
- `inactive_30d` — no SDK evaluations in the specified period
- `launched_no_changes` — fully rolled out, no recent changes
- Default `inactiveDays` is 30. Increase for conservative cleanup (60, 90) or decrease for aggressive cleanup (7, 14).
- Default `includeOnly` is `temporary`. Set to `all` to include permanent flags.
**For a targeted investigation:**
- Use `get-flag-health` for a single-flag deep dive. It merges status data with configuration context in one call, returning lifecycle state, last-requested timestamp, targeting summary, age, and whether it's temporary.
- Or use `get-flag` for the full configuration including rules, targets, and fallthrough details.
### Step 3: Assess Flag Health
For flags that need deeper investigation, assess health signals. See [Flag Health Signals](references/flag-health-signals.md) for the full interpretation guide.
Key signals to evaluate:
| Signal | What it tells you |
|--------|-------------------|
| **Lifecycle state** | Where the flag is in its journey (new → active → launched → inactive) |
| **Last requested** | When an SDK last evaluated this flag — staleness indicator |
| **Targeting complexity** | Number of rules and targets — removal complexity indicator |
| **Cross-environment consistency** | Whether the flag behaves the same everywhere |
| **Flag age + temporary status** | Old temporary flags are strong cleanup candidates |
Use `get-flag-status-across-envs` to check if a flag is consistent across environments. A flag inactive in production but active in staging tells a different story than one inactive everywhere.
### Step 4: Categorize and Prioritize
Group flags into actionable categories:
1. **Ready to remove** — Inactive everywhere, temporary, no dependencies. Direct the user to the [flag cleanup skill](../launchdarkly-flag-cleanup/SKILL.md) for code removal.
2. **Likely safe, needs verification** — Launched (fully rolled out), no rule changes recently. The user should confirm the rollout is intentionally complete.
3. **Needs investigation** — Active in some environments but not others, or has complex targeting. Don't recommend action without more context.
4. **Leave alone** — Active flags doing their job, or permanent flags that are intentionally long-lived.
### Step 5: Assess Removal Readiness (When Applicable)
If the user wants to know whether a specific flag can be removed, use `check-removal-readiness`. This tool orchestrates multiple API calls in parallel and returns a structured verdict:
- **`safe`** — No blockers or warnings. Proceed with cleanup.
- **`caution`** — Warnings exist (code references, expiring targets, permanent flag type). Present and let the user decide.
- **`blocked`** — Hard blockers (dependent flags, active requests, targeting rules). Must resolve first.
See [Removal Readiness Checklist](references/removal-readiness-checklist.md) for the full details on interpreting each signal.
### Step 6: Present Findings
Structure your response based on what the user asked for:
**For audits:** Lead with a summary (total flags, breakdown by state and type), then highlight what needs attention, then provide specific recommendations.
**For specific flags:** Lead with the verdict (healthy / needs attention / ready to remove), then support it with the signals you found.
**For cleanup planning:** Lead with the count of cleanup candidates, prioritize by confidence (safest removals first), and link to the cleanup workflow for execution.
## Important Context
- **"Launched" means fully rolled out** — targeting is on, a single variation is served to everyone, and no changes have been made recently. It doesn't mean "recently deployed."
- **"Inactive" doesn't always mean safe to remove.** The flag might be used in code that hasn't shipped yet, or referenced as a prerequisite by another flag.
- **Permanent flags can be inactive on purpose.** Some flags are designed to be dormant until needed (kill switches, emergency toggles). Don't automatically flag these for cleanup.
- **Weights are scaled by 1000 in the API.** A weight of `60000` means 60%. Always convert to human-readable percentages.
- **This skill is for discovery, not action.** If the user wants to remove a flag from code, direct them to the [flag cleanup skill](../launchdarkly-flag-cleanup/SKILL.md). If they want to change targeting, direct them to the [flag targeting skill](../launchdarkly-flag-targeting/SKILL.md).
## References
- [Flag Health Signals](references/flag-health-signals.md) — How to interpret lifecycle states, staleness, and health data
- [Removal Readiness Checklist](references/removal-readiness-checklist.md) — Full safety assessment before recommending flag removal
@@ -0,0 +1,23 @@
{
"name": "launchdarkly-flag-discovery",
"description": "Audit your LaunchDarkly feature flags to understand the landscape, find stale or launched flags, and assess removal readiness",
"version": "1.0.0-experimental",
"author": "LaunchDarkly",
"repository": "https://github.com/launchdarkly/agent-skills",
"skills": ["./"],
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"flag-audit",
"flag-health",
"stale-flags",
"tech-debt",
"inventory",
"discovery",
"mcp"
],
"requirements": {
"mcp-servers": ["@launchdarkly/mcp-server"]
}
}
@@ -0,0 +1,61 @@
# Flag Health Signals
How to interpret the data you get back from LaunchDarkly when assessing flag health.
## Lifecycle States
Every flag in every environment has a lifecycle state. Here's what each one means and what action it implies:
| State | Meaning | Action |
|-------|---------|--------|
| `new` | Flag was recently created, hasn't received meaningful traffic | Leave alone — still being set up |
| `active` | Flag is receiving SDK evaluations and serving variations | Healthy, doing its job |
| `launched` | Flag is on, serving a single variation to everyone, no recent changes | Candidate for cleanup — rollout is complete |
| `inactive` | Flag hasn't received SDK evaluations in a while | Strong candidate for cleanup |
## Staleness Signals
| Signal | How to check | Interpretation |
|--------|-------------|----------------|
| **Last requested date** | `status.lastRequested` on the flag | How recently an SDK evaluated this flag. Older = more stale. |
| **Inactive duration** | Compare `lastRequested` to today | 30+ days: likely stale. 7-30 days: might be infrequent. <7 days: probably active. |
| **Never requested** | `lastRequested` is null | Flag was created but never evaluated by any SDK. Possibly abandoned during development. |
| **Flag age** | Compare `creationDate` to today | Old temporary flags that are inactive are strong cleanup candidates. |
## Targeting Complexity
The more complex a flag's targeting, the more carefully you need to assess it:
| Indicator | What to check | Implications |
|-----------|--------------|--------------|
| **Rules count** | Number of targeting rules | More rules = more contexts depending on this flag = higher removal risk |
| **Individual targets** | Users/contexts individually targeted | Someone specifically configured these — check before removing |
| **Prerequisites** | Other flags that depend on this flag | **Hard blocker** — cannot remove without updating dependent flags |
| **Percentage rollout** | Fallthrough uses weighted variations | Flag is mid-rollout — not ready for removal |
## Cross-Environment Signals
Use `get-flag-status-across-envs` to build a complete picture:
| Pattern | Interpretation |
|---------|---------------|
| Inactive everywhere | Safe to consider for removal |
| Launched everywhere | Rollout complete — candidate for code cleanup |
| Active in production, inactive in staging | Normal — production is the source of truth |
| Inactive in production, active in staging | Unusual — might be pre-release, or staging is stale |
| Mixed states across environments | Needs investigation — don't recommend action without understanding why |
## Decision Matrix
Combine signals to reach a recommendation:
| Temporary? | State | Age | Dependencies | Recommendation |
|-----------|-------|-----|-------------|----------------|
| Yes | Inactive 30+ days | Any | None | **Strong cleanup candidate** |
| Yes | Launched | Any | None | **Ready to hardcode and remove** |
| Yes | Never requested, 7+ days old | Any | None | **Likely abandoned — verify and remove** |
| Yes | Active | Any | Any | **Leave alone — actively used** |
| No | Inactive 30+ days | Any | None | **Ask the user** — permanent flags may be intentionally dormant |
| No | Launched | Any | None | **Ask the user** — may want to keep as permanent config |
| Any | Any | Any | Has dependents | **Cannot remove** — update dependents first |
| Any | Active in some envs | Any | Any | **Needs investigation** — understand why states differ |
@@ -0,0 +1,110 @@
# Removal Readiness Checklist
A systematic safety check to determine whether a feature flag can be safely removed. Run through this checklist before recommending flag removal to a user.
## The Checklist
### 1. Cross-Environment Status
**Check:** Use `get-flag-status-across-envs` to verify the flag's state in all environments.
**Pass criteria:**
- Flag is `inactive` or `launched` in ALL critical environments (production, staging, etc.)
- No environment shows `new` or `active` state
**Fail criteria:**
- Flag is `active` in any critical environment
- Flag is `new` anywhere (still being rolled out)
- Critical environments show different states (e.g., production ON, staging OFF)
### 2. Configuration Consistency
**Check:** Use `get-flag` for each critical environment and compare configurations.
**Pass criteria:**
- All critical environments serve the same variation (same `fallthrough.variation` or same `offVariation`)
- No targeting rules or individual targets exist in critical environments
**Caution criteria:**
- Environments serve the same variation but through different mechanisms (one via fallthrough, another via rules)
- Simple rules exist but all resolve to the same variation
**Fail criteria:**
- Critical environments serve different variations
- Complex targeting rules exist that serve multiple variations
- Individual targets override the default behavior
### 3. Dependency Check
**Check:** Look for `prerequisites` in the flag configuration. Also check if this flag appears as a prerequisite in other flags.
**Pass criteria:**
- No other flags list this flag as a prerequisite
- This flag has no prerequisites of its own (simpler removal)
**Fail criteria (hard blocker):**
- Other flags depend on this flag as a prerequisite — removing it would break their targeting logic
### 4. Code References
**Check:** If available, use `check-removal-readiness` which includes code reference statistics. Otherwise, use `get-code-references` to find repositories that reference this flag.
**Pass criteria:**
- No code references found, or references only exist in the current repository (about to be cleaned up)
**Caution criteria:**
- Code references exist in multiple repositories — flag removal in code needs to be coordinated
**Note:** Code reference scanning has limitations. It tracks static string matches and may miss dynamic flag key construction (`flag-${name}`) or have false positives from comments/documentation.
### 5. Expiring Targets
**Check:** Look for scheduled expiring targets on the flag.
**Pass criteria:**
- No expiring targets scheduled
**Caution criteria:**
- Expiring targets exist — someone actively set a future removal date. Coordinate with them.
### 6. Flag Type
**Check:** The `temporary` field on the flag.
**Pass criteria:**
- Flag is marked as `temporary` — it was intended to be removed
**Caution criteria:**
- Flag is marked as `permanent` — it may be intentionally long-lived. Confirm with the user before recommending removal.
## Readiness Levels
After running the checklist, categorize the result:
### Safe
All checks pass. No blockers or warnings.
- Recommend proceeding with code removal using the [flag cleanup skill](../launchdarkly-flag-cleanup/SKILL.md)
- Suggest archival in LaunchDarkly after code changes are deployed
### Caution
No hard blockers, but warnings exist.
- Present each warning with context
- Recommend **archive** (reversible) over **delete** (permanent)
- Suggest addressing warnings first (e.g., remove code references, then re-check)
### Blocked
Hard blockers prevent safe removal.
- Present each blocker with specifics
- For prerequisite dependencies: user must update dependent flags first
- For active targeting: user should toggle off and wait for a cool-down period
- For active status: flag is still being used — don't remove
## Presenting Results
Structure the assessment as:
1. **Verdict** — Lead with safe / caution / blocked
2. **Blockers** (if any) — Each with type and actionable detail
3. **Warnings** (if any) — Each with type and context
4. **Forward value** — What variation should replace the flag in code (only if safe or caution)
5. **Next steps** — What to do now (proceed with cleanup, address warnings, resolve blockers)
@@ -0,0 +1,71 @@
# LaunchDarkly Flag Targeting Skill
An Agent Skill for controlling feature flag targeting, rollouts, and rules in LaunchDarkly.
## Overview
This skill teaches agents how to:
- Understand current flag targeting state before making changes
- Toggle flags on/off safely
- Set up percentage rollouts
- Add and manage targeting rules
- Manage individual user/context targets
- Copy targeting config between environments
- Follow safety practices for production changes
## Installation (Local)
For now, install by placing this skill directory where your agent client loads skills.
Examples:
- **Generic**: copy `skills/feature-flags/launchdarkly-flag-targeting/` into your client's skills path
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. The remote server provides higher-level, agent-optimized tools that orchestrate multiple API calls and return pruned, actionable responses.
Refer to your LaunchDarkly account settings for instructions on connecting to the remotely hosted MCP server.
## Usage
Once installed, the skill activates automatically when you ask about flag targeting:
```
Turn on the new-checkout flag in staging
```
```
Roll out dark-mode to 25% of users in production
```
```
Target beta users for the new-pricing feature
```
```
Copy the staging config for checkout-v2 to production
```
## Structure
```
launchdarkly-flag-targeting/
├── SKILL.md
├── marketplace.json
├── README.md
└── references/
├── targeting-patterns.md
└── safety-checklist.md
```
## Related
- [LaunchDarkly Flag Create](../launchdarkly-flag-create/) — Create flags before targeting them
- [LaunchDarkly Flag Discovery](../launchdarkly-flag-discovery/) — Audit flags and understand the landscape
- [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server)
- [LaunchDarkly Docs](https://docs.launchdarkly.com)
## License
Apache-2.0
@@ -0,0 +1,114 @@
---
name: launchdarkly-flag-targeting
description: "Control LaunchDarkly feature flag targeting including toggling flags on/off, percentage rollouts, targeting rules, individual targets, and copying flag configurations between environments. Use when the user wants to change who sees a flag, roll out to a percentage, add targeting rules, or promote config between environments."
license: Apache-2.0
compatibility: Requires the remotely hosted LaunchDarkly MCP server
metadata:
author: launchdarkly
version: "1.0.0-experimental"
---
# LaunchDarkly Flag Targeting & Rollout
You're using a skill that will guide you through changing who sees what for a feature flag. Your job is to understand the current state of the flag, figure out the right targeting approach for what the user wants, make the changes safely, and verify the resulting state.
## Prerequisites
This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment.
**Required MCP tools:**
- `get-flag` — understand current state before making changes
- `toggle-flag` — turn targeting on or off for a flag in an environment
- `update-rollout` — change the default rule (fallthrough) variation or percentage rollout
- `update-targeting-rules` — add, remove, or modify custom targeting rules
- `update-individual-targets` — add or remove specific users/contexts from individual targeting
**Optional MCP tools:**
- `copy-flag-config` — copy targeting configuration from one environment to another
## Core Concept: Evaluation Order
Before making any targeting changes, understand how LaunchDarkly evaluates flags. This determines what your changes actually do:
1. **Flag is OFF** → Serve the `offVariation` to everyone. Nothing else matters.
2. **Individual targets** → If the context matches a specific target list, serve that variation. Highest priority.
3. **Custom rules** → Evaluate rules top-to-bottom. First matching rule wins.
4. **Default rule (fallthrough)** → If nothing else matched, serve this variation or rollout.
This means: if you add a targeting rule but the flag is OFF, nobody sees the change. If you set a percentage rollout on the default rule but there's an individual target, that targeted user bypasses the rollout.
## Workflow
### Step 1: Understand Current State
Before changing anything, check what's already configured.
1. **Confirm the environment.** "Turn it on" without specifying an environment is ambiguous. Always confirm which environment the user means. Default to asking rather than assuming.
2. **Fetch the flag.** Use `get-flag` with the target environment to see:
- `on` — Is targeting currently enabled?
- `fallthrough` — What's the default rule? (variation or percentage rollout)
- `offVariation` — What serves when the flag is off?
- `rules` — Any custom targeting rules?
- `targets` — Any individually targeted users/contexts?
- `prerequisites` — Any flags this depends on?
3. **Assess complexity.** A flag with no rules and no individual targets is simple. A flag with multiple rules, targets, and prerequisites needs more care.
### Step 2: Determine the Right Approach
Based on what the user wants and what you found, choose the right tool and strategy. See [Targeting Patterns](references/targeting-patterns.md) for the full reference.
**Common scenarios:**
| User wants | Tool | Notes |
|-----------|------|-------|
| "Turn it on" | `toggle-flag` with `on: true` | Simplest change |
| "Turn it off" | `toggle-flag` with `on: false` | Serves offVariation to everyone |
| "Roll out to X%" | `update-rollout` with `rolloutType: "percentage"` | Weights must sum to 100 |
| "Enable for beta users" | `update-targeting-rules` — add a rule with clause | Rules are ANDed within, ORed between |
| "Add specific users" | `update-individual-targets` | Highest priority, overrides all rules |
| "Full rollout" | `update-rollout` with `rolloutType: "variation"` | Serve one variation to everyone |
| "Copy from staging" | `copy-flag-config` | Promote tested config to production |
### Step 3: Run the Safety Checklist
Before applying changes, especially in production, run through the [Safety Checklist](references/safety-checklist.md). The key checks:
1. **Right environment?** Double-check you're targeting the intended environment.
2. **Approval required?** Some environments require approval workflows. If `toggle-flag` or other tools return `requiresApproval: true`, surface this to the user with the approval URL.
3. **Prerequisite flags?** If this flag has prerequisites, they must be met before targeting works as expected.
4. **Rule ordering impact?** If adding rules, consider where they fall in evaluation order. Rules evaluate top-to-bottom, first match wins.
5. **Include a comment.** Always add an audit trail comment, especially for production changes.
### Step 4: Apply Changes
Use the appropriate tool for the change. Key notes:
- **`toggle-flag`**: Specify `on: true` or `on: false`, the `env`, and a `comment`.
- **`update-rollout`**: Use `rolloutType: "percentage"` with human-friendly weights (e.g., 80 for 80%) that sum to 100, or `rolloutType: "variation"` with a `variationIndex`.
- **`update-targeting-rules`**: Instructions support `addRule`, `removeRule`, `updateRuleVariationOrRollout`, `addClauses`, `removeClauses`, `reorderRules`.
- **`update-individual-targets`**: Instructions support `addTargets`, `removeTargets`, `addContextTargets`, `removeContextTargets`, `replaceTargets`.
See [Targeting Patterns](references/targeting-patterns.md) for detailed instruction examples.
### Step 5: Verify
After applying changes, confirm the result:
1. **Fetch the updated flag.** Use `get-flag` again to verify the new state.
2. **Confirm what the user expects.** Describe the resulting targeting in plain language:
- "The flag is now ON in production, serving `true` to 25% of users and `false` to 75%."
- "Beta users now see variation A. Everyone else gets the default (variation B)."
3. **Check for side effects.** If there are rules or individual targets, make sure the change interacts correctly with them.
## Important Context
- **`update-rollout` uses human-friendly percentages.** Pass 80 for 80%, not 80000. The tool handles the internal weight conversion.
- **Weights must sum to 100.** For percentage rollouts, the weights across all variations must total exactly 100.
- **Rule ordering matters.** Rules evaluate top-to-bottom. Reordering rules can change behavior without changing any individual rule.
- **Individual targets are highest priority.** They override all rules and the default. Adding someone as an individual target means rules don't apply to them.
- **"Launched" flags are still ON.** A flag with status "launched" is serving a single variation to everyone. If you want to remove the flag, use the [cleanup skill](../launchdarkly-flag-cleanup/SKILL.md), not targeting changes.
## References
- [Targeting Patterns](references/targeting-patterns.md) — Rollout strategies, rule construction, individual targeting, and cross-environment copying
- [Safety Checklist](references/safety-checklist.md) — Pre-change verification, approval workflows, environment awareness
@@ -0,0 +1,21 @@
{
"name": "launchdarkly-flag-targeting",
"description": "Control LaunchDarkly feature flag targeting including toggling, rollouts, rules, individual targets, and cross-environment copying",
"version": "1.0.0-experimental",
"author": "LaunchDarkly",
"repository": "https://github.com/launchdarkly/agent-skills",
"skills": ["./"],
"tags": [
"launchdarkly",
"feature-flags",
"feature-management",
"targeting",
"rollout",
"percentage-rollout",
"devops",
"mcp"
],
"requirements": {
"mcp-servers": ["@launchdarkly/mcp-server"]
}
}
@@ -0,0 +1,77 @@
# Targeting Safety Checklist
Run through this checklist before applying any targeting changes, especially in production.
## Before Every Change
### 1. Right Environment?
- [ ] Confirmed the environment with the user (don't assume "production")
- [ ] If the user said "turn it on" without specifying, ask which environment
### 2. Right Flag?
- [ ] Confirmed the flag key matches what the user intends
- [ ] If the flag key could be ambiguous, verify with `get-flag`
### 3. Understand Current State
- [ ] Fetched the flag's current configuration in the target environment
- [ ] Noted the current `on` state, rules, and targets
- [ ] Identified any prerequisites that must be met
### 4. Approval Required?
Some environments require approval for changes.
- [ ] If the API returns `requiresApproval: true`, inform the user
- [ ] Provide the approval URL so they can follow the workflow
- [ ] Do NOT attempt to bypass approval
### 5. Audit Trail
- [ ] Added a `comment` to the change explaining what and why
- [ ] This is especially important for production changes
## For Percentage Rollouts
- [ ] Weights sum to exactly 100% (100000 in the API)
- [ ] The rollout is on the default rule (fallthrough) unless intentionally on a specific rule
- [ ] Individual targets and higher-priority rules aren't silently overriding the rollout for some users
- [ ] Consider starting small (1-5%) for high-risk features
## For Targeting Rules
- [ ] New rules are placed at the correct position in evaluation order
- [ ] Clauses correctly express the targeting intent (AND within a rule, OR between rules)
- [ ] The `negate` field is set correctly (default `false`)
- [ ] The context kind matches what the codebase sends (e.g., `user`, `device`, `organization`)
- [ ] Attribute names match exactly what the SDK sends (case-sensitive)
## For Individual Targets
- [ ] The values match exactly what the SDK sends as the user/context key
- [ ] Individual targets are intended to override rules (they always win)
- [ ] Using `replaceTargets` intentionally — it replaces ALL targets, not just adds
## For Cross-Environment Copies
- [ ] Source environment is the one you tested in
- [ ] Target environment is correct
- [ ] You've selected the right included actions (don't accidentally copy ON state to production if you only meant to copy rules)
- [ ] Target environment's approval requirements are considered
## Production-Specific Checks
For any change to a production environment:
- [ ] Change has been tested in a lower environment first (staging, dev)
- [ ] Rollback plan is clear (what to do if something goes wrong)
- [ ] Comment explains the change for audit trail
- [ ] If doing a percentage rollout, start with a small percentage first
## After the Change
- [ ] Verified the new state with `get-flag`
- [ ] Described the resulting targeting to the user in plain language
- [ ] Confirmed the change achieves what the user asked for
@@ -0,0 +1,319 @@
# Targeting Patterns
Reference for all targeting operations available through the LaunchDarkly API semantic patch system.
## Toggle Flag On/Off
The simplest targeting change.
```json
{"kind": "turnFlagOn"}
```
```json
{"kind": "turnFlagOff"}
```
**Notes:**
- Turning a flag OFF makes it serve the `offVariation` to everyone, regardless of rules or targets.
- Turning a flag ON activates the full targeting evaluation (individual targets → rules → default rule).
## Percentage Rollouts (Default Rule)
The default rule (fallthrough) is what applies when no individual targets or custom rules match.
### Serve a single variation to everyone
```json
{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "<variation-id>"
}
```
Or by index:
```json
{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "<variation-id-of-index-0>"
}
```
### Percentage rollout
```json
{
"kind": "updateFallthroughVariationOrRollout",
"rolloutWeights": {
"<variation-id-0>": 25000,
"<variation-id-1>": 75000
}
}
```
**Note on weights:** The API uses weights scaled by 1000. So:
- 25% = 25000
- 50% = 50000
- 75% = 75000
- 100% = 100000
Weights must sum to 100000.
### Common rollout patterns
| Goal | Weights (variation 0 / variation 1) |
|------|-------------------------------------|
| 1% canary | 1000 / 99000 |
| 10% canary | 10000 / 90000 |
| 25% rollout | 25000 / 75000 |
| 50/50 A/B test | 50000 / 50000 |
| Full rollout (100%) | Use single variation instead of rollout |
| Kill switch | Turn flag OFF instead of changing rollout |
## Custom Targeting Rules
Rules let you target specific segments of users based on context attributes.
### Add a rule
```json
{
"kind": "addRule",
"clauses": [
{
"contextKind": "user",
"attribute": "email",
"op": "endsWith",
"values": ["@company.com"],
"negate": false
}
],
"variationId": "<variation-id>",
"description": "Internal users"
}
```
### Rule clause operators
| Operator | Meaning | Example |
|----------|---------|---------|
| `in` | Exact match (any value in list) | `attribute: "country", values: ["US", "CA"]` |
| `endsWith` | String ends with | `attribute: "email", values: ["@company.com"]` |
| `startsWith` | String starts with | `attribute: "name", values: ["test-"]` |
| `matches` | Regex match | `attribute: "email", values: [".*@company\\.com"]` |
| `contains` | String contains | `attribute: "plan", values: ["enterprise"]` |
| `lessThan` | Numeric less than | `attribute: "age", values: [18]` |
| `greaterThan` | Numeric greater than | `attribute: "score", values: [100]` |
| `semVerEqual` | Semantic version equals | `attribute: "version", values: ["2.0.0"]` |
| `semVerGreaterThan` | Semver greater than | `attribute: "version", values: ["1.5.0"]` |
| `semVerLessThan` | Semver less than | `attribute: "version", values: ["3.0.0"]` |
### Multiple clauses (AND logic)
Clauses within a single rule are ANDed. All must match for the rule to apply:
```json
{
"kind": "addRule",
"clauses": [
{
"contextKind": "user",
"attribute": "plan",
"op": "in",
"values": ["enterprise"]
},
{
"contextKind": "user",
"attribute": "country",
"op": "in",
"values": ["US"]
}
],
"variationId": "<variation-id>",
"description": "US enterprise users"
}
```
### Rule with percentage rollout
Instead of serving a single variation, a rule can do a percentage rollout:
```json
{
"kind": "addRule",
"clauses": [
{
"contextKind": "user",
"attribute": "beta",
"op": "in",
"values": [true]
}
],
"rolloutWeights": {
"<variation-id-0>": 50000,
"<variation-id-1>": 50000
},
"description": "50/50 for beta users"
}
```
### Remove a rule
```json
{
"kind": "removeRule",
"ruleId": "<rule-id>"
}
```
The `ruleId` (also shown as `_id`) can be found in the flag's current configuration.
### Reorder rules
```json
{
"kind": "reorderRules",
"ruleIds": ["<rule-id-1>", "<rule-id-2>", "<rule-id-3>"]
}
```
Rule order matters — rules evaluate top to bottom, first match wins.
### Update a rule's variation
```json
{
"kind": "updateRuleVariationOrRollout",
"ruleId": "<rule-id>",
"variationId": "<variation-id>"
}
```
### Add/remove clauses on a rule
```json
{
"kind": "addClauses",
"ruleId": "<rule-id>",
"clauses": [
{
"contextKind": "user",
"attribute": "country",
"op": "in",
"values": ["UK"]
}
]
}
```
```json
{
"kind": "removeClauses",
"ruleId": "<rule-id>",
"clauseIds": ["<clause-id>"]
}
```
## Individual Targets
Individual targets are the highest priority — they override all rules.
### Add users to a variation
```json
{
"kind": "addTargets",
"variationId": "<variation-id>",
"values": ["user-key-1", "user-key-2"]
}
```
### Remove users from a variation
```json
{
"kind": "removeTargets",
"variationId": "<variation-id>",
"values": ["user-key-1"]
}
```
### Context-kind targets (non-user)
For custom context kinds (device, organization, etc.):
```json
{
"kind": "addContextTargets",
"contextKind": "organization",
"variationId": "<variation-id>",
"values": ["org-123", "org-456"]
}
```
```json
{
"kind": "removeContextTargets",
"contextKind": "organization",
"variationId": "<variation-id>",
"values": ["org-123"]
}
```
### Replace all targets for a variation
```json
{
"kind": "replaceTargets",
"variationId": "<variation-id>",
"values": ["user-key-1", "user-key-2"]
}
```
**Warning:** This replaces ALL targets for the variation, not just adds to them.
## Cross-Environment Config Copying
Copy targeting configuration from one environment to another.
This is a separate API call (not a semantic patch). Use the flag copy endpoint:
- **Source:** The environment to copy from
- **Target:** The environment to copy to
- **Included actions:** Selectively copy `updateOn` (toggle state), `updateRules`, `updateFallthrough`, `updateOffVariation`, `updatePrerequisites`, `updateTargets`
### Common use case: promote staging to production
Copy the full targeting config from staging after testing:
```
source: "staging"
target: "production"
includedActions: ["updateOn", "updateRules", "updateFallthrough", "updateOffVariation", "updateTargets"]
```
**Note:** The target environment may have approval requirements. If so, the copy operation creates an approval request instead of applying immediately.
## Batching Instructions
Multiple instructions can be batched. For example, turning on and setting a rollout in one call to `toggle-flag` and `update-rollout`, or sending multiple rule changes to `update-targeting-rules`:
```json
{
"environmentKey": "production",
"instructions": [
{"kind": "turnFlagOn"},
{
"kind": "updateFallthroughVariationOrRollout",
"rolloutWeights": {
"<variation-id-0>": 10000,
"<variation-id-1>": 90000
}
}
],
"comment": "Turning on with 10% rollout"
}
```
This is preferred over multiple separate calls — it's atomic (all changes apply together or none do).
+11 -6
View File
@@ -1,14 +1,16 @@
# Create Skill (LaunchDarkly)
This skill helps contributors add new skills to the LaunchDarkly agent-skills repository.
This skill guides adding new skills to the LaunchDarkly agent-skills repository. It follows the same workflow pattern as other skills: explore existing skills, assess what's needed, create following conventions, and verify with validation scripts.
## Overview
The workflow covers:
- Selecting a category and skill name
- Creating `SKILL.md` using the template
- Updating `README.md` and `skills.json`
- Validating with the repo scripts
- Exploring existing skills to understand patterns
- Assessing category, name, and structure
- Creating `SKILL.md` from the template with job-to-be-done workflow
- Adding references for detailed content
- Updating `README.md` and regenerating the catalog
- Validating with `scripts/validate_skills.py`
## Usage
@@ -23,7 +25,10 @@ Add a new skill for <workflow> in the LaunchDarkly agent-skills repo
```
create-skill/
├── SKILL.md
── README.md
── README.md
└── references/
├── skill-structure.md
└── frontmatter.md
```
## Related
+127 -44
View File
@@ -1,76 +1,159 @@
---
name: create-skill
description: "Add a new skill to the LaunchDarkly agent-skills repo. Use when creating a new SKILL.md, updating the skills catalog, and aligning with repo conventions."
description: "Add a new skill to the LaunchDarkly agent-skills repo. Use when creating a new SKILL.md, adding a skill to the catalog, or aligning with repo conventions. Guides exploration of existing skills before creating."
license: Apache-2.0
compatibility: Works in repositories following the Agent Skills open standard
metadata:
author: launchdarkly
version: "0.1.0"
version: "0.2.0"
---
# Create a LaunchDarkly Skill
This skill guides contributors through adding a new skill to the LaunchDarkly agent-skills repository, following the open standard and local repo conventions.
You're using a skill that will guide you through adding a new skill to the LaunchDarkly agent-skills repository. Your job is to explore existing skills to understand the patterns, assess what the new skill needs, create it following conventions, and verify it validates correctly.
## Prerequisites
- Access to the LaunchDarkly agent-skills repo
- Familiarity with the workflow you want to encode
- Access to the LaunchDarkly agent-skills repo (or a fork)
- Understanding of the workflow you want to encode
- Python 3.x (for validation scripts)
## Steps
## Core Principles
1. **Pick a category and name**
- Choose a category under `skills/` (for example, `feature-flags`, `ai-config`).
- Create a directory `skills/<category>/<skill-name>/`.
- Ensure `<skill-name>` is lowercase with hyphens, and matches the `name` field exactly.
1. **Explore First**: Look at existing skills before creating. Match their structure and style.
2. **Job to Be Done**: Every skill should clearly state what job it helps accomplish.
3. **References for Details**: Keep SKILL.md focused on the workflow. Move deep content to `references/`.
4. **Validate Before Commit**: Run validation scripts to catch issues.
2. **Create `SKILL.md`**
- Copy `template/SKILL.md.template` into the new skill directory and rename it to `SKILL.md`.
- Fill in required frontmatter: `name`, `description`.
- Keep `SKILL.md` under 500 lines and move deep details to `references/`.
## Workflow
3. **Add supporting files**
- If needed, add `references/` and optional `scripts/` or `assets/`.
- Keep reference files small and focused for on-demand loading.
### Step 1: Explore Existing Skills
4. **Update repo docs**
- Add the skill to the table in `README.md`.
- If the skill requires specific tooling, document it clearly in the skill.
Before creating anything, understand how skills are structured in this repo.
5. **Update the catalog**
- Run `python3 scripts/generate_catalog.py` to update `skills.json`.
1. **Browse the skills directory.**
- Look at `skills/feature-flags/` and other categories
- Note the directory layout: `skills/<category>/<skill-name>/`
- Each skill has `SKILL.md` and optionally `references/`, `README.md`, `marketplace.json`
6. **Validate**
- Run `python3 scripts/validate_skills.py`.
- Run `python3 -m unittest discover -s tests`.
2. **Read 12 similar skills.**
- If adding a feature-flag skill, read `launchdarkly-flag-create` or `launchdarkly-flag-cleanup`
- If adding an AI-config skill, read those under `ai-configs/` if present
- Observe: job-to-be-done intro, workflow steps, Core Principles, Edge Cases, What NOT to Do, References
## Guidelines
3. **Check the template.**
- Read `template/SKILL.md.template` for the expected structure
- The template reflects the workflow-based pattern used across skills
- Follow the Agent Skills spec for naming and frontmatter.
- Make “when to use this” explicit in the description.
- Avoid internal-only links or tools unless the skill is internal-only.
See [Skill Structure](references/skill-structure.md) for the full structure guide.
## Examples
### Step 2: Assess What's Needed
### Example: Add an AI config skill
Based on the user's request and your exploration:
**User**: "Add a skill to guide creating AI Configs"
1. **Choose category and name.**
- Category: `feature-flags`, `ai-configs`, `skill-authoring`, or new category
- Name: lowercase, hyphens only, under 64 chars (e.g., `my-new-skill`)
- Directory: `skills/<category>/<skill-name>/`
**Expected behavior**:
1. Create `skills/ai-configs/create-ai-config/`.
2. Fill `SKILL.md` using the template.
3. Add references if needed.
4. Update `README.md` and `skills.json`.
5. Run validation scripts.
2. **Identify the job to be done.**
- What does the user want to accomplish?
- What should the agent explore, assess, and verify?
- What references will the skill need?
3. **Plan the workflow.**
- Step 1: Explore (what to look for)
- Step 2: Assess (decision table or logic)
- Step 3: Execute (with references)
- Step 4: Verify (what the agent actually does)
See [Frontmatter & Metadata](references/frontmatter.md) for required fields.
### Step 3: Create the Skill
1. **Create the directory.**
```
skills/<category>/<skill-name>/
```
2. **Create SKILL.md.**
- Copy `template/SKILL.md.template` into the new directory
- Fill in frontmatter: `name` (must match folder name), `description`, `compatibility`, `metadata`
- Write the job-to-be-done intro and workflow steps
- Link to references for detailed content
- Keep SKILL.md under 500 lines
3. **Add references.**
- Create `references/` directory
- Add reference files for implementation details, API patterns, decision guides
- Link from SKILL.md
4. **Add supporting files (optional).**
- `README.md` — short description, link to SKILL.md
- `marketplace.json` — if publishing to a marketplace (see existing skills for format)
5. **Update repo docs.**
- Add the skill to the table in `README.md`
- If the skill requires specific tools, document them in the skill
See [Skill Structure](references/skill-structure.md) for file layout and content guidelines.
### Step 4: Update the Catalog
Regenerate the skills catalog so the new skill is discoverable:
```bash
python3 scripts/generate_catalog.py
```
This updates `skills.json`. Commit the updated file with your new skill.
### Step 5: Verify
Confirm the skill is valid and complete:
1. **Run validation:**
```bash
python3 scripts/validate_skills.py
```
Fix any reported errors (frontmatter, naming, length limits).
2. **Run tests (if present):**
```bash
python3 -m unittest discover -s tests
```
3. **Check structure:**
- SKILL.md exists and has valid frontmatter
- `name` in frontmatter matches directory name
- References are linked and exist
- README.md table includes the new skill
4. **Report results:**
- ✓ Skill created and validates
- ✓ Catalog updated
- ⚠️ Flag any validation issues or missing pieces
## Edge Cases
- **Name mismatch**: If `name` doesnt match the folder name, fix the folder or frontmatter.
- **Overlong SKILL.md**: Move detailed content into `references/`.
- **Missing catalog update**: Regenerate `skills.json` before committing.
| Situation | Action |
|-----------|--------|
| `name` doesn't match folder name | Fix folder name or frontmatter so they match exactly |
| SKILL.md over 500 lines | Move detailed content into `references/` |
| Category doesn't exist | Create `skills/<new-category>/` and add the skill |
| Marketplace.json needed | Copy format from `launchdarkly-flag-create/marketplace.json` |
| Validation fails | Fix the specific error (often frontmatter or naming) |
| Catalog not regenerated | Run `python3 scripts/generate_catalog.py` before commit |
## What NOT to Do
- Don't create a skill without exploring existing ones first
- Don't put long implementation details in SKILL.md — use references
- Don't forget to run `validate_skills.py` before committing
- Don't skip updating README.md and the catalog
- Don't use internal-only links or tools unless the skill is internal-only
## References
- `README.md`
- `docs/skills.md`
- `docs/versioning.md`
- [Skill Structure](references/skill-structure.md) — File layout, workflow pattern, content guidelines
- [Frontmatter & Metadata](references/frontmatter.md) — Required fields, naming rules, versioning
@@ -0,0 +1,94 @@
# Frontmatter & Metadata
Required and optional fields for SKILL.md frontmatter.
## Required Fields
### name
- **Format:** `lowercase-with-hyphens` only
- **Must match:** The directory name (`skills/<category>/<name>/`)
- **Pattern:** `^[a-z0-9]+(?:-[a-z0-9]+)*$`
- **Max length:** 64 characters
```yaml
name: launchdarkly-flag-create
```
### description
- **Purpose:** Helps the agent identify when to use this skill
- **Include:** Keywords, use cases, and "when to use" language
- **Max length:** 1024 characters
```yaml
description: "Create and configure LaunchDarkly feature flags in a way that fits the existing codebase. Use when the user wants to create a new flag, wrap code in a flag, or set up an experiment."
```
### compatibility
- **Purpose:** What the skill requires to work
- **Examples:**
- `Requires the remotely hosted LaunchDarkly MCP server`
- `Requires LaunchDarkly API token with ai-configs:write permission`
- `Works on all platforms`
- **Max length:** 500 characters
```yaml
compatibility: Requires the remotely hosted LaunchDarkly MCP server
```
## Optional Fields
### license
```yaml
license: Apache-2.0
```
### metadata
```yaml
metadata:
author: launchdarkly
version: "0.1.0"
```
### metadata.version
- Use semantic versioning: `MAJOR.MINOR.PATCH`
- Update when skill behavior changes
- Experimental skills may use: `1.0.0-experimental`
## Full Example
```yaml
---
name: launchdarkly-flag-create
description: "Create and configure LaunchDarkly feature flags in a way that fits the existing codebase. Use when the user wants to create a new flag, wrap code in a flag, add a feature toggle, or set up an experiment."
license: Apache-2.0
compatibility: Requires the remotely hosted LaunchDarkly MCP server
metadata:
author: launchdarkly
version: "1.0.0-experimental"
---
```
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| `name` has uppercase | Use lowercase only |
| `name` has underscores | Use hyphens |
| `name` doesn't match folder | Rename folder or fix frontmatter |
| Description too vague | Add keywords and "when to use" |
| Missing `compatibility` | Add requirement or "Works on all platforms" |
## Validation
Run `python3 scripts/validate_skills.py` to check:
- Opening and closing `---` delimiters
- Required fields present
- Name pattern and length
- Description and compatibility length
@@ -0,0 +1,121 @@
# Skill Structure Guide
How LaunchDarkly skills are organized and what content belongs where.
## Directory Layout
```
skills/
├── <category>/ # e.g., feature-flags, ai-configs, skill-authoring
│ └── <skill-name>/ # e.g., launchdarkly-flag-create
│ ├── SKILL.md # Required — main workflow guide
│ ├── README.md # Optional — short description
│ ├── marketplace.json # Optional — for marketplace publishing
│ └── references/ # Optional — detailed guides
│ ├── guide-1.md
│ └── guide-2.md
```
## SKILL.md Structure
Follow this pattern (see `template/SKILL.md.template`):
### 1. Frontmatter
```yaml
---
name: skill-name # Must match directory name
description: "..." # Clear, keyword-rich
compatibility: "..." # Requirements
metadata:
author: launchdarkly
version: "0.1.0"
---
```
### 2. Job-to-Be-Done Intro
Start with a sentence like:
> You're using a skill that will guide you through [the job]. Your job is to explore [what], assess [what], choose the right path, execute, and verify it was done correctly.
### 3. Prerequisites
- What's required to use this skill
- MCP tools, API access, permissions
### 4. Core Principles
34 short principles that guide the workflow.
### 5. Workflow
Numbered steps (Step 1, Step 2, …):
- **Step 1: Explore** — Understand the situation before acting
- **Step 2: Assess** — Decide the right approach
- **Step 3: Execute** — Do the work (link to references)
- **Step 4: Verify** — Confirm completion (agent performs checks)
Each step should be actionable. Link to references for detailed implementation.
### 6. Edge Cases
Table: `| Situation | Action |`
### 7. What NOT to Do
Bullet list of anti-patterns.
### 8. References
Links to `references/*.md` files.
## When to Use References
Move content to `references/` when:
- Implementation details (API patterns, code examples)
- Long decision tables or guides
- Stack-specific or use-case-specific content
- Content that would make SKILL.md exceed ~500 lines
Keep in SKILL.md:
- The workflow steps
- Core principles
- Decision tables (if short)
- Edge cases
- Verification steps
## Workflow Pattern
All skills follow:
1. **Explore** — Don't assume. Look at the codebase, existing config, or context first.
2. **Assess** — Based on exploration, decide the right path.
3. **Choose** — Pick references that match the situation.
4. **Execute** — Follow the reference to do the work.
5. **Verify** — Actually perform checks (API calls, scripts) and report results.
## Naming Conventions
- **Skill name:** `lowercase-with-hyphens` (e.g., `launchdarkly-flag-create`)
- **Category:** `lowercase-with-hyphens` (e.g., `feature-flags`)
- **Reference files:** `kebab-case.md` (e.g., `sdk-patterns.md`)
- **Name length:** Under 64 characters
- **Description length:** Under 1024 characters
## Validation
The `validate_skills.py` script checks:
- Frontmatter exists and is valid
- Required fields: `name`, `description`, `compatibility`
- `name` matches directory name
- Name and description length limits
- No excluded directories
Run before every commit:
```bash
python3 scripts/validate_skills.py
```
+48 -30
View File
@@ -1,60 +1,78 @@
---
name: skill-name
description: A clear description of what this skill does and when the agent should use it. Include keywords that help the agent identify relevant tasks.
compatibility: Specify platform requirements (for example, "Works on all platforms" or "Requires LaunchDarkly MCP server").
compatibility: Specify requirements (e.g., "Requires LaunchDarkly MCP server" or "Works on all platforms").
metadata:
author: your-name
author: launchdarkly
version: "0.1.0"
---
# Skill Title
Brief overview of what this skill helps accomplish.
You're using a skill that will guide you through [the job to be done]. Your job is to explore [what to understand first], assess [what to decide], choose the right path, execute the work, and verify it was done correctly.
## Prerequisites
List any requirements:
- Required tools or CLIs
- Required MCP servers
- Required permissions or access
- Requirement 1
- Requirement 2
- Required tools or MCP servers (if any)
## Steps
## Core Principles
Describe the workflow the agent should follow:
1. **First principle**: Brief description
2. **Second principle**: Brief description
3. **Third principle**: Brief description
1. **First step**: What to do first
2. **Second step**: What comes next
3. **Continue**: As needed
## Workflow
## Guidelines
### Step 1: Explore
- Key principle or best practice
- Another guideline
- Things to watch out for
Before doing anything, understand the situation:
## Examples
1. What to look for
2. What patterns to identify
3. What context to gather
### Example 1: Basic usage
See [Reference Name](references/reference-name.md) for detailed guidance.
**User**: Example user request
### Step 2: Assess
**Expected behavior**:
1. What the agent should do
2. Expected outcome
Based on your exploration, determine the right approach:
### Example 2: Edge case
| Scenario | Recommended Path |
|----------|------------------|
| Situation A | Path or action |
| Situation B | Path or action |
**User**: Another example
### Step 3: Execute
**Expected behavior**:
1. How to handle this case
Follow the chosen path. Reference guides for implementation details:
- [By use case](references/use-case-guide.md)
- [By stack](references/stack-guide.md)
### Step 4: Verify
Confirm the job was done correctly:
1. **Check via API/MCP** (if applicable): Describe what to verify
2. **Run validation**: Commands or scripts to run
3. **Report results**: ✓ Success or ⚠️ Issues found
## Edge Cases
- **Scenario A**: How to handle it
- **Scenario B**: How to handle it
| Situation | Action |
|-----------|--------|
| Edge case A | How to handle |
| Edge case B | How to handle |
## What NOT to Do
- Don't do X
- Don't do Y
- Don't do Z
## References
Link to any additional documentation:
- [External resources](https://example.com)
- [Reference 1](references/reference-1.md) — Description
- [Reference 2](references/reference-2.md) — Description