release-notes
npx skills add https://github.com/anyproto/anytype-ts --skill release-notes
Agent 安装分布
Skill 文档
Release Notes Skill
Write and update release notes in src/ts/docs/help/whatsNew.ts. This skill can generate release note content from conversation context, git branch changes, or Linear issues.
Document Structure
The file src/ts/docs/help/whatsNew.ts exports a function that returns an array of block elements. Each release is a “page” with this structure:
// Helper definitions at top of file (lines 1-24)
const hl = (t: string) => `<span class="highlight">${t}</span>`;
const text = (t: string) => block(I.TextStyle.Paragraph, t);
const h1 = (t: string) => block(I.TextStyle.Header1, t);
const h2 = (t: string) => block(I.TextStyle.Header2, t);
const bullet = (t: string) => block(I.TextStyle.Bulleted, t);
const img = (src: string) => text(`<img src="..." />`);
const link = (url: string, t: string) => `<a href="${url}">${t}</a>`;
const div = () => ({ type: I.BlockType.Div, style: I.DivStyle.Dot });
// Release pages start after helpers (~line 25)
return [
{ type: I.BlockType.IconPage, icon: '...' },
title(`Catchy Release Title`), // PAGE START
h4(`<span>Release 0.XX.0</span>`),
text(''),
text('Intro paragraph...'),
text(''),
// Big Feature Sections (h2)
h2(`Feature Name`),
text(`Feature description...`),
img(`XX/1.png`),
text(``),
// Quality of Life Improvements
h2(`Quality of Life Improvements`),
text(``),
text(`<b>Improvement Name</b>`),
text(`Description...`),
text(``),
// Bug Fixes
h2(`Bug Fixes`),
text(``),
text(`<b>Category Name</b>`),
bullet(`Fix description. Thanks to @${link('url', 'user')}!`),
text(``),
div(), // PAGE END
// --------------------------------------------//
// Next release page...
];
Multi-Part Releases
A release may be split across multiple Linear root issues (parts), e.g.:
JS-8571“Release 18 | 0.54.0 | Desktop | Part 1” â contains Features, Design, TechJS-8672“Release 18 | 0.54.0 | Desktop | Part 2” â contains Bugs, Quality
Commands that accept issue IDs (all, from-parent, docx) support multiple IDs. When multiple roots are provided, fetch each one and merge their children by type (features, QoL, bugs). Each part’s items keep their relative Linear ordering; Part 1 items come before Part 2.
Exclusion Rules
When processing issues from Linear (via from-parent, all, docx), skip any issue that matches:
-
Analytics-only â labels contain only
ð analytics(no bug/quality/feature labels) -
Internal â labels contain only
ðï¸ designorâï¸ tech(no user-facing labels) -
Alpha-version references â the issue title or description contains a version string with an
-alphasuffix (e.g.,0.53.28-alpha,0.50.29-alpha). These issues were reported against pre-release builds and were already fixed before the public release; including them would confuse users who never saw the bug.Detection: match the regex
\d+\.\d+\.\d+-alphaintitleordescriptionfields.
Commands
Parse the user’s command to determine the action:
/release-notes feature "Title" [context]
Add a big feature (h2 section) to the current release.
Insertion point: Before h2(\Quality of Life Improvements`)`
Format:
h2(`Feature Title`),
text(`Description paragraph 1.`),
text(`Description paragraph 2 if needed.`),
text(``),
/release-notes qol "Title" [context]
Add a Quality of Life improvement.
Insertion point: After h2(\Quality of Life Improvements`), before h2(`Bug Fixes`)`
Format:
text(`<b>Improvement Title</b>`),
text(`Description. Can mention shortcuts like ${hl('Cmd+V')}.`),
text(``),
Ordering: When adding multiple QoL items, sort them by impact â largest first, smallest last:
- Major new capabilities â items that could almost be standalone features (e.g., Toggle Headings, Pinned Tabs, Spell Checking in Chat)
- New settings and preferences â user-facing options that change workflows (e.g., File Block Default Style, Click to Edit Title toggle)
- Meaningful workflow improvements â noticeably better experiences (e.g., full-text search in Collections, Jump to Message in Chat)
- Small but welcome polish â minor UX wins (e.g., Fullscreen preview click-to-close, URL properties openable in header)
- Micro-fixes that feel like QoL â tiny quality bumps (e.g., input field clearing, option sorting, clipboard edge cases)
Community-credited items can appear at any tier based on their impact â don’t group them separately.
/release-notes fix "Category" [context]
Add a bug fix under the specified category.
Insertion point: Under h2(\Bug Fixes`)`, find or create the category
Format:
text(`<b>Category Name</b>`), // Only if category doesn't exist
bullet(`Fix description. Thanks to @${link('https://community.anytype.io/t/XXXXX', 'username')}!`),
Existing categories:
- Chat & Messaging
- Editor & Blocks
- UI & Rendering
- Objects & Views
- Queries & Views
- Widget Sidebar
- Navigation & Window Management
- Keyboard & Shortcuts
- Modal Window Mode
- Miscellaneous
/release-notes from-parent JS-XXXX
Batch create entries from a Linear parent issue and its sub-issues.
- Fetch parent issue and all sub-issues from Linear API
- For each sub-issue, determine type from labels:
buglabel â fixfeaturelabel â featureimprovementlabel â qol
- Create appropriate entries for each
- If parent is a big feature, use its title for h2 section
/release-notes new "0.XX.0" "Title"
Create a new release page at the top of the file.
Insert after: The IconPage block and before the first title() call
Format:
title(`Catchy Title`),
h4(`<span>Release 0.XX.0</span>`),
text(''),
text('Intro paragraph describing the release highlights.'),
text(''),
h2(`Quality of Life Improvements`),
text(``),
h2(`Bug Fixes`),
text(``),
div(),
// --------------------------------------------//
/release-notes all JS-XXXX [JS-YYYY ...]
Generate a complete release notes page from one or more root Linear issues (typically sprint/milestone issues). When a release is split across multiple parts, pass all root issue IDs â their children are merged by type.
How it works:
- Fetch the root issue and all its direct children from Linear API:
curl -s -X POST "https://api.linear.app/graphql" \
--header "Content-Type: application/json" \
--header "Authorization: $(printenv LINEAR_API_KEY)" \
--data '{"query":"query{issue(id:\"JS-XXXX\"){title description labels{nodes{name}}children(first:250){nodes{identifier title description state{name}labels{nodes{name}}children(first:250){nodes{identifier title description state{name}labels{nodes{name}}}}}}}}"}' | jq .
- Classify each child by its labels:
| Child labels | Classification | Action |
|---|---|---|
ð folder + ð bug |
Bug folder | Process like from-parent: fetch grandchildren, categorize into bug fix categories, write bullet entries |
ð folder + ð quality |
QoL folder | Process like from-parent: fetch grandchildren, write QoL entries. Items with ð« feature label become h2 features instead |
ð« feature (no folder) |
Standalone feature | Write as h2 feature section |
ð analytics only |
Analytics (internal) | Skip entirely â not user-facing |
-
Create the release page structure (if not already present):
newpage with version and title- All h2 feature sections
- All QoL entries under
h2('Quality of Life Improvements') - All bug fixes under
h2('Bug Fixes')organized by category - Intro paragraph via
intro
-
For grandchildren (sub-issues of folder issues), apply the same label-based rules:
ð bugâ bug fix bulletð qualityâ QoL entryð« featureâ h2 feature or QoL depending on scopeð analyticsonly â skip- No relevant label â infer from parent folder type
ð¨âð» feedbackâ community-reported, extract username and link from description
-
Order of operations:
- Create new release page (if needed)
- Insert features (h2 sections)
- Insert QoL improvements
- Insert bug fixes by category
- Write intro paragraph
Community credits: When a sub-issue has ð¨âð» feedback label, look for community links in the description (https://community.anytype.io/t/XXXXX) and extract the reporter’s name. Add Thanks to @${link('url', 'name')}! to the entry.
Example:
User: /release-notes all JS-8500
Root issue "Sprint 18" has children:
JS-8574 "Bugs | 18" [ð folder, ð bug] â process 81 bug sub-issues
JS-8573 "Quality | 18" [ð folder, ð quality] â process 25 QoL sub-issues
JS-292 "[epic] Tabs" [ð« feature] â h2 feature
JS-4551 "[epic] Filters" [ð« feature] â h2 feature
JS-8725 "Chat Search" [ð« feature] â h2 feature
JS-8703 "Transfer Ownership" [ð« feature] â h2 feature
Result: Complete release page with features, QoL, bug fixes, and intro.
/release-notes docx JS-XXXX [JS-YYYY ...]
Export the current release notes as a .docx file with hyperlinks to Linear issues. Items follow Linear’s ordering (the order children appear under their parent issue), not the category-based grouping from whatsNew.ts.
Accepts one or more root issue IDs. When a release is split across multiple Linear issues (“parts”), pass all of them â their children are merged by type (features, QoL, bugs) and each part’s items keep their relative order within the merged section.
How it works:
- Fetch each root issue and its full children tree from Linear (using
first:250):
curl -s -X POST "https://api.linear.app/graphql" \
--header "Content-Type: application/json" \
--header "Authorization: $(printenv LINEAR_API_KEY)" \
--data '{"query":"query{issue(id:\"JS-XXXX\"){title description labels{nodes{name}}children(first:250){nodes{identifier title description state{name}labels{nodes{name}}children(first:250){nodes{identifier title description state{name}labels{nodes{name}}}}}}}}"}' | jq .
- Collect and classify children from all root issues using these rules:
| Child labels | Classification | Action |
|---|---|---|
ð« feature (with or without ð folder) |
Features | If folder: use grandchildren as individual features. If standalone: single feature entry |
ð folder + ð quality |
QoL folder | Grandchildren â QoL items. Items with ð« feature label become features instead |
ð bug (with or without ð folder) |
Bug folder | Grandchildren â Bug Fixes |
ð analytics only |
Analytics | Skip |
ðï¸ design / âï¸ tech only |
Internal | Skip â not user-facing |
When merging across parts, append Part 2’s items after Part 1’s items within each section (preserving each part’s internal ordering).
-
Read the current release page from whatsNew.ts to get the user-facing note text for each entry.
-
Match each Linear issue to its whatsNew.ts entry. Matching strategy:
- For features: match by h2 title keywords (e.g., JS-292 “Tabs” â
h2(\Tabs`)`) - For QoL items: match by bold title keywords (e.g., “Toggle Headings” â
text(\Toggle Headings`)`) and collect the description paragraph(s) that follow - For bug fixes: match by community link URL (
community.anytype.io/t/XXXXX), by keywords from the issue title, or by position within the same category - If no match is found, use the Linear issue title as fallback text, formatted as
**Title** â <Linear title>.
- For features: match by h2 title keywords (e.g., JS-292 “Tabs” â
-
Build a JSON data file with this structure, preserving Linear’s child ordering within each section:
{
"version": "0.54.0",
"title": "Focus & Flow",
"sections": [
{
"heading": "Features",
"items": [
{"id": "JS-292", "text": "Note text from whatsNew.ts (cleaned of HTML)."},
{"id": "JS-4551", "text": "..."}
]
},
{
"heading": "Quality of Life Improvements",
"items": [
{"id": "JS-XXXX", "text": "**Toggle Headings** â H1, H2, H3 can now be collapsible toggles..."}
]
},
{
"heading": "Bug Fixes",
"items": [
{"id": "JS-8845", "text": "Action icons now look consistent across light and dark modes."}
]
}
]
}
-
Text cleanup rules when extracting from whatsNew.ts:
- Strip HTML tags:
<span class="highlight">X</span>âX,<b>X</b>â**X**,<i>X</i>âX - Strip
<a href="...">text</a>âtext - Resolve template expressions:
${hl('Cmd+F')}âCmd+F,${link('url', 'name')}âname - For QoL items, combine the bold title and description paragraph(s) into one text string:
**Title** â Description text. - For features, combine all text paragraphs into one string
- Strip HTML tags:
-
Write the JSON to a temp file, then run the generator script:
python3 .claude/skills/release-notes/generate_docx.py /tmp/release_data.json <output_path>
Output location: Save the .docx in the project root as release-<version>.docx (e.g., release-0.54.0.docx).
Item ordering: Within each section, items MUST appear in the same order as they are listed under their parent issue in Linear. This is the order returned by the Linear API’s children field. Do NOT reorder by category, alphabet, or any other criterion. When multiple parts are merged, Part 1 items come first, then Part 2, etc.
Example (multi-part):
User: /release-notes docx JS-8571 JS-8672
1. Fetch JS-8571 (Part 1) children:
- JS-8575 [ð« + ð] â Features folder â 4 feature grandchildren
- JS-8630 [ðï¸ + ð] â Design folder â skip (internal)
- JS-8594 [âï¸ + ð] â Tech folder â skip (internal)
2. Fetch JS-8672 (Part 2) children:
- JS-8573 [ð + ð] â QoL folder â 33 grandchildren â QoL items
- JS-8574 [ð] â Bug folder â 82 grandchildren â Bug Fixes
3. Merge: Features from Part 1, QoL from Part 2, Bugs from Part 2
4. Read whatsNew.ts, match each issue to its note text
5. Write JSON with items in Linear order
6. Run generate_docx.py â release-0.54.0.docx
7. Report: "Generated release-0.54.0.docx with 4 features, 33 QoL items, 82 bug fixes."
/release-notes intro
Write or update the intro paragraph for the current release.
How it works:
- Read the current release page in whatsNew.ts
- Identify all h2 feature sections
- Write 2â3 sentences that highlight the essence of the main features
- Replace the empty intro
text('')lines betweenh4(...)and the firsth2(...)
Insertion point: The text('') lines between the h4(<span>Release ...</span>) and the first content section
Format:
text('Intro sentence one. Intro sentence two.'),
text('Intro sentence three if needed.'),
Style:
- 2â3 sentences, concise and enthusiastic but not over the top
- Mention the biggest features by name
- Focus on what users can now do, not implementation details
- Match the tone of previous release intros in the file
/release-notes show
Display the current release notes (first page in the file).
Context Resolution
When user provides a context hint instead of explicit text:
today or session
- Analyze the current conversation history
- Identify what features/changes were discussed or implemented
- Extract key benefits for users
- Write description in release notes style
branch
- Run
git log main..HEAD --onelineto see commits - Run
git diff main --statto see changed files - Analyze branch name for context (e.g.,
feature/JS-8826-advanced-filters) - Generate description based on the changes
JS-XXXX (Linear issue)
- Fetch issue from Linear API using:
curl -s -X POST "https://api.linear.app/graphql" \
--header "Content-Type: application/json" \
--header "Authorization: $(printenv LINEAR_API_KEY)" \
--data '{"query":"query{issue(id:\"JS-XXXX\"){title description state{name}priority labels{nodes{name}}}}"}' | jq .
- Extract title and description
- Use labels to determine category if not specified
- Format for release notes
Explicit text
Use the provided text directly, but ensure it follows the style guidelines.
Writing Style Guidelines
Tone
- Concise but informative
- Explain WHAT changed AND WHY it matters to users
- Active voice: “You can now…” not “It is now possible to…”
- Focus on user benefits, not implementation details
Feature Titles
Action-oriented, clear names:
- “Direct Channels”
- “Advanced Filters”
- “Manual Sorting in Queries”
- “Updated Navigation”
Descriptions
- Start with the user benefit or problem solved
- Mention keyboard shortcuts using
${hl('Cmd+V')}syntax - Keep paragraphs focused on single ideas
- Use
<b>bold</b>for emphasis within text
Community Credits
When fixing user-reported issues:
bullet(`Fix description. Thanks to @${link('https://community.anytype.io/t/12345', 'username')}!`)
Punctuation
- Use n-dash (â) not m-dash (â) for parenthetical asides and ranges
What to Avoid
- Technical jargon (API, refactor, component names)
- Implementation details (file names, function names)
- Passive voice
- Vague descriptions (“improved performance”)
Workflow
- Parse command – Determine action type and arguments
- Resolve context – Generate content from conversation/branch/Linear/explicit
- Read whatsNew.ts – Find the current release and insertion point
- Format entry – Apply correct TypeScript syntax and style
- Insert entry – Edit the file at the correct location
- Confirm – Show the user what was added
Examples
Adding a feature from session context
User: /release-notes feature "Advanced Filters" today
Action:
1. Review conversation - user worked on advanced filters with AND/OR logic
2. Find insertion point before h2(`Quality of Life Improvements`)
3. Insert:
h2(`Advanced Filters`),
text(`Need more control over what shows in your Views? You can now create Advanced Filters that combine multiple conditions using AND or OR logic. Group related rules together to build precise queries â like finding all tasks that are either high priority or due this week.`),
text(``),
Adding a QoL improvement
User: /release-notes qol "Filter Bar Redesign" branch
Action:
1. Analyze git changes on current branch
2. Find insertion point after h2(`Quality of Life Improvements`)
3. Insert:
text(`<b>Filter Bar Redesign</b>`),
text(`Filters and Sorts in Queries and Collections got a fresh look. Active filters now appear in a dedicated bar above your View, showing the property name, condition, and value at a glance.`),
text(``),
Adding a bug fix
User: /release-notes fix "Objects & Views" "Filter items now show correct active state"
Action:
1. Find h2(`Bug Fixes`)
2. Find text(`<b>Objects & Views</b>`) category (or create if missing)
3. Insert bullet after category header:
bullet(`Filter items now show correct active state.`),
Writing the release intro
User: /release-notes intro
Action:
1. Read whatsNew.ts â find h2 feature sections: "Tabs", "Advanced Filters", "Chat Search", "Transfer Channel Ownership"
2. Write 2â3 sentences covering the highlights
3. Replace empty text('') lines after h4(`<span>Release 0.54.0</span>`):
text('This release brings Tabs to Anytype â open multiple Objects side by side and pin the ones you use most. Advanced Filters let you combine conditions with AND/OR logic, Chat Search helps you find any message instantly, and Channel Owners can now transfer ownership to another member.'),
Generating all release notes from a root issue
User: /release-notes all JS-8500
Action:
1. Fetch root issue JS-8500 â "Sprint 18" with 6 children
2. Classify children:
- JS-8574 [ð + ð] â bug folder, fetch 81 grandchildren â bug fixes
- JS-8573 [ð + ð] â QoL folder, fetch 28 grandchildren â QoL entries + features
- JS-292 [ð«] â standalone feature "Tabs"
- JS-4551 [ð«] â standalone feature "Advanced Filters"
- JS-8725 [ð«] â standalone feature "Chat Search"
- JS-8703 [ð«] â standalone feature "Transfer Ownership"
3. Create new release page with `new "0.54.0" "Focus & Flow"`
4. Insert 4 feature h2 sections
5. Insert 25 QoL entries
6. Insert 80 bug fixes across categories
7. Write intro paragraph