<quick_start> <automation_workflow> One release, one announcement - fully automated:
- •Generate post: Extract highlights from CHANGELOG for version
- •User confirmation: Show preview, allow editing, get approval
- •Post to X: Send via API (http://5.161.75.135:8080)
- •Poll for tweet ID: Wait until post is live
- •Reply with link: Post GitHub release URL as threaded reply
- •Display URLs: Show both tweet links for verification
Example flow:
Generating X announcement for v2.7.0... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ X Announcement Preview ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Spec-Flow v2.7.0 is here! - One-command releases with CI validation - Auto-close GitHub issues when features ship - Essential cleanup for all deployment models Ship features faster with less manual work. Characters: 187/280 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Options: 1. Post as-is 2. Edit post text 3. Skip X announcement Posting to X... (ID: 12345) Waiting for publish... (3s) Posted to X! Posting GitHub link as threaded reply... (ID: 12346) GitHub link posted! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ X Announcement Posted! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Main Post: https://x.com/username/status/1234567890 GitHub Link Reply: https://x.com/username/status/1234567891 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
</automation_workflow>
<trigger_conditions> Auto-invoke when:
- •
/releasecommand completes successfully - •Manual invocation for any release
- •User mentions "announce release", "post to X", "tweet release"
Context available:
- •
NEW_VERSION- Version number (e.g., "2.7.0") - •
CHANGELOG.md- Release notes for extraction - •
README.md- Feature highlights - •
COMMIT_SHA- Git commit hash </trigger_conditions>
<post_generation_guidelines> Format requirements:
- •Include version number prominently
- •Highlight 1-3 key features/improvements
- •Keep under 280 characters (leave room for editing)
- •Use engaging language (not just bullet points)
- •End with call-to-action or benefit statement
- •Do NOT use emojis (UTF-8 encoding issues with X API)
Content extraction:
- •Read
CHANGELOG.md→ Extract## [NEW_VERSION]section - •Identify top features: Prioritize Added > Fixed > Changed
- •Format with engaging tone (no emojis)
- •Validate character count (≤280)
See references/post-templates.md for examples and guidelines. </post_generation_guidelines> </quick_start>
<workflow> <step_1_generate> **1. Generate Suggested Post**Extract release highlights:
# Read CHANGELOG section for version
SECTION=$(sed -n "/## \[${NEW_VERSION}\]/,/## \[/p" CHANGELOG.md | head -n -1)
# Extract Added features
ADDED=$(echo "$SECTION" | grep -A 10 "### Added" | grep "^-" | head -3)
# Extract Fixed items
FIXED=$(echo "$SECTION" | grep -A 10 "### Fixed" | grep "^-" | head -2)
# Format into engaging post
# Template: 🚀 Spec-Flow v${NEW_VERSION} is here!
# ${FEATURE_EMOJI} ${FEATURE_1}
# ${FEATURE_EMOJI} ${FEATURE_2}
# ${BENEFIT_STATEMENT}
Display preview with character count for user review. </step_1_generate>
<step_2_confirm> 2. Get User Confirmation
Use AskUserQuestion or direct prompt:
Options: 1. ✅ Post as-is 2. ✏️ Edit post text 3. ❌ Skip X announcement
If user selects Edit:
- •Prompt for new text
- •Validate ≤280 characters
- •Show updated preview
- •Ask for confirmation again
If user selects Skip:
- •Exit gracefully
- •Continue with release summary </step_2_confirm>
<step_3_post> 3. Post to X API
Send POST request with confirmed content:
# Write content to temp file for proper UTF-8 encoding
cat > /tmp/x-post.txt << 'EOF'
<user-confirmed text>
EOF
POST_CONTENT=$(cat /tmp/x-post.txt | jq -Rs .)
RESPONSE=$(curl -s -X POST "http://5.161.75.135:8080/api/v1/posts/" \
-H "Content-Type: application/json" \
-d "{\"content\": $POST_CONTENT, \"scheduled_at\": null}")
POST_ID=$(echo "$RESPONSE" | jq -r '.id')
echo "📤 Posting to X... (ID: $POST_ID)"
Error handling:
- •API unreachable → Warn, provide manual posting instructions
- •POST fails → Display error, offer manual fallback
- •Continue release process regardless
See references/api-reference.md for complete API documentation. </step_3_post>
<step_4_poll> 4. Poll for Tweet ID
Wait for post to be published:
MAX_ATTEMPTS=20 # 60 seconds total (20 × 3s)
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
STATUS_RESPONSE=$(curl -s "http://5.161.75.135:8080/api/v1/posts/$POST_ID")
POST_STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')
TWEET_ID=$(echo "$STATUS_RESPONSE" | jq -r '.tweet_id // empty')
if [ "$POST_STATUS" = "posted" ] && [ -n "$TWEET_ID" ]; then
echo "✅ Posted to X!"
break
elif [ "$POST_STATUS" = "failed" ]; then
ERROR_REASON=$(echo "$STATUS_RESPONSE" | jq -r '.error_reason')
echo "❌ Post failed: $ERROR_REASON"
exit 1
fi
ATTEMPT=$((ATTEMPT + 1))
sleep 3
done
Display progress: ⏳ Waiting for publish... (Xs)
</step_4_poll>
<step_5_reply> 5. Reply with GitHub Link
Once main post is live, create threaded reply:
GITHUB_URL="https://github.com/marcusgoll/Spec-Flow/releases/tag/v${NEW_VERSION}"
# Write reply content to temp file for proper UTF-8 encoding
cat > /tmp/reply.txt << EOF
🔗 Release notes: ${GITHUB_URL}
EOF
REPLY_CONTENT=$(cat /tmp/reply.txt | jq -Rs .)
# Post as threaded reply using in_reply_to_tweet_id
REPLY_RESPONSE=$(curl -s -X POST "http://5.161.75.135:8080/api/v1/posts/" \
-H "Content-Type: application/json" \
-d "{\"content\": $REPLY_CONTENT, \"scheduled_at\": null, \"in_reply_to_tweet_id\": \"$TWEET_ID\"}")
REPLY_POST_ID=$(echo "$REPLY_RESPONSE" | jq -r '.id')
# Poll for reply tweet ID (same logic as step 4)
# ...
echo "✅ GitHub link posted!"
Fallback if reply fails:
- •Main post succeeded → Display main tweet URL
- •Prompt user to manually reply with GitHub link
- •Low impact (main announcement visible) </step_5_reply>
<step_6_summary> 6. Display Success Summary
Show both tweet URLs:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📱 X Announcement Posted!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Main Post:
https://x.com/username/status/{TWEET_ID}
GitHub Link Reply:
https://x.com/username/status/{REPLY_TWEET_ID}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Continue with release summary in /release command.
</step_6_summary>
</workflow>
<error_handling> Scenario 1: API Unreachable
⚠️ X Poster API is unavailable (http://5.161.75.135:8080/)
Release completed successfully, but X announcement could not be posted.
Manual posting option:
1. Copy the post text above
2. Post manually to X: https://x.com/compose
3. Reply with: 🔗 Release notes: https://github.com/marcusgoll/Spec-Flow/releases/tag/v{VERSION}
Release will continue...
Scenario 2: Post Timeout
⏱️ Timeout waiting for post to publish (60s exceeded)
Post may still succeed in background.
Check status: http://5.161.75.135:8080/api/v1/posts/{POST_ID}
Release will continue...
Scenario 3: Main Post Succeeds, Reply Fails
✅ Main post successful!
⚠️ Reply post failed
Main announcement: https://x.com/username/status/{TWEET_ID}
Manually reply with:
🔗 Release notes: https://github.com/marcusgoll/Spec-Flow/releases/tag/v{VERSION}
See references/error-scenarios.md for complete error handling. </error_handling>
<api_integration>
X Poster API Base URL: http://5.161.75.135:8080/
Key endpoints:
- •
POST /api/v1/posts/- Create post or threaded reply - •
GET /api/v1/posts/{id}- Get post status and tweet_id - •
POST /api/v1/posts/{id}/cancel- Cancel queued post
Post request format:
{
"content": "Tweet text (max 280 chars)",
"scheduled_at": null,
"in_reply_to_tweet_id": "1234567890" | null
}
Status values:
- •
queued- Waiting to post - •
posting- Currently posting - •
posted- Live (tweet_id available) - •
failed- Error (error_reason available)
Dependencies:
- •
jq- JSON parsing (required) - •
curl- HTTP requests (required) - •Network access to API endpoint
See references/api-reference.md for complete API documentation. </api_integration>
<anti_patterns> Avoid these mistakes:
1. Posting without user confirmation
❌ BAD: Auto-post without showing preview ✅ GOOD: Display preview, get explicit confirmation
2. Exceeding character limit
❌ BAD: Generate 300-char post, API rejects ✅ GOOD: Validate ≤280 chars, trim if needed
3. Not handling API failures gracefully
❌ BAD: Crash release process if X post fails ✅ GOOD: Warn, provide manual fallback, continue release
4. Blocking release on X announcement
❌ BAD: Release fails if tweet can't be posted ✅ GOOD: X announcement is optional enhancement
5. Exposing API URL in public docs
❌ BAD: Include API base URL in error messages, logs ✅ GOOD: Network-isolated, internal-only reference
</anti_patterns>
<success_criteria> X announcement working when:
- •✓ Post generated from CHANGELOG highlights
- •✓ Preview shown with character count
- •✓ User confirmation obtained before posting
- •✓ Main post created via API successfully
- •✓ Tweet ID retrieved via polling
- •✓ Threaded reply posted with GitHub link
- •✓ Both tweet URLs displayed
- •✓ Release continues even if X post fails
Error handling passing when:
- •API unreachable → Manual fallback provided
- •Post timeout → Status check URL shown
- •Reply fails → Main post URL + manual reply instructions
- •Release never blocked by X announcement failures </success_criteria>
<reference_guides> For detailed templates, API documentation, and error handling:
- •references/post-templates.md - Engaging post examples and generation guidelines
- •references/api-reference.md - Complete X Poster API documentation
- •references/error-scenarios.md - Comprehensive error handling strategies
- •references/legacy-documentation.md - Original detailed implementation guide </reference_guides>