npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

conflict-pilot

v0.1.0

Published

Detects merge conflicts, explains what each one actually is, and resolves them once you approve. Zero dependencies, works from any code editor.

Readme

Conflict Pilot

npm test node license

Detects merge conflicts, works out what each one actually is, and resolves it once you approve. Zero dependencies, one small Node package, and it works in any code editor.

── src/app.js  ·  conflict 1/2  ·  line 2 ─────────────────────────────

  ── current: main
    - import { logger } from './logger';
  ── incoming: feature/metrics
    + import { metrics } from './metrics';

  ● 91% high  Import block union
     Both sides only add imports. Imports are order-independent here, so the
     union of both lists (duplicates removed) preserves what each branch needs.

  ── proposed resolution
   │ import { logger } from './logger';
   │ import { metrics } from './metrics';

  [a] accept  [o] yours  [t] incoming  [b] both  [e] edit  [s] skip  [q] quit

Nothing is ever written until you press a key.

Install

npm install -g conflict-pilot

Then, once:

conflict-pilot setup

That registers Conflict Pilot as your git mergetool, which is what makes it work in any editor — including editors with no plugin. It prints every git config line it intends to write and asks before changing anything (--print shows them without applying, --local scopes them to a single repo).

Or skip installing entirely:

npx conflict-pilot

Requires Node 16+ and git. Runs on macOS, Linux and Windows. The cpilot alias is installed too.

Use it

conflict-pilot

That is the whole workflow: run it in a repo mid-merge or mid-rebase, review each proposal, approve the ones you agree with. Files that end up fully resolved are staged for you.

| Command | What it does | | --- | --- | | conflict-pilot | Review every conflict, one approval at a time | | conflict-pilot --list | Show every conflict and proposal, change nothing | | conflict-pilot --auto | Apply proposals at ≥90% confidence, review the rest | | conflict-pilot --yes | Same, but skip everything below the bar instead of asking | | conflict-pilot --check | Exit 1 if any conflict remains — for hooks and CI | | conflict-pilot --dry-run | Show what would be written, touch nothing | | conflict-pilot src/app.js | Just this file |

--help lists the rest.

What it can work out

Each conflict is matched against a set of rules. The one with the highest confidence wins, and the reasoning is always shown.

| Confidence | What it means | | --- | --- | | 100% | Provably identical — no judgement involved | | 90–99% | Structurally safe: the common ancestor proves only one side moved | | 70–89% | Very likely right, but worth a glance | | below 70% | A convenience shortcut — never applied without an explicit keystroke |

