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
US web checkout via the StoreKit External Purchase Link entitlement — currently 0% Apple commission (litigation ongoing), how to ship it safely, and how to architect for a commission flip so a future ruling is a config change, not a rewrite. Use when adding external purchase links, weighing web checkout vs IAP, or planning US-storefront pricing strategy.
tools
Revenue beyond the single-app price tag — own-app bundles, Family Sharing as a conversion lever, cross-developer bundles & suites, and institutional licensing via Group Purchases / Apple School & Business Manager. Use when a developer has multiple apps, a subscription worth sharing, complementary indie partners, or school/clinic/business buyers.
testing
Run a structured accessibility audit on an iOS/macOS app — automated XCUITest audits, Accessibility Inspector, manual VoiceOver/Dynamic Type passes, and App Store Accessibility Nutrition Label evaluation. Use before release, when preparing Nutrition Label declarations, or for EU Accessibility Act compliance.
tools
Stage-by-stage audit of an app's App Store growth machinery against a 54-item P0–P9 playbook — every item scored from an App Store Connect MCP call, a codebase check, or an explicit question to the user, then routed to the skill or command that fixes it. Read-only on App Store Connect. Use for a growth audit or scorecard, a pre-launch growth plan, a quarterly re-audit, or "which growth levers am I missing."