Overview
PhoneClaw’s scheduler lets you run automations automatically at specific times or recurring intervals using cron expressions. This is perfect for social media posting, periodic data checks, or any task that needs to run without manual intervention.
Scheduled tasks run in the background even when PhoneClaw isn’t actively open. The scheduler checks for tasks every minute and executes them according to their cron schedule.
The schedule() Function
Schedule tasks using the ClawScript schedule() function:
schedule ( taskDescription , cronExpression )
Parameters:
taskDescription (string): A description or reference to your automation task
cronExpression (string): A cron expression defining when to run
Example:
schedule ( "Tweet every hour" , "0 * * * *" )
Creating Scheduled Tasks
First, create the automation logic you want to schedule:
const postTweet = () => {
speakText ( "Starting scheduled tweet" )
// Open Twitter
magicClicker ( "Compose tweet button" )
delay ( 2000 )
// Type and post
magicClicker ( "Tweet text field" )
delay ( 500 )
// Type your message here
magicClicker ( "Post button" )
delay ( 2000 )
speakText ( "Tweet posted successfully" )
}
Wrap your automation with a schedule:
const postTweet = () => {
speakText ( "Starting scheduled tweet" )
magicClicker ( "Compose tweet button" )
delay ( 2000 )
magicClicker ( "Tweet text field" )
delay ( 500 )
magicClicker ( "Post button" )
delay ( 2000 )
speakText ( "Tweet posted" )
}
// Run every hour
schedule ( "postTweet" , "0 * * * *" )
speakText ( "Scheduled to run every hour" )
Open PhoneClaw
Go to the Scheduled Tasks tab
Your task appears with:
Task description
Cron expression
Last execution time
Next scheduled run
Active status
To remove all scheduled tasks:
Open PhoneClaw
Tap Clear Schedule button
Confirm to remove all scheduled tasks
Understanding Cron Expressions
Cron expressions define when tasks run using 5 time fields:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 7) (0 and 7 are Sunday)
│ │ │ │ │
│ │ │ │ │
* * * * *
Special Characters
* - Any value (every minute, every hour, etc.)
, - Value list separator (1,15,30)
- - Range of values (1-5)
/ - Step values (*/15 = every 15 units)
Common Cron Patterns
Every Hour
schedule ( "Hourly task" , "0 * * * *" )
// Runs at: 1:00, 2:00, 3:00, etc.
Every 30 Minutes
schedule ( "Half-hourly task" , "*/30 * * * *" )
// Runs at: :00 and :30 of every hour
Every Day at 9 AM
schedule ( "Morning task" , "0 9 * * *" )
// Runs daily at 9:00 AM
Every Weekday at 8 AM
schedule ( "Weekday morning" , "0 8 * * 1-5" )
// Runs Monday through Friday at 8:00 AM
Every Monday at Noon
schedule ( "Weekly Monday task" , "0 12 * * 1" )
// Runs every Monday at 12:00 PM
Twice Daily (9 AM and 6 PM)
schedule ( "Twice daily" , "0 9,18 * * *" )
// Runs at 9:00 AM and 6:00 PM every day
First Day of Every Month
schedule ( "Monthly task" , "0 0 1 * *" )
// Runs at midnight on the 1st of each month
Every 15 Minutes During Work Hours
schedule ( "Work hours" , "*/15 9-17 * * 1-5" )
// Runs every 15 minutes from 9 AM to 5 PM on weekdays
Use crontab.guru to test and validate your cron expressions with human-readable descriptions.
Real-World Scheduling Examples
Social Media Posting
Post to multiple platforms throughout the day:
const postToSocial = () => {
speakText ( "Running social media post" )
// Post to Twitter
magicClicker ( "Compose tweet button" )
delay ( 2000 )
magicClicker ( "Tweet text field" )
delay ( 500 )
// Type content
magicClicker ( "Post button" )
delay ( 3000 )
// Switch to Instagram
// ... Instagram posting logic
speakText ( "Posted to all platforms" )
}
// Post 3 times per day: 9am, 1pm, 6pm
schedule ( "postToSocial" , "0 9,13,18 * * *" )
Email Check Every 10 Minutes
const checkEmail = () => {
speakText ( "Checking email" )
// Open email app
magicClicker ( "Inbox or email app" )
delay ( 2000 )
// Check for urgent emails
const hasUrgent = magicScraper ( "Are there any unread urgent emails?" )
if ( hasUrgent . toLowerCase (). includes ( "yes" )) {
speakText ( "Urgent email detected" )
// Handle urgent email
}
speakText ( "Email check complete" )
}
// Check every 10 minutes during work hours
schedule ( "checkEmail" , "*/10 9-17 * * 1-5" )
Nightly Backup
const backupData = () => {
speakText ( "Starting nightly backup" )
// Export data from various apps
// Upload to cloud storage
// Verify backup completed
speakText ( "Backup completed successfully" )
}
// Run every night at 2 AM
schedule ( "backupData" , "0 2 * * *" )
Weekend Morning Routine
const weekendRoutine = () => {
speakText ( "Good morning! Starting weekend routine" )
// Check weather
const weather = magicScraper ( "What is today's weather forecast?" )
speakText ( "Today's weather: " + weather )
// Check calendar
magicClicker ( "Calendar app" )
delay ( 2000 )
const events = magicScraper ( "What events are scheduled for today?" )
speakText ( "Today's events: " + events )
speakText ( "Weekend routine complete" )
}
// Run Saturday and Sunday at 8 AM
schedule ( "weekendRoutine" , "0 8 * * 0,6" )
Combining Multiple Schedules
Run different tasks on different schedules:
// Frequent: Check notifications every 5 minutes
const checkNotifications = () => {
magicClicker ( "Notifications" )
delay ( 1000 )
const count = magicScraper ( "How many unread notifications?" )
speakText ( count + " notifications" )
}
schedule ( "checkNotifications" , "*/5 * * * *" )
// Hourly: Post social media updates
const postUpdate = () => {
magicClicker ( "Create post" )
delay ( 2000 )
// Post content
}
schedule ( "postUpdate" , "0 * * * *" )
// Daily: Generate report at end of day
const generateReport = () => {
speakText ( "Generating daily report" )
// Collect and compile data
}
schedule ( "generateReport" , "0 17 * * 1-5" )
// Weekly: Clean up on Sundays
const weeklyCleanup = () => {
speakText ( "Running weekly cleanup" )
// Archive old data
}
schedule ( "weeklyCleanup" , "0 0 * * 0" )
speakText ( "All schedules configured" )
Managing Scheduled Tasks
View All Tasks
From the MainActivity code, scheduled tasks are stored with:
{
id : "unique-task-id" ,
taskDescription : "Your task description" ,
cronExpression : "0 * * * *" ,
createdAt : 1234567890 ,
lastExecuted : 1234567890 ,
isActive : true
}
Task Status
Each task shows:
Created At : When the schedule was created
Last Executed : When it last ran
Next Run : Calculated from cron expression
Active Status : Whether it’s currently enabled
Disable vs Delete
To temporarily pause without deleting:
// This requires accessing task management
// Currently, use clearSchedule() to remove all
clearSchedule ()
// Then re-add only the ones you want
schedule ( "Keep this one" , "0 * * * *" )
clearSchedule() removes ALL scheduled tasks. There’s no way to selectively remove individual tasks in the current ClawScript API.
Scheduler Behavior
How the Scheduler Works
From the PhoneClaw source code:
Cron Checker runs continuously in a coroutine
Checks every minute if any tasks are due
Compares current time against cron expressions
Executes matching tasks
Updates lastExecuted timestamp
Schedules next check
Execution Guarantees
Tasks run within 1 minute of scheduled time
If the device is asleep, tasks run when it wakes
Missed tasks don’t run retroactively
Only one instance of a task runs at a time
Battery Considerations
Frequent scheduled tasks can drain battery. Use reasonable intervals:
Every 5+ minutes is generally safe
Every 1-2 minutes may impact battery life
Every few seconds is not recommended for production
Debugging Scheduled Tasks
Test Your Cron Expression
Before scheduling, verify your cron works:
// Set to run in 2 minutes from now
schedule ( "Test task" , "*/2 * * * *" )
speakText ( "Test scheduled for 2 minutes" )
// Watch the Scheduled Tasks tab to verify it executes
Add Logging
Include speech feedback to confirm execution:
const myTask = () => {
const now = new Date (). toLocaleTimeString ()
speakText ( "Task running at " + now )
// Your automation logic
speakText ( "Task completed" )
}
schedule ( "myTask" , "*/15 * * * *" )
Check Last Execution
View the Scheduled Tasks tab to see:
When the task last ran
If it’s running on schedule
Any execution errors
Best Practices
Use Reasonable Intervals
❌ Too Frequent
✅ Reasonable
schedule ( "Check" , "* * * * *" ) // Every minute
Add Error Handling
const robustTask = () => {
try {
speakText ( "Task starting" )
magicClicker ( "Some button" )
delay ( 2000 )
const result = magicScraper ( "Did it work?" )
if ( result . includes ( "success" )) {
speakText ( "Task succeeded" )
} else {
speakText ( "Task may have failed" )
}
} catch ( error ) {
speakText ( "Error in scheduled task" )
}
}
schedule ( "robustTask" , "0 * * * *" )
Clear Old Schedules
Before creating new schedules, clear old ones:
// Remove all previous schedules
clearSchedule ()
// Add new schedules
schedule ( "newTask1" , "0 9 * * *" )
schedule ( "newTask2" , "0 18 * * *" )
Use Descriptive Names
schedule ( "task1" , "0 * * * *" )
Troubleshooting
Task Not Running
Verify cron expression at crontab.guru
Check device isn’t in aggressive battery saving mode
Ensure PhoneClaw accessibility service is enabled
Check Scheduled Tasks tab for error messages
Task Runs at Wrong Time
Verify device time zone is correct
Cron uses 24-hour format (0-23 for hours)
Day of week: 0 and 7 both mean Sunday
Check if you meant AM vs PM
Multiple Tasks Conflict
Stagger schedules by a few minutes
Don’t schedule two tasks at exact same time
Add delays between app switches
Battery Drain
Reduce task frequency
Combine multiple checks into one task
Schedule during specific hours only
Use */15 instead of */5 for intervals
Next Steps
Multi-App Workflows Chain scheduled tasks across apps
ClawScript Functions See all available automation functions
Voice Commands Generate schedules with voice