Claude Code Plugins

Community-maintained marketplace

Feedback

openfeature-eng

@aRustyDev/ai
0
0

Implement OpenFeature feature flags in software projects. Use when adding feature flags with OpenFeature SDKs, configuring providers, setting up evaluation context, or integrating the OpenFeature MCP Server.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name openfeature-eng
description Implement OpenFeature feature flags in software projects. Use when adding feature flags with OpenFeature SDKs, configuring providers, setting up evaluation context, or integrating the OpenFeature MCP Server.

OpenFeature Implementation

Guide for implementing OpenFeature - the open standard for feature flag management - across server and client applications.

When to Use This Skill

  • Adding feature flags to a new or existing project
  • Implementing OpenFeature Server SDKs (Go, Java, .NET, Node.js, PHP, Python, Ruby, Rust, Dart)
  • Implementing OpenFeature Client SDKs (JavaScript, React, Angular, Kotlin, iOS/Swift)
  • Configuring feature flag providers (flagd, LaunchDarkly, Split, etc.)
  • Setting up evaluation context for targeting
  • Using the OpenFeature MCP Server

This skill does NOT cover:

  • Creating custom OpenFeature providers (see provider development docs)
  • Vendor-specific flag management UIs
  • Feature flag strategy/design patterns

Core Concepts

OpenFeature Architecture

┌─────────────────────────────────────────────────────────────┐
│                     Application Code                         │
│  client.getBooleanValue("feature-x", false, context)        │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    OpenFeature SDK                           │
│  - Evaluation API                                            │
│  - Hooks (before/after/error/finally)                       │
│  - Event handling                                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Provider                                │
│  flagd | LaunchDarkly | Split | CloudBees | In-Memory       │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   Flag Management                            │
│  Flag definitions, rules, segments, rollouts                │
└─────────────────────────────────────────────────────────────┘

Key Terms

Term Description
Provider Backend that evaluates flags (flagd, LaunchDarkly, etc.)
Client SDK instance for evaluating flags
Context User/request attributes for targeting
Hook Lifecycle callbacks for logging, metrics
Flag Feature toggle with key, type, and default value

Server SDK Implementations

Go

go get github.com/open-feature/go-sdk
package main

import (
    "context"
    "github.com/open-feature/go-sdk/openfeature"
    "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg"
)

func main() {
    // Set up provider
    provider := flagd.NewProvider()
    openfeature.SetProvider(provider)

    // Get client
    client := openfeature.NewClient("my-app")

    // Evaluation context
    ctx := openfeature.NewEvaluationContext(
        "user-123",
        map[string]interface{}{
            "email": "user@example.com",
            "tier":  "premium",
        },
    )

    // Evaluate flags
    enabled, _ := client.BooleanValue(
        context.Background(),
        "new-feature",
        false,
        ctx,
    )

    if enabled {
        // New feature code
    }
}

Java

<dependency>
    <groupId>dev.openfeature</groupId>
    <artifactId>sdk</artifactId>
    <version>1.7.0</version>
</dependency>
import dev.openfeature.sdk.*;
import dev.openfeature.contrib.providers.flagd.FlagdProvider;

public class FeatureFlags {
    public static void main(String[] args) {
        // Set provider
        OpenFeatureAPI api = OpenFeatureAPI.getInstance();
        api.setProvider(new FlagdProvider());

        // Get client
        Client client = api.getClient("my-app");

        // Evaluation context
        EvaluationContext ctx = new ImmutableContext("user-123",
            Map.of(
                "email", new Value("user@example.com"),
                "tier", new Value("premium")
            )
        );

        // Evaluate flags
        boolean enabled = client.getBooleanValue("new-feature", false, ctx);

        if (enabled) {
            // New feature code
        }
    }
}

.NET

dotnet add package OpenFeature
dotnet add package OpenFeature.Contrib.Providers.Flagd
using OpenFeature;
using OpenFeature.Contrib.Providers.Flagd;

// Set provider
var provider = new FlagdProvider();
await Api.Instance.SetProviderAsync(provider);

// Get client
var client = Api.Instance.GetClient("my-app");

