ccppccpp home
Browse the documentation

Plugins · CPO

Scope

Confine a policy to areas of a monorepo, and how CPO locates files and shell commands.

scope confines a policy to directories of the project, so the packages of a monorepo keep their own rules.

.claude/policies/api-pnpm.policy.md
---
description: The API installs with pnpm
scope: [apps/api]
on: [shell.exec]
when: { builtin: command-ban, with: { commands: [npm] } }
---
`apps/api` uses pnpm.
  • Each glob names a directory relative to the project: apps/api, apps/*, packages/**. A trailing /** changes nothing.
  • A location is in scope when it or one of its parent directories matches. The project root and paths outside the project are in no scope.
  • scope combines with paths / exclude: both must pass.
  • A whole profile takes a scope too: its policies apply where their own scope and the profile's both hold (Profile sources).

How an event is located

EventLocated by
file.*, search and other events with a paththe path
shell.execeach command's cwd: the policy only sees the commands running in its scope, and does not apply when none does
any other eventClaude's working directory (event.session.cwd)

In cd apps/api && npm i; cd ../web && pnpm i, a policy scoped to apps/web sees only pnpm i. The raw command string stays the whole line.

A command's cwd

Every parsed command carries cwd, the absolute directory it runs in. It starts at Claude's working directory and follows the line:

  • cd, pushd / popd, command cd; a ( … ) subshell restores it after );
  • sh -c '…', eval and $( ) start where their parent runs and do not move the outer shell;
  • directory options: git -C, go -C, cargo -C, make -C, ninja -C, tar -C, pnpm --dir, npm --prefix, yarn --cwd, bun --cwd, turbo --cwd, uv --directory, poetry -C, gradle -p, terraform -chdir=, just -d, env -C, sudo -D.

cwd is null when CPO cannot know it: cd "$DIR", cd "$(…)", cd -, cd apps/*. Such a command is in every scope: hiding where a command runs does not dodge a gate.

cwd only locates commands for scope. The files a shell reads or writes keep resolving against Claude's working directory.

Edit this page on GitHub