When you're sitting in front of an agent, "don't touch anything outside src/" is enforced by you noticing. Unattended, it has to be enforced by something that runs whether or not anyone is watching.

Claude Code gives you two mechanisms for that, and they are not interchangeable. One is declarative and can't express what you probably want. The other can, but is structurally blind to a whole category of writes. Here's what each one actually does, and the code for the second.

Why permissions.deny isn't enough

Permission rules live in settings.json and take the form Tool(specifier):

{