Dotprompt turns a prompt into a file that a program can execute
Executable GenAI prompt templates
At a glance
- What is it?
- Dotprompt is a file format for generative AI prompts that extends Handlebars with model specific features and ships as libraries in six languages plus editors for VS Code, JetBrains, Vim and Emacs. It suits teams whose prompts live in version control and are filled in by code, and its cost is a new template dialect to learn and a monorepo-wide parity effort to keep in step.
- Who is it for?
- Teams that keep prompts in a repository, render them from application code, and want the same template to work across several model providers are the people Dotprompt was built for, and the fact that the same file format is implemented in six languages is what makes a shared prompt library possible in the first place.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A prompt as a file rather than a string in code
The definition in the readme is short and it carries the whole idea. Dotprompt is an executable prompt template file format for generative AI, and it is designed to be agnostic to programming language and model provider to allow for maximum flexibility in usage. Two words in that sentence are doing the work. Executable means the file is not a document to be read and copied, it is an artefact a program loads and renders. And agnostic to model provider means the prompt is not tied to one API's request shape, which is what lets the same template be reused when you change providers or when you call two of them in one workflow. The format extends the popular Handlebars templating language with GenAI-specific features, which is a deliberate choice to avoid inventing a second template language. The result is that a prompt becomes something you can lint, diff, review and unit test, and the cost of that is that a prompt author now needs to know Handlebars.
Six language bindings are what make a shared prompt library possible
The package table is the clearest statement of scope, and it lists core libraries for JavaScript and TypeScript, Python, Go, Rust and Java, each published to its own registry. The JavaScript one is dotprompt on npm, the Python ones are dotpromptz and dotpromptz-handlebars on PyPI, the Go one is dotprompt-go on pkg.go.dev, the Rust one is dotprompt-rs on crates.io, and the Java one is dotprompt-java on Maven Central. The reason there are two Python packages rather than one is worth noticing, since dotpromptz and dotpromptz-handlebars have separate version lines and the newer releases in the list are the 0.2.0 versions of both, published within hours of each other. The practical consequence for a team is that a prompt library in a shared repository can be consumed from a TypeScript service, a Python training script and a Go collector without any of them parsing the file format themselves.
Editors are part of the project, not an afterthought
Around the libraries sits a full set of editor integrations, which is what a template format needs to be usable by the people who write prompts rather than only by the people who ship code. There are IDE extensions for VS Code and JetBrains, both published to their marketplaces, plus packages for Vim and Emacs that are distributed from the repository itself. The web editor side has dotprompt-monaco and dotprompt-codemirror, which are the editor components that back those two environments. Below the editors sit two tools, tree-sitter-dotprompt, a grammar for the format so that syntax highlighting and parsing work in any tree-sitter based editor, and promptly, a command line tool published as promptly-cli. The tree-sitter grammar is the piece that makes the format a first-class citizen rather than a string in a language specific template, and it is also what lets the VS Code extension and the web editors share behaviour. A separate CI workflow covers the editor plugins and the web editors, so the format and its tooling are tested together.
The examples directory is a spec for the format's edge cases
The examples directory in the repository is unusual and useful, because its file names are a catalogue of what the format has to handle. There are valid examples, valid-greeting, valid-blog-generator, valid-customer-support and valid-comments-and-partials, and then there are the error and warning cases, error-invalid-yaml, error-multiple-issues, error-unbalanced-brace, error-unclosed-block and error-unmatched-closing-block. The warning cases are warning-undefined-variable and warning-unused-variable. The distinction the file names make is the one that matters for a format used in continuous integration, an error means the file is rejected while a warning means it parsed but something in it is suspicious. Then there are the structural features, a features.prompt and a partials.prompt with a partials directory beside it, and an autocomplete.prompt, which is a prompt whose job is to suggest completions inside another prompt. A specification expressed as a set of executable examples is easier to keep honest than prose, and it doubles as a conformance suite for anyone writing another implementation of the format.
Handlebars parity is tracked as a document, because the dialects drift
The repository carries a file named HANDLEBARS_PARITY.md at the top level, and the presence of that file is the most important signal about how Dotprompt relates to Handlebars. Dotprompt is an extension of Handlebars, and an extension that is only partly compatible creates a specific failure mode, a prompt that renders correctly in one binding and fails in another, with the difference usually being a template construct that one implementation supports and another does not. Tracking parity in a dedicated document is how a project makes that difference visible rather than leaving it to be discovered. It also explains the two Python packages. The core dotpromptz package and the separate dotpromptz-handlebars package suggest the two are not identical implementations, and a team that has to support a prompt library in more than one language needs to know exactly where the implementations agree. There is also a spec directory in the repository, which is where a format like this keeps its normative description.
The JavaScript package shows how little the format depends on a runtime
The root package.json is short and it makes the design choice visible. The package manager is pinned to pnpm at version 10.25.0, and the whole runtime dependency list is two entries, handlebars at version 4.7.8 and yaml at version 2.8.2. There is no model SDK in there, no HTTP client and no provider adapter, which tells you that the core library parses and renders a template and nothing more. The scripts are the build, format, lint and test entry points, and the format and lint steps both run biome, with the linter disabled for formatting and the formatter disabled for linting, plus a license header check that runs a script named add_license or check_license depending on the direction. The scripts block is short enough to read in one go.
"scripts": {
"build": "pnpm -r run --if-present build",
"format": "pnpm dlx @biomejs/biome check --formatter-enabled=true --linter-enabled=false --fix . && scripts/add_license",
"format:check": "pnpm dlx @biomejs/biome ci --linter-enabled=false --formatter-enabled=true . && scripts/check_license",
"lint": "pnpm dlx @biomejs/biome lint --fix . && scripts/add_license",
"test": "pnpm -C js run test"
},The test script delegates to the js package, and the workspace uses turbo-style recursive runs through pnpm, with a pnpm-workspace.yaml and a separate pnpm-lock.bazel.yaml, so the JavaScript, Python, Go, Rust and Java modules are all built through one workspace. The Rust module names its three crates, rs/smoke, rs/dotprompt and rs/promptly, which is the same division of library, tool and test seen in the other languages.
Where Dotprompt is the wrong choice
The first wrong case is a team that writes prompts once in a chat interface and never reuses them, since a file format only pays for itself when the prompt is stored, versioned and filled in by code. The second wrong case is a project that has already standardised on a different templating language, because Dotprompt is defined as an extension of Handlebars and adopting it means adopting Handlebars semantics along with the GenAI additions, and a Jinja or Liquid shop will inherit a dialect mismatch. The third is a team that needs model provider features no format can abstract, where a provider specific parameter has to reach the request payload, and the answer to that is usually to keep the prompt as a string and the provider call as code. The fourth is a build that cannot use one of the six core libraries, since a missing binding means writing a parser and renderer for the format yourself, and the format includes YAML front matter, partials and nested blocks, which is real work. The fifth is a team that needs the editor plugins to behave identically across editors, since the Vim and Emacs plugins come from the repository while the VS Code and JetBrains ones come from their marketplaces, and the repository has separate CI workflows for each group.
Getting the library is a package manager call, per language
There is no single install step, and the readme does not pretend otherwise. Each core library is published to the registry that suits its language, so the JavaScript and TypeScript binding is installed from npm, the two Python packages from PyPI, the Go binding from pkg.go.dev, the Rust binding from crates.io and the Java binding from Maven Central. The editor side is installed the same way, with the VS Code extension and the JetBrains plugin coming from their marketplaces and the Vim and Emacs packages from the repository. The command line tool promptly is published to npm as promptly-cli, and the tree-sitter grammar is on npm as tree-sitter-dotprompt. The first thing a new user should do is pick the binding for the language the rest of their stack is written in, because that is the binding that will parse and render the templates in production, and the parity document is where you check that the constructs you need behave the same in it.
Editorial conclusion
Teams that keep prompts in a repository, render them from application code, and want the same template to work across several model providers are the people Dotprompt was built for, and the fact that the same file format is implemented in six languages is what makes a shared prompt library possible in the first place. It is the wrong tool for a team whose prompts are written by hand in a chat interface and never reused, and it is the wrong tool if you need the templates to be portable to a different templating language, since the format is defined as an extension of Handlebars rather than of anything else. Check three things before you adopt it: that the language bindings you need are in the package list, because a missing binding means implementing the format yourself, that the features you need, such as partials, media handling and the media block, behave the same in your binding, since the repository carries a dedicated HANDLEBARS_PARITY.md for exactly that question, and that the editor plugin you use is maintained, since the Vim and Emacs plugins are distributed from the repository rather than from a marketplace. The licence is Apache-2.0, the newest releases are the dotpromptz 0.2.0 and dotpromptz-handlebars 0.2.0 from 2026-10-05, and the last push was on the same day.
Frequently asked questions
What is Dotprompt and what is it based on?
Dotprompt is an executable prompt template file format for generative AI, designed to be agnostic to programming language and model provider. It extends the Handlebars templating language with GenAI-specific features.
Which languages have Dotprompt libraries?
Six core libraries: dotprompt for JavaScript and TypeScript on npm, dotpromptz and dotpromptz-handlebars for Python on PyPI, dotprompt-go for Go on pkg.go.dev, dotprompt-rs for Rust on crates.io, and dotprompt-java for Java on Maven Central.
Which editors and tools support Dotprompt?
IDE extensions for VS Code and JetBrains, packages for Vim and Emacs distributed from the repository, web editor components dotprompt-monaco and dotprompt-codemirror, a tree-sitter grammar named tree-sitter-dotprompt, and a command line tool published as promptly-cli.
How does Dotprompt handle templates that are invalid?
The examples directory separates error cases from warning cases, with files such as error-invalid-yaml, error-unbalanced-brace, error-unclosed-block and error-unmatched-closing-block alongside warning-undefined-variable and warning-unused-variable, and there is a valid-comments-and-partials example and a partials directory for shared template pieces.
How do the Dotprompt implementations stay compatible with Handlebars?
The repository carries a HANDLEBARS_PARITY.md file at the top level, alongside a spec directory, and separate language packages including a Python core package and a separate dotpromptz-handlebars package. The root package.json depends only on handlebars and yaml, and the build is driven from a pnpm workspace with pnpm-lock.bazel.yaml alongside the normal lock file.
Official sources
Where developers are discussing it
Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 1 in the last 30 days; newest first.
- State of AI Instruction Quality: Coding Agent Comparisondev.to · Oct 21, 2026 · 6 points · 0 comments
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/google-dotprompt)Was this useful?