---
title: "@henryqw/pi-cron"
seo:
  description: "Run scheduled job prompts in new Pi sessions with per-job interval, Role, model, and thinking level."
---

<div class="not-prose my-6 flex flex-wrap items-center gap-3"><a href="https://www.npmjs.com/package/@henryqw/pi-cron" aria-label="View @henryqw/pi-cron version v0.5.6 on npm"><img alt="Version v0.5.6" height="20" src="https://img.shields.io/static/v1?cacheSeconds=7200&amp;color=1d4ed8&amp;label=version&amp;labelColor=6a7282&amp;style=flat-square&amp;message=v0.5.6" width="96"></a><div class="ml-auto flex flex-wrap items-center justify-end gap-3"><a href="https://www.npmjs.com/package/@henryqw/pi-cron" aria-label="View @henryqw/pi-cron on npm"><img alt="Monthly npm downloads" height="20" src="https://img.shields.io/npm/dm/%40henryqw%2Fpi-cron?cacheSeconds=7200&amp;color=1d4ed8&amp;label=downloads&amp;labelColor=6a7282&amp;style=flat-square" width="144"></a><a href="https://github.com/HenryQW/pi-harness/blob/main/extensions/pi-cron/LICENSE" aria-label="View the MIT license for @henryqw/pi-cron"><img alt="MIT license" height="20" src="https://img.shields.io/npm/l/%40henryqw%2Fpi-cron?cacheSeconds=7200&amp;color=1d4ed8&amp;label=license&amp;labelColor=6a7282&amp;style=flat-square" width="78"></a></div></div>

Run scheduled prompts in fresh Pi sessions while any Pi session with this extension is open. Each job selects its Role, model, and thinking level. Open saved run sessions to inspect results.

## Install

```bash
pi install npm:@henryqw/pi-task-models
pi install npm:@henryqw/pi-subagent
pi install npm:@henryqw/pi-cron
```

Configure the job profiles in `/task-models`. Add a job to the config file below. Run `/cron` to check its next slot.

## Works with

