Launch Roundup

SkillCommunication

Use when you want a weekly feature announcement package from recent merge requests, including Slack, blog, LinkedIn, and carousel outputs.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Launch Roundup skill

What this skill tells your AI

The instructions your AI receives, as published by j1ngg/tech-marketing-framework in .agents/skills/launch-roundup/SKILL.md and read by ahel’s review.

A weekly pipeline that turns recent merge requests into a complete announcement package: Slack copy, blog post, LinkedIn posts, and a LinkedIn carousel. One approval gate after Slack copy. Everything else runs autonomously.

Pipeline Overview

StepOutputMode
1. Gather MRsSummarized feature listAutomatic
2. Slack announcementSlack message copyApproval gate
3. Blog postFeature announcement blogAutonomous
4. LinkedIn postsBrand + personal postsAutonomous
5. LinkedIn carouselPPTX carousel slidesAutonomous

All outputs land in output/launch-roundups/{product-name}-{YYYY-MM-DD}/.


Step 1: Gather MR Source Material

Ask the user TWO questions:

  1. Repo path — Absolute path to the local git repo (e.g., ~/repos/ai-agent)
  2. Time window — How far back? (default: 7 days)

Wait for the user to answer before proceeding. If they only provide the path, use 7 days.

Fallback: If the user doesn't have a local repo, they can also provide:

  • A file path (Markdown, text, or PDF with MR summaries)
  • A pasted list of recent MRs
  • A URL to fetch (changelog page, release notes)

Reading MRs from a local repo

Run this git command against the provided repo path to extract merged MRs:

git -C {repo_path} log --merges --since="{N} days ago" --format="commit:%H%nauthor:%an%ndate:%ad%nsubject:%s%n%b%n---" --date=short

If the repo uses squash merges (no merge commits), fall back to:

git -C {repo_path} log --since="{N} days ago" --format="commit:%H%nauthor:%an%ndate:%ad%nsubject:%s%n%b%n---" --date=short --first-parent

If neither produces results, try without --first-parent and deduplicate by subject line.

For each commit/MR, also read the full diff summary to understand what changed:

git -C {repo_path} show --stat --format="" {commit_hash}

Enrich thin commit messages: If a commit subject is vague (e.g., "fix bug", "update"), read the diff stat and the changed files to infer what the feature does. Group related commits under a single feature when they clearly belong together (e.g., multiple commits touching the same module in the same day).

Extracting features from git history

From the git output, extract:

FieldWhere it comes from
Feature namesCommit subjects, MR titles, or inferred from changed files
What it doesCommit body, diff stat, or inferred from the code changes
Who it helpsCross-reference with target_personas.md based on the feature area
Technical detailDiff stat, changed files, commit body

Filtering rules:

  • Include: new features, significant enhancements, user-facing changes, new integrations
  • Exclude: dependency bumps, CI/CD changes, typo fixes, internal refactors with no user impact, test-only changes
  • When in doubt, include it in the summary table and let the user cut it during the sanity check

Then read these files for product context:

FileWhat to extract
docs/inputs/product_brief.mdProduct name, positioning, capabilities (for accuracy)
docs/inputs/messaging_positioning.mdValue props, pain points, competitive differentiation
docs/inputs/target_personas.mdAudience context, job titles, technical level
docs/inputs/brand_guidelines.mdVisual style for carousel generation

Private data override: If docs/inputs-local/ exists, read from there instead of docs/inputs/.

Compile a feature summary table:

| Feature | What it does | Who it helps | Technical detail |
|---------|-------------|--------------|------------------|
| [name]  | [summary]   | [persona]    | [detail]         |

Present this table to the user for a quick sanity check. If they correct anything, update before proceeding.


Step 2: Generate Slack Announcement

Generate a Slack announcement using these rules:

Format:

  • Start with a one line bold header: *What's New in [Product]: [Date Range]*
  • One blank line, then a brief (2 to 3 sentence) narrative intro summarizing the theme of this batch
  • Then one section per feature, each structured as:
    • Bold feature name on its own line
    • 2 to 3 sentences: what it does, why it matters, who benefits
    • If applicable, one concrete example or config snippet in a code block
  • End with a single line linking to the blog (placeholder: [blog link]) and a note like "Full writeup on the blog."

Voice:

  • Internal, conversational, engineer to engineer
  • Skip marketing speak entirely. This is for your PM and EM.
  • Be specific about what shipped, not why it's exciting
  • Use Slack formatting: *bold*, _italic_, `code`, code blocks with triple backticks

Length: 200 to 400 words total. Enough to be useful in a Slack channel, short enough to read without expanding.

Output: Save to output/launch-roundups/{product-name}-{YYYY-MM-DD}/slack-announcement.md


APPROVAL GATE

After generating the Slack copy, present it to the user and say:

"Here's the Slack announcement. Review this with your PM and EM. Once approved, reply and I'll generate the blog, LinkedIn posts, and carousel automatically."

Do not proceed until the user explicitly approves. If they request changes, revise and present again. The approved Slack copy becomes the source of truth for all downstream assets.


Step 3: Generate Blog Post (Autonomous)

Once approved, generate a feature announcement blog post. Do not ask any questions. Use these pre-filled inputs:

