Generate feature flag infrastructure with local defaults, remote configuration, SwiftUI integration, and debug menu. Use when adding feature flags or A/B testing to iOS/macOS apps.
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill feature-flags
Generate a complete feature flag infrastructure with typed flag definitions, protocol-based providers (local, remote, composite), SwiftUI environment integration, an @Observable manager, and a debug menu for toggling flags at runtime.
Use this skill when the user:
Search for existing feature flag code:
Glob: **/*FeatureFlag*.swift, **/*FeatureToggle*.swift, **/*RemoteConfig*.swift
Grep: "FeatureFlag" or "FeatureToggle" or "RemoteConfig" or "isFeatureEnabled"
If existing feature flag code is found:
If a third-party SDK (Firebase, LaunchDarkly, etc.) is detected:
Feature flags require:
Ask user via AskUserQuestion:
Check project structure:
Sources/ exists --> Sources/FeatureFlags/App/ exists --> App/FeatureFlags/FeatureFlags/Generate these files based on configuration answers:
FeatureFlag.swift -- Flag enum with typed default valuesFeatureFlagService.swift -- Protocol defining provider interfaceLocalFeatureFlagProvider.swift -- UserDefaults-based provider with debug overridesRemoteFeatureFlagProvider.swift -- URL-based provider with disk caching (if remote or composite)CompositeFeatureFlagProvider.swift -- Combines local + remote; remote overrides local (if composite)FeatureFlagManager.swift -- @Observable manager for SwiftUIFeatureFlagEnvironmentKey.swift -- SwiftUI Environment integration (if requested)FeatureFlagDebugView.swift -- Debug toggle view (if requested)Use the templates in templates.md and customize based on user answers:
After generation, provide:
Sources/FeatureFlags/
├── FeatureFlag.swift # Flag enum with typed defaults
├── FeatureFlagService.swift # Provider protocol
├── LocalFeatureFlagProvider.swift # UserDefaults-based provider
├── RemoteFeatureFlagProvider.swift # URL-based provider (if remote/composite)
├── CompositeFeatureFlagProvider.swift # Local + remote combiner (if composite)
├── FeatureFlagManager.swift # @Observable manager for SwiftUI
├── FeatureFlagEnvironmentKey.swift # SwiftUI Environment key (if requested)
└── FeatureFlagDebugView.swift # Debug toggle menu (if requested)
1. Initialize the manager in your App struct or entry point:
import SwiftUI
@main
struct MyApp: App {
@State private var featureFlagManager: FeatureFlagManager
init() {
// Local only
let provider = LocalFeatureFlagProvider()
// Or composite (remote overrides local)
// let provider = CompositeFeatureFlagProvider(
// local: LocalFeatureFlagProvider(),
// remote: RemoteFeatureFlagProvider(
// endpoint: URL(string: "https://api.example.com/flags")!
// )
// )
_featureFlagManager = State(initialValue: FeatureFlagManager(provider: provider))
}
var body: some Scene {
WindowGroup {
ContentView()
.environment(featureFlagManager)
}
}
}
2. Use flags in your views:
struct ContentView: View {
@Environment(FeatureFlagManager.self) private var flags
var body: some View {
VStack {
if flags.isEnabled(.newOnboarding) {
NewOnboardingView()
} else {
LegacyOnboardingView()
}
}
}
}
3. Refresh remote flags (if using remote or composite):
// Refresh on app launch or periodically
Task {
try await featureFlagManager.refresh()
}
4. Add debug menu (if generated, DEBUG builds only):
#if DEBUG
NavigationLink("Feature Flags") {
FeatureFlagDebugView()
.environment(featureFlagManager)
}
#endif
FeatureFlagService and can be tested in isolation. final class MockFeatureFlagProvider: FeatureFlagService {
var overrides: [FeatureFlag: Bool] = [:]
func isEnabled(_ flag: FeatureFlag) -> Bool {
overrides[flag] ?? flag.defaultValue
}
// ... implement remaining protocol methods
}
The most common pattern. Enable or disable a feature entirely.
if flags.isEnabled(.premiumPaywall) {
PremiumPaywallView()
}
Use string values to serve different text or configuration strings remotely.
let welcomeMessage = flags.stringValue(.welcomeMessage) ?? "Welcome!"
Text(welcomeMessage)
Control numeric parameters like retry counts, page sizes, or rate limits.
let maxRetries = flags.intValue(.maxRetries) ?? 3
For structured configuration that changes server-side.
struct PaywallConfig: Codable {
let title: String
let trialDays: Int
let showTestimonials: Bool
}
if let config: PaywallConfig = flags.jsonValue(.paywallConfig) {
PaywallView(config: config)
}
Combine feature flags with user segmentation.
// Server returns different flag values per user segment
// The flag is simply on/off from the client perspective
if flags.isEnabled(.newCheckoutFlow) {
NewCheckoutView()
} else {
LegacyCheckoutView()
}
FeatureFlagManager is @MainActor-isolated. Access it on the main thread or via @Environment in SwiftUI views. The providers use Sendable-conforming storage.#if DEBUG guards. Double-check that debug toggles never leak into release builds.cacheDuration (default 5 minutes). For time-sensitive flags, call refresh() explicitly.ff_ to avoid collisions with other UserDefaults entries in the app.Comprehensive healthcare AI toolkit for developing, testing, and deploying machine learning models with clinical data. This skill should be used when working with electronic health records (EHR), clinical prediction tasks (mortality, readmission, drug recommendation), medical coding systems (ICD, NDC, ATC), physiological signals (EEG, ECG), healthcare datasets (MIMIC-III/IV, eICU, OMOP), or implementing deep learning models for healthcare applications (RETAIN, SafeDrug, Transformer, GNN).
Comprehensive healthcare AI toolkit for developing, testing, and deploying machine learning models with clinical data. This skill should be used when working with electronic health records (EHR), clinical prediction tasks (mortality, readmission, drug recommendation), medical coding systems (ICD, NDC, ATC), physiological signals (EEG, ECG), healthcare datasets (MIMIC-III/IV, eICU, OMOP), or implementing deep learning models for healthcare applications (RETAIN, SafeDrug, Transformer, GNN).
Expert performance engineer specializing in modern observability, application optimization, and scalable system performance. Masters OpenTelemetry, distributed tracing, load testing, multi-tier caching, Core Web Vitals, and performance monitoring. Handles end-to-end optimization, real user monitoring, and scalability patterns. Use PROACTIVELY for performance optimization, observability, or scalability challenges.
Master AI-powered test automation with modern frameworks, self-healing tests, and comprehensive quality engineering. Build scalable testing strategies with advanced CI/CD integration. Use PROACTIVELY for testing automation or quality assurance.
Internet Court adapter for GenLayer Intelligent Contract supervision. Use to specify agent-performance rubrics, evidence schemas, decision outputs, and ERC-7710 connector expectations, while delegating actual GenLayer contract writing, linting, testing, deployment, and CLI interaction to the official GenLayer skills at https://skills.genlayer.com/.
> Suggests using Microsoft Testing Platform (MTP) hot reload to iterate fixes on failing tests without rebuilding. Use when user says "hot reload tests", "iterate on test fix", "run tests without rebuilding", "speed up test loop", "fix test faster", or needs to set up MTP hot reload to rapidly iterate on test failures. Covers setup (NuGet package, environment variable, launchSettings.json) and the iterative workflow for fixing tests. normally with dotnet test (use run-tests), applying test filters, producing TRX reports, CI/CD pipeline configuration, or Visual Studio Test Explorer hot reload (which is a different feature).
Build production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.
Build production-grade Azure Cosmos DB NoSQL services following clean code, security best practices, and TDD principles.
Take rshankras/feature-flags from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.