Skip to content
Skill Authoring
Skill

/writing-rules

How to write .claude/rules/ files: golden format, enforceability, budget, scope.

BOOST
From plugin
nlpm
15317 skills8 agents15 commands1 hook
Install
$ npx -y skills add xiaolai/nlpm --skill writing-rules --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/writing-rules

Context preview

The summary Claude sees to decide when to auto-load this skill.

How to write .claude/rules/ files: golden format, enforceability, budget, scope.

SKILL.md

writing-rules.SKILL.md
name: writing-rules
description: "How to write .claude/rules/ files: golden format, enforceability, budget, scope."
version: 0.2.0
user-invocable: false

Writing Rules

> Scope: covers `.claude/rules/` file authoring — a **Claude-Code-specific** concept (path-scoped, always-loaded instruction files with `paths:` glob frontmatter). Codex CLI and Antigravity have no exact `.claude/rules/` equivalent; their always-on project instructions live in the hierarchical memory file (`AGENTS.md` for Codex, `GEMINI.md` for Antigravity — both can be pointed at the canonical `AGENTS.md`; see [[nlpm:conventions-codex]] / [[nlpm:conventions-antigravity]]). The bold-imperative-plus-rationale writing technique here applies to any tool's instruction files. For CLAUDE.md / AGENTS.md conventions, see [[writing-plugins]]. For system prompts generally, see [[writing-prompts]].

1. The Golden Format

Every rule should have three parts:

**Use X, not Y.** Without X, [concrete bad thing happens]. Y causes [specific problem] because [mechanism].

| Part | Purpose | Example | |------|---------|---------| | Imperative | What to do | **Use `Result<T, AppError>` for all API handler returns.** | | Consequence | What goes wrong without it | Without it, errors propagate as 500s with no context. | | Mechanism | Why it fails | Raw panics bypass the error middleware and crash the worker. |

One-Line Rules (when mechanism is obvious)

**Use `const`/`let`, never `var`.** `var` hoists to function scope, causing stale-reference bugs.

Multi-Line Rules (when mechanism needs explanation)

**Use database transactions for multi-table writes.** Without transactions, partial writes leave the database in an inconsistent state. The ORM's `save()` method does not auto-wrap related writes -- you must explicitly call `db.transaction()`.

2. Positive Framing (Pink Elephant Effect)

Claude fixates on prohibited things. Saying "Don't use X" makes Claude think about X.

Before (negative framing -- score 60)

- Don't use var
- Don't mutate function parameters
- Don't use console.log in production code

After (positive framing -- score 90)

- **Use `const` for all bindings; use `let` only when reassignment is required.**
- **Return new objects instead of mutating function parameters.**
- **Use the `logger` service for all logging.** `console.log` is stripped in production builds.

Conversion Pattern

| Negative (avoid) | Positive (use instead) | |-------------------|----------------------| | Don't use X | **Use Y** (where Y is the correct alternative) | | Never do X | **Always do Y** | | Avoid X because... | **Use Y because...** (flip the rationale) | | X is deprecated | **Use Y, which replaced X in version N** |

3. Enforceability Test

Before writing a rule, ask: **"Can I check compliance in a 30-second code review?"** If no, it is not a rule.

Enforceable (specific, testable)

| Rule | Test | |------|------| | **Use `Result<T, AppError>` for all API handler returns.** | Grep for handler functions, check return types | | **All API endpoints require `@auth` decorator.** | Grep for route definitions, check for decorator | | **Database queries use parameterized statements, not string concatenation.** | Grep for SQL strings, check for `+` or template literals |

Not Enforceable (subjective, unmeasurable)

| Rule | Why it fails | |------|-------------| | "Write clean, maintainable code" | What is "clean"? No objective test. | | "Keep functions small" | How small? 10 lines? 20? 50? | | "Use meaningful variable names" | "Meaningful" is subjective. | | "Follow best practices" | Which practices? Says nothing specific. |

Making Vague Rules Enforceable

| Vague | Enforceable version | |-------|-------------------| | "Keep functions small" | **Functions must be under 40 lines.** Reference: enforced by `eslint max-lines-per-function` | | "Use meaningful names" | **Variable names must be >= 3 characters except loop indices (`i`, `j`, `k`).** | | "Handle errors properly" | **Every `catch` block must either re-throw, log + return error response, or call `reportError()`.** |

4. Budget Discipline

All rules across `.claude/rules/` must total **under 500 lines**. Every line costs tokens on every Claude interaction -- rules are always loaded.

Token Cost

| Rule lines | Approx tokens per interaction | Annual cost at 100 interactions/day | |-----------|------------------------------|-------------------------------------| | 100 | ~400 | Negligible | | 300 | ~1,200 | Noticeable | | 500 | ~2,000 | Budget line | | 800+ | ~3,200+ | Over budget -- consolidate |

Line Reduction Strategies

| Strategy | Example | Lines saved | |----------|---------|-------------| | Defer to linter | "Reference: enforced by `pnpm lint`" instead of re-stating lint rules | 10-30 | | Merge related rules | Combine 3 files about error handling into 1 | 15-25 | | Delete training knowledge | Remove rules Claude follows without being told | 5-15 | | Use tables instead of lists | 10 rules as list = 20 lines; as table = 12 lines | 5-10 |

Rules Claude Already Follows (safe to delete)

These are part of Claude's training and do not need rules:

  • "Use descriptive variable names" (Claude already does this)
  • "Add comments to complex code" (Claude already does this)
  • "Handle null/undefined checks" (Claude already does this)
  • "Use async/await instead of callbacks" (Claude already prefers this)

Only write rules for things **specific to your project** that Claude would not know.

5. Path Scoping

Rules without path scoping apply to every file -- expensive and often wrong.

---
paths: ["src/api/**/*.ts"]
---

Scoping Strategy

| Rule type | Scope | Example paths | |-----------|-------|---------------| | API conventions | API routes only | `src/api/**/*.ts`, `src/routes/**/*.ts` | | Database rules | Data layer only | `src/db/**/*.ts`, `src/models/**

Read more
Ships withnlpm

Natural-Language Programming Manager — score, check, fix, and test NL artifacts across Claude Code, Codex CLI, and Antigravity. Tier-aware scoring with per-tool overlays. Part of the xiaolai plugin marketplace.

Get the whole plugin

Other skills on nlpm.