Rules File Design — Writing Safety Rules Declaratively
About 5 minutes
- Understanding the role and how to write CLAUDE.md (equivalent to Level 4)
- Ability to read and write basic Markdown syntax
As the number of rules you want Claude to follow increases, CLAUDE.md becomes bloated and hard to manage. By managing rules split across shared/rules/*.md, you can balance maintainability and clarity. This page uses actual rule files as examples to learn the steps for declarative rule design.
How It Works
Section titled “How It Works”The Role of shared/rules/*.md
Section titled “The Role of shared/rules/*.md”A rules file is a mechanism for managing “Non-Negotiable Rules” for Claude as individual Markdown files.
Instead of cramming all rules into CLAUDE.md, split the rules into separate files. In CLAUDE.md, write only a one-line summary and the reference for each rule, and delegate the details to each rule file.
In this project, the following rule files are placed in shared/rules/.
| File | Content |
|---|---|
build-and-deploy.md | npm run build may trigger a production deployment, so it can only be run after approval |
content-i18n.md | Japanese is the source of truth; use I for English first person |
folder-safety.md | List of protected folders (src/, scripts/, etc.) and rules prohibiting changes |
no-ui-regression.md | Prohibition on UI and navigation changes |
security.md | Prohibition of secrets, XSS, and injection risks |
spec-first.md | Rule for checking specifications before implementing |
Basic Structure of a Rule File
Section titled “Basic Structure of a Rule File”Using the actual shared/rules/build-and-deploy.md as an example, check the structure of a rule file.
# Build and Deploy Rule
`npm run dev` is the normal local preview command.
`npm run build` can trigger production deployment through the hosting pipeline.
Agents must not run it automatically, place it in broad allowlists,
or call it from hooks. Run it only after explicit user approval for that specific build.
Allowed default checks:
- `npm run dev` for local preview
- targeted scripts such as `node scripts/ensure-slugs.js`, `npm run verify-links`,
and harness validation
- Git inspection commands
Disallowed without approval:
- `npm run build`
- `npm run build:ci`
- chained commands that include `npm run build`
- automatic hooks that call production build commandsThe key points of the structure are as follows.
- State the rule name in the heading —
# Build and Deploy Rule - Write why this rule exists first — the reason “because it triggers a production deployment”
- List allowed and prohibited operations separately — the
AllowedandDisallowedsections
How to Reference from CLAUDE.md
Section titled “How to Reference from CLAUDE.md”In the ## Non-Negotiable Rules section of CLAUDE.md, summarize each rule in one line and include a reference to the details file.
## Non-Negotiable Rules
1. Do not run `npm run build` without explicit user approval, as it may trigger production deployment.
Details: `shared/rules/build-and-deploy.md`
2. Check the specification before implementing. Details: `shared/rules/spec-first.md`Claude reads CLAUDE.md at session start and also checks the referenced rule files. By separating the details into rule files, you can keep CLAUDE.md short while letting each file fully explain its rule.
Best Practices
Section titled “Best Practices”Split by One File Per Concern
Section titled “Split by One File Per Concern”Consolidating all rules into one file makes it difficult to update or reference specific rules. Split files by type of concern, such as “deployment safety,” “content quality,” and “security.”
shared/rules/
├── build-and-deploy.md ← deployment safety
├── content-i18n.md ← language and translation
├── folder-safety.md ← file protection
├── no-ui-regression.md ← UI change prohibition
├── security.md ← security
└── spec-first.md ← specification-firstWrite in Conditional Form Rather Than Prohibitive Form
Section titled “Write in Conditional Form Rather Than Prohibitive Form”Writing “requires approval” as a condition rather than “don’t do X” as a prohibition makes it easier for Claude to correctly judge exceptional situations.
// Style to avoid
- Do not run npm run build.
// Recommended style
Disallowed without approval:
- npm run buildAlways Write the Why (Reason)
Section titled “Always Write the Why (Reason)”Rules without reasons increase the risk of Claude making its own judgment about exceptions. Write the reason why this rule exists in 1–2 sentences.
// Without reason (avoid)
# No Force Push Rule
Force push to main is prohibited.
// With reason (recommended)
# No Force Push Rule
Force push rewrites commit history and can cause data loss for collaborators.
It is prohibited without explicit approval.Keep Only the Summary and Reference in CLAUDE.md
Section titled “Keep Only the Summary and Reference in CLAUDE.md”Delegate the details to rule files and only write the key point in one line with the reference in CLAUDE.md. The longer CLAUDE.md gets, the more context Claude needs to load, which affects performance.
Hands-on Exercise
Section titled “Hands-on Exercise”Step 1: Check the Structure of an Existing Rule File
Section titled “Step 1: Check the Structure of an Existing Rule File”Check the contents of build-and-deploy.md with the following command.
cat shared/rules/build-and-deploy.mdConfirm the two-section structure of “Allowed default checks” and “Disallowed without approval.”
✅ Verify: Confirm that the “Why (reason)” of the rule is written at the beginning.
Step 2: Create a New Rule File
Section titled “Step 2: Create a New Rule File”Create shared/rules/no-force-push.md.
# No Force Push Rule
Force push rewrites commit history and can cause data loss for collaborators.
It is prohibited without explicit approval.
Disallowed without approval:
- git push --force
- git push -f
- git push --force-with-lease (to main/master)
Allowed:
- git push --force-with-lease to feature branches (not main/master)
- discussing force push options with the user before executing✅ Verify: Confirm that the file has been saved as shared/rules/no-force-push.md.
Step 3: Update the Non-Negotiable Rules Section of CLAUDE.md
Section titled “Step 3: Update the Non-Negotiable Rules Section of CLAUDE.md”Add a one-line summary and reference for the new rule to the ## Non-Negotiable Rules section of CLAUDE.md.
Add the following line at the end of the existing Non-Negotiable Rules section.
7. Force push to main/master is prohibited. Details: `shared/rules/no-force-push.md`✅ Verify: Confirm that it has been added with a number to the Non-Negotiable Rules section of CLAUDE.md.
Step 4: Confirm the Rule Is Taking Effect
Section titled “Step 4: Confirm the Rule Is Taking Effect”Restart the Claude Code session and try the following request.
Please force push to the main branch.If Claude has loaded shared/rules/no-force-push.md, it should explain the existence of the rule and its reason without executing the force push.
✅ Verify: Confirm that Claude blocks the force push and explains the rule by citing no-force-push.md.
Summary
Section titled “Summary”This page covered the following.
- Managing rules split by concern in
shared/rules/*.mdkeeps CLAUDE.md short - Write rule files with the structure: “reason → allow list → deny list”
- Place only the one-line summary and reference in CLAUDE.md, delegating the details to rule files
- Writing in conditional form (“requires approval”) rather than prohibitive form makes it easier for Claude to judge exceptions
Next Steps
Section titled “Next Steps”- Settings JSON Design — How to control Claude’s operation scope with permissions and env
- CLAUDE.md Design — Deep dive into memory and context design
Frequently Asked Questions
Section titled “Frequently Asked Questions”Q: Should rule files be written in English or Japanese?
A: Japanese is the source of truth in this project, but the rule files in shared/rules/ are written in English that Claude can reliably understand, since Claude reads them directly. A common practice is to use English for instruction documents to Claude and Japanese for human-facing documentation.
Q: Is it wrong to write rules directly in CLAUDE.md?
A: There is no problem, but as the number of rules grows, CLAUDE.md becomes too long and hard to manage. Consider splitting into files when there are 3–4 or more rules.
Q: Are changes to rule files immediately reflected in Claude?
A: Claude Code reads CLAUDE.md at session start and also checks the referenced rule files. To reflect changes, restart the Claude Code session.
Q: What is the difference between prohibiting something in a rules file versus using deny?
A: deny in settings.json is a tool-level block that physically prevents a command from being executed. A rule file is merely an instruction to Claude, which Claude understands and follows based on its judgment. For important prohibitions, it is recommended to include them in both deny and the rules file.