// Evaluation context
var context = EvaluationContext.Builder()
    .SetTargetingKey("user-123")
    .Set("email", "user@example.com")
    .Set("tier", "premium")
    .Build();

// Evaluate flags
var enabled = await client.GetBooleanValueAsync("new-feature", false, context);

if (enabled)
{
    // New feature code
}

Node.js / TypeScript

npm install @openfeature/server-sdk @openfeature/flagd-provider
import { OpenFeature } from '@openfeature/server-sdk';
import { FlagdProvider } from '@openfeature/flagd-provider';

// Set provider
await OpenFeature.setProviderAndWait(new FlagdProvider());

// Get client
const client = OpenFeature.getClient('my-app');

// Evaluation context
const context = {
  targetingKey: 'user-123',
  email: 'user@example.com',
  tier: 'premium',
};

// Evaluate flags
const enabled = await client.getBooleanValue('new-feature', false, context);

if (enabled) {
  // New feature code
}

NestJS Integration

npm install @openfeature/server-sdk @openfeature/nestjs-sdk @openfeature/flagd-provider
// app.module.ts
import { Module } from '@nestjs/common';
import { OpenFeatureModule } from '@openfeature/nestjs-sdk';
import { FlagdProvider } from '@openfeature/flagd-provider';

@Module({
  imports: [
    OpenFeatureModule.forRoot({
      defaultProvider: new FlagdProvider(),
    }),
  ],
})
export class AppModule {}
// feature.service.ts
import { Injectable } from '@nestjs/common';
import {
  OpenFeatureClient,
  BooleanFeatureFlag
} from '@openfeature/nestjs-sdk';
import { Client } from '@openfeature/server-sdk';

@Injectable()
export class FeatureService {
  constructor(
    @OpenFeatureClient() private client: Client,
  ) {}

  @BooleanFeatureFlag({
    flagKey: 'new-feature',
    defaultValue: false,
  })
  async isNewFeatureEnabled(): Promise<boolean> {
    return this.client.getBooleanValue('new-feature', false);
  }
}

Python

pip install openfeature-sdk openfeature-provider-flagd
from openfeature import api
from openfeature.evaluation_context import EvaluationContext
from openfeature.contrib.provider.flagd import FlagdProvider

# Set provider
api.set_provider(FlagdProvider())

# Get client
client = api.get_client("my-app")

# Evaluation context
context = EvaluationContext(
    targeting_key="user-123",
    attributes={
        "email": "user@example.com",
        "tier": "premium",
    }
)

# Evaluate flags
enabled = client.get_boolean_value("new-feature", False, context)

if enabled:
    # New feature code
    pass

Ruby

gem install openfeature-sdk openfeature-flagd-provider
require 'openfeature/sdk'
require 'openfeature/flagd/provider'

# Set provider
OpenFeature::SDK.configure do |config|
  config.set_provider(OpenFeature::Flagd::Provider.new)
end

# Get client
client = OpenFeature::SDK.build_client(name: 'my-app')

# Evaluation context
context = OpenFeature::SDK::EvaluationContext.new(
  targeting_key: 'user-123',
  email: 'user@example.com',
  tier: 'premium'
)

# Evaluate flags
enabled = client.fetch_boolean_value(
  flag_key: 'new-feature',
  default_value: false,
  evaluation_context: context
)

if enabled
  # New feature code
end

Rust

[dependencies]
open-feature = "0.2"
use open_feature::{
    provider::NoOpProvider,
    EvaluationContext, OpenFeature,
};

#[tokio::main]
async fn main() {
    // Set provider
    let mut api = OpenFeature::singleton_mut().await;
    api.set_provider(NoOpProvider::default()).await;

    // Get client
    let client = api.create_client();

    // Evaluation context
    let context = EvaluationContext::default()
        .with_targeting_key("user-123")
        .with_custom_field("email", "user@example.com")
        .with_custom_field("tier", "premium");

    // Evaluate flags
    let enabled = client
        .get_bool_value("new-feature", Some(&context), None)
        .await
        .unwrap_or(false);

    if enabled {
        // New feature code
    }
}

Dart

dependencies:
  openfeature_dart_sdk: ^0.1.0
import 'package:openfeature_dart_sdk/openfeature_dart_sdk.dart';

