# Foremerge names a binary after checking four package registries for collisions

> A coordination protocol that has coding agents declare what they intend to touch, so that conflicting intent surfaces before code is written. The interesting engineering decisions are in what it refuses to do.

**naw103/foremerge** — Catch intent conflicts before code conflicts. The open-source coordination protocol for coding agents, built above Git.

- Repository: https://github.com/naw103/foremerge
- Website: https://foremerge.com
- Stars: 519 · Forks: 22
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/naw103-foremerge

## One binary installs under two names, and the short one was researched

The installer puts `foremerge` and `fmg` on your path, and they are the same program. The README calls it two commands, one program, and notes that the shorter name exists so `fmg status` and `foremerge status` do the same thing, letting you type whichever you prefer. Both exist from release 0.4.0 onward, across the installer, the release archives and cargo install. The reasoning is recorded in the package manifest rather than in a design document, and it is unusually thorough. Both binaries are thin wrappers over the same CLI entry point, so they cannot drift apart and the CLI compiles once. The short name was chosen after checking that nothing installs a binary called fmg: it is unclaimed on crates.io, Homebrew and Debian, and the npm and PyPI packages holding the name are libraries with no executable.

## It never locks a file and never asks a model

Two things are stated as deliberate omissions, and they define what the tool is. The first is blocking. Foremerge never locks a file or blocks an agent, with the stated reason that a single crashed agent would then stall the whole fleet, so the warnings are advisory and you stay in charge of what happens next. The second is judgement by model. It never asks a model to judge conflicts, so the same inputs always produce the same answer. That is why the package lists a deterministic conflict detector as an implemented component rather than a model call. The trade is real in both directions. Without locking, nothing prevents an agent from proceeding through a HIGH advisory, and the conflict will land in your tree anyway. Without a model, the detector cannot reason about plans phrased in ways the parser does not recognise.

## The collision is a replace against an extend on the same symbol

The worked example is the whole thesis in four lines. Two agents work in separate trees, so no line ever overlaps:

```text
Agent A: Replace PaymentService with StripePaymentService
Agent B: Add PayPal support to PaymentService
```

Git merges both without complaint, because the edits are in different files, and the PayPal support ends up on a class nothing calls any more. Git compares text and not intent, so it stops you when two agents edit the same part of the same file and stays silent when both edits are individually reasonable. Foremerge catches it because both agents declared the same symbol:PaymentService scope, one saying it will replace it and the other that it will extend it. The detector compares those two declarations before either writes code and raises a HIGH advisory, suggesting they coordinate on a stable abstraction such as a PaymentProvider. That suggestion is described as explainable evidence rather than an automatic architecture decision.

## Phrasing does not matter because the operation is declared

The reason two differently worded plans reach the same verdict is that the operation is declared rather than inferred from prose. An agent that writes consolidate payments onto Stripe and an agent that writes replace PaymentService with Stripe both declare the same scope and the same operation, so the detector compares structured fields instead of sentences. This is the practical difference between a rule-based detector and a prompt-based one, and it is what lets the tool promise that identical inputs give identical answers. It also sets the boundary. An agent that describes its intent in a form the schema does not capture contributes nothing to the comparison, and the README does not describe a fallback for that case. The gap between what an agent says in prose and what it declares is the gap where a conflict can still slip through.

## Acceptance runs your check instead of trusting the agent

The lifecycle is verification-gated, and the mechanism is that Foremerge executes the check itself rather than taking an agent's word for it. That requires you to name the check and give it the command, which is why the quickstart tells you to register the command this repository actually uses:

```sh
foremerge checks set test -- cargo test --all-targets
```

Only checks you have defined by name may be requested by an agent, so the set is effectively a trust list an agent cannot extend on its own. The quickstart also ends with a confirmation step:

```sh
foremerge setup all
foremerge doctor --client all
```

The doctor command reports the wiring rather than the intent, which is the part worth running when an agent claims it is coordinating and nothing shows up. The same pattern governs upgrades: you upgrade the way you installed, then re-run setup and restart your clients, and a separate document explains why each of those steps is needed.

## The shared state lives in .git, which caps it at one machine

Every agent sees the same picture because the picture is a small database inside your project git folder. That placement is what makes the protocol invisible to your workflow: nothing is configured globally, nothing runs as a service, and there is no daemon to keep alive. It also sets the hard boundary, and the status note states it plainly: coordination between machines is outside the scope of this project. Two developers on two laptops, or one developer with a container and a host, coordinate nothing. The current release is 0.5.0 and is described as a pre-1.0, local-first MVP whose CLI, JSON API, MCP server, SQLite store, deterministic conflict detector and verification-gated lifecycle are implemented, with the caveat that public schemas may still change. Published benchmark results do not yet exist, which is a separate claim from the tool not working.

## The terminal session in the README came from release 0.1.0

The rendered output shown in the README is captioned as coming from the actual conflict fields captured by a 0.1.0 release-binary run, recorded in examples/terminal-session.txt, with the command shown using a jq filter and the output abridged for readability. The current version is 0.5.0. So the one piece of observed output in the documentation predates the current release by four minor versions, and the caption is honest about it in a footnote most readers will not reach. The repository does carry a benchmarks directory and Makefile targets that execute five committed benchmark scenarios plus an optimised query harness at documented scales, so the capability exists internally even though no published numbers are offered. The examples directory also holds a JSON API request script, an MCP configuration file and the query benchmark source, which is where you would look to see the wire formats rather than to infer them.

## Conclusion

Use Foremerge when several agents run in parallel worktrees on one machine against a repository whose architecture has extension points worth protecting, because the replace-versus-extend case it detects is exactly the failure Git will merge without complaint. Do not reach for it expecting a lock or a distributed protocol: it never blocks an agent, never calls a model, and explicitly excludes coordination between machines. Before you trust a verdict, register your real test command so acceptance is verified rather than asserted, and read the status note, since public schemas may still change before 1.0.

## FAQ

### What does Foremerge actually detect?

Conflicting intent rather than conflicting text. Two agents that declare the same symbol scope with different operations, one replacing it and one extending it, produce a HIGH advisory before either writes code. Git cannot see this case because the edits land in different files.

### Does Foremerge stop an agent from editing a conflicting file?

No, and that is deliberate. It never locks a file or blocks an agent, because one crashed agent would stall the whole fleet, so warnings are advisory and you decide what happens.

### Does Foremerge use a language model to judge conflicts?

No. The project states it never asks a model to judge conflicts so that identical inputs always produce an identical answer, which is why the detector is described as deterministic.

### Can Foremerge coordinate agents across two machines?

No. The shared database lives inside your project .git folder so agents on one machine see the same picture, and coordination between machines is stated to be outside the scope of the project.

### How do I install Foremerge?

Run the install script, which installs to ~/.local/bin, or build with Rust 1.85 or newer via cargo install --locked. Windows binaries are on the releases page. You need a recent Git and jq.

### What is the difference between foremerge and fmg?

Nothing. They are the same binary under two names, both thin wrappers over one CLI entry point, and both have shipped since 0.4.0. If another program already answers to fmg on your path, the installer leaves it alone.

## Sources

- [License: Apache-2.0](https://github.com/naw103/foremerge/blob/main/LICENSE)
- [naw103/foremerge on GitHub](https://github.com/naw103/foremerge)
- [Project website](https://foremerge.com)
- [README](https://github.com/naw103/foremerge/blob/main/README.md)
- [Releases](https://github.com/naw103/foremerge/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/naw103-foremerge
