
Daily Rhythm
- 56 installs
- 82 repo stars
- Updated August 2, 2026
- aaaaqwq/claude-code-skills
daily-rhythm is a Claude Code skill that automates morning briefs, evening wind-downs, sleep nudges, and weekly reviews to run a structured daily routine.
About
This Claude Code skill sets up a daily and weekly planning routine that automates morning briefings, evening wind-down prompts, sleep nudges, and weekly reviews. It syncs data from Google Tasks, optional Stripe ARR, and a calendar ICS feed, then compiles a formatted morning brief. A solo developer uses it to keep a structured daily rhythm and track priorities via cron jobs.
- Automated morning briefs, evening wind-downs, sleep nudges, and Sunday weekly reviews driven by cron jobs
- Optional Google Tasks, Stripe ARR, and calendar (ICS) data sources feed the morning brief
- Customizable Daily Intention and focus area configured through a HEARTBEAT.md file
Daily Rhythm by the numbers
- 56 all-time installs (skills.sh)
- Ranked #1,580 of 3,280 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
daily-rhythm capabilities & compatibility
Free; requires Google OAuth credentials and an optional Stripe API key for ARR
- Capabilities
- morning brief · weekly review · task sync · arr tracking · routine automation
- Works with
- stripe
- Use cases
- planning · project management
- Pricing
- Free
What daily-rhythm says it does
A comprehensive daily planning and reflection system that automates morning briefs, evening wind-downs, sleep nudges, and weekly reviews
npx skills add https://github.com/aaaaqwq/claude-code-skills --skill daily-rhythmAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 56 |
|---|---|
| repo stars | ★ 82 |
| Last updated | August 2, 2026 |
| Repository | aaaaqwq/claude-code-skills ↗ |
What it does
Automate a daily routine of morning briefs, wind-down prompts, and weekly reviews using cron and synced tasks, ARR, and calendar data.
Who is it for?
Solo developers who want an automated daily planning and reflection routine
Skip if: Team project management or task tracking beyond a single user's personal rhythm
When should I use this skill?
You want to set up morning briefings, wind-down routines, sleep reminders, or weekly planning automation
What you get
Automated daily briefs and prompts plus a weekly review, tied to your tasks, ARR, and calendar
- Automated morning brief
- Wind-down and sleep prompts
- Weekly review
By the numbers
- 4 daily/weekly automations (morning brief, wind-down, sleep nudge, weekly review)
- 3 scripts (sync-google-tasks.py, sync-stripe-arr.py, morning-brief.sh)
Files
Daily Rhythm
A comprehensive daily planning and reflection system that automates morning briefs, evening wind-downs, sleep nudges, and weekly reviews to help users stay focused, track progress, and maintain work-life balance.
Quick Start
1. Install the skill and ensure scripts are executable 2. Configure data sources (Google Tasks, optional Stripe, Calendar) 3. Set up cron jobs for automation 4. Customize your focus area and Daily Intention (prayer, affirmation, quote, or centering thought) 5. Enjoy automated daily briefings and prompts
Features
Daily Automation
- 7:00am: Background data sync (tasks, ARR)
- 8:30am: Morning Brief with priority, calendar, weather, tasks
- 10:30pm: Wind-down prompt to plan tomorrow's priority
- 11:00pm: Sleep nudge with encouraging words
Weekly Automation
- Sunday 8:00pm: Weekly review for reflection and task planning
Rich Morning Briefs Include
- 🙏 Daily Intention — Prayer, affirmation, quote, or centering thought
- Calendar events
- Focus area
- ARR progress tracking (optional Stripe integration)
- Today's priority (from wind-down or top task)
- Actionable suggestions
- Step-by-step plan
- Helpful resources
- Task list from Google Tasks
- Weather (if configured)
- Open loops from yesterday
Setup Instructions
Step 1: Install Dependencies
Ensure Python 3 and required packages:
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client stripeStep 2: Configure Google Tasks
1. Go to Google Cloud Console 2. Create project → Enable Tasks API 3. Create OAuth 2.0 credentials (Desktop app) 4. Download credentials.json to ~/.openclaw/google-tasks/ 5. Run once to authenticate: python3 scripts/sync-google-tasks.py
See CONFIGURATION.md for detailed steps.
Step 3: Configure Stripe (Optional)
For ARR tracking in morning briefs:
1. Create .env.stripe in workspace root:
STRIPE_API_KEY=sk_live_...2. Set ARR target in state file
Step 4: Configure Calendar
Add ICS URL to TOOLS.md:
### Calendar
- **ICS URL:** `https://calendar.google.com/calendar/ical/...`Step 5: Set Up Cron Jobs
Option A: System Cron (Traditional)
crontab -e
# Add these lines:
0 7 * * * cd /path/to/workspace && python3 skills/daily-rhythm/scripts/sync-stripe-arr.py
30 8 * * * cd /path/to/workspace && python3 skills/daily-rhythm/scripts/morning-brief.sh
0 20 * * 0 cd /path/to/workspace && echo "Weekly review time"
30 22 * * * cd /path/to/workspace && echo "Wind-down time"
0 23 * * * cd /path/to/workspace && echo "Sleep nudge"Option B: OpenClaw Cron (If Available) Use the cron tool to create jobs with agentTurn payloads that generate and send briefs.
Step 6: Create HEARTBEAT.md
Copy the template from assets/HEARTBEAT_TEMPLATE.md to workspace root and customize:
- Daily Intention text (prayer, affirmation, quote, or centering thought)
- Focus area
- ARR target (if using Stripe)
Workflow Details
Morning Brief Generation
The brief is generated by: 1. Syncing latest data (tasks, ARR) 2. Reading wind-down priority from memory/YYYY-MM-DD.md 3. Fetching calendar from ICS URL 4. Fetching weather (if configured) 5. Compiling all sections into formatted message
Wind-Down Response Flow
When user replies to 10:30pm prompt: 1. Parse their tomorrow priority 2. Generate actionable suggestions 3. Break into steps 4. Identify resources 5. Ask confirmation 6. Save to memory/YYYY-MM-DD.md 7. Include in next morning's brief
Weekly Review Flow
Sunday 8pm prompt asks reflection questions. When user replies: 1. Summarize their week 2. Identify key priorities 3. Create tasks in Google Tasks 4. Preview Monday's brief
Customization
Change Daily Intention
The morning brief opens with a centering section you can customize:
Examples:
- Faith-based: Prayer, scripture verse, devotional thought
- Secular: Affirmation, intention-setting, gratitude practice
- Quotes: Inspirational quotes, stoic philosophy, poetry
- Goals: Daily mission statement, values reminder
Edit in HEARTBEAT.md or modify the morning brief generation.
Change Focus Area
Update default focus in HEARTBEAT.md:
### Focus
Your primary focus (e.g., "Product growth and customer acquisition")Adjust Timing
Modify cron expressions:
30 8 * * *= 8:30am daily30 22 * * *= 10:30pm daily0 23 * * *= 11:00pm daily0 20 * * 0= 8:00pm Sundays
Add Custom Sections
Modify scripts/morning-brief.sh to include additional data sources.
File Structure
workspace/
├── memory/
│ ├── YYYY-MM-DD.md # Wind-down responses
│ ├── google-tasks.json # Synced tasks
│ ├── stripe-data.json # ARR data
│ └── heartbeat-state.json # State tracking
├── skills/daily-rhythm/
│ ├── scripts/
│ │ ├── sync-google-tasks.py
│ │ ├── sync-stripe-arr.py
│ │ └── morning-brief.sh
│ ├── references/
│ │ └── CONFIGURATION.md
│ └── assets/
│ └── HEARTBEAT_TEMPLATE.md
└── HEARTBEAT.md # Your custom scheduleScripts Reference
sync-google-tasks.py
Syncs Google Tasks to local JSON. Requires credentials.json.
sync-stripe-arr.py
Calculates ARR from active Stripe subscriptions. Requires .env.stripe.
morning-brief.sh
Orchestrates data sync and brief generation.
Troubleshooting
Google Tasks not syncing?
- Verify
credentials.jsonexists - Check Tasks API is enabled
- Run script manually to see errors
Stripe ARR not showing?
- Verify
.env.stripewith valid API key - Check for active subscriptions
- Run sync script manually
Cron jobs not firing?
- Verify cron is installed:
crontab -l - Check script paths are absolute
- Review system logs
See CONFIGURATION.md for detailed troubleshooting.
Best Practices
1. Reply to wind-down prompts for best morning brief experience 2. Keep tasks updated in Google Tasks 3. Do weekly reviews to stay aligned with goals 4. Customize focus as priorities change 5. Adjust timing to match your rhythms
Requirements
- Python 3.7+
- Google Tasks API credentials (for task sync)
- Stripe API key (optional, for ARR tracking)
- Calendar ICS URL (optional, for events)
- Cron or OpenClaw cron system
{
"ownerId": "kn731fmc750yp2fp7rfx57chbh80bnyf",
"slug": "daily-rhythm",
"version": "1.0.0",
"publishedAt": 1769943388253
}{
"version": 1,
"registry": "https://clawhub.ai",
"slug": "daily-rhythm",
"installedVersion": "1.0.0",
"installedAt": 1770442992765
}
Example HEARTBEAT.md for Daily Rhythm
Daily Rhythm Schedule
Schedule (Local time)
8:30am — Morning Brief
Pre-send: 1. Sync Google Tasks 2. Sync Stripe ARR (if configured)
Send via Telegram/WhatsApp/Signal with:
- 🙏 Daily Intention: "Your prayer, affirmation, quote, or centering thought here"
- 📆 Today's Calendar: (from ICS URL)
- 🎯 Focus: Your primary focus area
- 💰 ARR Progress: toward your target (if Stripe configured)
- ⭐ Today's Priority: (from wind-down response or top task)
- 💡 How to achieve it: Actionable suggestions
- 📝 Steps: Step-by-step plan
- 🔗 Resources: Helpful tools and links
- 📋 Tasks: Always show active tasks
- 🌤️ Weather: (if location configured)
- 🔄 Open Loops: (unresolved items from yesterday)
10:30pm — Wind-Down Prompt
"What's the one thing you want to accomplish tomorrow that would make the day feel successful?"
When user responds:
- Provide actionable suggestions
- Break into clear steps
- Offer relevant resources
- Ask to confirm for tomorrow's brief
- Save to memory/YYYY-MM-DD.md
11:00pm — Sleep Nudge
"Phone down. Sleep = tomorrow's energy. Target: 11pm."
Add encouraging words about rest and tomorrow's potential.
Weekly: Sunday 8pm — Weekly Review
Reflection & Planning Session
Part 1: Where am I?
- 🎭 What are you feeling? Good or bad?
- 😤 What's bothering you?
- 🏆 What were some wins?
- 🔮 What's up ahead for the week? Good or bad?
Part 2: What do I do next?
- 🎯 What's the big thing to address and get ahead of?
- 📅 Calendar check: What are your commitments?
- 💝 Is there something you can add this week for yourself?
Output: Create tasks in Google Tasks for the upcoming week
State Tracking
Check memory/heartbeat-state.json to avoid duplicate sends.
Daily Rhythm
Transform your daily routine with automated morning briefs, evening wind-down prompts, and weekly reviews. Stay focused, track progress, and maintain work-life balance without the mental overhead.
What It Does
Daily Rhythm creates a structured daily planning system that runs automatically:
☀️ Morning Brief (8:30am)
- Daily intention (prayer, affirmation, or centering thought)
- Calendar events
- Today's priority with actionable steps
- Task list from Google Tasks
- Weather
- Progress tracking (optional Stripe ARR)
🌙 Wind-Down Prompt (10:30pm)
- Plan tomorrow's priority
- Get actionable suggestions
- Break goals into steps
- Auto-saves to tomorrow's brief
😴 Sleep Nudge (11:00pm)
- Gentle reminder to rest
- Encouraging words for tomorrow
📅 Weekly Review (Sunday 8pm)
- Reflect on the week
- Celebrate wins
- Identify blockers
- Create tasks for the week ahead
Quick Start
1. Install the skill 2. Configure Google Tasks (required)
- Get API credentials from Google Cloud
- Place
credentials.jsonin~/.openclaw/google-tasks/
3. Optional: Add Stripe API key for ARR tracking 4. Optional: Add calendar ICS URL 5. Set up cron jobs or use OpenClaw's cron system 6. Customize your Daily Intention in HEARTBEAT.md 7. Enjoy automated briefings!
Perfect For
- Founders tracking ARR while managing daily priorities
- Professionals juggling multiple projects
- Anyone wanting structured daily planning without the setup work
- People who want to start and end their day with intention
Customization
The "Daily Intention" section is fully customizable:
- Faith-based: Prayers, scripture, devotional thoughts
- Secular: Affirmations, gratitude practice, intentions
- Philosophy: Stoic quotes, mindful centering
- Personal: Mission statements, core values
Requirements
- Python 3.7+
- Google Tasks API credentials
- Optional: Stripe API key (for ARR tracking)
- Optional: Calendar ICS URL
What's Included
- Google Tasks sync script
- Stripe ARR calculator
- Morning brief generator
- Wind-down response handler
- Weekly review system
- Complete setup documentation
---
Start each day with clarity. End each day with peace.
Daily Rhythm Configuration Guide
Overview
Daily Rhythm is a comprehensive daily planning and reflection system that helps you stay focused, track progress, and maintain work-life balance through automated briefings and prompts.
Features
Daily Schedule
- 7:00am: Data sync (Stripe ARR, Google Tasks)
- 8:30am: Morning Brief with priority, calendar, weather, and tasks
- 10:30pm: Wind-down prompt to plan tomorrow
- 11:00pm: Sleep nudge for healthy habits
Weekly Schedule
- Sunday 8:00pm: Weekly review for reflection and planning
Setup Requirements
1. Google Tasks Integration
Required for task syncing:
1. Go to Google Cloud Console 2. Create a new project or select existing 3. Enable the Tasks API 4. Create OAuth 2.0 credentials (Desktop application) 5. Download credentials.json 6. Place in ~/.openclaw/google-tasks/credentials.json 7. Run python3 scripts/sync-google-tasks.py once to authenticate
2. Stripe Integration (Optional)
Required for ARR tracking:
1. Get your Stripe API key from Stripe Dashboard 2. Create .env.stripe in workspace root:
STRIPE_API_KEY=sk_live_...3. Set ARR target in memory/heartbeat-state.json:
{
"arrTarget": 30000,
"arrCurrency": "£"
}3. Calendar Integration
Add your ICS calendar URL to TOOLS.md:
### Calendar
- **ICS URL:** `https://calendar.google.com/calendar/ical/...`4. Cron Job Setup
Install the cron jobs using your system's cron:
# Edit crontab
crontab -e
# Add these lines (adjust paths as needed):
0 7 * * * cd /Users/tom/.openclaw/workspace && python3 skills/daily-rhythm/scripts/sync-stripe-arr.py
30 8 * * * cd /Users/tom/.openclaw/workspace && python3 skills/daily-rhythm/scripts/morning-brief.sh
0 20 * * 0 cd /Users/tom/.openclaw/workspace && echo "Weekly review time"
30 22 * * * cd /Users/tom/.openclaw/workspace && echo "Wind-down time"
0 23 * * * cd /Users/tom/.openclaw/workspace && echo "Sleep nudge"Or use OpenClaw's built-in cron system if available.
Configuration Options
Daily Intention (Morning Brief Opening)
The morning brief opens with a centering section you can customize to match your beliefs and preferences:
Examples:
| Style | Example |
|---|---|
| Faith-based | "Thank you for already stabilizing my nervous system and guiding my next steps..." |
| Secular | "Today I choose to be present, focused, and kind to myself..." |
| Quote | "The best time to plant a tree was 20 years ago. The second best time is now." |
| Intention | "My intention today is to make progress, not perfection..." |
Edit in HEARTBEAT.md under the morning brief section.
Morning Brief Format
The morning brief includes:
- 🙏 Daily Intention — Your prayer, affirmation, quote, or centering thought
- Calendar events
- Focus area
- ARR progress (if Stripe configured)
- Today's priority (from wind-down or top task)
- Actionable suggestions
- Step-by-step plan
- Helpful resources
- Task list
- Weather
- Open loops from yesterday
Wind-down Priority
When you respond to the 10:30pm prompt, the system: 1. Captures your priority for tomorrow 2. Generates actionable suggestions 3. Breaks it into steps 4. Identifies resources 5. Saves to memory/YYYY-MM-DD.md 6. Includes in next morning's brief
Weekly Review Questions
The Sunday 8pm review asks:
Where am I?
- What are you feeling?
- What's bothering you?
- What were this week's wins?
- What's coming up next week?
What do I do next?
- What's the big thing to address?
- What are your calendar commitments?
- What can you deprioritize?
- What self-care can you add?
Customization
Changing Prayer/Affirmation
Edit the prayer text in the cron job configuration or morning brief script.
Changing Focus Area
Update the default focus area in HEARTBEAT.md:
### Focus
Your default focus area hereAdding Custom Sections
Modify the morning brief script to include additional data sources or sections.
Modifying Times
Adjust cron expressions to change when prompts fire:
0 7 * * *= 7:00am daily30 8 * * *= 8:30am daily0 20 * * 0= 8:00pm Sundays30 22 * * *= 10:30pm daily0 23 * * *= 11:00pm daily
File Structure
workspace/
├── memory/
│ ├── YYYY-MM-DD.md # Daily wind-down responses
│ ├── google-tasks.json # Synced tasks
│ ├── stripe-data.json # ARR data
│ └── heartbeat-state.json # Rhythm state
├── skills/daily-rhythm/
│ ├── scripts/
│ │ ├── sync-google-tasks.py
│ │ ├── sync-stripe-arr.py
│ │ └── morning-brief.sh
│ └── references/
│ └── CONFIGURATION.md # This file
└── HEARTBEAT.md # Rhythm scheduleTroubleshooting
Google Tasks Not Syncing
- Check
credentials.jsonexists and is valid - Run sync script manually to see errors
- Verify Tasks API is enabled in Google Cloud
Stripe ARR Not Showing
- Check
.env.stripeexists with valid API key - Verify Stripe account has active subscriptions
- Run sync script manually to see errors
Cron Jobs Not Firing
- Check cron is installed:
crontab -l - Verify paths in cron entries are correct
- Check system logs for errors
Morning Brief Missing Data
- Ensure sync scripts run successfully
- Check memory files exist and contain data
- Verify file paths in configuration
Best Practices
1. Reply to wind-down prompts for the best morning brief experience 2. Keep Google Tasks updated so briefs reflect current priorities 3. Do weekly reviews to stay aligned with goals 4. Customize focus areas as your priorities change 5. Adjust timing to match your natural rhythms
Support
For issues or feature requests, consult the skill documentation or create an issue in the skill repository.
#!/bin/bash
# Daily Rhythm - Morning Brief Generator
# Generates and sends a comprehensive morning brief
cd /Users/tom/.openclaw/workspace
echo "🌅 Generating Morning Brief..."
# Sync data sources
echo "📋 Syncing Google Tasks..."
python3 skills/daily-rhythm/scripts/sync-google-tasks.py 2>/dev/null || echo "⚠️ Google Tasks sync skipped"
echo "💰 Syncing Stripe ARR..."
python3 skills/daily-rhythm/scripts/sync-stripe-arr.py 2>/dev/null || echo "⚠️ Stripe sync skipped"
echo "✅ Data sync complete. Brief ready for delivery."
#!/usr/bin/env python3
"""
Google Tasks Sync - Fetches tasks from Google Tasks API
"""
import os
import json
import sys
# Add path for google auth
sys.path.insert(0, '/Users/tom/Library/Python/3.9/lib/python/site-packages')
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from datetime import datetime
SCOPES = ['https://www.googleapis.com/auth/tasks.readonly']
def get_credentials():
"""Get or refresh Google credentials."""
creds_dir = os.path.expanduser('~/.openclaw/google-tasks')
token_path = os.path.join(creds_dir, 'token.json')
creds_path = os.path.join(creds_dir, 'credentials.json')
creds = None
if os.path.exists(token_path):
creds = Credentials.from_authorized_user_file(token_path, SCOPES)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
if not os.path.exists(creds_path):
print(f"❌ Credentials not found at {creds_path}")
print("Please set up Google Tasks API first")
return None
flow = InstalledAppFlow.from_client_secrets_file(creds_path, SCOPES)
creds = flow.run_local_server(port=0)
with open(token_path, 'w') as token:
token.write(creds.to_json())
return creds
def sync_tasks():
"""Sync Google Tasks to local JSON file."""
creds = get_credentials()
if not creds:
return False
try:
service = build('tasks', 'v1', credentials=creds, cache_discovery=False)
# Get all task lists
tasklists = service.tasklists().list().execute()
all_data = {
'synced_at': datetime.now().isoformat(),
'tasklists': []
}
for tasklist in tasklists.get('items', []):
list_id = tasklist['id']
list_title = tasklist['title']
# Get tasks for this list
tasks_result = service.tasks().list(tasklist=list_id, showCompleted=False).execute()
tasks = tasks_result.get('items', [])
tasklist_data = {
'id': list_id,
'title': list_title,
'updated': tasklist.get('updated'),
'task_count': len(tasks),
'tasks': []
}
for task in tasks:
task_data = {
'id': task['id'],
'title': task['title'],
'notes': task.get('notes', ''),
'due': task.get('due'),
'updated': task.get('updated'),
'position': task.get('position'),
'parent': task.get('parent'),
'links': task.get('links', [])
}
tasklist_data['tasks'].append(task_data)
all_data['tasklists'].append(tasklist_data)
# Save to memory file
output_dir = '/Users/tom/.openclaw/workspace/memory'
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'google-tasks.json')
with open(output_path, 'w') as f:
json.dump(all_data, f, indent=2)
total_tasks = sum(tl['task_count'] for tl in all_data['tasklists'])
print(f"✅ Synced {total_tasks} tasks to {output_path}")
return True
except Exception as e:
print(f"❌ Error syncing tasks: {e}")
return False
if __name__ == '__main__':
sync_tasks()
#!/usr/bin/env python3
"""
Stripe ARR Sync - Fetches active subscriptions and calculates ARR
"""
import os
import json
import warnings
from datetime import datetime
# Suppress urllib3 SSL warning on macOS (LibreSSL vs OpenSSL)
warnings.filterwarnings('ignore', category=UserWarning, module='urllib3')
import stripe
def load_config():
"""Load Stripe API key from env file."""
env_paths = [
'/Users/tom/.openclaw/workspace/.env.stripe',
os.path.expanduser('~/.openclaw/workspace/.env.stripe'),
'.env.stripe'
]
for env_path in env_paths:
if os.path.exists(env_path):
with open(env_path) as f:
for line in f:
if '=' in line and not line.startswith('#'):
key, value = line.strip().split('=', 1)
os.environ[key] = value
break
return os.environ.get('STRIPE_API_KEY')
def fetch_active_subscriptions():
"""Fetch all active subscriptions from Stripe."""
api_key = load_config()
if not api_key:
print("❌ No Stripe API key found")
return None
stripe.api_key = api_key
try:
subscriptions = stripe.Subscription.list(
status='active',
limit=100,
expand=['data.customer']
)
return subscriptions.data
except Exception as e:
print(f"❌ Stripe API error: {e}")
return None
def calculate_arr(subscriptions):
"""Calculate ARR from active subscriptions."""
if not subscriptions:
return 0, 0, []
customer_subscriptions = {}
for sub in subscriptions:
customer = sub.get('customer')
if isinstance(customer, dict):
customer_id = customer.get('id')
else:
customer_id = customer
if not customer_id:
continue
# Calculate subscription amount
amount_cents = 0
for item in sub.get('items', {}).get('data', []):
amount_cents += item.get('price', {}).get('unit_amount', 0) * item.get('quantity', 1)
amount_gbp = amount_cents / 100
interval = sub.get('items', {}).get('data', [{}])[0].get('price', {}).get('recurring', {}).get('interval', 'month')
if interval == 'month':
annual_amount = amount_gbp * 12
elif interval == 'year':
annual_amount = amount_gbp
elif interval == 'week':
annual_amount = amount_gbp * 52
else:
annual_amount = amount_gbp * 12
if customer_id in customer_subscriptions:
customer_subscriptions[customer_id] += annual_amount
else:
customer_subscriptions[customer_id] = annual_amount
total_arr = round(sum(customer_subscriptions.values()))
customer_count = len(customer_subscriptions)
return total_arr, customer_count, list(customer_subscriptions.keys())
def sync_stripe():
"""Main sync function."""
subscriptions = fetch_active_subscriptions()
if subscriptions is None:
return False
arr, customer_count, customer_ids = calculate_arr(subscriptions)
# Save detailed data
output_dir = '/Users/tom/.openclaw/workspace/memory'
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'stripe-data.json')
data = {
'synced_at': datetime.now().isoformat(),
'arr': arr,
'customer_count': customer_count,
'customer_ids': customer_ids,
'subscription_count': len(subscriptions),
'method': 'active_subscriptions_only'
}
with open(output_path, 'w') as f:
json.dump(data, f, indent=2)
# Update heartbeat state
heartbeat_path = os.path.join(output_dir, 'heartbeat-state.json')
if os.path.exists(heartbeat_path):
with open(heartbeat_path, 'r') as f:
hb_data = json.load(f)
else:
hb_data = {}
hb_data['arrCurrent'] = arr
hb_data['customerCount'] = customer_count
hb_data['arrLastSynced'] = datetime.now().isoformat()
with open(heartbeat_path, 'w') as f:
json.dump(hb_data, f, indent=2)
print(f"✅ Updated ARR: £{arr:,} ({customer_count} active customers)")
return True
if __name__ == '__main__':
sync_stripe()
Related skills
FAQ
What data sources does the morning brief use?
It can pull Google Tasks, optional Stripe ARR, a calendar ICS feed, weather, and yesterday's open loops.
How is it scheduled?
Via system cron jobs (or OpenClaw cron) at fixed times such as 8:30am morning brief and 10:30pm wind-down.