Easy Conflict Resolver
Find every file with merge conflicts in your git repositories, including all their worktrees, and resolve them in a three-column editor, with word-level diff, per-change accept/ignore controls and optional AI proposals from the Claude Code CLI.
Preview release. Git is used to find conflicted files; resolving them works on the conflict markers (<<<<<<<, |||||||, =======, >>>>>>>) and the files are not staged for you. See the Roadmap.
Features
Conflicts view
- A Conflicts view in the activity bar lists every file git reports as unmerged (
git diff --name-only --diff-filter=U) that still has conflict markers, with the number of conflicts per file.
- Every worktree of each repository open in the workspace is checked (
git worktree list), wherever it lives on disk. When conflicts come from more than one worktree, they are grouped by worktree, with its branch and path, and Accept All Yours / Accept All Theirs are available per worktree.
- Files matching
conflictResolver.scan.exclude are skipped. Stray markers in files git does not consider conflicted are not listed.
- The list refreshes when git's index changes (merge, rebase,
git add, new worktrees), when files are saved, when the window regains focus, and with the refresh button.
- Inline actions per file: Accept Yours, Accept Theirs, Resolve… (opens the merge editor) and Resolve File with AI.
- Title actions: Accept All Yours and Accept All Theirs for every listed file, with a confirmation first.
- Files whose markers are malformed (nested, unterminated, out of order) are flagged with a warning and never rewritten automatically; clicking them jumps to the offending line.
Three-column merge editor
- Your version | Result | Their version, like a classic three-way merge tool. Open it from the Conflicts view, from the explorer or editor context menu (Resolve Conflicts…), or with Reopen Editor With… → Easy Conflict Resolver.
- Rows are aligned between the columns and scrolling is synchronised; curved ribbons in the gutters connect each change with the result.
- Every change has » / « to take that side and × to ignore it. After taking one side, the other side's arrow appends it, so you can keep both sides in either order.
- With diff3 markers (
|||||||), each conflict is split against the base into smaller changes. Changes where only one side differs from the base are marked as non-conflicting and Apply Non-Conflicting resolves all of them at once. The Base toggle shows the common ancestor as an extra column.
- Word-level highlighting between both sides of a conflict, or between a side and the base for non-conflicting changes.
- The result column is fully editable, with syntax highlighting (highlight.js).
- Toolbar: Accept All Yours, Accept All Theirs, Apply Non-Conflicting, Undo/Redo, a Conflict N of M counter with previous/next navigation, Collapse unchanged lines, Base and Save.
- Integrated with VS Code: the editor shows as dirty,
Ctrl/Cmd+S saves, Ctrl/Cmd+Z undoes, and unsaved work survives a restart (hot exit).
- Save writes the result without markers. If changes are still unresolved you are warned first; if you save anyway, those changes are written back as conflict markers so you can finish later.
- Follows the active VS Code theme (light, dark and high contrast) and the editor font settings.
AI resolution (Claude Code CLI)
- If the
claude executable is found in PATH (or in conflictResolver.ai.claudePath), a ✦ button appears on each conflict, plus Resolve File with AI in the toolbar and in the Conflicts view. If it is not found, the AI buttons stay hidden and you are told once.
- The CLI runs non-interactively (
claude -p --output-format json --json-schema … --tools ""), with no tools enabled and no saved session. The prompt goes through stdin and contains the file path and language, the base (when present), both sides with their labels and 30 lines of context before and after the block.
- The answer is inserted into the result as an editable proposal, marked with a purple AI badge. Its one-sentence justification shows as a tooltip and in a small panel under the editor. AI proposals are never saved automatically.
- Before the first AI request you are asked to confirm that code will be sent to Claude; see Privacy.
- Configurable timeout, and cancellation from the progress notification or the block.
- The integration sits behind an
AiResolver interface (src/ai/aiResolver.ts) so other providers can be added.
Keyboard shortcuts
Active while the merge editor has focus. All of them can be changed under Keyboard Shortcuts; search for "Easy Conflict Resolver".
| Action |
Windows / Linux |
macOS |
| Next change |
F7 |
F7 |
| Previous change |
Shift+F7 |
Shift+F7 |
| Accept yours for the current change |
Ctrl+Alt+Left |
Ctrl+Cmd+Left |
| Accept theirs for the current change |
Ctrl+Alt+Right |
Ctrl+Cmd+Right |
| Ignore yours for the current change |
Ctrl+Alt+Shift+Left |
Ctrl+Cmd+Shift+Left |
| Ignore theirs for the current change |
Ctrl+Alt+Shift+Right |
Ctrl+Cmd+Shift+Right |
| Resolve the current change with AI |
Ctrl+Alt+I |
Ctrl+Cmd+I |
| Save |
Ctrl+S |
Cmd+S |
| Undo / Redo |
Ctrl+Z / Ctrl+Shift+Z |
Cmd+Z / Cmd+Shift+Z |
Settings
| Setting |
Default |
Description |
conflictResolver.ai.enabled |
true |
Offer AI resolution when the Claude Code CLI is available. |
conflictResolver.ai.claudePath |
"" |
Path to claude; empty means look it up in PATH. |
conflictResolver.ai.model |
"" |
Model passed to claude --model; empty uses the CLI default. |
conflictResolver.ai.timeoutSeconds |
120 |
Time limit for one AI resolution. |
conflictResolver.ai.contextLines |
30 |
Context lines sent before and after each block. |
conflictResolver.scan.exclude |
[] |
Glob patterns, relative to each worktree root, for conflicted files that should not be listed. |
conflictResolver.scan.maxFileSizeKb |
2048 |
Larger conflicted files are not listed. |
conflictResolver.editor.collapseUnchanged |
false |
Collapse unchanged regions when the merge editor opens. |
Which side is "yours"?
The block between <<<<<<< and |||||||/======= is yours (left column) and the block between ======= and >>>>>>> is theirs (right column), as git writes them during a merge. The labels after the markers (for example HEAD and feature/x) are shown in the column headers. During a rebase git swaps the meaning of the two sides; detecting that needs git and is part of phase 2.
Development
npm install
npm run build # bundle extension + webview into dist/
npm run watch # rebuild on change
npm test # unit tests (parser, model, diff, AI adapter)
npm run test:integration # runs the extension inside a downloaded VS Code
npm run typecheck
npm run preview # then serve the folder and open preview/index.html
npm run package # build a .vsix
Press F5 in VS Code to launch an Extension Development Host.
preview/ is a standalone harness: it loads the real webview in a browser with a fake host built on the same core, so the UI can be exercised without VS Code (?sample=greeting.py, ?collapse=on, ?ai=off).
Layout
| Folder |
Contents |
src/core |
Pure logic: marker parser, merge model (diff3 split), resolution state and serialization, Myers diff, word diff, view model. No VS Code dependency. |
src/extension |
Activation, commands, conflict scanner, Conflicts tree view, custom editor provider and document. |
src/git |
Git CLI wrapper: repository and worktree discovery, unmerged paths. |
src/webview |
Merge editor UI (plain TypeScript and DOM, highlight.js for syntax). |
src/ai |
AiResolver interface, prompt building and response parsing, Claude CLI adapter. |
test/core, test/ai, test/git |
Unit tests with Vitest and fixtures for two-way, three-way and malformed conflicts. |
test/integration |
Extension tests that run inside VS Code. |
Roadmap
Phase 2: git integration
- Load the three versions from the index with
git show :1:<path> (base), :2:<path> (ours) and :3:<path> (theirs) instead of relying only on markers, so the merge can be recomputed even when markers were edited by hand.
- Detect merge, rebase and cherry-pick states, show real branch names and swap yours/theirs correctly during a rebase.
- Mark files as resolved with
git add after saving and offer to commit the merge.
- Handle deleted/modified and binary conflicts.
Later
- More AI providers behind
AiResolver (Anthropic API directly, local models).
- Line-level alignment inside large changes.
- Localisation.
Transparency about AI
This notice follows the transparency principles of the EU Artificial Intelligence Act (Regulation (EU) 2024/1689, Article 50).
How this project was made. The source code, tests, documentation and logo were produced by an AI model (Claude, by Anthropic) under the direction of the author. The code has automated tests but has not yet been fully reviewed by a human; treat this version as a preview. The logo is marked as AI-generated in its own metadata (IPTC DigitalSourceType: trainedAlgorithmicMedia in media/icon.png and media/icon.svg).
AI inside the extension. Proposals produced by the optional AI feature are always presented as AI-generated: they carry an AI badge and a purple outline, come with the model's one-sentence justification, are never saved automatically and must be reviewed by you. Once you edit a proposal or save the file, the result is your own decision. The extension does not use AI for anything else.
Privacy
- Without AI, everything runs locally; nothing leaves your machine.
- With AI, for each block you resolve the extension sends to your local
claude executable the file path, its language, the conflicting sides (and the base, if present) and up to conflictResolver.ai.contextLines lines around the block. The Claude Code CLI forwards that to Anthropic under your own account and its terms. The extension does not store or send anything itself, and it collects no telemetry.
- You are asked for confirmation before the first request. Set
conflictResolver.ai.enabled to false to turn the feature off completely, and do not use it on code you are not allowed to share with a third party.
License
MIT. The full text is in the LICENSE file shipped with the extension; third-party licenses are in ThirdPartyNotices.txt.
| |