Releases: HarshK97/diffmantic.nvim
v0.5.0-alpha
diffmantic.nvim - v0.5.0-alpha Release Notes
This is the first public pre-release of diffmantic.nvim. Released at the halfway point of the v0.5->v1.0 roadmap to collect real feedback before hardening the pipeline. Expect rough edges.
What is diffmantic?
diffmantic.nvim is a semantic diff engine for Neovim, built on Tree-sitter.
The goal is to drop-in semantic alternative to vim.diff, something other diff viewers and plugins can plug into to get AST-aware diffing instead of line-by-line diffing. The engine parses both files into ASTs and runs a multi-phase matching pipeline inspired by the Gumtree algorithm, producing structured actions: move, update, rename, insert, delete.
A reference UI ships with it -> a side-by-side split with semantic highlights, as a proof of concept and for direct use. But the engine (core.diff()) is the real deliverable.
Requirements
- Neovim 0.9+
- Tree-sitter parser for your language(Only 7 Languages properly supported though with tree-sitter query files)
Installation
lazy.nvim
{
"HarshK97/diffmantic.nvim",
config = function()
require("diffmantic").setup()
end,
}What's in v0.5.0-alpha?
The Core Pipeline
The pipeline runs in five deterministic phases:
| Phase | What it does |
|---|---|
| Pre-match | Seeds stable mapping from lines that are byte-identical across both files |
| Top-down | Finds identical or high-confidence subtree pairs using structural hashing |
| Bottom-up | Expands matches upward using already mapped descendants |
| Recovery | Iteratively recovers remaining valid mappings with bounded LCS |
| Action generation | Produces move/update/insert/delete actions with enriched metadata |
Detection Capabilities
Move detection
When a function, block, or statement is relocated in the file, diffmantic marks it as a move, not a delete + insert. Virtual text annotations show the direction and destination line (⤵ moved to L42 / ⤶ from L17).
Update detection
Modified nodes are marked as updates. The analysis phase refines updates to the smallest changed span, sometimes sub-line, token-level. Rename-only updates are suppressed to reduce noise.
Rename detection
The rename promotion pipeline identifiers when an identifier was renamed across its definition and uses. It is score-aware: a function rename only triggers once(at the declaration anchor), and call-siter references are suppressed. Virtual text shows the old -> new name inline.
Insert/Delete detection
New and removed nodes are clearly marked. Insert/delete actions that overlap with update hunks are deduplicated so you don't see double-highlights.
Language Support
Query packs ships for 7 Languages out of the box, plus a fallback:
- C
- C++
- Go
- JavaScript
- TypeScript
- Python
- Lua
Fallback (basic structural matching, no semantic roles)
UI & Highlights
| Group | Meaning |
|---|---|
| DiffmanticAdd | Inserted node |
| DiffmanticDelete | Deleted node |
| DiffmanticChange | Updated node / hunk |
| DiffmanticChangeAccent | Update that overlaps a move (underline + bold) |
| DiffmanticMove | Moved node |
| DiffmanticRename | Renamed identifier (italic + underline) |
Signs in the gutter(+,-,U,M,R) gives a quick summary of what changed per line. Priority layering ensures rename and update highlights sit above more move highlights, which sit above insert/delete
Performance
Currently performance is great till ~2500 lines, but the time increases greatly after it.
Planned for v0.6.0 for smaller optimizations and final optimization at v0.9.0
Known Limitations
These are documented in LIMITATIONS.md and are primary drivers of the v0.6->v0.7 roadmap:
- L1 -> Move detection is function/struct level only: sub-blocks moves (if/else branches, class methods, loop bodies) are not tracked as moves, they appear as delete+insert instead. (Planned: v0.7.0)
- L2 -> No side-by-side alignment or filler lines: there is no blank-line padding. When one side has more content than the other, the two panels drifts out of visual sync. (Planned: v0.6.0)
- L3 -> Update hunk granularity is heuristic: some edits still render as broader node/line-level changes rather than ideal token-level spans. (Planned: v0.6.0->v0.7.0)
- *L4 -> Performance degrades on larger files: files approaching or exceeding ~2500 lines will see noticeable slowdowns. No time-budget threshold or large-file guardrail exists yet. (Guardrails planned: v0.6.0; full optimization: v0.9.0->v1.0.0)
- L5 -> No enforced performance/correctness/regression gates: benchmarks and fixtures exist but are not gated. (Planned: v0.9.0->v1.0.0)
- L6 -> No automated tests for regression/correctness tests: currently there is no automated test for regression/correctness. (Planned: v0.6.0->v.0.8.0)
What's Next?
| Version | Focus |
|---|---|
| v0.6.0 | Configuration surface, navigation helpers (next/prev), error handling, large-file guardrails + threshold, filler lines for alignment |
| v0.7.0 | Sub-block move detection, more precise update hunks, community API feedback, regression test suite |
| v0.8.0 | Git integration (working tree vs staged, commit/branch comparison) |
| v0.9.0 | Stable public Lua API, performance profiling pass |
| v1.0.0 | Non-blocking execution, production hardening |
Feedback
This alpha is released specifically to gather feedback on:
- Query quality -> Does the semantic signal feel right for your language? Are there false positives (moves that aren't moves, renames that aren't renames)?
- Highlight noise -> Too much? Too little? Wrong priority?
- Real-world refactors -> What kinds of edits does it get wrong?
- Features -> What kinds of features would you love in diffmantic?
Open an issue or start a discussion on the GitHub repo. All feedback goes directly into the v0.6.0 scope.Open an issue or start a discussion on the GitHub repo. All feedback goes directly into the v0.6.0 scope.
Acknowledgements
GumTree — the algorithm this pipeline is inspired by
GumTree paper
Beyond GumTree paper