Chain Prompts Like Unix Tools with Dotprompt
Dotprompt turns prompt engineering into small, reusable files and lets you run them like programs. Pair it with runprompt and you can wire prompts together with pipes the same way you chain curl, grep, and sed.
Problem
Most prompt workflows are copy-paste scripts hidden in notebooks or docs. They are hard to reuse, hard to review, and fragile when you change models or providers. You need a way to package prompts so they are executable, typed, and composable from the command line.
Solution
Use Dotprompt (.prompt files) for the prompt definition and runprompt as the runner. Each .prompt file:
- Stores metadata in YAML frontmatter (model, parameters, expected inputs).
- Uses Handlebars templating to inject variables safely.
- Can declare an output shape so downstream steps know what to expect.
runprompt reads those files and streams results, so you can pipe prompts just like Unix filters. Swapping models or providers stays inside the file, not your shell script.
Reference specs and tooling:
- Dotprompt spec and examples: https://github.com/google/dotprompt
- runprompt CLI that executes
.promptfiles: https://github.com/chr15m/runprompt
Example
Create two prompts and a one-line pipeline.
summarize.prompt
---
model: gemini-2.5-flash
input:
text: string
output:
summary: string
---
Summarize this text in three bullet points:
{{text}}
fr.prompt
---
model: gemini-2.5-flash
input:
summary: string
output:
french: string
---
Traduis en français, garde les puces:
{{summary}}
Now chain them with runprompt:
curl -s "https://github.com/google/dotprompt" \
| runprompt ~/summarize.prompt \
| runprompt ~/fr.prompt
What happens:
curlgrabs the page HTML.summarize.promptturns it into three bullets (summary).fr.prompttranslates that summary to French (french).
Because each prompt declares its inputs and outputs, you can swap steps without rewriting glue code.
One-liner code review from staged changes:
git diff | runprompt ~/codereview.prompt
codereview.prompt
---
model: googleai/gemini-2.5-flash
---
do code review on current changeset:
<CODE>
{{STDIN}}
</CODE>
Pipe a review straight into a summary for teammates:
git diff | runprompt ~/codereview.prompt | runprompt ~/summarize.prompt
Example output:
Here's a summary of the text in bullet points:
* The new section is clear, concise, and illustrates Unix-style piping with dotprompt.
* `git diff | runprompt codereview.prompt` shows how piped input becomes `<CODE>` via `{{STDIN}}`.
* Including the full `codereview.prompt` keeps the example self-contained and readable.
Take it further
- Add a
detect-language.promptbefore translation to branch between French, Spanish, or Japanese outputs. - Store shared defaults (temperature, max_tokens) in the frontmatter so every prompt runs consistently across providers.
- Version prompts in Git and review them like code; small
.promptfiles make diffs obvious. - Wrap pipelines in
maketargets (make translate) to give teammates a single command. - Test prompts with fixtures: pipe a sample text file through
runpromptand assert the JSON fields you expect.
Tip: gemini-2.5-flash is fast and cheap, making it ideal for multi-step CLI pipelines. If a step needs more reasoning, swap just that prompt to a heavier model without touching your shell script.
With Dotprompt plus runprompt, AI workflows become transparent shell pipelines instead of hidden notebook cells.