README
¶
dotprompt-cli
Run local .prompt files against any OpenAI-compatible backend.
dotprompt-cli path/to/file.prompt
Install
go install github.com/spicyneuron/dotprompt-cli@latest
Quickstart
greet.prompt:
---
model: openai/<model>
config:
temperature: 0.3
input:
default:
language: English
---
{{role "system"}}
You are a terse assistant. Reply in {{language}}.
{{role "user"}}
Say hello to {{name}}.
export OPENAI_API_KEY=sk-...
echo '{"name": "Ada", "language": "French"}' | dotprompt-cli greet.prompt
# Bonjour Ada.
Add --dry-run to print the resolved request (messages, model, config) as JSON without calling a model.
Input
Template variables are merged in precedence order (lowest to highest):
input.defaultin the prompt frontmatter--data file.json- stdin
Piped stdin that is a JSON object is merged as variables. Any other piped text is available to the template as {{stdin}}:
cat notes.txt | dotprompt-cli summarize.prompt
Providers
The model field is provider/model. openai and anthropic are built in and need only OPENAI_API_KEY / ANTHROPIC_API_KEY. Other providers are defined in ~/.config/dotprompt-cli/config.yaml:
default_model: local/<model>
providers:
local:
base_url: http://localhost:8080/v1
api_key: unused # or api_key_env: MY_KEY_VAR
headers: # optional extra request headers
X-Custom: value
insecure_skip_verify: true # optional; allow self-signed certs (TLS otherwise verified)
Anthropic is reached through its OpenAI-compatible endpoint, so every provider speaks the same chat-completions protocol.
Flags
--dry-run Print the resolved model request without calling a model
--data <file> JSON file with template input variables
--model <ref> Override the model, as provider/model
--config <file> Config file (default ~/.config/dotprompt-cli/config.yaml)
--version Print version
Dotprompt subset
This tool implements a practical subset of the Dotprompt spec (frontmatter, templates):
Supported:
- YAML frontmatter:
model,config,input.default,input.schema,output.format(textorjson),output.schema - Handlebars templates with common control flow (
#if,#each, ...) {{role "system"}}/{{role "user"}}/{{role "model"}}message markers{{json value}}helper{{media url=...}}image parts (see below)
Not supported: tool calling, streaming, prompt variants, partials, named schema references, and prompt registries.
Deviations from the spec:
modelmust beprovider/modeland routes via the config file rather than a Genkit plugin registry.- Raw (non-JSON) stdin is exposed as
{{stdin}}— a CLI convenience, not part of Dotprompt.
Config passthrough
The Dotprompt names topP, topK, maxOutputTokens, and stopSequences are translated to their wire names (top_p, top_k, max_tokens, stop). Every other config field is sent to the provider verbatim, so provider-specific samplers just work:
config:
temperature: 0.7
min_p: 0.05 # sent as-is
seed: 42 # sent as-is
Use --dry-run to see the exact request body.
Schemas
input.schema validates merged input variables before rendering; a mismatch fails with a non-zero exit. output.schema implies JSON output, is sent as response_format: json_schema so capable servers enforce it during generation, and the response is validated locally after the fact (printed either way; validation failure sets a non-zero exit).
Schemas are written in Picoschema, Dotprompt's compact schema notation:
output:
schema:
language: string, the detected language
greeting: string
formality?(enum): [FORMAL, INFORMAL] # "?" marks optional fields
tags?(array): string
As in upstream Dotprompt, a schema whose top level contains type or properties is treated as raw JSON Schema instead — useful for constraints picoschema can't express (minLength, pattern, numeric ranges, ...).
Images and attachments
{{media url=...}} inserts a file into the surrounding message:
{{role "user"}}
What is in this image? {{media url=photo}}
echo '{"photo": "vacation.jpg"}' | dotprompt-cli describe.prompt
Local file paths (relative to the working directory, ~/ expands to your home directory) are embedded as base64 and shaped by MIME type: images as image_url parts, audio as input_audio, and everything else (e.g. PDFs) as file attachments. http(s):// URLs are passed through as image_url for the server to fetch. Whether a given type actually works depends on the server and model — vision-only backends will reject audio and file parts. --dry-run truncates embedded data for readability.
Documentation
¶
There is no documentation for this package.