$npx -y skills add rorkai/app-store-connect-cli-skills --skill asc-whats-new-writerGenerate engaging, localized App Store release notes (What's New) from git log, bullet points, or free text using canonical metadata under ./metadata. Optionally pairs with promotional text updates.
| 1 | # asc What's New Writer |
| 2 | |
| 3 | Generate engaging, localized release notes from flexible input. Optionally pair with promotional text updates. |
| 4 | |
| 5 | ## Preconditions |
| 6 | |
| 7 | - Metadata pulled locally into canonical files via `asc metadata pull --app "APP_ID" --version "1.2.3" --dir "./metadata"`. OR: user provides keywords manually. |
| 8 | - Auth configured for upload (`asc auth login` or `ASC_*` env vars). |
| 9 | - The **primary locale** is `en-US` unless the user specifies otherwise. |
| 10 | |
| 11 | ## Before You Start |
| 12 | |
| 13 | 1. Read `references/release_notes_guidelines.md` for tone, structure, and examples. |
| 14 | 2. Identify the **latest version directory** under `metadata/version/` (highest semver). Use this for all metadata reads. |
| 15 | 3. Enumerate **existing locales** by listing the JSON files in that version directory. |
| 16 | |
| 17 | ## Phase 1: Gather Input |
| 18 | |
| 19 | Accept one of three input modes (auto-detect): |
| 20 | |
| 21 | ### Git Log |
| 22 | |
| 23 | Parse commits since the last tag: |
| 24 | |
| 25 | ```bash |
| 26 | # Find latest tag |
| 27 | git describe --tags --abbrev=0 |
| 28 | |
| 29 | # List commits since that tag |
| 30 | git log $(git describe --tags --abbrev=0)..HEAD --oneline --no-merges |
| 31 | ``` |
| 32 | |
| 33 | Filter out noise: merge commits, dependency bumps, CI changes, formatting-only commits. Extract user-facing changes. |
| 34 | |
| 35 | ### Bullet Points |
| 36 | |
| 37 | User provides rough bullets like: |
| 38 | - "improved search" |
| 39 | - "fixed crash on launch" |
| 40 | - "added sleep timer" |
| 41 | |
| 42 | ### Free Text |
| 43 | |
| 44 | User describes changes conversationally: |
| 45 | > "We made search faster, fixed that annoying crash when you open the app, and added a sleep timer feature" |
| 46 | |
| 47 | The skill extracts and structures the changes from the text. |
| 48 | |
| 49 | ### No Input Provided |
| 50 | |
| 51 | Prompt the user: "What changed in this release? You can paste git log output, bullet points, or just describe the changes." |
| 52 | |
| 53 | ## Phase 2: Draft Notes (Primary Locale) |
| 54 | |
| 55 | ### Step 1: Classify Changes |
| 56 | |
| 57 | Group changes into sections per the guidelines: |
| 58 | - **New** — new features or capabilities |
| 59 | - **Improved** — enhancements to existing features |
| 60 | - **Fixed** — bug fixes users would notice |
| 61 | |
| 62 | Omit empty sections. If all changes are fixes, only show "Fixed." |
| 63 | |
| 64 | ### Step 2: Write Benefit-Focused Copy |
| 65 | |
| 66 | Follow the tone rules from `references/release_notes_guidelines.md`: |
| 67 | - Describe user impact, not implementation details |
| 68 | - Use direct address ("you") and action verbs |
| 69 | - Be specific — mention concrete improvements |
| 70 | |
| 71 | ### Step 3: Front-Load the Hook |
| 72 | |
| 73 | The first ~170 characters are the only visible part before "more." Lead with the single most impactful change in a complete, compelling sentence. |
| 74 | |
| 75 | ### Step 4: Echo Keywords for Conversion |
| 76 | |
| 77 | 1. Read `keywords` from `metadata/version/{latest}/{primary-locale}.json` |
| 78 | - These canonical files are also what `asc metadata keywords ...` reads and writes. |
| 79 | 2. If the field is empty or missing, skip this step |
| 80 | 3. Identify keywords relevant to the changes being described |
| 81 | 4. Weave them naturally into the notes — never force or stuff |
| 82 | |
| 83 | ### Step 5: Respect Character Limits |
| 84 | |
| 85 | - Keep total length between 500-1500 characters in the primary locale |
| 86 | - This leaves room for localized expansions (some languages expand 30-40%) |
| 87 | - Hard limit: 4,000 characters |
| 88 | |
| 89 | ### Step 6: Optionally Draft Promotional Text |
| 90 | |
| 91 | If the user wants it, draft a 170-char promotional text that: |
| 92 | - Summarizes the update's theme in one punchy line |
| 93 | - Can reference seasonal events |
| 94 | - Is updatable without a new submission |
| 95 | |
| 96 | ### Present Draft |
| 97 | |
| 98 | Show the draft to the user with character count. Wait for approval before localizing. |
| 99 | |
| 100 | ## Phase 3: Localize |
| 101 | |
| 102 | Translate the approved notes to all existing locales. |
| 103 | |
| 104 | ### Translation Rules |
| 105 | |
| 106 | - Use formal register and formal "you" forms (Russian: вы, German: Sie, French: vous, Spanish: usted, Dutch: u, Italian: Lei) |
| 107 | - Adapt tone to local market — playful English may need adjustment for formal markets (ja, de-DE) |
| 108 | - Do NOT literally translate idioms — adapt them to local equivalents |
| 109 | - A playful tone in English may need to be more respectful or formal in other cultures |
| 110 | |
| 111 | ### Locale-Specific Keyword Echo |
| 112 | |
| 113 | For each locale: |
| 114 | 1. Read `keywords` from `metadata/version/{latest}/{locale}.json` |
| 115 | 2. Echo locale-specific keywords naturally in the translated notes |
| 116 | 3. If keywords field is empty, skip echo for that locale |
| 117 | |
| 118 | ### Validate |
| 119 | |
| 120 | - All translations must be ≤ 4,000 characters |
| 121 | - Promotional text must be ≤ 170 characters per locale |
| 122 | - If a translation exceeds the limit, shorten it — never truncate mid-sentence |
| 123 | |
| 124 | ## Phase 4: Review & Upload |
| 125 | |
| 126 | ### Step 1: Present Summary |
| 127 | |
| 128 | Show a table of all locales with their notes and character counts: |
| 129 | |
| 130 | ``` |
| 131 | | Locale | What's New (first 80 chars...) | Chars | Promo Text | Chars | |
| 132 | |--------|-------------------------------|-------|------------|-------| |
| 133 | | en-US | Search just got faster — ... | 847 | New sleep… | 142 | |
| 134 | | ar-SA | البحث أصبح أسرع — ... | 923 | نوم جديد… | 138 | |
| 135 | | ... | ... | ... |