Skip to main content

Rule precedence — platform vs repo vs personal

A developer runs under three layers of rules at once. This page is the single answer to "which one wins?" — so a repo's CLAUDE.md, a personal preference, and the org standard never silently contradict each other.

The three layers

LayerWhere it livesScopeOwns
1. Platform (org)the bewith plugin (agents/skills/commands/policies/hooks) + autonomy/defaults.yamlevery developer, every repothe standards + the hard floors
2. Repothe repo's CLAUDE.md, git-hooks/config.env, .claude/ overrides at the repo rootone reporepo-specific extensions + overrides
3. Personal (per-machine)~/.bewith/config.json (role, language, notify, …) + ~/.claude/settings.jsonone developer, one machinepersonal preferences

This maps onto Anthropic's CLAUDE.md hierarchy (enterprise/system → project → user): the plugin is the org/system layer (it provides the generic rules globally via name-shadowing), the repo CLAUDE.md is the project layer, and ~/.claude + ~/.bewith are the user layer.

The two-axis model

Precedence is not a single ordering. It depends on whether the rule is a tunable preference or a hard floor:

Axis A — tunable preferences: most-local wins

Personal > Repo > Platform-default. The platform ships a sensible default; the repo can override it for its context; the developer can override it for themselves.

Examples:

  • Conversation language (personal) — a developer sets Hebrew; it overrides the English default. (Artifacts stay English regardless — that's a floor, see Axis B.)
  • Role (personal) — dev vs product filters which capabilities surface.
  • defaultMode: acceptEdits (personal/repo) — opt in to fewer prompts.
  • Stricter lint / REQUIRE_CU_ID=true (repo) — a repo tightens a default via git-hooks/config.env.

Axis B — hard floors: the platform is a floor nobody can lower

For governance and safety, the platform wins. A repo or a personal setting may make a floor stricter, never looser.

Examples of floors (cannot be disabled by any CLAUDE.md or personal setting):

  • The mandatory policiesauth-touch, payment-change, schema-migration require a human + the owning expert agent.
  • no-master-edit, dangerous-git/bash blocks, the session-guard collision block.
  • Pre-push lint/typecheck/tests, branch-name-check, file-size, the CI gate, branch protection.
  • Secrets handling and the Definition of Done gates.
  • Artifacts are always English (a repo or personal language preference changes conversation, not written artifacts).

The one test

Is this a preference or a floor? Preference → the most-local layer wins. Floor → the platform wins, and local layers can only tighten it.

Why floors can't be loosened locally

Because the floors are enforced by code, not prose. A repo CLAUDE.md that says "skip tests on this repo" cannot beat the pre-push test hook; a personal setting can't disable the auth-touch policy. The model reads CLAUDE.md (it can be talked around); the git hooks, PreToolUse blocks, CI, branch protection, and the policy engine run regardless of what any prose says. That is the point of the enforcement tiers — the deterministic layers are immune to a persuasive prompt or a well-meaning local override.

The one structured exception: autonomy. autonomy/defaults.yaml explicitly separates Hard Floor items (never overridable) from configurable ones. A developer's user-override.yaml may loosen a configurable item — and only a configurable item. The Hard Floor list is the canonical floor for autonomy decisions.

Worked resolutions

SituationLayer that winsWhy
Developer prefers Hebrew chatPersonalpreference (Axis A)
Repo needs REQUIRE_CU_ID=trueRepotightens a default (Axis A — stricter is fine)
Repo CLAUDE.md: "commit straight to master here"Platformfloor (Axis B) — no-master-edit + branch protection ignore it
Personal setting tries to skip the auth policyPlatformfloor (Axis B) — the policy engine + agent-guard still fire
Repo wants a stricter file-size limit than the defaultRepotightening a floor is allowed (Axis B)
user-override.yaml loosens a configurable autonomy gatePersonalallowed — it's configurable, not Hard Floor

How a session resolves it (order of reading)

  1. The platform loads via the plugin (standards + floors).
  2. The repo CLAUDE.md + git-hooks/config.env refine it (the git hooks read the repo's config.env first, then the platform default).
  3. The personal ~/.bewith/config.json / ~/.claude/settings.json apply the developer's preferences.
  4. For every action, the deterministic floors (hooks / PreToolUse / CI / policy engine) run last and unconditionally — they are not subject to layers 2–3 except to be made stricter.

See also

  • consumption-model.md — how the platform federates into repos (name-shadowing, references-not-copies).
  • enforcement-tiers.md — where each rule fires (Tier 0 opt-in → Tier 5 branch protection); why floors are code, not prose.
  • autonomy-model.md — Hard Floor vs configurable vs never-ask; the canonical floor for autonomy.
  • repo-migration.md — onboarding a repo, where the repo layer is authored.