Detect and visualize drift between versions of LLM prompts.
Prompts are untyped, high-entropy configuration. When they silently drift between versions β a variable renamed, a constraint dropped β downstream code breaks and nobody notices until production. promptdrift gives you visibility: line-level diffs, template-variable tracking, and a severity verdict you can gate CI on.
- π Line + variable diff β see exactly what changed between two prompt versions
- π§© Variable drift detection β added/removed template variables are flagged as breaking; renames are not
- π¦ Severity scoring β
breaking/major/minor/trivial/none, with--fail-on-breakingfor CI - ποΈ Snapshot store β versioned, hash-keyed snapshots in
.promptdrift/;watchcompares the working file vs the last baseline - π¨ Readable output β color-coded unified diff, plus
--jsonfor automation - π« Zero dependencies β pure Python stdlib
| Syntax | Example | Tag |
|---|---|---|
| Jinja2 / Mustache | {{ name }} |
jinja |
| Python str.format | {name} |
format |
| Dollar-brace | ${name} |
dollar-brace |
| Bare dollar | $name |
dollar |
| Angle brackets | <<name>> |
angle |
| Double brackets | [[name]] |
bracket |
pip install promptdriftpromptdrift diff prompts/v1.txt prompts/v2.txtBREAKING Breaking drift: -variables ['target_language']
Variable drift:
- target_language (removed β breaking)
Diff:
--- prompts/v1.txt
+++ prompts/v2.txt
@@ -1,1 +1,1 @@
-You are a translator. Translate {text} into {target_language}.
+You are a translator. Translate {text}.
promptdrift diff old.txt new.txt --fail-on-breaking --json
# exits 1 if a variable was added/removedpromptdrift variables prompts/sys.txtVariables in prompts/sys.txt (3):
name [jinja]
question [format]
context [dollar-brace]
promptdrift snapshot prompts/sys.txt --label "v1 production"
# ...edit the prompt...
promptdrift watch prompts/sys.txt # compare vs last snapshot
promptdrift history prompts/sys.txt # show all snapshots| Severity | Trigger | CI gate |
|---|---|---|
breaking |
a variable was added or removed (not a 1:1 rename) | fails |
major |
β₯40% of lines changed (large rewrite) | passes |
minor |
10β40% of lines changed | passes |
trivial |
<10% of lines changed | passes |
none |
identical | passes |
A rename (variable set size preserved, names swapped with token overlap) is not breaking β it's reported but allowed, since the caller can usually adapt the fill key.
git clone https://github.com/alvabillwu/promptdrift.git
cd promptdrift
pip install -e ".[dev]"
pytest -v
python examples/demo.pyMIT Β© alvabillwu