Scheduled prompts
The schedule tool (and /schedule command) fires a prompt at the agent on a timer, exactly as if the user typed it. A
fired prompt re-enters the session as a synthetic user turn, so you act on it like real input. Use it when a session
should do something on a cadence, at a future moment, or during idle gaps - without the user nudging each time. This
skill is the policy for when scheduling is worth it and which trigger fits.
When to use this skill
Schedule a prompt when the session should act on its own:
- Recurring cadence - "summarize what changed every 30 minutes", a 9am morning report. Use
interval (--every)
for a fixed gap from creation, or cron (--cron) for wall-clock times.
- A future one-shot - "remind me to stretch in 10 minutes", "at 17:00 wrap up". Use
once (--in <dur> for a
delay, --at <HH:MM> for the next clock time).
- Keeping a scene alive - a roleplay character that should speak during silence. Use
after (--after <min-max>),
the activity-anchored idle nudge.
Do NOT schedule when:
- The user is asking for something now. Just do it this turn. A schedule is for later or repeated action, not a
detour for the current request.
- A human reminder is better. If the user themselves should be pinged outside pi, say so - the schedule fires the
agent, not a notification to the person away from the terminal.
- You would persist without being asked. Both the tool and
/schedule default to session scope (dies with the
session). Only pass --scope global / --scope project when the user wants it to outlive this session - a stray
global schedule fires in every future session.
Pick the trigger
Exactly one trigger per schedule:
| Need |
Trigger |
Flag |
Notes |
| Fixed cadence from now |
interval |
--every 30m |
Anchored on creation. |
| Wall-clock times (daily, hourly) |
cron |
--cron "0 9 * * *" |
5-field, local time, numeric. Quote the expression. |
| Once after a delay |
once |
--in 10m |
Fires once, then retires. |
| Once at the next clock time |
once |
--at 17:00 |
Next local HH:MM. |
| Fill idle silence (roleplay) |
after |
--after 30s-5m |
Random gap after last activity; idle-only; backs off. |
Workflow
- Confirm a timer is the right tool. Re-check the ask-now test above. If the action is for now, skip scheduling.
- Choose the trigger from the table. Recurring vs one-shot vs idle is the core decision.
- Choose the scope deliberately. Default
session unless the user wants persistence. project writes
<cwd>/.pi/scheduled-prompts.json; global writes ~/.pi/agent/scheduled-prompts.json.
- Bound unattended schedules. Add
--max-runs N so a recurring or idle schedule cannot fire forever. Add
--chance <0..1> for organic unpredictability and --jitter <dur> so multiple sessions sharing a persisted file do
not stampede.
- Tune idle nudges (
after). It resets when the user speaks, re-anchors after each agent reply, and widens the gap
(x2 per unanswered fire, capped x8) during silence. Give it a prompt pool (-- look around | hum a tune) so the
nudge varies; use ${t} (elapsed since anchor) / ${d} (current time) for context-aware prompts.
- Manage existing schedules. The tool supports
create / list / update / delete. The user-facing
/schedules lists them; /schedules on|off <id> toggles without deleting; /schedules cancel <id> removes one;
/schedules clear [scope] clears a scope.
Recurring vs one-shot vs idle
- Recurring (
interval / cron) keeps firing on a schedule until cancelled or --max-runs retires it. Reach for
it for periodic reports and cadence pings. Prefer cron when the time of day matters, interval when only the gap
matters.
- One-shot (
once) fires exactly once and removes itself. Reach for it for reminders and "do X later". A one-shot
whose time passed while pi was closed still fires on the next start; a missed recurring fire is skipped, not fired
late.
- Idle (
after) is special: it fires only while the agent is idle, re-anchors to conversation activity, and backs
off during silence. It is built for keeping a roleplay scene alive, not for precise timing.
Common pitfalls
- Persisting by accident. Forgetting scope leaves it
session, which is usually right - but a deliberate
--scope global that the user did not ask for pollutes every future session. Confirm intent before persisting.
- Unbounded idle nudges. An
after schedule with no --max-runs keeps nudging an unattended session forever. Bound
it.
- Using a schedule for a now-action. If the next thing is for this turn, do it inline.
- Two pi instances, one file. Each process arms its own timer, so a shared
global / project schedule can fire in
both. Documented limitation - account for it before relying on exactly-once persisted fires.
Related docs
scheduled-prompts.md - full reference: triggers, options, prompt variables,
scopes, scheduler internals.
notes-decision-tree - durable cross-session facts belong in memory, not a
recurring self-reminder.
1---2name: scheduled-prompts3description: WHAT: Decide when to fire a prompt at yourself on a timer with the `schedule` tool, and which trigger to pick - recurring (cron / interval), one-shot (in / at), or activity-anchored idle (after). WHEN: A session should act without a manual nudge - a cadence ping, a future reminder, or a roleplay character that keeps a scene alive. DO-NOT: Schedule something the user could just ask for now, or persist a schedule the user did not ask to outlive the session.4---56# Scheduled prompts78The `schedule` tool (and `/schedule` command) fires a prompt at the agent on a timer, exactly as if the user typed it. A9fired prompt re-enters the session as a synthetic user turn, so you act on it like real input. Use it when a session10should do something on a cadence, at a future moment, or during idle gaps - without the user nudging each time. This11skill is the policy for when scheduling is worth it and which trigger fits.1213## When to use this skill1415Schedule a prompt when the session should act on its own:1617- **Recurring cadence** - "summarize what changed every 30 minutes", a 9am morning report. Use `interval` (`--every`)18 for a fixed gap from creation, or `cron` (`--cron`) for wall-clock times.19- **A future one-shot** - "remind me to stretch in 10 minutes", "at 17:00 wrap up". Use `once` (`--in <dur>` for a20 delay, `--at <HH:MM>` for the next clock time).21- **Keeping a scene alive** - a roleplay character that should speak during silence. Use `after` (`--after <min-max>`),22 the activity-anchored idle nudge.2324Do NOT schedule when:2526- **The user is asking for something now.** Just do it this turn. A schedule is for later or repeated action, not a27 detour for the current request.28- **A human reminder is better.** If the user themselves should be pinged outside pi, say so - the schedule fires the29 _agent_, not a notification to the person away from the terminal.30- **You would persist without being asked.** Both the tool and `/schedule` default to `session` scope (dies with the31 session). Only pass `--scope global` / `--scope project` when the user wants it to outlive this session - a stray32 global schedule fires in _every_ future session.3334## Pick the trigger3536Exactly one trigger per schedule:3738| Need | Trigger | Flag | Notes |39| -------------------------------- | ---------- | -------------------- | ----------------------------------------------------- |40| Fixed cadence from now | `interval` | `--every 30m` | Anchored on creation. |41| Wall-clock times (daily, hourly) | `cron` | `--cron "0 9 * * *"` | 5-field, local time, numeric. Quote the expression. |42| Once after a delay | `once` | `--in 10m` | Fires once, then retires. |43| Once at the next clock time | `once` | `--at 17:00` | Next local `HH:MM`. |44| Fill idle silence (roleplay) | `after` | `--after 30s-5m` | Random gap after last activity; idle-only; backs off. |4546## Workflow47481. **Confirm a timer is the right tool.** Re-check the ask-now test above. If the action is for _now_, skip scheduling.492. **Choose the trigger** from the table. Recurring vs one-shot vs idle is the core decision.503. **Choose the scope deliberately.** Default `session` unless the user wants persistence. `project` writes51 `<cwd>/.pi/scheduled-prompts.json`; `global` writes `~/.pi/agent/scheduled-prompts.json`.524. **Bound unattended schedules.** Add `--max-runs N` so a recurring or idle schedule cannot fire forever. Add53 `--chance <0..1>` for organic unpredictability and `--jitter <dur>` so multiple sessions sharing a persisted file do54 not stampede.555. **Tune idle nudges (`after`).** It resets when the user speaks, re-anchors after each agent reply, and widens the gap56 (x2 per unanswered fire, capped x8) during silence. Give it a prompt pool (`-- look around | hum a tune`) so the57 nudge varies; use `${t}` (elapsed since anchor) / `${d}` (current time) for context-aware prompts.586. **Manage existing schedules.** The tool supports `create` / `list` / `update` / `delete`. The user-facing59 `/schedules` lists them; `/schedules on|off <id>` toggles without deleting; `/schedules cancel <id>` removes one;60 `/schedules clear [scope]` clears a scope.6162## Recurring vs one-shot vs idle6364- **Recurring (`interval` / `cron`)** keeps firing on a schedule until cancelled or `--max-runs` retires it. Reach for65 it for periodic reports and cadence pings. Prefer `cron` when the time of day matters, `interval` when only the gap66 matters.67- **One-shot (`once`)** fires exactly once and removes itself. Reach for it for reminders and "do X later". A one-shot68 whose time passed while pi was closed still fires on the next start; a missed _recurring_ fire is skipped, not fired69 late.70- **Idle (`after`)** is special: it fires only while the agent is idle, re-anchors to conversation activity, and backs71 off during silence. It is built for keeping a roleplay scene alive, not for precise timing.7273## Common pitfalls7475- **Persisting by accident.** Forgetting scope leaves it `session`, which is usually right - but a deliberate76 `--scope global` that the user did not ask for pollutes every future session. Confirm intent before persisting.77- **Unbounded idle nudges.** An `after` schedule with no `--max-runs` keeps nudging an unattended session forever. Bound78 it.79- **Using a schedule for a now-action.** If the next thing is for this turn, do it inline.80- **Two pi instances, one file.** Each process arms its own timer, so a shared `global` / `project` schedule can fire in81 both. Documented limitation - account for it before relying on exactly-once persisted fires.8283## Related docs8485- [`scheduled-prompts.md`](../../extensions/scheduled-prompts.md) - full reference: triggers, options, prompt variables,86 scopes, scheduler internals.87- [`notes-decision-tree`](../notes-decision-tree/SKILL.md) - durable cross-session facts belong in `memory`, not a88 recurring self-reminder.