skills/generators/feature-flags/SKILL.md
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 skillsauth add rshankras/claude-code-apple-skills feature-flagsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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:
What features do you want to flag? (freeform)
What flag value types do you need?
What provider architecture?
Include debug menu?
Include SwiftUI environment integration?
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.development
Build, install, and launch an iOS app on a physical iPhone or iPad entirely from the command line (no Xcode GUI), using xcodebuild + devicectl. Use when the user wants to run, test, or screenshot their app on a real device without opening Xcode.
development
Comprehensive iOS development guidance including Swift best practices, SwiftUI patterns, UI/UX review against HIG, and app planning. Use for iOS code review, best practices, accessibility audits, or planning new iOS apps.
development
Build, install, launch, and screenshot an iOS app in the Simulator to verify a change visually. Use when the user wants to run the app, see a change live, screenshot the running app, or confirm a UI fix actually works (not just that it compiles).
development
Audits skills in this repo for consistency, API drift, and structural gaps. Produces a prioritized report grouped by severity (Critical/High/Medium/Low). Use when asked to "audit skills", "check the skill repo for drift", or when planning bulk skill cleanup. Read-only — does not apply fixes.