dotprompt-cli

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 20 Imported by: 0

README

dotprompt-cli

A lightweight dotprompt runner.

dotprompt-cli path/to/file.prompt

This implements a practical subset of the Dotprompt spec (frontmatter, templates):

  • YAML frontmatter: model, config, input.default, input.schema, output.format (text or json), output.schema
  • Handlebars templates with common control flow (#if, #each, ...)
  • {{role "system"}} / {{role "user"}} / {{role "model"}} message markers
  • {{json value}} helper
  • {{media url=...}} media parts

Deviations from the spec:

  • Not supported: tool calling, prompt variants, partials, named schema references, and prompt registries.
  • model must be provider/model and 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.

Install

go install github.com/spicyneuron/dotprompt-cli@latest

Quickstart

1. Configure a provider

Set an API key for OpenAI or Anthropic, or configure another provider:

export OPENAI_API_KEY=your-api-key
# or
export ANTHROPIC_API_KEY=your-api-key

2. Create a prompt

greet.prompt:

---
model: provider/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}}.

Replace provider/model with the provider and model you configured, such as openai/<model> or anthropic/<model>.

3. Run the prompt

echo '{"name": "Ada", "language": "French"}' | dotprompt-cli greet.prompt
# Bonjour Ada.

Configuration

Settings come from three places:

Location Scope What it controls
config.yaml and environment User or machine Provider connections, credentials, and the default model
.prompt file Reusable prompt Model, provider request settings, input defaults and schemas, and the rendered messages
Command line One run Model override, template input, streaming, metrics, and the dry-run preview

config.yaml and the config: block inside a prompt are separate: the file configures how the CLI reaches providers, while the prompt block is copied into the provider request.

Model selection uses --model, then the prompt's model, then default_model from config.yaml. Template input uses stdin, then --data, then the prompt's input.default, from highest to lowest precedence.

Global config

The default path is ~/.config/dotprompt-cli/config.yaml; select another file with --config.

Models use provider/model references. openai and anthropic are built in and need only OPENAI_API_KEY or ANTHROPIC_API_KEY. Other providers are defined in the config file:

default_model: local/<model>
providers:
  local:
    api: chat_completions       # default; or responses
    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)

The built-in openai provider uses POST /v1/responses. The built-in anthropic provider and custom providers default to POST /v1/chat/completions; Anthropic is reached through its OpenAI-compatible endpoint. An openai provider override keeps the Responses default unless api is set explicitly.

Prompt files

A prompt file combines YAML frontmatter with a Handlebars template. Frontmatter controls the model request and template data contract; the template produces the messages sent to the model.

Model and provider request config
# Pin a model
model: provider/model

# `config` fields are copied directly into the request body, so use the names
# expected by the configured provider. This example uses Responses, Chat
# Completions uses `max_tokens`, and a Google GenAI-compatible proxy may need
# `topP` and `maxOutputTokens`.
config:
  temperature: 0.7
  top_p: 0.9
  max_output_tokens: 500

The CLI rejects config.model, config.messages, config.input, and config.stream because it manages those fields. When output.format or output.schema is set, it also rejects config.response_format for Chat Completions and config.text.format for Responses because output controls structured-output formatting.

Input and output schemas

input.schema validates merged input variables before rendering; a mismatch fails with a non-zero exit. output.schema implies JSON output and is sent as the protocol's JSON Schema response format. Whether and how strictly it constrains generation depends on the server. The response is also 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 base64 payloads for readability while preserving text and remote URLs.

Command line

Flags
--dry-run        Print the resolved model request without calling a model
--stream         Stream response text as it is generated
--metrics        Print request metrics as JSON to stderr
--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
Runtime input

Template variables are merged in precedence order (lowest to highest):

  1. input.default in the prompt frontmatter
  2. --data file.json
  3. 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
Streaming and metrics

Add --metrics to write request metadata as one JSON object to stderr while keeping stdout clean. Combine it with --stream to print response text as it is generated and report ttft_ms:

dotprompt-cli --stream --metrics greet.prompt >answer.txt 2>metrics.json

For example:

{
  "request_id": "request-abc123",
  "model": "model-name",
  "prompt_tokens": 124,
  "cached_prompt_tokens": 20,
  "completion_tokens": 86,
  "reasoning_tokens": 32,
  "total_tokens": 210,
  "ttft_ms": 241.397,
  "total_time_ms": 1842.125,
  "tokens_per_second": 46.685,
  "cost_usd": 0.00123
}

cached_prompt_tokens and reasoning_tokens are subsets of their parent totals. tokens_per_second is completion tokens divided by total request time, and cost_usd is provider-reported; provider-dependent values may be null.

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL