ccppccpp home
Browse the documentation

Plugins · CCPP PQL

CCPP PQL: Prompt Query Language

PQL is a structured language for prompting Claude Code. A prompt that starts with $ is a program, checked and compiled before Claude reads it.

A free-form prompt mixes what to change, where, under which constraints and when to stop. PQL (Prompt Query Language) gives each of those a keyword. Start a prompt with $ and Claude Code's prompt box becomes a PQL editor: the program is colored as you type, errors show above the box, and on Enter ccpp pql compile turns it into a precise natural-language prompt. A program with an error never reaches Claude.

A PQL prompt
$ FROM @packages {
  SESSION SUCCESS "The parser yields a valid AST for every supported input";
  STOP WHEN "A secret needed by the next action is missing from the expected environment";
  !ts-no-any;
 
  HOW {
    LIMIT FILE TO 250 LINES;
    FOLLOW KISS, YAGNI;
    PACKAGES NO_NEW;
  }
 
  MAKE @packages/parser {
    ADD "A lexer", "A parser and its AST";
  }
}

Claude works in packages, creates packages/parser, adds two features there, keeps files under 250 lines without new dependencies, respects the CPO policy ts-no-any, stops if a secret is missing, and declares success only when the criterion holds. You keep seeing what you typed; Claude reads the compiled prompt.

Install

PQL needs the ccpp CLI and Claude Code 2.1.306 or later (the plugin is a hooks module).

curl -fsSL https://s3.ccpp.dev/ccpp-public/install.sh | sh
claude plugin marketplace add https://s3.ccpp.dev/ccpp-public/marketplace.json
claude plugin install pql@ccpp

Then type $, a space, FROM @ and press Tab on a suggestion. Remove the $ and the box is a normal prompt again. Without ccpp, a $ prompt is refused with a hint: an uncompiled program is never sent.

The language at a glance

RoleKeywordsPage
ScopeFROM, MAKEScopes
ObjectiveADD, REMOVE, MODIFY, REFACTOR, SKIP, CONTINUEObjectives
ConditionIF HAPPEN, IF NOT HAPPEN, ELSE IF …, ELSEConditions
Stop rulesSESSION SUCCESS, STOP WHEN, ASK WHENStop rules
HOWHOW { }, LIMIT, FOLLOW, PACKAGES, NAMING…HOW directives
Policies!policy-id;Policy references
Functions#name(...), .pql files, FORFunctions

Every keyword, directive and registered identifier fits on one page: the identifier cheatsheet.

What the compiler guarantees

The compiler is code, not a model. Every stage reports diagnostics, and any error blocks the whole prompt:

prompt ─▶ parse ─▶ expand (#calls, FOR, {{ }}) ─▶ validate ─▶ resolve (@paths, scopes) ─▶ project (!policies) ─▶ render
  • Syntax and types. Every statement ends with ; or a block, every parameter has a type: FROM "x" is an error, FROM @x is a directory reference.
  • The file system. FROM targets must exist, MAKE targets must not, and no scope leaves the project or its parent scope, even through a symbolic link.
  • Conflicts. Two naming conventions for one category, PACKAGES ALLOW under an inherited NO_NEW, a looser bound than one in force: reported, never silently overridden.
  • Policies. A !policy reference is checked against the CPO policies installed for the project.

Descriptions in quotes (objectives, conditions, criteria) are never evaluated by the compiler: Claude establishes whether they hold. Quoted text is data for Claude, never an instruction about the protocol.

After the submission

Until the next PQL prompt or /pql reset, file writes (Write, Edit, MultiEdit, NotebookEdit) outside every scope of the program are refused. Reading stays free. See Prompt mode.

The same compiler runs in a terminal: ccpp pql compile program.pql prints the prompt Claude would read (CLI).