ccppccpp home
Browse the documentation

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.

PolicyEffectPaths
cpo-protected-filesask: you confirm the change.claude/policies/**, ~/.ccpp/**, .claude/settings*.json, ~/.claude/settings*.json, ~/.claude/plugins/**
cpo-locked-filesblockevery 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

.claude/policies/env-files.policy.md
---
description: .env files hold secrets; Claude may only touch the committed examples
on: [file.read, file.write]
paths: ["**/.env", "**/.env.*"]
claudeCanEdit: false
then: [deny]
---
WhereValueClaude changing it
policy frontmattertrue (default)asked to the user
policy frontmatterfalserefused: the policy, a same-id override in any scope and its module are locked
~/.ccpp/config.yml, cpo.claudeCanEdittrue (default)asked to the user
~/.ccpp/config.yml, cpo.claudeCanEditfalseevery 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

~/.ccpp/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 read

The file lives in ~/.ccpp/, which is itself protected. An invalid cpo section stops every ccpp command with the file and field at fault.

Edit this page on GitHub