LoopCLI

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

  1. Create the workflow:

    loopcli loop create gradual-feature-rollout
    
  2. Set your secrets:

    loopcli loop secrets set LAUNCHDARKLY_API_KEY
    loopcli loop secrets set SENTRY_TOKEN
    loopcli loop secrets set SLACK_WEBHOOK_URL
    
  3. 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

  1. Install LoopCLI:

    npm install -g loopcli
    
  2. Initialize project:

    loopcli project init
    
  3. Create your workflow:

    loopcli loop create my-pm-workflow
    
  4. Test locally:

    loopcli loop run my-pm-workflow
    
  5. Deploy for scheduled runs:

    loopcli loop deploy my-pm-workflow --activate
    

Need Help?

Related Documentation

Continue learning with these related topics