@jl1990/pi-scheduler
Give Pi coding agents a clock: schedule reminders, shell commands, and self-waking prompts for CI polling and autonomous follow-ups.
Package details
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.