Two agents. Same repo.
Clean merge. Broken code.

conflict-check catches semantic conflicts between parallel AI coding agents — the ones git merge never sees, because the changes never touch the same line, or even the same file.

~/demo — real output, npm run demo, nothing edited
$ git checkout agent-a-rename && git merge agent-b-add-helper
Auto-merging math.js
# clean merge. no conflict markers. exit code 0.

$ conflict-check check --branch-a agent-a-rename --branch-b agent-b-add-helper

Checking "agent-a-rename" (1 file) against "agent-b-add-helper" (1 file)...
Using gemini (gemini-3.6-flash)

Overlapping files: math.js

Checking math.js... CONFLICT

✗ math.js
Agent A renames the `add()` function to `sum()`, while Agent B adds a new
`sumAll()` function that explicitly calls `add()`. If both changes are
merged, `sumAll()` will attempt to call `add()`, which no longer exists,
resulting in a runtime ReferenceError.

Summary:
✗ 1 of 1 overlapping file(s) have a likely semantic conflict.

Why this exists

Run multiple AI coding agents — Claude Code, Codex, Cursor, whatever — in parallel git worktrees on the same repo, and eventually they collide in a way git merge can't see. Agent A renames a function, changes what it returns, or changes some assumption about shared state. Agent B, working in a different worktree with zero visibility into what A is doing, writes new code that depends on the old behavior.

“No markers, no warning, exit code 0. The build's green. It just doesn't work anymore.”

conflict-check tries to catch that before you merge. You tell it what each agent was supposed to be doing, it grabs the diff each agent actually produced, and it asks an LLM whether the two look like they're making conflicting assumptions about the same code.

It catches cross-file conflicts too

The same-file example above is the easy case — both agents touched math.js, so there was an overlapping file to even look at. The harder, more common case is when they don't share a file: one agent renames a function, and the other calls the old name from a completely different file it added or already had. No overlapping filename, no diff collision — git merge sees nothing.

conflict-check parses each branch's diff with a real AST (via ts-morph) to find functions and methods that were added, removed, or renamed, then searches the whole repo — not just the diff — for anything that still calls the old name.

~/demo — same scenario, agent B's new file never overlaps agent A's
$ conflict-check check --branch-a agent-a-rename --branch-b agent-b-add-helper

Checking 2 branches (1 pair): agent-a-rename, agent-b-add-helper
Using gemini (gemini-3.6-flash)

=== "agent-a-rename" ⇄ "agent-b-add-helper" ===

[same-file] 0 file(s) touched by both branches
  ✓ No files touched by both branches.

[cross-file] renamed/removed symbols still referenced elsewhere
  Checking math.js: `add` renamed to `sum`... CONFLICT
 CROSS-FILE  math.js — `add` renamed to `sum` — from branch "agent-a-rename"
   CONFIRMED REFERENCE 
    [confirmed] batch.js:1 (branch "agent-b-add-helper") — import { add } from "./math.js";
    [confirmed] batch.js:4 (branch "agent-b-add-helper") — return numbers.reduce((total, n) => add(total, n), 0);
  Branch agent-a-rename renamed `add` to `sum` in math.js, but branch
  agent-b-add-helper's new batch.js still imports and calls `add`, which no
  longer exists after the rename. Merging both branches will throw at
  import/call time.

=== Summary ===
✓ No same-file conflicts across 0 checked file(s).
✗ 1 cross-file conflict(s) with a CONFIRMED reference (real import/scope resolution).
CONFIRMED REFERENCE

Resolved through real import/scope binding — ts-morph's language service, not a name that just happens to match.

POSSIBLE — NAME MATCH ONLY

The old declaration couldn't be resolved semantically (say, both branches touched the same symbol), so this is a plain AST name match instead. Still worth a look — but a coincidentally reused name could slip through here. Treat it as a lead to verify, not a confirmed diagnosis.

Installing it

Not on npm yet, so you'll have to build it yourself.

# clone, install, build, link
git clone https://github.com/Cipher-08/conflict-check.git
cd conflict-check
npm install
npm run build
npm link

npm link symlinks the built output globally, so after pulling changes you just need npm run build again — no re-linking. If it blows up with EACCES, that's your global npm prefix not being writable, not this tool — fix the prefix permissions, or switch to nvm, which sidesteps the whole problem.

then, inside whatever repo you actually want to check:

conflict-check init

What it doesn't do

Being upfront about this, most important first.

  • Cross-file detection currently understands JS/TS/JSX/TSX only — functions, arrow/function-expression consts, and class methods. Other languages or symbol kinds aren't tracked yet.
  • The POSSIBLE — NAME MATCH ONLY tag means exactly that: worth checking, not a verdict. A coincidentally reused name can still slip through it.
  • It only warns — it never touches your code or does the merge for you.
  • No dashboard, no accounts, nothing hosted. Just your terminal, one repo at a time.

See the full list in the README for the rest, including exactly how cross-file checking depends on snapshot metadata and git history.