| Package | Relationship | Purpose |
| --- | --- | --- |
| [`@henryqw/pi-subagent`](https://pi.henry.wang/extensions/pi-subagent) | Required | Provides Roles and runs each job with bounded limits. |
| [`@henryqw/pi-task-models`](https://pi.henry.wang/extensions/pi-task-models) | Required | Resolves `modelClass` and explicit model routes. |

## Use

Keep Pi open for the job's next slot, or use `/cron run <job-id>` for an immediate run.

| Surface | Type | Purpose |
| --- | --- | --- |
| `/cron` | command | For users: list jobs, next runs, and last outcomes. In the TUI, run, enable, disable, or show the last result. Otherwise, only list jobs. |
| `/cron run <job-id>` | command | For users: start a job immediately, with the same delivery as scheduled runs. |

Each job runs its prompt as one task in a new Pi process at `cwd`. As with `delegate_task`, its Role selects tools, extensions, Skills, and MCP servers. Any configured Role can run, including one with write access. Limit the prompt and Role tools to the task's needs.

The run inherits the current session environment plus `env`. Open its saved run session with `pi --session <file>`.

## Flow

![An open Pi session runs due jobs with limits and delivers their results.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgwIiBoZWlnaHQ9IjcyMCIgdmlld0JveD0iMCAwIDEyODAgNzIwIiByb2xlPSJpbWciIGFyaWEtbGFiZWxsZWRieT0iY3Jvbi1mbG93LXRpdGxlIGNyb24tZmxvdy1kZXNjIiBpZD0iY3Jvbi1mbG93LXJvb3QiPgo8dGl0bGUgaWQ9ImNyb24tZmxvdy10aXRsZSI+UGkgQ3JvbiBzY2hlZHVsZXIgZmxvdzwvdGl0bGU+CjxkZXNjIGlkPSJjcm9uLWZsb3ctZGVzYyI+QW4gb3BlbiBQaSBzZXNzaW9uIHJlYWRzIGpvYiBjb25maWcsIGNsYWltcyBhIGR1ZSBqb2IgaW4gc2hhcmVkIHN0YXRlLCBsYXVuY2hlcyBhIGJvdW5kZWQgY2hpbGQsIGFuZCByZWNvcmRzIGl0cyBvdXRjb21lIHdpdGggYW4gb3B0aW9uYWwgcGVyc2lzdGVkIHNlc3Npb24gYmVmb3JlIGRlbGl2ZXJpbmcgdGhlIHJlc3VsdC48L2Rlc2M+CjxkZWZzPgogICAgICA8c3R5bGU+QGltcG9ydCB1cmwoJ2h0dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzMj9mYW1pbHk9SW5zdHJ1bWVudCtTZXJpZjppdGFsQDA7MSZhbXA7ZmFtaWx5PUdlaXN0OndnaHRANDAwOzUwMDs2MDAmYW1wO2ZhbWlseT1HZWlzdCtNb25vOndnaHRANDAwOzUwMDs2MDAmYW1wO2ZhbWlseT1Ob3RvK1NlcmlmOml0YWxAMDsxJmFtcDtmYW1pbHk9Tm90bytTYW5zK0tSOndnaHRANDAwOzUwMDs2MDAmYW1wO2ZhbWlseT1Ob3RvK1NlcmlmK0tSOndnaHRANDAwJmFtcDtmYW1pbHk9Tm90bytTYW5zK1RDOndnaHRANDAwOzUwMDs2MDAmYW1wO2ZhbWlseT1Ob3RvK1NlcmlmK1RDOndnaHRANDAwJmFtcDtkaXNwbGF5PXN3YXAnKTsKICAgICAgI2Nyb24tZmxvdy1yb290IHsgY29sb3I6ICMxMDE4Mjg7IH0KICAgICAgI2Nyb24tZmxvdy1yb290IC5kaWFncmFtLWNvbnRhaW5lciB7IG92ZXJmbG93LXg6IGF1dG87IH08L3N0eWxlPgo8bWFya2VyIGlkPSJjcm9uLWZsb3ctYXJyb3ciIHZpZXdCb3g9IjAgMCA4IDgiIHJlZlg9IjciIHJlZlk9IjQiIG1hcmtlcldpZHRoPSI4IiBtYXJrZXJIZWlnaHQ9IjgiIG9yaWVudD0iYXV0byI+PHBhdGggZD0iTTAgMCBMOCA0IEwwIDhaIiBmaWxsPSIjNGM1NjY1Ii8+PC9tYXJrZXI+CjxtYXJrZXIgaWQ9ImNyb24tZmxvdy1hcnJvdy1ibHVlIiB2aWV3Qm94PSIwIDAgOCA4IiByZWZYPSI3IiByZWZZPSI0IiBtYXJrZXJXaWR0aD0iOCIgbWFya2VySGVpZ2h0PSI4IiBvcmllbnQ9ImF1dG8iPjxwYXRoIGQ9Ik0wIDAgTDggNCBMMCA4WiIgZmlsbD0iIzFkNGVkOCIvPjwvbWFya2VyPgo8L2RlZnM+CjxyZWN0IHdpZHRoPSIxMjgwIiBoZWlnaHQ9IjcyMCIgZmlsbD0iI2YwZWVlOSIvPgo8dGV4dCB4PSI0MCIgeT0iNTIiIGZvbnQtZmFtaWx5PSJJbnN0cnVtZW50IFNlcmlmLCBzZXJpZiIgZm9udC1zaXplPSIyOCIgZmlsbD0iIzEwMTgyOCI+U2NoZWR1bGVkIHdvcmssIG9uZSBib3VuZGVkIHJ1biBhdCBhIHRpbWU8L3RleHQ+CjwhLS0gQ29ubmVjdGlvbnMgcHJlY2VkZSBub2Rlcy4gRWFjaCBwYXRoIGhhcyBpdHMgb3duIGF0dGFjaG1lbnQgcG9pbnQuIC0tPgo8ZyBmaWxsPSJub25lIiBzdHJva2U9IiM0YzU2NjUiIHN0cm9rZS13aWR0aD0iMS4yIiBtYXJrZXItZW5kPSJ1cmwoI2Nyb24tZmxvdy1hcnJvdykiPgo8cGF0aCBkPSJNMjAwIDE5MiBWMjcyIi8+CjxwYXRoIGQ9Ik0zMjAgMjkyIEgzOTIgUTQwMCAyOTIgNDAwIDI4NCBWMjQwIFE0MDAgMjMyIDQwOCAyMzIgSDUxMiBRNTIwIDIzMiA1MjAgMjI0IFYyMDAiLz4KPHBhdGggZD0iTTEwMzIgMjcyIFYyNDAgUTEwMzIgMjMyIDEwMjQgMjMyIEg2ODggUTY4MCAyMzIgNjgwIDIyNCBWMjAwIi8+CjxwYXRoIGQ9Ik0xMDMyIDM5MiBWNDY0IiBzdHJva2UtZGFzaGFycmF5PSI1LDQiLz4KPHBhdGggZD0iTTk4NCAzOTIgVjQxNiBROTg0IDQyNCA5NzYgNDI0IEg2MDggUTYwMCA0MjQgNjAwIDQzMiBWNDY0Ii8+CjwvZz4KPHBhdGggZD0iTTMyMCAzMzIgSDkwMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMWQ0ZWQ4IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNjcm9uLWZsb3ctYXJyb3ctYmx1ZSkiLz4KPCEtLSBMYWJlbCBtYXNrcyBzdGF5IGNsZWFyIG9mIHRoZWlyIGNvbm5lY3RvcnMgYW5kIGFsbCBub2RlIHJlY3RhbmdsZXMuIC0tPgo8ZyBmaWxsPSIjZjBlZWU5Ij4KPHJlY3QgeD0iMjA4IiB5PSIyMjQiIHdpZHRoPSI3MiIgaGVpZ2h0PSIxMiIvPgo8cmVjdCB4PSI0MDgiIHk9IjI0OCIgd2lkdGg9IjExMiIgaGVpZ2h0PSIxMiIvPgo8cmVjdCB4PSI3ODAiIHk9IjIxMCIgd2lkdGg9Ijk2IiBoZWlnaHQ9IjEyIi8+CjxyZWN0IHg9IjU0MCIgeT0iMzEyIiB3aWR0aD0iMTEyIiBoZWlnaHQ9IjEyIi8+CjxyZWN0IHg9IjEwNDAiIHk9IjQyNCIgd2lkdGg9IjEwNCIgaGVpZ2h0PSIxMiIvPgo8cmVjdCB4PSI3NjAiIHk9IjQwMiIgd2lkdGg9Ijk2IiBoZWlnaHQ9IjEyIi8+CjwvZz4KPGcgZm9udC1mYW1pbHk9IkdlaXN0IE1vbm8sIG1vbm9zcGFjZSIgZm9udC1zaXplPSI4IiBmaWxsPSIjNGM1NjY1Ij4KPHRleHQgeD0iMjE2IiB5PSIyMzMiPlJFQUQgSk9CUzwvdGV4dD4KPHRleHQgeD0iNDY0IiB5PSIyNTciIHRleHQtYW5jaG9yPSJtaWRkbGUiPkNMQUlNIERVRSBKT0I8L3RleHQ+Cjx0ZXh0IHg9IjgyOCIgeT0iMjE5IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5GSU5JU0ggQ0xBSU08L3RleHQ+Cjx0ZXh0IHg9IjU5NiIgeT0iMzIxIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjMWQ0ZWQ4Ij5ST0xFICsgUFJPTVBUPC90ZXh0Pgo8dGV4dCB4PSIxMDQ4IiB5PSI0MzMiPklGIENSRUFURUQ8L3RleHQ+Cjx0ZXh0IHg9IjgwOCIgeT0iNDExIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5ERUxJVkVSIFJFU1VMVDwvdGV4dD4KPC9nPgo8IS0tIENvbmZpZyBhbmQgc2hhcmVkIGNsYWltIHN0YXRlIGFyZSBzZXBhcmF0ZSBmcm9tIHRoZSBhY3RpdmUgcHJvY2Vzcy4gLS0+CjxyZWN0IHg9IjgwIiB5PSI5NiIgd2lkdGg9IjI0MCIgaGVpZ2h0PSI5NiIgcng9IjgiIGZpbGw9IiNlNmU0ZGUiIHN0cm9rZT0iIzEwMTgyOCIgc3Ryb2tlLW9wYWNpdHk9IjAuMiIvPgo8cmVjdCB4PSI0NjAiIHk9Ijk2IiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjEwNCIgcng9IjgiIGZpbGw9IiNlNmU0ZGUiIHN0cm9rZT0iIzEwMTgyOCIgc3Ryb2tlLW9wYWNpdHk9IjAuMiIvPgo8cmVjdCB4PSI4MCIgeT0iMjcyIiB3aWR0aD0iMjQwIiBoZWlnaHQ9IjEyMCIgcng9IjgiIGZpbGw9IiMxZDRlZDgiIGZpbGwtb3BhY2l0eT0iMC4wOCIgc3Ryb2tlPSIjMWQ0ZWQ4Ii8+CjxyZWN0IHg9IjkwMCIgeT0iMjcyIiB3aWR0aD0iMjg4IiBoZWlnaHQ9IjEyMCIgcng9IjgiIGZpbGw9IiMxZDRlZDgiIGZpbGwtb3BhY2l0eT0iMC4wOCIgc3Ryb2tlPSIjMWQ0ZWQ4Ii8+CjxyZWN0IHg9IjkwMCIgeT0iNDY0IiB3aWR0aD0iMjg4IiBoZWlnaHQ9Ijk2IiByeD0iOCIgZmlsbD0iI2U2ZTRkZSIgc3Ryb2tlPSIjMTAxODI4IiBzdHJva2Utb3BhY2l0eT0iMC4yIi8+CjxyZWN0IHg9IjQ2MCIgeT0iNDY0IiB3aWR0aD0iMjgwIiBoZWlnaHQ9IjEyMCIgcng9IjgiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzEwMTgyOCIgc3Ryb2tlLW9wYWNpdHk9IjAuMiIvPgo8ZyBmb250LWZhbWlseT0iR2Vpc3QsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTIiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiMxMDE4MjgiPgo8dGV4dCB4PSIxMDQiIHk9IjEyOCI+VXNlci1hdXRob3JlZCBqb2JzPC90ZXh0Pgo8dGV4dCB4PSI0ODQiIHk9IjEyOCI+U2hhcmVkIGNsYWltcyBhbmQgb3V0Y29tZXM8L3RleHQ+Cjx0ZXh0IHg9IjEwNCIgeT0iMzA0Ij5PcGVuIFBpIHNlc3Npb248L3RleHQ+Cjx0ZXh0IHg9IjkyNCIgeT0iMzA0Ij5GcmVzaCBib3VuZGVkIGNoaWxkPC90ZXh0Pgo8dGV4dCB4PSI5MjQiIHk9IjQ5NiI+UmVvcGVuYWJsZSBydW4gc2Vzc2lvbjwvdGV4dD4KPHRleHQgeD0iNDg0IiB5PSI0OTYiPlJlc3VsdCBkZWxpdmVyeTwvdGV4dD4KPC9nPgo8ZyBmb250LWZhbWlseT0iR2Vpc3QgTW9ubywgbW9ub3NwYWNlIiBmb250LXNpemU9IjgiIGZpbGw9IiM0YzU2NjUiPgo8dGV4dCB4PSIxMDQiIHk9IjE1MiI+Y29uZmlnL3BpLWNyb24vY29uZmlnLmpzb248L3RleHQ+Cjx0ZXh0IHg9IjEwNCIgeT0iMTcyIj5ldmVyeSAvIGF0IMK3IFJvbGUgwrcgcm91dGUgwrcgY3dkPC90ZXh0Pgo8dGV4dCB4PSI0ODQiIHk9IjE1MiI+Y29uZmlnL3BpLWNyb24vc3RhdGUuanNvbjwvdGV4dD4KPHRleHQgeD0iNDg0IiB5PSIxNzIiPmZpbGUgbG9jayDCtyBvd25lciArIHN0YXJ0IGlkZW50aXR5PC90ZXh0Pgo8dGV4dCB4PSIxMDQiIHk9IjMyOCI+c2Vzc2lvbl9zdGFydCArIDYwcyBjaGVja3M8L3RleHQ+Cjx0ZXh0IHg9IjEwNCIgeT0iMzUyIj5vbmUgbG9jYWwgcnVuIGFkbWl0dGVkIGJlZm9yZSBjbGFpbTwvdGV4dD4KPHRleHQgeD0iOTI0IiB5PSIzMjgiPnBpLXN1YmFnZW50IMK3IHBpLXRhc2stbW9kZWxzPC90ZXh0Pgo8dGV4dCB4PSI5MjQiIHk9IjM1MiI+bWF4VHVybnMgwrcgaWRsZU1zIMK3IG1heE1zPC90ZXh0Pgo8dGV4dCB4PSI5MjQiIHk9IjUyMCI+c2Vzc2lvbnMvJmx0O2pvYi1pZCZndDsvJmx0O3RpbWVzdGFtcCZndDsuanNvbmw8L3RleHQ+Cjx0ZXh0IHg9IjQ4NCIgeT0iNTIwIj5ub3RpZnkgLyBmb2xsb3dVcCAvIG5vbmU8L3RleHQ+CjwvZz4KPGcgZm9udC1mYW1pbHk9IkdlaXN0LCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBmaWxsPSIjNGM1NjY1Ij4KPHRleHQgeD0iNDg0IiB5PSI1NTIiPk9ubHkgdGhlIGNsYWltIG93bmVyIGNhbiBmaW5pc2guPC90ZXh0Pgo8dGV4dCB4PSI4MCIgeT0iNDkyIj5PdGhlciBQaSBzZXNzaW9ucyBzaGFyZSB0aGUgc2FtZSBjbGFpbXMuPC90ZXh0Pgo8dGV4dCB4PSI4MCIgeT0iNTIwIj5CdXN5IG1hbnVhbCByZXF1ZXN0cyBkbyBub3QgcXVldWUuPC90ZXh0Pgo8dGV4dCB4PSI4MCIgeT0iNTQ4Ij5EdWUgam9icyByZXRyeSBvbiBhIGxhdGVyIGNoZWNrLjwvdGV4dD4KPC9nPgo8cGF0aCBkPSJNNDAgNjQ0IEgxMjQwIiBzdHJva2U9IiMxMDE4MjgiIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+Cjx0ZXh0IHg9IjQwIiB5PSI2ODAiIGZvbnQtZmFtaWx5PSJHZWlzdCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzRjNTY2NSI+UnVucyBvbmx5IHdoaWxlIFBpIGlzIG9wZW4uIFNodXRkb3duIGFib3J0cyB0aGUgY2hpbGQ7IG5vIGJhY2tncm91bmQgZGFlbW9uIGlzIGNyZWF0ZWQuPC90ZXh0Pgo8L3N2Zz4K)

The extension checks jobs at session start and every minute. First sighting sets the anchor; a new job waits for its next slot. Missed slots produce one catch-up run, not a backlog. Open Pi sessions do not run the same job concurrently.

The extension saves the outcome, bounded output summary, and available session path before delivery.

| `notify` value | Delivery |
| --- | --- |
| `notify` | One-line notice with an active session UI. |
| `followUp` | Sends output, including failures, to the current conversation and starts a turn. A synchronous delivery error shows a UI recovery notice; otherwise, no notice. |
| `none` | Silent on success. Failures show only with an active session UI. |

## Config

Package-owned: `~/.pi/agent/config/pi-cron/config.json`

```json
{
  "jobs": [
    {
      "id": "digest",
      "at": "07:30",
      "timezone": "Asia/Hong_Kong",
      "role": "digest",
      "modelClass": "balanced",
      "cwd": "/Users/me/.config/miniflux",
      "promptFile": "/Users/me/.config/miniflux/digest.md"
    }
  ]
}
```

| Name | Description | Values | Default |
| --- | --- | --- | --- |
| `jobs` | Scheduled jobs. | Array of job objects with unique `id`. | No jobs. |
| `jobs[].id` | Job name used in `/cron` and state. | Lowercase letters, digits, and hyphens, up to 64 characters. | — |
| `jobs[].every` | Interval schedule. Exactly one of `every` or `at` is required. | `<n>m`, `<n>h`, or `<n>d` between `1m` and `7d`. | — |
| `jobs[].at` | Daily wall-clock schedule. | `HH:MM` in 24-hour time. | — |
| `jobs[].timezone` | Zone for `at`. Only valid with `at`. | IANA name such as `Asia/Hong_Kong`. | The system time zone. |
| `jobs[].role` | pi-subagent Role to run. | Name of a built-in or user Role. | — |
| `jobs[].modelClass` | Shared task-models profile. Not allowed with `model`. | `fast`, `balanced`, `frontier`, or `fav`. | The Role's `modelClass`, else the `pi-cron/job` task assignment (`fast`). |
| `jobs[].model` | Explicit model. Requires `thinking`. | `provider/model` available in the current session. | — |
| `jobs[].thinking` | Thinking level for `model`. | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`. | — |
| `jobs[].cwd` | Working directory of the run. | Absolute path. | — |
| `jobs[].env` | Extra environment variables for the run. | Object of variable name to string. | No extra variables. |
| `jobs[].prompt` | Inline task text. Exactly one of `prompt` or `promptFile` is required. | Non-empty text. | — |
| `jobs[].promptFile` | File whose contents are the task. Read at each run. | Absolute path to a UTF-8 file up to 256 KiB. | — |
| `jobs[].enabled` | Whether the scheduler considers the job. | `true` or `false`. | `true` |
| `jobs[].notify` | How a result reaches you. | `notify`, `followUp`, or `none`. | `notify` |
| `limits.maxTurns` | Provider-turn limit per run. | Safe integer ≥ 1. | `50` |
| `limits.idleMinutes` | Minutes without child activity before the run is stopped. | Positive number; converted milliseconds must be ≤ 2,147,483,647. | `10` |
| `limits.maxMinutes` | Hard runtime cap per run. | Greater than `idleMinutes`; converted milliseconds must be ≤ 2,147,483,647. | `30` |

Edit this file yourself; only `/cron` Enable or Disable changes a job's `enabled` flag. The scheduler rereads config before each run, so edits, disablement, and removal apply without restart. New jobs wait for the next check. Active jobs keep their original definition and limits.

Invalid jobs are ignored without stopping other jobs. Problems include unknown keys, both or neither schedule, unknown time zones, relative paths, invalid routes, and repeated IDs.

If effective `maxMinutes` is not greater than `idleMinutes`, all limits use defaults. A file problem, such as malformed JSON, stops all jobs until you fix it. Enable and Disable cannot write while the file has problems. For the shared rules, see [Config files](https://pi.henry.wang/overview#config-files).

Do not store secrets here. Use `env` to point to a private file, or export secrets in the shell that starts Pi.

## State and storage

`~/.pi/agent/config/pi-cron/state.json` stores first sighting, last start, outcome, bounded output summary, session path, and active run state. Deleting it resets anchors; jobs wait for their next slots.

Invalid version 1 state, including malformed job records or run claims, stays unchanged with an error. Repeated state or scheduling errors show once until scheduling succeeds. Writes above 1 MiB fail without replacing readable state. To make space, close Pi and remove inactive job records. Stale runs cannot overwrite replacement outcomes.

`~/.pi/agent/config/pi-cron/sessions/<job-id>/<timestamp>.jsonl` contains each run's prompt and model output. Delete unneeded session files.

## Limits and recovery

There is no background daemon. Each Pi session runs one job at a time. If busy, `/cron run` does not queue; scheduled jobs wait for a later check.

Runs cannot answer questions or approval prompts. Interactive confirmation blocks a Role until idle timeout. Failed or timed-out runs record `failure` with error text. Open the run session if available; pre-launch failures show `Session: none created`. Retry with `/cron run <job-id>`.

Other sessions cannot restart an unfinished job until its original `limits.maxMinutes` plus five minutes have elapsed from its start. Lowering limits does not shorten that wait.

Shutdown aborts preparation and the active child, even if another session starts in the same process. Results still save, but delivery stops. After shutdown or a synchronous delivery error, recover results with `/cron` → Show last run.