Rules include: identical sides, only-one-side-changed, non-overlapping edits merged three-way, import-block unions (JS/TS, Python, Java, Go, Rust, Ruby, PHP, C#, C/C++, Swift, Dart, Elixir), package.json dependency unions with semver tie-breaking, .gitignore-style entry unions, whitespace-only differences, and changelog bullet unions.

Lockfiles (package-lock.json, yarn.lock, Cargo.lock, go.sum, …) are never merged line by line. Conflict Pilot tells you to regenerate them and gives you the command.

Two things that make the proposals better than a guess

It recovers the common ancestor. Most people never set merge.conflictStyle=diff3, so the conflict in your file shows only two sides — which makes "who actually changed this?" unanswerable. Conflict Pilot replays the merge against git's staged blobs to recover the ancestor, so it can tell a real disagreement from one side simply standing still.

It splits mixed hunks. git reports one conflict per hunk, so a single block routinely mixes something easy (each branch added a different import) with something hard (each branch set the same constant differently) — and the mix makes the whole block look unresolvable. Conflict Pilot re-segments the hunk against the ancestor and resolves the pieces independently:

// git gives you one conflict covering all of this:
<<<<<<< HEAD
import { logger } from './logger';
...
  const timeout = 90;
  return core(timeout);
=======
import { metrics } from './metrics';
...
  const timeout = 30;
  return core(timeout, { retries: 3 });
>>>>>>> feature

// Conflict Pilot resolves it to:
import { logger } from './logger';
import { metrics } from './metrics';
...
  const timeout = 90;                        // your change
  return core(timeout, { retries: 3 });      // their change

Both branches' work survives. A block only re-segments when collapsing every conflict to one side yields a byte-identical file both ways, which means local edits you already made are never silently dropped — if you have edited the file, it declines and leaves your version alone.

Editor setup

The CLI works in any editor's integrated terminal with no setup at all. The integrations below add editor-native touches.

Any editor — as your git mergetool

conflict-pilot setup does this for you. It is equivalent to:

git config --global mergetool.conflict-pilot.cmd 'conflict-pilot "$MERGED"'
git config --global mergetool.conflict-pilot.trustExitCode true
git config --global merge.tool conflict-pilot

Then git mergetool runs it on each conflicted file, whatever you edit code in.

Recommended for everyone

git config --global merge.conflictStyle zdiff3

This keeps the common ancestor in the file. Conflict Pilot can recover it without this, but having it there makes every tool you use smarter, not just this one.

VS Code / Cursor / VSCodium / Windsurf

npm run build:vscode          # vendors the engine into the extension
code --install-extension editors/vscode

VS Code already ships Accept Current / Incoming / Both, so the extension does not repeat them. It adds the missing piece above each conflict:

  • ⚡ Resolve: Import block union (91%) — applies the proposal in one click
  • Why? — explains the reasoning
  • A status-bar count of conflicts, and how many are resolvable
  • Conflict Pilot: Resolve confident conflicts in this file, which previews every change and asks once before applying

Proposals below conflictPilot.minConfidence always show a preview you must confirm. Settings: minConfidence, showCodeLens, preferOnFormatting.

Prefer a terminal? editors/vscode/tasks.json has ready-made tasks.

Neovim

{ dir = "/path/to/conflict-pilot/editors/nvim",
  config = function() require("conflict-pilot").setup() end }

:ConflictPilot reviews everything in a terminal split, :ConflictPilotList loads conflicts into the quickfix list, :ConflictPilotExplain explains the one under your cursor, :ConflictPilotFile resolves the confident ones after showing you what they are.

JetBrains (IntelliJ, WebStorm, PyCharm, GoLand, Rider, …)

Copy editors/jetbrains/conflict-pilot-tools.xml into your IDE's tools/ directory (the file lists the exact path per OS) and restart. Four entries appear under Tools → External Tools → Conflict Pilot, and you can bind keys to them in Settings → Keymap.

Sublime Text

Copy editors/sublime/* into Packages/User/. The commands appear in the command palette under "Conflict Pilot".

Zed, Helix, Emacs, anything else

Use the terminal, or the git mergetool setup above.

Safety

  • Nothing is written without your approval. --auto only applies proposals at or above the confidence threshold; everything else is still shown to you.
  • Originals are backed up to .git/conflict-pilot/backups/ before the first write. --no-backup turns this off.
  • Skipped conflicts keep their markers and the file stays unmerged, so you can quit halfway and come back.
  • Your local edits win. Any analysis that would not reproduce your file exactly is discarded rather than applied.
  • Ambiguity is left alone. When both sides change the same line differently, there is no proposal — by design.

In CI or a hook

--check exits 1 when any conflict remains, so a pre-commit hook can stop a commit that still contains markers:

#!/bin/sh
conflict-pilot --check || {
  echo "Unresolved conflicts. Run: conflict-pilot"
  exit 1
}

As a library

const { analyzeFile, discover, writeFile } = require('conflict-pilot');

const found = discover(process.cwd());
for (const entry of found.files) {
  const { file } = analyzeFile(entry.absPath, {
    relPath: entry.relPath,
    repoRoot: found.repoRoot,
  });

  for (const conflict of file.conflicts) {
    const s = conflict.suggestion;
    if (s && s.lines && s.confidence >= 0.95) {
      conflict.resolution = s.lines;   // opt in per conflict
    }
  }
  writeFile(file, { repoRoot: found.repoRoot, stage: true });
}

conflict-pilot --json gives the same analysis as machine-readable output; that is what the editor integrations consume.

Exit codes

0 everything resolved · 1 conflicts remain · 2 error

Development

npm test                  # 74 tests, including real git merges and rebases
npm run build:vscode      # vendor the engine into the extension

The test suite builds throwaway repos and runs actual git merge operations, so the parser and strategies are exercised against git's real output rather than hand-written marker text.

License

MIT