Plugins · CPO
Protection
A rule is only a gate if Claude cannot remove it. How CPO protects its own files.
Without protection, Claude could write .claude/policies/env-files.policy.md with enabled: false and silently
disable a profile's rule. CPO therefore ships two built-in policies, defined in code: no file can override or
disable them, and they run before every other policy. ccpp cpo list shows them with the scope built-in.
| Policy | Effect | Paths |
|---|---|---|
cpo-protected-files | ask: you confirm the change | .claude/policies/**, ~/.ccpp/**, .claude/settings*.json, ~/.claude/settings*.json, ~/.claude/plugins/** |
cpo-locked-files | block | every file defining, overriding (same id, any scope or profile) or run by (module) a policy marked claudeCanEdit: false |
Both watch file.write (Write, Edit, NotebookEdit, redirections, tee, and what a shell command wrote) and
shell.exec, through the protected-paths
builtin. rm -rf .claude, sed -i … .claude/policies/x.policy.md or ccpp cpo profile unset are caught before
they run. Reading policies stays free: Claude may run ccpp cpo view and cat them.
claudeCanEdit
---
description: .env files hold secrets; Claude may only touch the committed examples
on: [file.read, file.write]
paths: ["**/.env", "**/.env.*"]
claudeCanEdit: false
then: [deny]
---| Where | Value | Claude changing it |
|---|---|---|
| policy frontmatter | true (default) | asked to the user |
| policy frontmatter | false | refused: the policy, a same-id override in any scope and its module are locked |
~/.ccpp/config.yml, cpo.claudeCanEdit | true (default) | asked to the user |
~/.ccpp/config.yml, cpo.claudeCanEdit | false | every protected file is refused |
claudeCanEdit binds Claude only: a person still edits these files, and ccpp cpo profile view and
ccpp doctor report a profile file edited since it was set. An organisation ships its non-negotiable rules in a
profile with claudeCanEdit: false (the bundled secrets-baseline does), from a
signed source.
config.yml
cpo:
claudeCanEdit: true # false: Claude may not change any CPO file, even with confirmation
profiles:
source: https://acme-ccpp.s3.eu-west-3.amazonaws.com/profiles/
publicKey: ed25519:… # only indexes signed with this key are readThe file lives in ~/.ccpp/, which is itself protected. An invalid cpo section stops every ccpp command with
the file and field at fault.