$npx -y skills add rshankras/claude-code-apple-skills --skill feedback-formGenerates an in-app feedback collection form with category selection, text input, optional screenshot attachment, device diagnostics, and smart routing — directing happy users to App Store reviews and unhappy users to support. Use when user wants feedback, bug reports, feature re
| 1 | # Feedback Form Generator |
| 2 | |
| 3 | Generate a production in-app feedback form with category selection, sentiment-based rating, optional screenshot attachment, device diagnostics collection, and smart routing that funnels satisfied users to the App Store review prompt and dissatisfied users to a support channel. |
| 4 | |
| 5 | ## When This Skill Activates |
| 6 | |
| 7 | Use this skill when the user: |
| 8 | - Asks to "add a feedback form" or "feedback form" |
| 9 | - Wants "in-app feedback" or "user feedback" collection |
| 10 | - Mentions "bug report form" or "feature request" form |
| 11 | - Asks about "contact support" from within the app |
| 12 | - Wants "feedback collection" with categories or screenshots |
| 13 | - Asks to "route users to App Store review" based on sentiment |
| 14 | |
| 15 | ## Pre-Generation Checks |
| 16 | |
| 17 | ### 1. Project Context Detection |
| 18 | - [ ] Check Swift version (requires Swift 5.9+) |
| 19 | - [ ] Check deployment target (iOS 16+ / macOS 13+) |
| 20 | - [ ] Check for @Observable support (iOS 17+ / macOS 14+) |
| 21 | - [ ] Identify source file locations |
| 22 | |
| 23 | ### 2. Conflict Detection |
| 24 | Search for existing feedback or support code: |
| 25 | ``` |
| 26 | Glob: **/*Feedback*.swift, **/*Support*.swift, **/*BugReport*.swift, **/*ContactForm*.swift |
| 27 | Grep: "MFMailComposeViewController" or "FeedbackForm" or "SKStoreReviewController" |
| 28 | ``` |
| 29 | |
| 30 | If third-party feedback SDK found (Instabug, UserVoice, Zendesk): |
| 31 | - Ask if user wants to replace or keep it |
| 32 | - If keeping, don't generate — advise on best practices instead |
| 33 | |
| 34 | ### 3. Framework Detection |
| 35 | Check for MessageUI availability: |
| 36 | ``` |
| 37 | Grep: "import MessageUI" or "MFMailCompose" |
| 38 | ``` |
| 39 | Note: MessageUI is iOS-only. macOS uses `NSSharingService` or direct webhook delivery. |
| 40 | |
| 41 | ## Configuration Questions |
| 42 | |
| 43 | Ask user via AskUserQuestion: |
| 44 | |
| 45 | 1. **Feedback categories?** (multi-select) |
| 46 | - Bug Report |
| 47 | - Feature Request |
| 48 | - General Feedback |
| 49 | - Praise |
| 50 | - Other |
| 51 | - All of the above — recommended |
| 52 | |
| 53 | 2. **Delivery method?** |
| 54 | - Email (via MFMailComposeViewController / NSSharingService) |
| 55 | - Webhook (POST to a URL endpoint) |
| 56 | - Both — recommended |
| 57 | |
| 58 | 3. **Include screenshot capture?** |
| 59 | - Yes — recommended (capture current screen + annotation overlay) |
| 60 | - No |
| 61 | |
| 62 | 4. **Include device diagnostics?** |
| 63 | - Yes — recommended (device model, OS, app version, disk, memory) |
| 64 | - No |
| 65 | |
| 66 | 5. **Sentiment routing?** |
| 67 | - Yes — recommended (rating >= 4 suggests App Store review, rating <= 2 routes to support) |
| 68 | - No (all feedback goes through the same channel) |
| 69 | |
| 70 | ## Generation Process |
| 71 | |
| 72 | ### Step 1: Read Templates |
| 73 | Read `templates.md` for production Swift code. |
| 74 | |
| 75 | ### Step 2: Create Core Files |
| 76 | Generate these files: |
| 77 | 1. `FeedbackCategory.swift` — Enum with SF Symbol icons and display names |
| 78 | 2. `FeedbackEntry.swift` — Data model for a feedback submission |
| 79 | 3. `DeviceDiagnostics.swift` — Collects device and app info |
| 80 | |
| 81 | ### Step 3: Create UI Files |
| 82 | 4. `FeedbackFormView.swift` — SwiftUI form with sentiment, category, message, screenshots |
| 83 | |
| 84 | ### Step 4: Create Delivery Files |
| 85 | 5. `FeedbackSubmitter.swift` — Protocol + EmailFeedbackSubmitter + WebhookFeedbackSubmitter |
| 86 | |
| 87 | ### Step 5: Create Optional Files |
| 88 | Based on configuration: |
| 89 | - `ScreenshotCapture.swift` — If screenshot capture selected |
| 90 | |
| 91 | ### Step 6: Determine File Location |
| 92 | Check project structure: |
| 93 | - If `Sources/` exists -> `Sources/Feedback/` |
| 94 | - If `App/` exists -> `App/Feedback/` |
| 95 | - Otherwise -> `Feedback/` |
| 96 | |
| 97 | ## Output Format |
| 98 | |
| 99 | After generation, provide: |
| 100 | |
| 101 | ### Files Created |
| 102 | ``` |
| 103 | Feedback/ |
| 104 | ├── FeedbackCategory.swift # Category enum with icons |
| 105 | ├── FeedbackEntry.swift # Feedback data model |
| 106 | ├── DeviceDiagnostics.swift # Device info collector |
| 107 | ├── FeedbackFormView.swift # SwiftUI form view |
| 108 | ├── FeedbackSubmitter.swift # Email + webhook delivery |
| 109 | └── ScreenshotCapture.swift # Screen capture (optional) |
| 110 | ``` |
| 111 | |
| 112 | ### Integration Steps |
| 113 | |
| 114 | **Present the feedback form from any view:** |
| 115 | ```swift |
| 116 | @State private var showFeedback = false |
| 117 | |
| 118 | Button("Send Feedback") { |
| 119 | showFeedback = true |
| 120 | } |
| 121 | .sheet(isPresented: $showFeedback) { |
| 122 | FeedbackFormView() |
| 123 | } |
| 124 | ``` |
| 125 | |
| 126 | **In a settings screen:** |
| 127 | ```swift |
| 128 | Form { |
| 129 | Section("Support") { |
| 130 | Button { |
| 131 | showFeedback = true |
| 132 | } label: { |
| 133 | Label("Send Feedback", systemImage: "bubble.left.and.text.bubble.right") |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | .sheet(isPresented: $showFeedback) { |
| 138 | FeedbackFormView() |
| 139 | } |
| 140 | ``` |
| 141 | |
| 142 | **With a pre-selected category (e.g., from a help menu):** |
| 143 | ```swift |
| 144 | FeedbackFormView(initialCategory: .bugReport) |
| 145 | ``` |
| 146 | |
| 147 | ### Testing |
| 148 | |
| 149 | ```swift |
| 150 | @Test |
| 151 | func feedbackEntryEncodesCorrectly() throws { |
| 152 | let entry = FeedbackEntry( |
| 153 | category: .bugReport, |
| 154 | message: "App |