All sections

11Resolving

Conflicting rules

Each subsystem resolves disagreements differently, and two of them resolve in opposite directions. This is the page to re-read when Claude does something you did not ask for.

The master table

Subsystem Resolution model Who wins Deterministic?
Memory files (CLAUDE.md, CLAUDE.local.md) Additive, all concatenated Nobody. Later text has a mild edge No
Rules (.claude/rules/) Additive, all concatenated Nobody. Project rules read after user rules No
Settings (settings.json) Override Managed > CLI > local > project > user Yes
Skills (name collision) Shadowing Enterprise > personal > project Yes
Agents (name collision) Shadowing Managed > CLI > project > user > plugin Yes
Output style Single value Resolved by the settings hierarchy Yes
Hooks Additive, all matching hooks run Everyone. No shadowing Yes
Permissions Deny wins An explicit deny beats any allow Yes
flowchart TD
    START["Two pieces of configuration disagree"] --> T{"What kind?"}

    T -->|"Prose:<br/>CLAUDE.md, rules"| PROSE["<b>Both are in context.</b><br/>Model picks — possibly arbitrarily.<br/>➜ Remove the contradiction yourself"]
    T -->|"Structured value:<br/>settings.json key"| CFG["<b>Precedence order applies.</b><br/>Managed > CLI > local > project > user"]
    T -->|"Same-named skill"| SKL["<b>Personal shadows project.</b><br/>➜ Rename one, or namespace via a plugin"]
    T -->|"Same-named agent"| AGT["<b>Project shadows personal.</b><br/>➜ Opposite of skills. Check with /agents"]
    T -->|"Permission rules"| PRM["<b>Deny always wins.</b>"]
    T -->|"Multiple hooks<br/>on one event"| HK["<b>All of them run.</b><br/>Order is not guaranteed"]

Memory files: there is no precedence engine

This is the most consequential misunderstanding about Claude Code.

All discovered memory files are concatenated into the prompt. They do not override each other. The discovery order (root → cwd, and CLAUDE.local.md after CLAUDE.md within a directory) is a reading order, not a priority order.

If two memory files contradict each other, Claude may pick either one. Text read later tends to have a mild edge, and more specific instructions tend to beat more general ones, but neither is guaranteed, and the choice can differ between turns in the same session.

The failure case

~/.claude/CLAUDE.md

- Always write tests before implementation.

./CLAUDE.md

- This is a spike repository. Do not write tests.

What happens: both statements are in context. Claude will comply with one, usually the project file, but not reliably. You will see it write tests roughly one time in five and have no idea why.

Three correct fixes, in order of preference

1. Remove the contradiction. Rewrite the global rule so it never fires here:

- Write tests before implementation unless the project's CLAUDE.md
  says otherwise.

This works because you have converted a conflict into a conditional. The model is good at conditionals and bad at silent arbitration.

2. Scope the global rule out of existence. Move it from ~/.claude/CLAUDE.md into ~/.claude/rules/testing.md with a paths: glob so it only loads for the file types where you actually mean it.

3. Exclude the ancestor file with claudeMdExcludes. This is the only true override available for memory, and it is blunt: it removes the whole file, not one line.

Design principle: keep the layers disjoint. Global memory holds preferences that are true everywhere; project memory holds facts about the project. If you find yourself relying on “the project file should win”, you have already put the wrong thing in the global file.

Rules: additive, with a soft ordering

~/.claude/rules/ loads before .claude/rules/, so project rules are read later and carry more weight. But both load. “Higher priority” is not “replaces”.

~/.claude/rules/go.md

---
paths: ["**/*.go"]
---
- Use `github.com/pkg/errors` for wrapping.

.claude/rules/go.md

---
paths: ["**/*.go"]
---
- Use standard library `fmt.Errorf` with `%w`. Do not add `pkg/errors`.

Same filename does not cause shadowing. Both are in context, directly contradicting each other. The project rule usually wins because it is read later. Usually.

Fix: your personal rules directory should hold preferences that no project would contradict: how you like explanations, review depth, commit message style. Authoritative technical conventions belong in the project’s committed rules. If a personal rule ever conflicts with a repository standard, delete the personal rule; the conflict is a signal it should never have been global.

Settings: real precedence

Settings are the well-behaved subsystem. A given key resolves to exactly one value.

File model env.GOFLAGS
~/.claude/settings.json "opus" "-mod=readonly"
.claude/settings.json "sonnet" (unset)
.claude/settings.local.json (unset) "-mod=mod"
Effective "sonnet", project beats user "-mod=mod", local beats user

Note that resolution is per key, not per file. The user file still supplies any key the higher-priority files don’t set.

Permissions are the exception within settings: they merge rather than override, and a deny rule beats an allow rule from any scope. An enterprise deny cannot be overridden at all.

Skills vs agents: opposite directions

The genuinely confusing one.

graph TD
    subgraph SK["SKILLS personal wins"]
        S1["Enterprise"] --> S2["<b>Personal ~/.claude/skills/</b>"]
        S2 --> S3["Project .claude/skills/"]
    end

    subgraph AG["AGENTS project wins"]
        A1["Managed"] --> A2["--agents CLI flag"]
        A2 --> A3["<b>Project .claude/agents/</b>"]
        A3 --> A4["Personal ~/.claude/agents/"]
        A4 --> A5["Plugin agents/"]
    end

The skills trap

You wrote ~/.claude/skills/deploy/SKILL.md months ago for a side project. You join a team whose repo ships .claude/skills/deploy/SKILL.md.

Typing /deploy runs yours. Silently. Against their infrastructure.

Fix How
Rename yours ~/.claude/skills/deploy-personal/
Package the team’s as a plugin Becomes /platform:deploy, namespaced, cannot collide
Audit before trusting Run /skills (or /help) in a new repo and look for names you recognise

For agents the direction is reversed, so a project agent correctly overrides your personal one of the same name, which is usually what you want. Verify with /agents.

The practical rule: never give a personal skill a generic name. deploy, review, test, commit, release and build are all names a repository is likely to claim. Prefix yours.

Output style: last write wins, via settings

outputStyle is a single settings key, so the settings hierarchy applies. A project-level outputStyle overrides your personal one.

Two subtleties:

  • The change only takes effect after /clear or a new session, because the system prompt is assembled at session start. Setting it mid-conversation and seeing no change is expected, not a bug.
  • A custom output style with keep-coding-instructions: false removes the built-in engineering instructions. This is not a conflict the model arbitrates; the text is simply gone. If Claude suddenly stops verifying its work after you add a custom style, this is why.

Hooks: everybody runs

There is no precedence. All hooks matching an event execute. A PreToolUse hook from your settings, one from the project settings, and one from a plugin will all fire.

  • Order is not guaranteed. Never write two hooks that depend on running in a particular sequence.
  • Any one of them can block. A single non-zero exit is enough.
  • They compose badly if they mutate the same file. Two PostToolUse formatters on the same path will fight.

The interaction that catches everyone

Layers can conflict across subsystems, not just within one. The resolution is by mechanism strength, not by scope:

Conflict Winner Why
CLAUDE.md says “always run gofmt” vs. a PostToolUse hook that runs gofumpt Hook Deterministic beats probabilistic. Claude’s own attempt is then overwritten
CLAUDE.md says “you may edit migrations” vs. a PreToolUse hook blocking migrations/ Hook The tool call never executes
A rule says “use Bash freely” vs. permissions.deny on Bash(rm *) Permission Deny is enforced outside the model
A subagent’s system prompt vs. your CLAUDE.md Both apply Custom subagents load CLAUDE.md. Explore and Plan do not
An output style vs. CLAUDE.md Both apply Different parts of the prompt; if they contradict, you are back to the additive case

A conflict-resolution checklist

When Claude does something you didn’t expect:

  1. /context. Was the instruction even loaded? Half of all “Claude ignored my rule” cases end here.
  2. /memory. Is there a second memory file saying the opposite? Check ancestor directories, which is where the surprises live.
  3. /agents and /skills. Is a personal definition shadowing the project’s?
  4. Check settings.local.json. A value you set once and forgot outranks the committed project file.
  5. Check plugin hooks. Enabled plugins contribute hooks you did not write.
  6. Only then conclude the model made a judgement call.