Product Manager Templates
Workflow templates for product managers who need to automate feature releases, track metrics, coordinate launches, and keep stakeholders informed—all from the terminal.
Feature Flag Automation & Rollouts
Automate feature flag rollouts with gradual percentage increases, monitoring, and automatic rollbacks on errors.
Use Case
Release a new feature gradually: start at 10% of users, monitor error rates, automatically increase to 25%, 50%, then 100% if metrics look good. Rollback if errors spike.
Workflow Configuration
name: gradual-feature-rollout
description: Automated feature flag rollout with monitoring
trigger:
type: manual
steps:
- name: enable_10_percent
type: http
config:
method: PATCH
url: https://api.launchdarkly.com/api/v2/flags/${PROJECT_KEY}/${FEATURE_FLAG_KEY}
headers:
Authorization: ${LAUNCHDARKLY_API_KEY}
Content-Type: application/json
body: |
{
"patch": [
{
"op": "replace",
"path": "/environments/${ENVIRONMENT}/rollout/variations/0/weight",
"value": 10000
}
]
}
output: rollout_10
- name: notify_team_10_percent
type: http
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "🚀 Feature '${FEATURE_FLAG_KEY}' rolled out to 10% of users",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Gradual Rollout Started*\n• Feature: ${FEATURE_FLAG_KEY}\n• Current: 10% of users\n• Monitoring for 1 hour before next increase"
}
}
]
}
- name: wait_1_hour
type: cli
config:
command: sleep 3600
- name: check_error_rate_10
type: http
config:
method: GET
url: https://api.sentry.io/api/0/organizations/${SENTRY_ORG}/stats/?stat=received&query=release:${FEATURE_FLAG_KEY}
headers:
Authorization: Bearer ${SENTRY_TOKEN}
output: errors_10
- name: rollback_if_errors
type: http
condition: errors_10.total > 50
config:
method: PATCH
url: https://api.launchdarkly.com/api/v2/flags/${PROJECT_KEY}/${FEATURE_FLAG_KEY}
body: |
{
"patch": [{"op": "replace", "path": "/environments/${ENVIRONMENT}/on", "value": false}]
}
- name: enable_25_percent
type: http
condition: errors_10.total <= 50
config:
method: PATCH
url: https://api.launchdarkly.com/api/v2/flags/${PROJECT_KEY}/${FEATURE_FLAG_KEY}
headers:
Authorization: ${LAUNCHDARKLY_API_KEY}
body: |
{
"patch": [{"op": "replace", "path": "/environments/${ENVIRONMENT}/rollout/variations/0/weight", "value": 25000}]
}
- name: notify_team_25_percent
type: http
condition: errors_10.total <= 50
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "📈 Feature '${FEATURE_FLAG_KEY}' increased to 25% (no errors detected)"
}
- name: wait_2_hours
type: cli
condition: errors_10.total <= 50
config:
command: sleep 7200
- name: enable_100_percent
type: http
condition: errors_10.total <= 50
config:
method: PATCH
url: https://api.launchdarkly.com/api/v2/flags/${PROJECT_KEY}/${FEATURE_FLAG_KEY}
body: |
{
"patch": [{"op": "replace", "path": "/environments/${ENVIRONMENT}/rollout/variations/0/weight", "value": 100000}]
}
- name: notify_team_complete
type: http
condition: errors_10.total <= 50
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "✅ Feature '${FEATURE_FLAG_KEY}' fully rolled out to 100% of users"
}
Setup Instructions
-
Create the workflow:
loopcli loop create gradual-feature-rollout -
Set your secrets:
loopcli loop secrets set LAUNCHDARKLY_API_KEY loopcli loop secrets set SENTRY_TOKEN loopcli loop secrets set SLACK_WEBHOOK_URL -
Run when ready to release:
loopcli loop run gradual-feature-rollout
Product Launch Coordination
Coordinate a product launch: schedule social posts, send customer emails, update product pages, and notify stakeholders.
Use Case
Execute a coordinated product launch at a specific time: publish changelog, send customer emails, post to social media, and update marketing pages—all in the correct sequence.
Workflow Configuration
name: product-launch-coordinator
description: Coordinate multi-channel product launch
trigger:
type: schedule
cron: "0 9 * * *" # Launch at 9am on specified date
steps:
- name: publish_changelog
type: http
config:
method: POST
url: https://api.github.com/repos/${GITHUB_REPO}/releases
headers:
Authorization: token ${GITHUB_TOKEN}
Content-Type: application/json
body: |
{
"tag_name": "v${VERSION}",
"name": "${PRODUCT_NAME} ${VERSION}",
"body": "${CHANGELOG_TEXT}",
"draft": false
}
output: release
- name: send_customer_announcement
type: http
config:
method: POST
url: https://api.resend.com/emails/batch
headers:
Authorization: Bearer ${RESEND_API_KEY}
Content-Type: application/json
body: |
{
"from": "product@yourapp.com",
"to": ["${CUSTOMER_LIST}"],
"subject": "Introducing ${PRODUCT_NAME} ${VERSION}",
"html": "${EMAIL_TEMPLATE}"
}
output: email_sent
- name: post_to_twitter
type: http
config:
method: POST
url: https://api.twitter.com/2/tweets
headers:
Authorization: Bearer ${TWITTER_BEARER_TOKEN}
Content-Type: application/json
body: |
{
"text": "🚀 We just launched ${PRODUCT_NAME} ${VERSION}! ${LAUNCH_TWEET_TEXT}\n\n${release.html_url}"
}
- name: update_product_page
type: http
config:
method: POST
url: https://api.vercel.com/v1/integrations/deploy/${VERCEL_DEPLOY_HOOK}
output: deploy
- name: notify_internal_team
type: http
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "🎉 ${PRODUCT_NAME} ${VERSION} launched!",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Launch Complete*\n• Release: ${release.html_url}\n• Emails sent: ${email_sent.count}\n• Site updated: ${deploy.url}"
}
}
]
}
User Feedback Collection & Analysis
Automatically collect user feedback, categorize it, and create tasks in Linear for high-priority issues.
Workflow Configuration
name: feedback-to-linear
description: Process feedback and create Linear issues
trigger:
type: webhook
path: /webhooks/feedback
steps:
- name: store_feedback
type: http
config:
method: POST
url: https://your-project.supabase.co/rest/v1/feedback
headers:
apikey: ${SUPABASE_KEY}
Content-Type: application/json
body: |
{
"user_email": "${webhook.email}",
"feedback_type": "${webhook.type}",
"description": "${webhook.description}",
"priority": "${webhook.priority}"
}
output: feedback
- name: create_linear_issue
type: http
condition: webhook.priority == 'high'
config:
method: POST
url: https://api.linear.app/graphql
headers:
Authorization: ${LINEAR_API_KEY}
Content-Type: application/json
body: |
{
"query": "mutation { issueCreate(input: {title: \"User Feedback: ${webhook.type}\", description: \"${webhook.description}\\n\\nFrom: ${webhook.email}\", teamId: \"${LINEAR_TEAM_ID}\", priority: 1}) { success issue { id url } } }"
}
output: linear_issue
- name: notify_pm_high_priority
type: http
condition: webhook.priority == 'high'
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "🔥 High-priority feedback received",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*High-Priority Feedback*\n• Type: ${webhook.type}\n• User: ${webhook.email}\n• Linear: ${linear_issue.data.issueCreate.issue.url}\n• Description: ${webhook.description}"
}
}
]
}
Sprint Metrics Dashboard Update
Automatically update sprint metrics in a dashboard: pull data from Linear, GitHub, and Sentry, then update Notion.
Workflow Configuration
name: sprint-metrics-update
description: Daily sprint metrics aggregation
trigger:
type: schedule
cron: "0 10 * * 1-5" # Weekdays at 10am
steps:
- name: fetch_linear_stats
type: http
config:
method: POST
url: https://api.linear.app/graphql
headers:
Authorization: ${LINEAR_API_KEY}
body: |
{
"query": "{ team(id: \"${LINEAR_TEAM_ID}\") { issues(filter: {state: {type: {in: [\"started\", \"completed\"]}}}) { nodes { id title state { name } } } } }"
}
output: linear_data
- name: fetch_github_prs
type: http
config:
method: GET
url: https://api.github.com/repos/${GITHUB_REPO}/pulls?state=all&since=${SPRINT_START_DATE}
headers:
Authorization: token ${GITHUB_TOKEN}
output: pr_data
- name: fetch_sentry_errors
type: http
config:
method: GET
url: https://sentry.io/api/0/projects/${SENTRY_ORG}/${SENTRY_PROJECT}/issues/?query=firstSeen:>${SPRINT_START_DATE}
headers:
Authorization: Bearer ${SENTRY_TOKEN}
output: error_data
- name: update_notion_dashboard
type: http
config:
method: PATCH
url: https://api.notion.com/v1/pages/${NOTION_PAGE_ID}
headers:
Authorization: Bearer ${NOTION_TOKEN}
Notion-Version: "2022-06-28"
Content-Type: application/json
body: |
{
"properties": {
"Issues Completed": {"number": ${linear_data.data.team.issues.nodes.length}},
"PRs Merged": {"number": ${pr_data.length}},
"New Errors": {"number": ${error_data.length}},
"Last Updated": {"date": {"start": "${timestamp}"}}
}
}
A/B Test Result Notification
Monitor A/B test results and notify team when statistical significance is reached.
Workflow Configuration
name: ab-test-monitor
description: Monitor A/B test and notify on significance
trigger:
type: schedule
cron: "0 */6 * * *" # Every 6 hours
steps:
- name: fetch_test_results
type: http
config:
method: GET
url: https://api.optimizely.com/v2/experiments/${EXPERIMENT_ID}/results
headers:
Authorization: Bearer ${OPTIMIZELY_TOKEN}
output: results
- name: check_significance
type: cli
config:
command: |
python3 -c "
import json
results = json.loads('${results}')
p_value = results['variations'][0]['p_value']
if p_value < 0.05:
print('SIGNIFICANT')
else:
print('NOT_SIGNIFICANT')
"
output: significance
- name: notify_on_significance
type: http
condition: significance.stdout == 'SIGNIFICANT'
config:
method: POST
url: ${SLACK_WEBHOOK_URL}
body: |
{
"text": "📊 A/B test reached statistical significance!",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Test Results*\n• Experiment: ${EXPERIMENT_ID}\n• Winner: Variation ${results.variations[0].name}\n• Lift: ${results.variations[0].lift}%\n• P-value: ${results.variations[0].p_value}"
}
}
]
}
Getting Started
-
Install LoopCLI:
npm install -g loopcli -
Initialize project:
loopcli project init -
Create your workflow:
loopcli loop create my-pm-workflow -
Test locally:
loopcli loop run my-pm-workflow -
Deploy for scheduled runs:
loopcli loop deploy my-pm-workflow --activate