Scheduled Tasks
Scheduled tasks let you run automation actions — commands, snippets, or workflows — on a recurring schedule without manual intervention. On Android, this is powered by WorkManager, which ensures tasks execute even if the app is not running in the foreground.
Platform Availability
Section titled “Platform Availability”| Platform | Status |
|---|---|
| Android | Fully supported via WorkManager |
| iOS | Not available. Use iOS Shortcuts Automations instead (time-based triggers in the Shortcuts app) |
| Desktop | Not available. Use your OS task scheduler (cron, Task Scheduler) to invoke zestssh:// URLs or the CLI |
Scheduled tasks are an Android-only feature because WorkManager is an Android-specific API. The TaskSchedulerService checks Platform.isAndroid and silently no-ops on other platforms.
Schedule Types
Section titled “Schedule Types”Recurring (Periodic)
Section titled “Recurring (Periodic)”Run a task at a regular interval. WorkManager enforces a minimum interval of 15 minutes — you cannot schedule tasks more frequently than this (it is an Android system constraint).
Common intervals:
- Every 15 minutes (minimum).
- Every hour (60 minutes).
- Every 6 hours (360 minutes).
- Daily (1440 minutes).
An optional initial delay lets you offset the first execution (e.g., schedule an hourly task but wait 30 minutes before the first run).
One-Shot (Delayed)
Section titled “One-Shot (Delayed)”Run a task once after a specified delay in minutes. The task executes once and does not repeat. Useful for scheduling a one-time operation like a delayed deployment or a timed check.
Creating a Scheduled Task
Section titled “Creating a Scheduled Task”- Navigate to Settings > Automation > Scheduled Tasks.
- Tap New Task.
- Configure the task:
- Action: choose Execute, Snippet, or Workflow.
- Connection: select the target connection (not needed for workflows).
- Command/Snippet/Workflow: specify what to run.
- API Key: select which key to use for authentication.
- Schedule: choose interval (recurring) or delay (one-shot).
- Save the task.
API Key Reference
Section titled “API Key Reference”When a scheduled task is created, ZestSSH stores the API key’s ID (UUID) in the WorkManager task data — not the raw key string. This is a security measure: WorkManager persists task data in an internal SQLite database, and storing the raw key there would expose it in plain text on disk.
At execution time, the WorkManager worker passes the key ID to the Flutter automation handler via the api_key_id field. The handler looks up the matching key from FlutterSecureStorage and uses it for validation:
- WorkManager fires the scheduled task.
- The worker sends an intent with
api_key_id=UUIDto the Flutter layer. - The automation handler finds the key with that UUID in the in-memory key list.
- The actual key value is passed to
validateAndMarkUsed()for normal validation (including rate limiting and expiration checks).
If the referenced key has been revoked (deleted) since the task was scheduled, the task will fail with an “invalid or missing API key” error. If the key has expired, it will also fail and count toward the rate limit.
Task Management
Section titled “Task Management”Viewing Tasks
Section titled “Viewing Tasks”The Scheduled Tasks screen lists all tasks with their:
- Task ID and action type.
- Current state (enqueued, running, succeeded, failed).
- Run attempt count.
This information comes from WorkManager’s getScheduledTasks() query.
Cancelling Tasks
Section titled “Cancelling Tasks”Tap a task to cancel it. You can cancel individual tasks by ID or cancel all scheduled tasks at once. Cancelled tasks are removed from WorkManager’s queue.
How WorkManager Executes Tasks
Section titled “How WorkManager Executes Tasks”The Flutter side communicates with native Android code through a MethodChannel (com.affluentlabs.zestssh/scheduler). The native Android code:
- Receives task parameters via
scheduleTaskorscheduleOneShotmethod calls. - Creates a WorkManager
PeriodicWorkRequestorOneTimeWorkRequestwith the specified interval/delay and task data. - When the task fires, the worker sends an automation intent to the Flutter engine with the stored action, connection ID, command, and API key ID.
- The Flutter automation handler processes the intent through the normal automation pipeline (Pro check, enabled check, key validation, execution).
Parameters
Section titled “Parameters”Each scheduled task stores these parameters:
| Parameter | Description |
|---|---|
taskId | Unique identifier for the scheduled task |
action | execute, snippet, or workflow |
connectionId | Target connection label or UUID |
command | Shell command (for execute action) |
apiKeyId | UUID of the API key (not the raw key) |
intervalMinutes | Repeat interval (recurring) or n/a (one-shot) |
initialDelayMinutes | Delay before first execution (recurring) |
delayMinutes | Delay before execution (one-shot) |
snippetName | Snippet label (for snippet action) |
workflowId | Workflow UUID (for workflow action) |
workflowName | Workflow name (for workflow action) |
Limitations
Section titled “Limitations”- 15-minute minimum interval: Android WorkManager does not support intervals shorter than 15 minutes. For more frequent checks, consider using Tasker with ZestSSH intents or a server-side cron job.
- Execution timing is approximate: WorkManager batches work to optimize battery. Tasks may fire slightly after the scheduled time, especially in Doze mode or battery-saver mode.
- No chaining: each scheduled task is independent. For multi-step sequences, schedule a workflow rather than individual commands.
- App must be installed: if ZestSSH is uninstalled or force-stopped, scheduled tasks will not fire. WorkManager respects app lifecycle.
- Results are logged: scheduled task results appear in the automation history log, but there is no push notification by default (workflows can have their own notification settings).
Best Practices
Section titled “Best Practices”- Use recurring tasks for regular health checks, log rotation triggers, or certificate expiry monitoring.
- Use one-shot tasks for delayed operations like “deploy in 2 hours” or “restart at 3 AM tonight”.
- Choose a dedicated API key for scheduled tasks with a descriptive label (e.g., “Scheduled Tasks”). This makes it easy to audit usage and revoke if needed.
- Monitor the automation history to verify tasks are running as expected.
- If a task’s API key expires, the task will fail silently. Set a calendar reminder to rotate keys before they expire.