void main() async {
  // Set provider
  final api = OpenFeatureAPI.instance;
  await api.setProvider(InMemoryProvider());

  // Get client
  final client = api.getClient('my-app');

  // Evaluation context
  final context = EvaluationContext(
    targetingKey: 'user-123',
    attributes: {
      'email': 'user@example.com',
      'tier': 'premium',
    },
  );

  // Evaluate flags
  final enabled = await client.getBooleanValue(
    'new-feature',
    defaultValue: false,
    context: context,
  );

  if (enabled) {
    // New feature code
  }
}

PHP

composer require open-feature/sdk open-feature/flagd-provider
<?php
use OpenFeature\OpenFeatureAPI;
use OpenFeature\Providers\Flagd\FlagdProvider;
use OpenFeature\implementation\flags\EvaluationContext;

// Set provider
$api = OpenFeatureAPI::getInstance();
$api->setProvider(new FlagdProvider());

// Get client
$client = $api->getClient('my-app');

// Evaluation context
$context = new EvaluationContext(
    'user-123',
    [
        'email' => 'user@example.com',
        'tier' => 'premium',
    ]
);

// Evaluate flags
$enabled = $client->getBooleanValue('new-feature', false, $context);

if ($enabled) {
    // New feature code
}

Client SDK Implementations

React

npm install @openfeature/react-sdk @openfeature/web-sdk @openfeature/flagd-web-provider
// App.tsx
import { OpenFeatureProvider, useBooleanFlagValue } from '@openfeature/react-sdk';
import { FlagdWebProvider } from '@openfeature/flagd-web-provider';

const provider = new FlagdWebProvider({
  host: 'localhost',
  port: 8013,
});

function App() {
  return (
    <OpenFeatureProvider provider={provider}>
      <FeatureComponent />
    </OpenFeatureProvider>
  );
}

function FeatureComponent() {
  const enabled = useBooleanFlagValue('new-feature', false);

  return enabled ? <NewFeature /> : <OldFeature />;
}
// With evaluation context
import { useOpenFeatureClient } from '@openfeature/react-sdk';

function UserFeature({ userId }: { userId: string }) {
  const client = useOpenFeatureClient();

  const enabled = useBooleanFlagValue('premium-feature', false, {
    targetingKey: userId,
    tier: 'premium',
  });

  return enabled ? <PremiumFeature /> : <StandardFeature />;
}

Angular

npm install @openfeature/angular-sdk @openfeature/web-sdk
// app.module.ts
import { NgModule } from '@angular/core';
import { OpenFeatureModule } from '@openfeature/angular-sdk';
import { InMemoryProvider } from '@openfeature/web-sdk';

@NgModule({
  imports: [
    OpenFeatureModule.forRoot({
      provider: new InMemoryProvider({
        'new-feature': {
          disabled: false,
          variants: { on: true, off: false },
          defaultVariant: 'on'
        },
      }),
    }),
  ],
})
export class AppModule {}
// feature.component.ts
import { Component } from '@angular/core';
import { BooleanFeatureFlag } from '@openfeature/angular-sdk';

@Component({
  selector: 'app-feature',
  template: `
    <div *ngIf="isEnabled$ | async">
      New Feature Content
    </div>
  `,
})
export class FeatureComponent {
  @BooleanFeatureFlag({ flagKey: 'new-feature', defaultValue: false })
  isEnabled$!: Observable<boolean>;
}

Kotlin (Android)

// build.gradle.kts
dependencies {
    implementation("dev.openfeature:android-sdk:0.3.0")
}
import dev.openfeature.sdk.OpenFeatureAPI
import dev.openfeature.sdk.EvaluationContext
import dev.openfeature.contrib.providers.flagd.FlagdProvider

class FeatureFlags(context: Context) {
    private val client: Client

    init {
        // Set provider
        val api = OpenFeatureAPI.getInstance()
        api.setProvider(FlagdProvider())

        client = api.getClient("my-app")
    }

    suspend fun isNewFeatureEnabled(userId: String): Boolean {
        val context = EvaluationContext(
            targetingKey = userId,
            attributes = mapOf(
                "platform" to "android",
                "version" to BuildConfig.VERSION_NAME
            )
        )

        return client.getBooleanValue("new-feature", false, context)
    }
}

