curl for prompts โ run .prompt files against any LLM provider
Project description
prompt-run
curl for prompts. Run .prompt files against any LLM from the terminal.
Prompts are code. Treat them like it.
๐ Privacy & Security
prompt-run runs entirely on your machine. It is a local CLI tool with no backend, no telemetry, and no cloud component of its own.
| API keys | Read from environment variables, passed directly to your chosen provider. Never stored, logged, or sent anywhere else. |
| Prompts & outputs | Stay on your machine. The only server that sees them is the AI provider you explicitly call. |
| Telemetry | None. Zero usage data, no crash reports, no background calls, no tracking of any kind. |
| Accounts | Not required. There is no prompt-run account or sign-up. |
When you run prompt run, the only network traffic is the request you intentionally send to your chosen AI provider.
Quick start
1. Install
pip install "prompt-run[anthropic]"
export ANTHROPIC_API_KEY="sk-ant-..."
2. Run an example prompt from this repo
prompt run examples/summarize.prompt --var text="LLMs are changing how developers build software."
3. Try streaming, dry-run, and diff
# Stream tokens as they arrive
prompt run examples/summarize.prompt --var text="Your text here" --stream
# Preview the resolved prompt without calling the LLM
prompt run examples/summarize.prompt --var text="Your text here" --dry-run
# Compare two inputs side by side
prompt diff examples/summarize.prompt \
--a-var text="First article content..." \
--b-var text="Second article content..."
4. Write your own
prompt new my-prompt.prompt # interactive wizard
prompt run my-prompt.prompt --var input="hello"
That's it. No config files, no accounts, no platform.
Why?
Every team building with LLMs ends up with the same mess โ prompts buried in Python strings, Notion docs, and Slack threads. No history. No review. No way to test them.
prompt-run fixes this by giving prompts a home: .prompt files.
- โ Committed alongside code in git
- โ Reviewed in PRs like any other file
- โ Swappable across models and providers without touching application code
- โ Runnable from the terminal or CI with one command
Why not LangChain / promptfoo / Langfuse?
| prompt-run | LangChain | promptfoo | Langfuse | |
|---|---|---|---|---|
| Prompt format | Plain .prompt file |
Python code | YAML config | Web UI / SDK |
| Works in terminal | โ | โ | โ | โ |
| Works as Python library | โ | โ | โ | โ |
| No framework lock-in | โ | โ | โ | โ |
| Diff two prompt outputs | โ | โ | Partial (web UI) | โ |
| Pipe stdin / shell-friendly | โ | โ | โ | โ |
| Works offline (Ollama) | โ | โ | โ | โ |
| Zero config beyond API key | โ | โ | โ | โ |
| Prompt lives in git | โ | Partial | โ | Partial |
prompt-run is a single-purpose tool โ it does one thing well and stays out of your stack. No agents, no chains, no platform.
Install
pip install prompt-run
# With provider SDKs (pick what you need):
pip install "prompt-run[anthropic]" # Anthropic Claude
pip install "prompt-run[openai]" # OpenAI / Azure
pip install "prompt-run[all]" # Everything
Set your API key:
export ANTHROPIC_API_KEY="sk-..." # for Anthropic
export OPENAI_API_KEY="sk-..." # for OpenAI
# Ollama needs no key โ just run `ollama serve`
The .prompt file format
A .prompt file has two parts: YAML frontmatter and a plain text body.
---
name: summarize
description: Summarizes text into bullet points
model: claude-sonnet-4-6
provider: anthropic
temperature: 0.3
max_tokens: 512
vars:
text: string
style: string = bullet points
max_bullets: int = 5
---
Summarize the following text as {{style}}.
Use no more than {{max_bullets}} bullets.
Text:
{{text}}
Variables use {{double braces}}. Defaults are declared in frontmatter. Everything is overridable at the CLI.
Frontmatter reference
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | filename | Human name for this prompt |
description |
string | โ | What this prompt does |
provider |
string | anthropic |
anthropic / openai / ollama |
model |
string | provider default | Model to use |
temperature |
float | 0.7 |
Randomness (0.0โ2.0) |
max_tokens |
int | 1024 |
Max output tokens |
system |
string | โ | System prompt |
vars |
map | โ | Variable declarations with types/defaults |
Variable types
vars:
text: string # required string
count: int = 5 # optional int, defaults to 5
verbose: bool = false # optional bool
ratio: float = 0.5 # optional float
Commands
prompt new
Scaffold a new .prompt file interactively โ no YAML knowledge needed.
prompt new # guided wizard, prints to stdout
prompt new summarize.prompt # guided wizard, writes to file
You'll be asked for name, description, provider, model, temperature, and variables. The file is ready to run immediately.
prompt run
Run a .prompt file against an LLM.
# Basic
prompt run summarize.prompt --var text="Hello world"
# Multiple vars
prompt run translate.prompt --var text="Bonjour" --var target_lang=English
# Override model/provider at runtime
prompt run summarize.prompt --model gpt-4o --provider openai
# Pipe stdin (auto-detected for single required var)
cat article.txt | prompt run summarize.prompt
# Stream tokens as they arrive
prompt run summarize.prompt --var text="test" --stream
# Save response to a file
prompt run summarize.prompt --var text="test" --output summary.txt
# Preview the resolved prompt without sending
prompt run summarize.prompt --var text="test" --dry-run
# Get JSON output with metadata
prompt run summarize.prompt --var text="test" --json
Flags
| Flag | Description |
|---|---|
--var KEY=VALUE |
Pass a variable (repeatable) |
--model MODEL |
Override model |
--provider PROVIDER |
Override provider |
--temperature FLOAT |
Override temperature |
--max-tokens INT |
Override max tokens |
--system TEXT |
Override system prompt |
--stream |
Stream tokens to stdout as they arrive |
--stdin-var VAR |
Pipe stdin into a specific variable |
--output FILE |
Write response to file instead of stdout |
--dry-run |
Print resolved prompt, don't call LLM |
--json |
Return JSON with response + token metadata |
--show-prompt |
Print resolved prompt before response |
prompt diff
Run a prompt with two different inputs and compare outputs side by side.
# Same prompt, two different inputs
prompt diff summarize.prompt \
--a-var text="First article content here..." \
--b-var text="Second article content here..."
# Two prompt versions, same input (A/B testing a prompt change)
prompt diff prompts/v1/summarize.prompt prompts/v2/summarize.prompt \
--var text="$(cat article.txt)"
Output:
โโ v1/summarize.prompt โโโโโโโโโโโฌโ v2/summarize.prompt โโโโโโโโโโโ
โ โข The company reported record โ 1. Record quarterly revenue of โ
โ revenue this quarter. โ $2.1B, up 14% YoY. โ
โ โข Growth was driven by cloud โ 2. Cloud services drove growth, โ
โ services. โ up 32%. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Tokens โ A: 312 in / 48 out | B: 318 in / 61 out
prompt validate
Static check one or more .prompt files without calling any LLM.
prompt validate summarize.prompt
prompt validate prompts/*.prompt # glob support
Checks (these are errors โ validation fails):
- Valid YAML frontmatter
- Known provider name (
anthropic,openai,ollama) - Temperature in range
0.0โ2.0 - Body is not empty
max_tokensis at least 1
Checks (these are warnings โ validation passes with a note):
- Variables used in body but not declared in frontmatter
- Variables declared in frontmatter but never used in body
prompt inspect
Show metadata and the fully-resolved prompt body.
prompt inspect summarize.prompt
prompt inspect summarize.prompt --var text="Hello world"
Use as a Python library
from prompt_run import run_prompt_file, RunConfig
config = RunConfig(
vars={"text": "My article content here..."},
model="claude-sonnet-4-6",
)
result = run_prompt_file("summarize.prompt", config)
print(result.response.content)
print(result.response.token_summary)
Parse and render without calling LLM:
from prompt_run import parse_prompt_file, render_prompt
pf = parse_prompt_file("summarize.prompt")
system, body = render_prompt(pf, {"text": "hello"})
print(body)
Provider setup
Anthropic (default)
export ANTHROPIC_API_KEY="sk-ant-..."
prompt run my.prompt --provider anthropic --model claude-sonnet-4-6
OpenAI
export OPENAI_API_KEY="sk-..."
prompt run my.prompt --provider openai --model gpt-4o
Ollama (local, no key needed)
ollama serve # in another terminal
ollama pull llama3
prompt run my.prompt --provider ollama --model llama3
Use in CI / GitHub Actions
- name: Validate all prompts
run: prompt validate prompts/*.prompt
- name: Test prompt output
run: |
output=$(prompt run prompts/classify.prompt \
--var text="I love this product!" \
--var categories="positive,negative,neutral")
echo "Classification: $output"
Examples
The examples/ folder contains ready-to-run .prompt files:
| File | Description |
|---|---|
| summarize.prompt | Summarize text into bullet points |
| translate.prompt | Translate text to any language |
| classify.prompt | Classify text into categories |
| extract-json.prompt | Extract structured JSON from text |
Contributing
See CONTRIBUTING.md.
Changelog
See CHANGELOG.md for a full history of releases and changes.
Security
See SECURITY.md for the supported versions and vulnerability reporting policy.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file prompt_run-0.1.0.tar.gz.
File metadata
- Download URL: prompt_run-0.1.0.tar.gz
- Upload date:
- Size: 34.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba82db4dadee394d808227e83c7590abed2f1201abc092cb87ba2eca6bc48f07
|
|
| MD5 |
33e04682435b6e1bad6e0b0354646bbb
|
|
| BLAKE2b-256 |
51ea25603a17446bba6cec59d896cdb000e109f5b1366542ad767cda1b3f72c3
|
File details
Details for the file prompt_run-0.1.0-py3-none-any.whl.
File metadata
- Download URL: prompt_run-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9bd8c1f2d985b38e2eaaf3c909d384231431565ea4a12903dc7472e21deeb95
|
|
| MD5 |
53ed074b75421f7034e53ed4ca0652e3
|
|
| BLAKE2b-256 |
45607f8469d494bde86cf2e41b091aa32c9848d8ec898bff1bd0cb3daba81fb1
|