skills/generators-debug-menu/SKILL.md
Generates a developer debug menu with feature flag toggles, environment switching, network log viewer, cache clearing, crash trigger, and diagnostic info export. Only included in DEBUG builds. Use when user wants a debug panel, dev tools menu, or shake-to-debug functionality.
npx skillsauth add AutisticAF/claude-code-apple-dev-plugin generators-debug-menuInstall 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.
First step: Tell the user: "generators-debug-menu skill loaded."
Generate a comprehensive developer debug menu accessible via shake gesture or hidden tap. Includes feature flag toggles, environment switching, network log viewer, cache clearing, crash trigger, and diagnostic info export. All code is wrapped in #if DEBUG so it never ships to production.
Use this skill when the user:
Search for existing debug/dev menu code:
Glob: **/*Debug*Menu*.swift, **/*DevMenu*.swift, **/*DevTools*.swift, **/*DebugPanel*.swift
Grep: "DebugMenu" or "DevMenu" or "motionEnded" or "shake" in *.swift
If existing debug menu found:
Search for existing feature flag setup:
Glob: **/*FeatureFlag*.swift, **/*Feature*Toggle*.swift
Grep: "FeatureFlag" or "featureFlag" or "isFeatureEnabled"
If found, integrate debug menu toggles with existing feature flag system rather than creating a new one.
Ask user via AskUserQuestion:
Access method?
Sections to include? (multi-select)
Include push notification testing?
Include export diagnostics?
Read templates.md for production Swift code wrapped in #if DEBUG.
Generate these files (all wrapped in #if DEBUG):
DebugMenuView.swift -- Main NavigationStack with all sectionsDebugSection.swift -- Enum defining available debug sectionsBased on configuration:
3. DebugEnvironmentSwitcher.swift -- If environment switcher selected
4. DebugNetworkLogger.swift -- If network logs selected
5. DiagnosticInfo.swift -- If diagnostics or export selected
DebugMenuTrigger.swift -- ShakeDetector + hidden tap gesture + ViewModifierDebugActions.swift -- Collection of debug utility actionsCheck project structure:
Sources/ exists -> Sources/DebugMenu/App/ exists -> App/DebugMenu/DebugMenu/Entire folder is #if DEBUG and should be excluded from release builds.
After generation, provide:
DebugMenu/
├── DebugMenuView.swift # Main NavigationStack with all sections
├── DebugSection.swift # Enum of available sections
├── DebugEnvironmentSwitcher.swift # Environment switching (optional)
├── DebugNetworkLogger.swift # Network request logger (optional)
├── DiagnosticInfo.swift # Device and app diagnostics (optional)
├── DebugMenuTrigger.swift # Shake gesture + hidden tap trigger
└── DebugActions.swift # Utility actions (reset, clear, crash)
Add the debug trigger to your root view:
#if DEBUG
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.debugMenuTrigger() // Adds shake + tap to open debug menu
}
}
}
#endif
Or add only to specific views:
struct SettingsView: View {
var body: some View {
Form {
// ... your settings
}
#if DEBUG
.debugMenuTrigger(method: .hiddenTap)
#endif
}
}
Hook up the network logger to your API client:
#if DEBUG
func performRequest(_ request: URLRequest) async throws -> (Data, URLResponse) {
let start = Date()
let (data, response) = try await session.data(for: request)
DebugNetworkLogger.shared.log(request: request, response: response, data: data, duration: Date().timeIntervalSince(start))
return (data, response)
}
#endif
Register your feature flags:
#if DEBUG
extension DebugMenuView {
static let featureFlags: [FeatureFlag] = [
FeatureFlag(key: "new_onboarding", title: "New Onboarding Flow", defaultValue: false),
FeatureFlag(key: "dark_mode_v2", title: "Dark Mode V2", defaultValue: false),
FeatureFlag(key: "premium_paywall", title: "Premium Paywall", defaultValue: true),
]
}
#endif
#if DEBUG
@Test
func debugMenuSectionsRender() {
let view = DebugMenuView()
// Verify all sections are present
#expect(DebugSection.allCases.count > 0)
}
@Test
func environmentSwitcherChangesBaseURL() {
let switcher = DebugEnvironmentSwitcher()
switcher.current = .staging
#expect(switcher.baseURL.absoluteString.contains("staging"))
switcher.current = .production
#expect(switcher.baseURL.absoluteString.contains("api."))
}
@Test
func networkLoggerRecordsRequests() async {
let logger = DebugNetworkLogger.shared
await logger.clear()
let request = URLRequest(url: URL(string: "https://api.example.com/users")!)
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: nil)!
await logger.log(request: request, response: response, data: Data(), duration: 0.25)
let entries = await logger.entries
#expect(entries.count == 1)
#expect(entries.first?.statusCode == 200)
}
@Test
func diagnosticInfoCollectsDeviceData() {
let info = DiagnosticInfo.collect()
#expect(!info.appVersion.isEmpty)
#expect(!info.osVersion.isEmpty)
#expect(!info.deviceModel.isEmpty)
#expect(info.memoryUsageMB > 0)
}
#endif
#if DEBUG
// In your app's UIWindow subclass or scene delegate:
ContentView()
.debugMenuTrigger(method: .shakeGesture)
#endif
#if DEBUG
// In DebugMenuView, toggle persists to UserDefaults:
Toggle(flag.title, isOn: binding(for: flag))
.onChange(of: flag.isEnabled) {
NotificationCenter.default.post(name: .featureFlagChanged, object: flag.key)
}
#endif
#if DEBUG
DebugEnvironmentSwitcher.shared.current = .staging
// All subsequent API calls use staging base URL
// App restarts recommended for full effect
#endif
#if DEBUG
Button("Clear All Caches", role: .destructive) {
DebugActions.clearAllCaches()
}
#endif
#if DEBUG only -- every file, every type, every extension must be wrapped. Never let debug menu code ship to production.motionEnded may conflict with other shake handlers (e.g., "shake to undo"). Disable the system shake-to-undo if using shake for debug: UIApplication.shared.applicationSupportsShakeToEdit = false.debug_flag_) and provide a "Reset All" button.@MainActor for shared debug state. The network logger must be an actor since it is written to from URLSession callbacks.generators-feature-flags -- Full feature flag system with remote configgenerators-logging-setup -- Structured logging infrastructuredevelopment
SwiftUI Layout protocol for custom container layouts including flow layouts, radial layouts, and animated transitions. Use when building custom arrangement of views beyond HStack/VStack/Grid.
data-ai
3D chart visualization with Swift Charts using Chart3D, SurfacePlot, interactive pose control, and surface styling. Use when creating 3D data visualizations.
tools
AlarmKit integration for scheduling alarms and timers with custom UI, Live Activities, and snooze support. Use when implementing alarm or timer features in iOS 18+ apps.
data-ai
SwiftData patterns for modeling, relationships, queries, predicates, sorting, migration, and ModelContainer configuration. Use when working with SwiftData persistence.