iOS / Swift

// Package.swift
dependencies: [
    .package(url: "https://github.com/open-feature/swift-sdk.git", from: "0.1.0")
]
import OpenFeature

class FeatureFlags {
    private let client: Client

    init() {
        // Set provider
        let api = OpenFeatureAPI.shared
        api.setProvider(provider: InMemoryProvider())

        client = api.getClient(name: "my-app")
    }

    func isNewFeatureEnabled(userId: String) async -> Bool {
        let context = MutableContext(
            targetingKey: userId,
            structure: MutableStructure(
                attributes: [
                    "platform": .string("ios"),
                    "version": .string(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "")
                ]
            )
        )

        return await client.getBooleanValue(
            key: "new-feature",
            defaultValue: false,
            context: context
        )
    }
}

Provider Configuration

flagd (Open Source)

# flagd-config.yaml
flags:
  new-feature:
    state: ENABLED
    variants:
      "on": true
      "off": false
    defaultVariant: "off"
    targeting:
      if:
        - in:
            - var: tier
            - ["premium", "enterprise"]
        - "on"
        - "off"
# Run flagd
docker run -p 8013:8013 -v ./flagd-config.yaml:/config.yaml \
  ghcr.io/open-feature/flagd:latest start --uri file:/config.yaml

In-Memory Provider (Testing)

import { InMemoryProvider } from '@openfeature/server-sdk';

const flags = {
  'new-feature': {
    disabled: false,
    variants: { on: true, off: false },
    defaultVariant: 'on',
  },
  'feature-limit': {
    disabled: false,
    variants: { low: 10, medium: 50, high: 100 },
    defaultVariant: 'medium',
  },
};

await OpenFeature.setProviderAndWait(new InMemoryProvider(flags));

OpenFeature MCP Server

The OpenFeature MCP Server enables flag evaluation through Claude.

Installation

npx @openfeature/mcp-server

Configuration

{
  "mcpServers": {
    "openfeature": {
      "command": "npx",
      "args": ["@openfeature/mcp-server"],
      "env": {
        "FLAGD_HOST": "localhost",
        "FLAGD_PORT": "8013"
      }
    }
  }
}

Usage

The MCP server provides tools for:

  • Evaluating feature flags
  • Listing available flags
  • Getting flag metadata

Hooks

Logging Hook

import { Hook, HookContext, EvaluationDetails } from '@openfeature/server-sdk';

const loggingHook: Hook = {
  before: (hookContext: HookContext) => {
    console.log(`Evaluating flag: ${hookContext.flagKey}`);
  },
  after: (hookContext: HookContext, details: EvaluationDetails<any>) => {
    console.log(`Flag ${hookContext.flagKey} = ${details.value}`);
  },
  error: (hookContext: HookContext, error: Error) => {
    console.error(`Error evaluating ${hookContext.flagKey}:`, error);
  },
};

client.addHooks(loggingHook);

Metrics Hook

const metricsHook: Hook = {
  after: (hookContext, details) => {
    metrics.increment('feature_flag.evaluation', {
      flag: hookContext.flagKey,
      variant: details.variant,
      reason: details.reason,
    });
  },
};

Testing

Unit Testing with Mocks

import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk';

describe('Feature Tests', () => {
  beforeEach(async () => {
    await OpenFeature.setProviderAndWait(
      new InMemoryProvider({
        'new-feature': {
          disabled: false,
          variants: { on: true, off: false },
          defaultVariant: 'on',
        },
      })
    );
  });

  it('should show new feature when enabled', async () => {
    const client = OpenFeature.getClient();
    const enabled = await client.getBooleanValue('new-feature', false);
    expect(enabled).toBe(true);
  });
});

Best Practices

  1. Set default values defensively - Always provide sensible defaults
  2. Use targeting keys - Enable user-level targeting and consistency
  3. Add evaluation context - Include relevant attributes for targeting
  4. Implement hooks - Add logging and metrics for observability
  5. Clean up flags - Remove flags after features are fully rolled out
  6. Use typed values - Prefer specific value types over strings
  7. Test both paths - Test feature on and off states

References