Prompt Runner 0.9.0 uses two primary authoring files:
prompt_runner_packet.md*.prompt.md
Both are markdown documents with YAML front matter.
Optional supporting authoring files include:
templates/*.prompt.md- packet-local docs such as
docs/*.md
Packet Manifest
Recommended filename:
prompt_runner_packet.md
Example:
---
name: "demo"
profile: "codex-default"
prompt_template: "from-adr"
provider: "codex"
model: "gpt-5.6-luna"
reasoning_effort: "xhigh"
permission_mode: "bypass"
allowed_tools:
- "Read"
- "Edit"
- "Write"
- "Bash"
cli_confirmation: "require"
recovery:
resume_attempts: 2
retry:
max_attempts: 3
base_delay_ms: 1000
max_delay_ms: 30000
jitter: true
repair:
enabled: true
max_attempts: 2
trigger_on_nominal_success_with_failed_verifier: true
trigger_on_provider_failure_with_workspace_changes: true
trigger_on_retry_exhaustion_with_workspace_changes: true
repos:
app:
path: "./workspace"
default: true
phases:
"1": "Bootstrap"
"2": "Wrap Up"
---
# Demo PacketPacket Keys
Core keys:
nameprofileprompt_templatereposphasesrecovery
Shared execution keys:
providermodelpermission_modeallowed_toolstimeoutlog_modelog_metaevents_modetool_output
Provider-specific keys:
adapter_optssdk_optsclaude_optscodex_optscodex_thread_optsamp_optscursor_optsantigravity_optssystem_promptappend_system_promptmax_turnscli_confirmation
Every provider option map also accepts the normalized common options
(allow_unknown_model, completion_only, output_schema,
transport_headless_timeout_ms). See the
Provider Guide for which providers support each one at
runtime.
timeout And The Run Deadline
timeout (milliseconds, packet-level or prompt-level) is the single lever for
how long a session may take. PromptRunner.Session derives four bounds from
it:
| Bound | Derived as |
|---|---|
| stream timeout | the configured timeout |
| transport timeout | the configured timeout |
| stream idle timeout | max(120_000, timeout + 30_000) |
ASM run_deadline_ms | the configured timeout |
The run deadline is a total wall-clock budget for the whole run, armed
independently of the stream and transport bounds. ASM.Run.State defaults it
to 600_000 — ten minutes — and Prompt Runner did not set it before 0.9.0. A
packet that deliberately left timeout unset therefore got seven days on the
stream and transport bounds and ten minutes on the run, and every prompt
doing more than a few minutes of work was killed with a
provider_runtime_claim naming a deadline nothing had configured, after the
model had already done the work.
Since 0.9.0 all four derive from the same value:
timeoutunset — the seven-day emergency bound, not ASM's 600s default. This is the right posture for prompts sized in tens of minutes.timeoutset — that value bounds the run as well. A smalltimeoutalso shrinks the idle bound, and a high-reasoning session can go minutes between stream events, so set it deliberately or not at all.unbounded,infinity, andinfiniteall resolve to the seven-day bound.
stream_idle_timeout is not a packet or prompt key. It exists only inside
PromptRunner.Session and is derived, never configured directly.
Prompt Front Matter
Recommended filename pattern:
01_create_hello.prompt.md
Example:
---
id: "01"
phase: 1
name: "Create hello file"
template: "from-adr"
targets:
- "app"
commit: "docs: add hello file"
provider: "codex"
model: "gpt-5.6-luna"
verify:
files_exist:
- "hello.txt"
contains:
- path: "hello.txt"
text: "Hello from Prompt Runner"
commands:
- "timeout 60 test -s hello.txt"
changed_paths_only:
- "hello.txt"
---
# Create hello file
## Required Reading
- `docs/adr-001-runtime-boundaries.md`
## Mission
Create `hello.txt` with exactly one line: `Hello from Prompt Runner`.The filename must carry the same numeric prefix as id:. Prompts are ordered
by the filename prefix, not by id:, so a mismatch silently reorders the run.
mix prompt_runner packet lint reports it as an error.
Prompt Keys
Scheduling and identity:
idphasenametemplatetargetscommit
Parsed But Never Read
referencesrequired_readingcontext_filesdepends_on
These four are accepted, normalized, and stored on PromptRunner.Prompt, and
then never read at runtime. They are not sent to the provider — only the
markdown body after the front matter is — and depends_on does not
influence ordering, which comes from the numeric filename prefix.
Write required reading into the prompt body, where the model will see it.
mix prompt_runner packet lint warns when a prompt carries any of them, and
since 0.9.0 the scaffolding templates no longer emit them.
Prompt-local execution overrides:
providermodelreasoning_effortpermission_moderecoveryallowed_toolssdk_optsadapter_optsclaude_optscodex_optscodex_thread_optsamp_optscursor_optsantigravity_optscli_confirmationtimeoutsystem_promptappend_system_promptmax_turns
Completion contract:
verifysimulate
Prompt-local recovery is deep-merged onto the packet default. Use it when a
single prompt needs a tighter or more generous retry/repair budget than the
rest of the packet.
Example:
recovery:
retry:
class_attempts:
provider_runtime_claim: 1Completion Contract Keys
Prompt Runner 0.9.0 supports:
files_existfiles_absentcontainsmatchesdoccommandschanged_paths_onlyrepos_clean
Entries can be repo-scoped:
verify:
files_exist:
- repo: "alpha"
path: "NOTES.md"doc: is an artifact-quality gate for written deliverables, and repos_clean:
asserts that sessions committed (and optionally pushed) their own work:
verify:
doc:
- path: "docs/report.md"
min_lines: 100
requires_sections: ["## Method", "## Verdict"]
forbids_markers: ["TODO", "TBD", "FIXME"]
repos_clean:
- repo: "app"
pushed: trueWrap every commands: entry in timeout. The verifier runs commands through
bash -lc with no timeout of its own, so a hung command hangs the run after
the model work is already spent.
Anything else under verify: is parsed, stored, and never evaluated.
mix prompt_runner packet lint reports an unrecognized clause as an error.
See Verification And Repair for the full clause
reference.
Generated Checklist Files
mix prompt_runner checklist sync converts the deterministic contract into a
human-readable checklist file next to each prompt.
The checklist is derived output, not the source of truth.
If a prompt still has no verifier items, checklist sync prints a warning and
the generated checklist explicitly says that verification items are still
missing.
mix prompt_runner packet preflight reports runtime readiness as JSON and
exits non-zero when packet-local repos or git state are not ready. run calls
this gate before invoking a provider unless --skip-preflight is explicit.
mix prompt_runner packet doctor also reports common authoring gaps:
- packet has no prompts
- packet has no default repo
- prompt has no targets
- prompt has no verification items
- prompt still contains scaffold placeholder markers
mix prompt_runner packet lint reports authoring hazards rather than gaps:
constructs that load and run and quietly mean something else. See
Packet Linting.
Simulated Provider Scripts
When provider: "simulated" is active, prompts can define deterministic
recovery scripts:
simulate:
attempts:
- error:
kind: "provider_capacity"
message: "Selected model is at capacity. Please try again."
- writes:
- path: "retry.txt"
text: "retry ok"
resume:
writes:
- path: "resumed.txt"
text: "resumed ok"Supported simulation keys:
attemptsresume
Each step can include:
messageswriteserrorerror.recovery