ccppccpp home
Browse the documentation

Plugins · CCPP PQL

Prompt mode

How the pql plugin turns Claude Code's prompt box into a PQL editor: colors, completion, diagnostics, compilation and the scope guard.

The pql plugin is a Claude Code hooks module. No command is needed: a prompt whose first character is $ is a PQL program, and removing the $ restores the normal prompt.

──────────────────────────── PQL MODE ────────────────────────────
✗ 2:24 PQL-S005 Expected `;` to end the instruction.
$ FROM @packages/pql {
    ADD "The PQL lexer"
  }
  ◆ PQL Mode · ✗ 1 error

Colors

Colors are theme keys, so they follow your Claude Code theme.

ElementTheme key
$, FROM, MAKE, @pathspermission
Objectives, #callsclaude
Conditions, numberswarning
Stop rules, !policiesmerged
HOW and directivesplanMode
Registered identifiers (FILE, KISS, camelCase)ide
Connectors (TO, OVER, NO_NEW), IN, RANGEinactive, italic
Stringssuccess; interpolations diffRemoved
Commentsdimmed, italic

Keywords are bold. Errors and warnings are underlined.

Completion

Suggestions appear above Claude Code's own; Tab takes one. What is offered depends on the cursor:

  • Start of a statement: only the keywords allowed there. A fresh program offers FROM and MAKE; a block's preamble adds STOP WHEN, ASK WHEN, HOW and the directives; after an objective, a condition or a scope, only executable keywords; SESSION SUCCESS only at the root; inside HOW { } only directives; after the } of an IF branch, the ELSE forms come first.
  • Second word of a phrase: STOP then WHEN, ELSE then IF HAPPEN, DEPTH then MAX.
  • Inside a directive: LIMIT categories, then TO, then the units valid for the category; NAMING categories then conventions; principles not used yet after FOLLOW; PACKAGES modes; metrics and modes.
  • # the active functions, with their signature. ! the active CPO policies.
  • Nothing inside strings, comments, interpolations or numbers, and after @ Claude Code's own path popover takes over.

Completion fires for a non-empty word: after a space, type a letter. Functions and policies come from ccpp pql catalog --json, loaded at session start and refreshed every 30 seconds at most.

Diagnostics

The PQL MODE band above the box shows up to three diagnostics, errors first, as line:column code message ((+N more) when there are others). The line under the box shows the status:

StatusMeaning
◆ PQL Mode · start with FROM or MAKEEmpty program
◆ PQL Mode · ✓ Valid syntaxNo error
◆ PQL Mode · ✗ 2 errorsEnter will refuse the prompt

The box only checks what needs no file system. @ targets, functions and policies are checked on Enter.

Submission

On Enter the plugin pipes the whole prompt to ccpp pql compile --json in the session directory.

  • Success: your PQL stays the visible message, and Claude receives the compiled prompt as context.
  • Errors: the prompt is dropped with a one-line list (1:8 PQL-R001 message | …) and your draft stays in the box.
  • ccpp missing or failing: dropped with a hint. An uncompiled program is never sent.

The plugin runs its own bin/ccpp launcher: the binary in libexec/ when the marketplace is bundled, otherwise the ccpp on PATH.

Scope guard

A compiled program records its scopes. Until the next PQL prompt or /pql reset, a Write, Edit, MultiEdit or NotebookEdit call whose file lies outside every scope is denied, with the reason. Reading stays free.

  • The scopes of a program form a union; a scope inside a condition branch counts.
  • A program without a scope falls back to the session directory.
  • Paths are normalized lexically (., ..); symbolic links are not resolved here (the compiler already checked them).

/pql prints the active program (its normalized form) and its scopes. /pql reset clears them and lifts the guard.

Limits

  • Hooks modules cannot recolor the prompt border: the band and the status line stand in for it.
  • The guard does not see Bash or MCP tools, and nested scopes do not narrow the union. For hard gates on those, use CPO.
  • The active program lives in the module: reloading the plugin forgets it.