Plugins · CPO
Claude Policy Objects
CPO turns your team's rules into policies that Claude Code hooks check before a write, a command or the end of a turn.
A policy is a Markdown file with a YAML frontmatter: which events it watches, the condition that triggers it, and what happens then (block, ask the user, steer Claude, log…). CPO evaluates every policy that applies to an event, in a fixed order, and answers Claude Code. No model is involved: conditions are code checks and CEL expressions.
---
description: Keep source files under 400 lines
on: [file.write]
paths: ["src/**/*.{ts,tsx}"]
when: { builtin: max-lines, with: { max: 400 } }
---
`{{ file.relative }}` would have {{ facts.lines }} lines (max {{ params.max }}). Split it.When Claude writes a 450-line file under src/, the write is refused and Claude reads the body as the
reason. It splits the file and tries again.
What CPO adds to hooks
Claude Code runs matching hooks in parallel and unordered, with loosely typed payloads. CPO routes every hook
to one entry point, ccpp cpo hook, and takes over from there:
- One ordered evaluation. Policies run by priority, then by cost, then by id. The result does not depend on which hook process finished first.
- Typed events. A
Bashcall becomestool.call, thenshell.execwith every parsed command, then onefile.writeper redirection. Policies target the action, whatever tool performs it. - State and history. Counters per session, turn or tool use; the git status; a ledger of what Claude changed this session.
- Protection. Claude cannot quietly edit or disable the policies that guard it.
Quick start
-
Install the plugin in Claude Code (details):
claude plugin marketplace add CCPP-dev/CCPP claude plugin install cpo@ccpp -
Set a ready-made profile for the project, from inside Claude Code:
! ccpp cpo profile set secrets-baseline -
See what is in force. Claude can run this too, and refusals tell it to:
ccpp cpo view -
Add a rule of your own in
.claude/policies/<id>.policy.md, then validate it:ccpp cpo lint -
Dry-run a hook input to see which policies would fire, without writing state or logs:
ccpp cpo trace hook-input.json
Reference
| Page | |
|---|---|
| Policy files | Where policies live, the frontmatter, placeholders. |
| Rules | on → let → when → then, CEL variables and functions. |
| Events | The evaluation pipeline, lifecycle and action events. |
| Builtins | Ready-made checks: size limits, banned commands, protected paths… |
| Actions and messages | What then can do. |
| State and git, Work | Memory between events, the repository, Claude's own changes. |
| Scope, Protection | Monorepos, and keeping Claude from removing a gate. |
| Profiles, Profile sources | Ready-made policy sets, and publishing your own. |
| Code rules, Language servers | Rules over syntax trees, configuration keys and type information. |
| CLI, SDK | Commands, and extending CPO in TypeScript. |