@jl1990/pi-scheduler

Give Pi coding agents a clock: schedule reminders, shell commands, and self-waking prompts for CI polling and autonomous follow-ups.

Packages

Package details

extension

Install @jl1990/pi-scheduler from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@jl1990/pi-scheduler
Package
@jl1990/pi-scheduler
Version
0.5.0
Published
Sep 13, 2026
Downloads
966/mo · 461/wk
Author
jl1990
License
MIT
Types
extension
Size
350.5 KB
Dependencies
2 dependencies · 4 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions/scheduler/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Pi Scheduler

Run checks on a schedule. Wake the agent when there’s something to do.

Schedule shell commands, agent prompts, and reminders inside Pi. Commands run directly and bring their output back to the agent when your wake policy matches.

“Run the tests every five minutes. Wake yourself if they fail. Stop after ten runs.”

Why this package?

Pi Scheduler focuses on scheduled actions: run a command, capture stdout/stderr, and trigger a follow-up on success or failure. Execution limits, persistent tasks, and atomic claims let multiple Pi processes share scheduled work.

Prompt loops suit checks that need agent judgment every time. Broader packages such as pi-loop also provide workflows, event triggers, orchestration, and command monitoring. Choose Pi Scheduler when you want a focused scheduler for commands, prompts, and reminders.

Pi must be running for tasks to fire. Tasks persist across restarts, but this package does not run an always-on daemon.

Get started

pi install npm:@jl1990/pi-scheduler

Restart Pi or run /reload. Ask for a scheduled task in plain language, or try:

/remind 20m take a break
/schedule prompt 5m :: Check whether the deployment has finished.
/schedules

A compact widget shows upcoming tasks below the editor.

Example: run tests, investigate failures

Ask Pi to schedule this, or use these arguments with its schedule_task tool:

{
  "action": "shell",
  "type": "interval",
  "schedule": "5m",
  "command": "npm test",
  "timeoutMs": 120000,
  "wakeOn": "failure",
  "failurePrompt": "Review the test output, diagnose the failure, and report the cause.",
  "maxRuns": 10,
  "scope": "cwd"
}

Use a test command that finishes rather than entering watch mode. Every five minutes, the scheduler runs it and captures the result:

  • Pass: no agent turn. Pi may still show execution notifications and result messages.
  • Non-zero exit or timeout: wake the agent with stdout/stderr to investigate.
  • Ten executions: disable the task automatically.

For recurring shell tasks, stopOn may be success, failure, or never (the default). It disables recurrence after the matching result; non-zero exits, timeouts, and killed commands count as failures. stopOn is independent of wakeOn.

Recurring tasks do not stop when an external goal completes unless configured with stopOn. Cancel them when finished, or bound them with maxRuns.

Use expiresIn: "2h" to stop starting new runs after two hours. The absolute deadline persists across restarts. Expiry is silent and visible as expired in task history; an already-running command finishes with its usual wake policy. Renew an expired task with a new expiresIn, or set it to null in manage_scheduled_task to clear the deadline and resume it.

Scheduling options

Option Choices
Action shell runs a command; prompt wakes the agent; notify shows a reminder; message adds a custom message
Schedule once: 5m, tomorrow at 9am, ISO datetime; interval: 30s, 5m, 1h; cron: 0 0 9 * * 1-5 (weekdays at 9am)
Scope session (default): creating session; cwd: sessions in the same project directory; global: any session
Limits maxRuns caps executions; timeoutMs bounds each shell command; expiresIn sets a positive lifetime (for example 2h)
stopOn For shell actions, stop recurrence after success, failure, or never (default)
backoff Interval-only { "factor": 2, "maxInterval": "15m" } grows the delay after each execution, up to the cap

Backoff applies to every outcome and persists across restarts. Updating the schedule or backoff, or explicitly enabling a task, resets the delay to the base interval. Set backoff: null to return to a fixed interval; remove it explicitly when switching to cron or once. Execution limits still count runs normally.

Cron uses croner; six-field expressions with seconds are recommended. Use session scope when a follow-up must return to a specific session. For shared scopes, the process that claims the task receives the follow-up.

Shell wake policy

wakeOn Wake the agent when…
failure The command exits non-zero or is killed/times out
success The command exits 0 without being killed
always Any run finishes
never Never; just record the result
change After the first run, when stdout, stderr, exit status, or killed/timeout state changes

Use successPrompt or failurePrompt for outcome-specific instructions, or followUpPrompt for either outcome. The wake policy is checked first. Without an explicit policy, supplying a prompt defaults to always; otherwise the default is never. An explicit matching policy without a custom prompt uses a default review instruction.

change stores a SHA-256 fingerprint of the complete (untruncated) shell result in task state. The first run establishes the baseline without waking; repeated identical results stay quiet. Editing the command, working directory, or opting into change starts a new baseline. If that first run matches stopOn, the task stops silently; use success or failure when the stopping result must wake the agent.

Exit status matters. A command that prints a failed CI pipeline may still exit 0. For CI polling, use a command or wrapper that maps pipeline states to the intended exit status; pending is not automatically a separate state.

Manage tasks

Ask Pi to list, update, disable, or remove tasks. Its tools are schedule_task, list_scheduled_tasks, cancel_scheduled_task, and manage_scheduled_task.

Completed runs keep a compact history of the latest 10 attempts (timestamps, duration, outcome, and wake disposition). Use list_scheduled_tasks with includeHistory: true (and optionally id) to inspect it; the default listing remains compact. delivered means a wake was submitted to Pi, not that an agent turn finished; pending means delivery was not yet recorded.

/schedules                       # active tasks
/schedules all                   # include inactive tasks
/schedules history               # show compact run history
/schedule-cancel <id-or-prefix>
/schedule-enable <id-or-prefix>
/schedule-disable <id-or-prefix>
/schedule-remove <id-or-prefix>
/schedule-cleanup
/schedule-widget [on|off]

To create tasks directly:

/schedule [notify|prompt|shell|message] [once|interval|cron|every] <schedule> :: <payload>

Persistence and recovery

Tasks live in ~/.pi/agent/state/scheduler/tasks.json. Atomic state transactions and task claims coordinate execution across Pi processes; shared state refreshes every five seconds.

On restart, overdue one-shot and interval tasks run. Cron catches up the most recent missed occurrence per task, newest first, within these limits:

Environment variable Default
PI_SCHEDULER_CATCHUP_WINDOW_H 24 hours
PI_SCHEDULER_CATCHUP_MAX 5 tasks per startup; 0 disables cron catch-up

Interrupted executions are recorded as failed: one-shot tasks remain failed, while recurring tasks are rescheduled. Shell commands run with your local user permissions.

Development

npm test
npm pack --dry-run
PI_OFFLINE=1 pi --no-extensions -e ./extensions/scheduler/index.ts --list-models __unlikely_model_filter__

Published GitHub Releases trigger the npm publishing workflow, which tests, checks package contents, and publishes with provenance.

MIT license