Step 1 — Parse the Request
Identify what to generate:- Repo: Which repository? Default to the user’s primary repo if only one is connected.
- Range: Date range (“last 2 weeks”, “since March 1”), version tags (“v0.2.3..v0.2.4”), or milestone name.
- Version label: If the user specifies a version, use it. Otherwise, ask or omit.
“Which time period or version range should I cover? For example: ‘last 2 weeks’, ‘since v0.2.3’, or ‘February 2026’.”
Step 2 — Fetch Commits
Use GitHub integration to fetch all commits in the specified range:- List commits for the repo filtered by date or tag range
- For each commit, extract: hash, message, author, date
- If merge commits reference a PR number, fetch the PR title and description for better context
- Filter out noise: merge commits with no meaningful message, version bump-only commits, CI-only changes
Step 3 — Categorize Commits
Classify each commit into exactly one category using the commit message prefix and content:| Prefix / Signal | Category |
|---|---|
feat: or feature: | New Features |
perf: or performance-related | Performance & Reliability |
fix: or bugfix: | Fixes |
security: or auth/permission/vulnerability-related | Security & Privacy |
chore:, refactor:, docs:, style:, ci:, build:, improvements | Improvements |
Step 4 — Enrich with Issues (GitHub / Linear)
Extract issue references from commit messages or PR descriptions and fetch context:| Pattern | Source | Example |
|---|---|---|
#123 | GitHub Issue | fix: resolve search bug (#456) |
ABC-123 (letters + dash + number) | Linear Issue | feat: add onboarding (ENG-789) |
- Extract
#numberreferences from commit messages and PR bodies - Fetch issue title, description, and labels from GitHub
- Use the issue context to write clearer, user-facing descriptions
- Extract
PREFIX-numberreferences (e.g.ENG-123,CORE-456) - Fetch issue title, description, and priority from Linear
- Use Linear context alongside or instead of commit messages for richer descriptions
Step 5 — Group by Feature Area
Within each category, group related commits under a bold feature-area header:- Identify clusters: commits touching the same integration, module, or feature
- Name each group after the feature (e.g. Gmail Integration, Search Improvements, Onboarding Flow)
- Standalone commits that don’t cluster get listed individually without a group header
Step 6 — Write the Changelog
Generate the changelog using this exact structure. Only include sections that have entries.-
Lead with the user benefit, not the implementation. Open feature descriptions with what the user can now do or what problem is solved — not what was built.
- Good: “Time spent in individual statuses is now tracked and available throughout Linear. Hovering over any issue’s status indicator reveals the cumulative time it has spent in each status.”
- Bad: “Added status duration tracking to the issue model with hover tooltip rendering.”
-
Features get 2-3 sentences of context. Explain the capability, then explain why it matters or how to use it. Don’t just list what was shipped — frame it as a workflow improvement.
- Good: “You can now launch your preferred coding tool directly from a Linear issue, with a prefilled prompt that includes the issue ID and all relevant context. No copying or reformatting required.”
- Bad: “Added deeplink support for coding tools from issues.”
-
Fixes use
**Category:** descriptionformat. One line each, concise, past tense.- Good: “Search: Fixed duplicate results appearing for broad queries”
- Good: “Editor: Fixed draft loss when switching tabs while commenting”
- Bad: “deduplicate invalidated facts at Cypher query level”
-
Improvements use the same
**Category:** descriptionformat. Focus on what’s better for the user.- Good: “Onboarding: Streamlined setup flow — fewer steps to first memory”
- Good: “Images: Removed meaningless captions”
-
Include specific metrics when available. Numbers make improvements tangible.
- Good: “Faster Search: Agent orchestrator architecture for 2-3x speed improvement”
- Good: “Pages on Windows open 27% faster”
- Don’t include commit hashes, PR numbers, file paths, or internal jargon in the output.
- Merge multiple small commits about the same thing into one bullet.
- Drop purely internal changes (CI config, linting, dependency bumps) unless they meaningfully affect users.
Step 7 — Clarify User Stories
Before finalizing, review each feature entry. If the commit messages, PR descriptions, and issue context don’t clearly answer “what can the user do now that they couldn’t before?” — ask the user. Flag features where the user story is unclear:“I have a few features where the commit/issue context doesn’t tell the full story. Can you help me fill in the gaps?Wait for the user’s response before writing the final changelog. Use their answers to write benefit-first descriptions instead of guessing from code changes. Skip this step if all features have clear user stories from the issues/PRs.
- [Feature name] — I see commits around [brief technical summary]. What’s the user-facing story here? What problem does this solve?
- [Feature name] — The issue says [quote], but I’m not sure how to frame the benefit. What should users know about this?”
Step 8 — Present and Confirm
Show the generated changelog and ask:“Here’s the changelog. Want me to adjust anything — add detail, reword, or move items between sections?”Accept edits and regenerate if needed.
Step 8 — Commit to Repo (Optional)
After the user approves the changelog, offer to commit it directly via GitHub:“Want me to commit this changelog to the repo? I’ll create a branch and open a PR.”If yes:
- Create a branch: Use
create_branchto create a branch namedchangelog/[month]-[year](e.g.changelog/march-2026) from main - Commit the file: Use
create_or_update_filewith:path: The changelog file path (default:docs/opensource/changelog.mdx— confirm with user)content: The approved changelog prepended to the existing file contentmessage:docs: add [Month Year] changelogbranch: The branch created in step 1sha: Required when updating an existing file — fetch it first
- Open a PR: Use
create_pull_requestwith:title:docs: [Month Year] changeloghead: The changelog branchbase:mainbody: Brief summary of what’s included
- Share the PR link with the user
Edge Cases
- No commits in range → tell the user: “No commits found for [range]. Check the date range or repo.”
- All commits are internal/CI → “All changes in this range are internal (CI, deps, config). Nothing user-facing to include.”
- Ambiguous categorization → when a commit spans multiple categories (e.g. a feature that also fixes a bug), pick the primary intent. Mention the secondary benefit in the description.
- Squash commits with long descriptions → use the PR title as the primary description, pull details from the body.
- Monorepo with multiple packages → if the user specifies a scope (e.g. “changelog for the webapp”), filter commits by path prefix.
