promptbook

Introduction

The problem promptbook solves, the fix, and your first 60 seconds.

The problem

System prompts start as throwaway text. Then they get reused across flows, grow if (model === "gpt") branches, and end up scattered through the codebase as template literals. At that point you can't answer three basic questions:

  • Which pieces are shared between prompts?
  • What is safe to change without breaking another flow?
  • What does the model actually receive under a given context?

So editing is scary, and reviewing a prompt PR means eyeballing a string blob.

The fix

promptbook turns prompts into a folder of small plain files, split into three boring layers:

  • WHAT · reusable Markdown fragments with a YAML frontmatter id.
  • WHEN · declarative YAML rules that say which fragments apply for which context.
  • HOW · resolve() returns a { text, trace } pair you then send to a model.

Same folder + same context → byte-identical string, every time. The trace explains why: which rules fired, what got replaced or forbidden, and every warning. Nothing throws on bad data; holes surface as warnings instead.

Your first 60 seconds

No install needed. Try the in-browser demo right now — it is the real viewer running the real resolver. Or run it locally:

npx skills add markbrutx/promptbook       # teach your agent
npx @markbrutx/promptbook-cli init        # scaffold a starter book in ./prompts
npx @markbrutx/promptbook-cli view        # open it: canvas + graph
npm install @markbrutx/promptbook-core    # use resolve() in code

init writes promptbook.json plus five fragments and one composition whose rule swaps the tone fragment on tone=terse — a working cascade you can resolve, lint, and view immediately. It never overwrites existing files.

Any one of the three is a complete entry point. The agent skills include promptbook-migrate, which moves your existing scattered prompts into a book without changing what the model receives.

Not a framework

Adopting promptbook does not restructure your app:

  • No orchestration. No chain helper, no retry loop, no streaming client. The unit of work is one assembled prompt string; what you do with it is your code.
  • No model calls in the engine. resolve(), lint(), and loading are pure and deterministic. The only stochastic step — calling a model — lives behind an adapter you control, and only eval uses it.
  • No DSL beyond the rule shape. Rules have four actions (add, replace, forbid, order) and a when clause. That is the entire surface.
  • No lock-in. Your prompts are Markdown and YAML on disk. Delete the tool and the files still read as plain text. The target model is just another context axis, so no provider is privileged.

The runtime stays dumb on purpose; the intelligence lives in the agent that drafts your fragments and rules.

Where to go next

  • Concepts — the WHAT / WHEN / HOW split, with code.
  • Examples — two runnable books, each with a live in-browser demo.
  • CLIresolve, lint, view, and friends, captured from the built binary.
  • Viewer — the canvas and graph views, and how to read the explain panel.