Example

Turn a Markdown file into a /review command

Write the smallest prompt template, expand /review bare and with an argument, and see what an extension of the same name changes.

The /review from chapter 11 is a four-line Markdown file. This page writes the smallest prompt template that matters, expands it for a bare /review and for one argument, and then shows the two ordering rules behind “my template does not expand”. This is documented Pi 1.0.4 behaviour, confirmed by a session test.

Write the template

Save this as ~/.pi/agent/prompts/review.md (or <project>/.pi/prompts/review.md), then run /reload in an active session. It is the chapter’s template, unescaped for readability:

---
description: Review uncommitted git changes
argument-hint: "[focus]"
---
Review the uncommitted git changes (`git status --short`, `git diff`).
Focus on ${1:-correctness, security, and error handling}.
Keep findings short, ordered by severity, each with the file path.

The filename is the command name, so review.md is /review. description shows in completion; omit it and Pi uses the first non-empty line. In argument-hint, <angle brackets> mark a required argument and [square brackets] an optional one. ${1:-default} is the workhorse: it reads the first argument, or supplies the default when there is none. $@ and $ARGUMENTS are every argument joined by spaces.

One worked expansion

A bare /review leaves the default in place:

Focus on correctness, security, and error handling.

/review concurrency replaces exactly that line:

Focus on concurrency.

Arguments follow shell-like quoting, so /review "API compatibility" supplies one argument containing a space, not two. The full substitution table, seen in one template invoked as /t a b c, is $1 → a, $2 → b, $@ and $ARGUMENTS → a b c, ${@:2} → b c, ${@:2:1} → b, and ${9:-none} → none.

Expected outcome

The model is asked to run The user message that arrives Why
/review the default focus line ${1:-default} fills the hole
/review concurrency Focus on concurrency. the argument arrives
/review "API compatibility" one argument with a space shell-like quoting

These are expected expansions, not a transcript from your machine. The backing test is an observed run: it starts a real AgentSession with a scripted provider and asserts the text of the last user message the provider received.

Two rules for “it does not expand”

An extension command named review wins outright: the template is never expanded and the model is not called, which the test pins with a zero call count. Separately, an extension’s input handler sees the raw text, /review concurrency, before expansion. So before blaming the template syntax, check whether an extension claimed the name. Conventional prompt directories also load direct .md children only — prompts/nested/deep.md is not discovered, while a file selected explicitly through settings or a package manifest can be.

Mechanism and limitations

Documented: the pinned docs/prompt-templates.md specifies the frontmatter, the substitution table, that expansion happens before the text enters the agent, and that conventional directories load direct .md children only. Observed: templates.test.ts drives a real session with a scripted provider and asserts the default, the argument replacement, quoted-phrase handling, the whole substitution table, command precedence, the raw input text, and nested-file non-discovery. It does not show a real model choosing anything.

A template is one file with no directory beside it. It saves the wording; it does not run the repository’s checks, and a checklist or script it grows to need has nowhere to live. It is also text, not a boundary.

Full source and test .

Understand this example

Copy this prompt into your AI tool. No code runs here.

Apply this example

Copy this prompt into your AI tool. No code runs here.