InputValue
Blog typeFeature announcement
Source contentThe approved Slack announcement + the original MR summaries
Target keywordDerive from the product name + primary feature theme
Distribution surfacesWebsite + LinkedIn Pulse (tri-publish if the user's messaging_positioning.md mentions LinkedIn as a channel, otherwise website only)
DisclosureNone (this is brand content, not personal)
Internal link domainExtract from product_brief.md or messaging_positioning.md if a domain is mentioned. If not found, skip internal linking.

Follow the full blog skill structure for Feature Announcement type:

# [Feature Name or Theme]: [Benefit Statement]

TLDR (2 to 3 sentences)

## The Problem
## Introducing [Feature/Theme]
## How It Works (with code snippets if applicable)
## Use Cases (2 to 3, each highlighting a DIFFERENT capability)
## Getting Started
## FAQ (3 to 5 questions)

CTA + Post-Publication Checklist

Apply all blog skill rules: Authority Content bar, SEO/AEO requirements (metadescription, TLDR, FAQ, schema markup, internal linking), writing rules (no passive voice, no banned words, max 3 dashes, Oxford comma), visual callout flags.

If multiple features shipped: Frame the blog as a "What's New" roundup rather than a single feature deep-dive. Use H2s for each major feature and H3s for sub-features.

Output: Save to output/launch-roundups/{product-name}-{YYYY-MM-DD}/blog-post.md


Step 4: Generate LinkedIn Posts (Autonomous)

Generate LinkedIn posts using the approved Slack copy and the blog post as source material. Do not ask any questions. Use these pre-filled inputs:

InputValue
PlatformLinkedIn
Account typesBoth (brand + personal)
Brand/company nameFrom product_brief.md
Key link[blog link] (placeholder for the blog URL)
Author context (personal)Extract from messaging_positioning.md if an author or spokesperson is mentioned. If not, use: "a member of the [Product] team"

Follow the full social-posts skill rules for LinkedIn:

Brand LinkedIn:

  • Lead with the problem or market insight, not the product
  • Focus on business impact and governance implications
  • Structure: Problem, Impact, Solution exists, Link
  • 150 to 250 words
  • No hashtags in body, no emojis, no subject line

Personal LinkedIn:

  • Lead with personal experience ("We shipped", "I built", "I learned")
  • Include narrative arc: problem, action, insight
  • Disclose affiliation
  • 200 to 350 words
  • No hashtags, no emojis

Output: Save to output/launch-roundups/{product-name}-{YYYY-MM-DD}/linkedin-posts.md


Step 5: Generate LinkedIn Carousel (Autonomous)

Generate a LinkedIn carousel using the blog post as source material. Do not ask any questions.

Carousel structure:

SlideContent
1. Cover"WHAT'S NEW" + Product name + Date range + "Swipe for details"
2 to N. Feature slidesOne slide per major feature. Bold feature name, 2 to 3 sentence description, visual element (before/after card, screenshot placeholder, or diagram placeholder)
Final. CTASummary statement + product URL + CTA button

Visual style:

  • Read docs/inputs/brand_guidelines.md for colors, fonts, and motifs
  • If brand guidelines are sparse, default to: dark background (#1A1A1E), monospace font, orange accent color (#D48A29), white text
  • Each feature slide gets an orange accent bar at top
  • Use card components for before/after comparisons
  • Flag screenshot placeholders: [Replace with {feature} screenshot]

Build method:

  • Generate a Python script (build_carousel.py) using python-pptx that creates the PPTX
  • Slides are 1080x1080px (10.8in square at 100dpi), optimized for LinkedIn carousel
  • Run the script to produce the PPTX file
  • If python-pptx is not available or the script fails, output the carousel as a detailed Markdown specification that can be built manually

Output: Save all carousel files to output/launch-roundups/{product-name}-{YYYY-MM-DD}/carousel/:

  • build_carousel.py
  • {product-name}-whats-new-carousel.pptx

Final Output Summary

After all steps complete, present the user with a summary:

## Launch Roundup Complete

**Date:** {YYYY-MM-DD}
**Features covered:** {count}

### Outputs

| Asset | Path | Status |
|-------|------|--------|
| Slack announcement | output/launch-roundups/{name}/slack-announcement.md | Ready to post |
| Blog post | output/launch-roundups/{name}/blog-post.md | Ready for review |
| LinkedIn (brand) | output/launch-roundups/{name}/linkedin-posts.md | Ready to post |
| LinkedIn (personal) | output/launch-roundups/{name}/linkedin-posts.md | Ready to post |
| LinkedIn carousel | output/launch-roundups/{name}/carousel/ | Ready (replace screenshot placeholders) |

### Next steps
- Post the Slack announcement to your channel
- Publish the blog and update the [blog link] placeholders in the LinkedIn posts
- Upload the carousel PPTX to LinkedIn or import into Canva for final polish
- Replace screenshot placeholders in the carousel with actual product screenshots

Adaptation Notes

When only 1 feature shipped:

  • Skip the "What's New roundup" framing
  • Blog becomes a single feature announcement
  • Carousel becomes 3 slides: cover, feature detail, CTA

When 5+ features shipped:

  • Group related features under themes for the blog (e.g., "Governance" theme, "Detection" theme)
  • Carousel covers top 3 to 4 features max (pick the ones with the most user impact)
  • Mention remaining features in the blog but not the carousel

When MR descriptions are thin:

  • Flag gaps: "The MR for [feature] doesn't have enough detail to write a compelling description. Can you add 1 to 2 sentences about what it does and why?"
  • Do not fabricate technical details

When product_brief.md is empty:

  • Ask the user for: product name, 2 to 3 key capabilities, target audience
  • Flag: "Running without full product context. Claims will be generic."

When brand_guidelines.md is sparse:

  • Use defaults for carousel (dark bg, orange accent, monospace)
  • Note in summary: "Carousel uses default styling. Update brand_guidelines.md for branded visuals."

Signals

GitHub stars
56
Forks
8
Last commit
Apr 2026
Advanced
Catalog kind
skill
Gateway key
launch-roundup
Source
github.com/j1ngg/tech-marketing-framework