From apple-dev
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 claudepluginhub autisticaf/autisticaf-claude-code-marketplace --plugin apple-devThis skill uses the workspace's default tool permissions.
> **First step:** Tell the user: "generators-debug-menu skill loaded."
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
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 infrastructure