picoclaw

Scheduled Tasks and Cron Jobs

Back to README

PicoClaw stores scheduled jobs in the current workspace and can run them either as reminders, full agent turns, or shell commands.

Schedule Types

PicoClaw currently uses three schedule forms in the cron tool:

The CLI command picoclaw cron add currently supports recurring jobs only:

There is no CLI flag for a one-time at job today.

Examples:

picoclaw cron add --name "Daily summary" --message "Summarize today's logs" --cron "0 18 * * *"
picoclaw cron add --name "Ping" --message "heartbeat" --every 300

Agent Tool Actions

The agent-facing cron tool supports these actions:

When rescheduling an existing task, use list -> get -> update. Do not use remove -> add just to change the schedule, because recreating a job can drop the original prompt, delivery target, or command payload.

Remote channel access is scoped to the current channel/chat_id: remote callers can only list, get, or update jobs whose saved payload.channel and payload.to match the current conversation. Command jobs include a shell command payload, so they can only be listed, inspected, or updated from internal channels or remote channels allowed by tools.cron.command_allowed_remotes.

Example tool calls:

{"action":"get","job_id":"79095b2f5685a0f2"}
{"action":"update","job_id":"79095b2f5685a0f2","cron_expr":"30 10 * * *"}

update accepts name, message, command, and exactly one schedule field (at_seconds, every_seconds, or cron_expr). Omit command to preserve it, set command to a non-empty string to replace it, or set command to "" to clear it. Setting or replacing a command requires the same channel allowlist and confirmation gates as command creation; clearing it does not.

Execution Modes

Jobs are stored with a message payload. When a job fires, PicoClaw picks one of two execution paths based on the payload.

command

When a cron-tool job includes command, PicoClaw runs that shell command through the exec tool and publishes the command output directly to the job’s channel and recipient. The saved message becomes descriptive text only; the scheduled action is the shell command. Command jobs do not go through the agent.

The current CLI picoclaw cron add command does not expose a command flag.

Agent turn

Without a command, PicoClaw sends the saved message through the agent loop as a new agent turn. Use this for scheduled work that may need reasoning, tools, or a generated reply. This is the default for the cron tool.

A turn started by a cron job receives a tool registry without cron, so the agent cannot call it to manage jobs. This also applies to subagents spawned by that turn.

Config and Security Gates

tools.cron

tools.cron.enabled controls whether the agent-facing cron tool is registered. Default: true.

If you disable tools.cron, users can no longer create or manage jobs through the agent tool. The gateway still starts CronService, but it does not install the job execution callback. As a result, due jobs do not actually run; one-time jobs may be deleted and recurring jobs may be rescheduled without executing their payload. Jobs that fire without a callback are recorded with state.lastStatus: "skipped". The CLI still uses the same job store.

tools.cron.exec_timeout_minutes sets the timeout used for scheduled command execution. Default: 5. Set 0 for no timeout.

tools.exec

Scheduled command jobs depend on tools.exec.enabled. Default: true.

If tools.exec.enabled is false:

tools.exec.allow_remote is still enforced by the exec tool, but cron command scheduling has its own channel gate when the job is created. In practice, reminder jobs can be scheduled from remote channels, while scheduled command jobs are limited to internal channels and configured remote channels.

allow_command

tools.cron.allow_command defaults to true.

This is not a hard disable switch. If you set allow_command to false, PicoClaw still allows a command job when the caller explicitly passes command_confirm: true.

Command jobs also require either an internal channel or a remote channel allowed by tools.cron.command_allowed_remotes. Non-command reminders do not have that restriction.

command_allowed_remotes

tools.cron.command_allowed_remotes defaults to an empty list. With the default empty list, remote channels cannot schedule command jobs.

Entries can be either a channel name or a channel plus chat id:

Warning: * is potentially dangerous because any remote channel that can talk to PicoClaw can schedule shell commands. Use it only when every enabled remote channel and chat is trusted to request command execution.

This setting only controls the remote-channel gate. It does not bypass tools.cron.allow_command, command_confirm, tools.exec.enabled, or the exec tool’s command safety checks.

Example:

{
  "tools": {
    "cron": {
      "enabled": true,
      "exec_timeout_minutes": 5,
      "allow_command": true,
      "command_allowed_remotes": [
        "telegram:1234567890"
      ]
    },
    "exec": {
      "enabled": true
    }
  }
}

Persistence and Location

Cron jobs are stored in:

<workspace>/cron/jobs.json

By default, the workspace is:

~/.picoclaw/workspace

If PICOCLAW_HOME is set, the default workspace becomes:

$PICOCLAW_HOME/workspace

Both the gateway and picoclaw cron CLI subcommands use the same cron/jobs.json file.

Notes: