Take two commits filed about an hour apart, both landing in the same six lines of a project's CLAUDE.md. One developer tightens a convention: "prefer named exports" becomes "use named exports only; default exports are not allowed outside route files." The other, working on an import queue, adds a line to the same block noting that staging resets nightly. Git does what git does and hands back a CLAUDE.md merge conflict, and neither person wants to resolve it by guessing which half matters more.

This is a made-up collision, but it is the ordinary kind. Nobody did anything wrong. Both edits were small, both were correct in isolation, and the file they share has no test that will tell you whether the merged version still makes sense.

What makes it worth walking through is that the conflict markers are hiding the real problem. The two developers were not disagreeing. They were writing two different kinds of content into one file.

Two changes to the same file, filed an hour apart

Here is roughly what lands in the working tree:

<<<<<<< HEAD
## Conventions
- Use named exports only. Default exports are not allowed outside route files.
- Run `pnpm test` before committing.
=======
## Conventions
- Prefer named exports.
- Run `pnpm test` before committing.
- Staging resets nightly at 02:00, so seed data is not durable.
>>>>>>> feature/import-queue

The first developer tightened the export rule because a default export had slipped through review and broken a barrel import, and the assistant had cheerfully suggested the default export in the first place. The second developer added the staging note because an agent had spent twenty minutes building a seeding script on the assumption that data survived overnight.

Both changes exist because an assistant got something wrong and someone decided the file should prevent the repeat. That is the right instinct. The file is now the collision point for it.

Why a CLAUDE.md merge conflict isn't like a code conflict

With code, a conflict has an arbiter. You resolve it, run the suite, and the build tells you whether you merged nonsense. With a shared project instructions file there is nothing to run. A badly merged CLAUDE.md produces no error. It produces an assistant that behaves slightly differently than you expect, two weeks later, in a way nobody connects back to this afternoon.

The second difference matters more. In code, "keep both sides" is often a legitimate resolution: two functions, two imports, two test cases, all fine. In an instruction file, keeping both sides can leave you with a document that says "prefer named exports" in one place and "default exports are not allowed" in another. A human reading that picks the stricter one and moves on. An assistant reads both, has no way to rank them, and resolves the tension silently in whichever direction the surrounding tokens push it. That is one of the quieter reasons an assistant seems to ignore CLAUDE.md: the file contradicted itself and something had to give.

And a diff carries no intent. - Prefer named exports / + Use named exports only tells you the text changed. It does not tell you a default export broke a barrel import last Thursday, which is the only fact that makes the stricter rule defensible.

What actually collided: a rule, a fact, and a preference wearing the same hat

Unpack the conflict and there are three things in it.

The export line is a rule. It constrains what the assistant may write, it applies to every file in the repo, and it should change rarely. The staging line is a fact about the environment. It constrains nothing; it corrects a wrong assumption. It will also change the first time someone moves the reset window or points staging at a persistent volume.

The third thing is the word "prefer." A rule that says prefer is a preference, and preferences get overridden by anything that looks like a reason. Rewriting it to "only, except route files" turned a preference into a guardrail with a stated exception, which is the kind of edit that actually changes behaviour. The piece on why guardrails fail and how to rewrite them covers that shape of change in more detail.

So the hour-apart collision was a rule being hardened and a fact being filed, into a section called "Conventions" that was never meant to hold both. The git conflict is a symptom of the file doing two jobs.

The split that would have kept them out of each other's way

Separate the two kinds of content and the two edits stop touching each other. One lands in the instruction file, the other in project memory:

CLAUDE.md                        # rules the assistant must follow
.prjcontext/memory/
  environments.md                # staging resets, local setup, what is ephemeral
  decisions.md                   # why the export rule got stricter, and when

Plain folders work exactly as well if you are not using PrjLab: docs/context/ with the same three files does the job. The split is the useful part, not the path. Splitting rules from facts is the version of this argument without a merge conflict attached.

A few habits make the rules file itself conflict less often:

  • One rule per line, phrased so it stands alone. Prose paragraphs conflict on every edit; bullet lists conflict only when two people touch the same bullet.
  • Stable section order, so nobody reshuffles the file and turns a one-line change into a 40-line diff.
  • New rules appended to the end of their section rather than inserted in the middle.

If your team keeps both files because people use different assistants, the same thing happens with a git conflict on AGENTS.md, usually worse, because the duplicated content drifts. Keeping one file or two without drift goes through the options.

Resolving it without losing either person's reasoning

Resolving context file conflicts is less about the markers than about a two-minute conversation. For the case above:

  1. Ask each person what their edit was reacting to. "An agent wrote a default export and the barrel import broke" and "an agent assumed seed data persisted" are the two answers, and they are the part worth keeping.
  2. Keep the tightened rule, because it came from a concrete failure. Drop the exception clause into its own line so it is visible rather than buried in a sentence.
  3. Move the staging fact to environments.md, where it belongs and where it can be updated without anyone opening the instruction file.
  4. Write one line in decisions.md recording why the rule got stricter and when. That is the line that stops someone loosening it back to "prefer" in six months.
  5. Have the other person review the resolved version, not just approve the merge. An instruction change alters what every future session does.

The reasoning in step 4 is the thing a bare diff cannot give you. Because PrjLab stores CLAUDE.md, memory and sessions in the same pushed repository as the source, every push is an immutable version you can open in the browser with its list of changes and a line diff against the previous one, so "when did this rule tighten, and what else arrived with it" is a question you can answer by looking. It sits beside git rather than replacing it, and prj pull reports conflicting files instead of overwriting your local edits, which matters when the file in question is the one your assistant reads first.

Making the next collision rarer, not impossible

You will still get conflicts. People edit shared files. What you can change is how expensive each one is.

The most effective habit in a team CLAUDE.md workflow is to stop editing instructions as a drive-by. If a rule needs tightening, that is its own commit with its own message, not line 14 of a branch about import queues. Reviewers notice it, and the person who disagrees gets a chance to say so before the merge rather than during it.

Worth adding to the top of the file: a sentence saying what belongs in it and where facts go instead. Two lines of meta-instruction save a surprising amount of arbitration later. And when someone new joins, point them at the split before they start adding to it, which is most of what sharing AI coding context with your team is about.

If you want the folder layout and the push workflow in order, the getting-started guide walks through capturing instructions, memory and sessions as part of the same repository.