Skip to main content

promptlock

A package-lock.json for your prompts. Hash every prompt in your repo, fail CI when one changes without a re-eval. Catch the silent regression that kills agent quality at 3am.

PyPI Python License: MIT


The problem

You ship an LLM-powered feature. Six weeks later a teammate tweaks one sentence in your RAG_PROMPT. Your evals are out of date — nobody re-ran them. Production accuracy quietly drops 12% and nobody notices for a week.

This happens because prompts have no version contract. Code has package-lock.json and go.sum so a bumped dependency fails the build. Prompts have nothing.

promptlock is that nothing.


Install

pip install promptlocker
# or
uvx promptlocker --help

Zero dependencies. Pure Python ≥3.10.


Use it

# 1. Scaffold a prompts/ dir and a prompts.lock
cd your-repo
promptlock init

# 2. Edit your prompts. They're just markdown.
$EDITOR prompts/answer.md

# 3. After you re-evaluate, refresh the lock:
promptlock update

# 4. Wire it into CI so future drift fails the build:
promptlock check       # exits 1 if any prompt drifted vs the lockfile

That's the whole workflow.


Prompt file format

A prompt is a markdown file under prompts/ (configurable). Optional YAML-style frontmatter records which model + settings it was last evaluated against:

---
model: claude-sonnet-4
temperature: 0.0
last_evaluated: 2026-05-19
eval_pass_rate: 0.94
---
You are a helpful assistant. Answer the user's question based only on the
provided context. If you don't know, say so.

The file's name (relative to prompts/, with .md stripped) becomes the prompt's id. Nested folders use . separators, e.g. prompts/rag/answer.md → id rag.answer.


The lockfile

{
  "version": 1,
  "prompts": {
    "answer": {
      "file": "prompts/answer.md",
      "sha": "sha256:5b1a...",
      "meta": {"model": "claude-sonnet-4", "last_evaluated": "2026-05-19"}
    }
  }
}

The sha covers the prompt body (frontmatter excluded), so you can update metadata without invalidating the lock. The lockfile is committed to git — drift is then visible in PR reviews.


CLI

Command What it does
promptlock init Create prompts/ + prompts.lock + a starter prompt.
promptlock check Exit 1 if current prompts ≠ lockfile. Use in CI.
promptlock update Refresh the lockfile from current prompts.
promptlock diff Print {added, removed, changed} as JSON.
promptlock list List all discovered prompts with their hashes.

GitHub Actions

Drop this in .github/workflows/promptlock.yml:

name: promptlock
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install promptlocker
      - run: promptlocker check

Now any PR that touches a prompt without bumping the lockfile fails the build, forcing whoever made the change to explicitly acknowledge it.


Why this works

  • Two-keystroke workflow. Edit a prompt → promptlock update is one command. Skipping it = failing CI.
  • PR-visible. Lockfile drift shows up as a 1-line diff every reviewer spots.
  • Zero runtime cost. No instrumentation, no SDK lock-in. Your prompts stay in plain markdown your team can grep.
  • Tool-agnostic. Works with OpenAI, Anthropic, Cohere, local models, Cursor rules, Claude Code skills, anything that loads strings from files.

Companion projects


About the author

Built by yubinkim444, who also makes Kay's Records — an app for iOS and Android.

If this project saved you time, giving the app a try is the nicest way to say thanks.

License

MIT © yubinkim444

Metadata

Release files for promptlocker 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for promptlocker 0.1.1
File Size Uploaded
promptlocker-0.1.1.tar.gz 7.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for promptlocker 0.1.1
File Interpreter ABI Platform
promptlocker-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 15.8 kB

Release files / promptlocker-0.1.1.tar.gz

Download URL promptlocker-0.1.1.tar.gz
Size 7.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a92c79c146851166d2ec50b6d6845612aa90d9d3f4228fce8e1f86075190a12b
BLAKE2b-256 checksum
How to use checksums
1bd1f04783d9b678cb8c2a30bdd4c8dac3412917c7f99659b5d3931e156590f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / promptlocker-0.1.1-py3-none-any.whl

Download URL promptlocker-0.1.1-py3-none-any.whl
Size 8.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
031ffd28bc6273834730ed52fe7d504ee39b039883881daffe2aa7224808990c
BLAKE2b-256 checksum
How to use checksums
a7b66923213f51b2a69372181e28be6d1a9800df23f1759ab8ee905431c891d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page