Skip to content

Repository files navigation

diffmantic

Stop Diffing Text, Start Diffing Logic.

CI Latest Release License: MIT Go Version


diffmantic TUI demo


Note

Diffmantic is under active development and not yet ready for public use. We're getting closer to a public release, but features and internals are still shifting quickly.

Why diffmantic?

Line-based diffs like git diff break down when you refactor code. Move a function down 50 lines, and git shows it as a full Delete and re-add. Rename a parameter, and entire lines light up red and green.

Now with AI tools generating massive PRs with Moved functions and renamed symbols everywhere, the actual Change gets buried in noise. So human reviewers end up just giving in.

diffmantic fixes this by parsing your code into ASTs using Tree-sitter. It tracks structural shifts, so it knows when a function was Moved instead of deleted, and shows exact inline node edits instead of lighting up entire lines.

It works as a standalone CLI, a drop-in for git diff, or a backend for editor plugins via JSON output.

Features

  • Move Detection. When you move a function or a block, diffmantic tracks it as a Move. Not a delete + re-add. Moved functions, blocks, and statements are all first-class.
  • Update & Rename Detection. Shows exactly what changed inside a syntax node. A variable rename, a string literal swap, a type change, you see the precise edit, not a wall of red and green.
  • Git Integration. Run diffm in any Git repo and it launches an interactive TUI. Browse modified files, stage/unstage changes, commit, all without leaving the terminal.
  • Interactive TUI. Side-by-side diff view with syntax highlighting, code folding, search, Action Inspector panel (i), change indicators, and jump-to-change keys (n, N, [, ]). Built with Bubbletea and Lipgloss.
  • JSON Output. Stable schema with AST actions, line alignment, and character-level highlight spans. Includes selective --ui and --full modes for editor plugins and frontends.
  • 16 Core Languages. Go, Java, JavaScript, TypeScript, Python, Rust, Zig, C, C++, PHP, Ruby, JSON, YAML, TOML, HTML, CSS, Lua. Full AST normalization and matching rules powered by Tree-sitter.
  • Line Diff Fallback. For unsupported file types or plain text files, Diffmantic automatically falls back to line-based diffing so you can diff any file.

Supported Languages

Programming Languages (10)

Language Extensions
Go .go
Java .java
JavaScript .js .jsx .mjs .cjs
TypeScript .ts .tsx .mts .cts
Python .py
Rust .rs
Zig .zig
C .c .h
C++ .cpp .cc .cxx .hpp .hh
PHP .php
Ruby .rb

Markup & Data Formats (6)

Format Extensions
JSON .json
YAML .yaml .yml
TOML .toml
HTML .html .htm
CSS .css
Lua .lua

Note: Fully supported languages include tailored AST normalization (stripping punctuation noise and flattening comment/string blocks). Other languages built via make build-core or make build-all fall back to raw AST matching.

Installation

Install Script (recommended)

curl -fsSL https://raw.githubusercontent.com/HarshK97/diffmantic/main/install.sh | sh

This installs the diffm binary to ~/.local/bin. Make sure it's in your $PATH.

It auto-detects your OS and architecture, grabs the right binary from GitHub Releases, and verifies the SHA256 checksum.

# Install to a specific directory
curl -fsSL https://raw.githubusercontent.com/HarshK97/diffmantic/main/install.sh | sh -s -- --dir=/usr/local/bin

# Install a specific version
curl -fsSL https://raw.githubusercontent.com/HarshK97/diffmantic/main/install.sh | sh -s -- --version=v0.6.0

Homebrew

brew install HarshK97/tap/diffmantic

Download Binary

Prebuilt binaries for Linux, macOS, and Windows (amd64 + arm64) are on the Releases page.

Build from Source

Requires Go 1.26+. No C compiler or CGo required (CGO_ENABLED=0).

git clone https://github.com/HarshK97/diffmantic.git
cd diffmantic

# Default build: 16 core languages (13 MB binary)
make build

# Or install directly with Go:
go install github.com/HarshK97/diffmantic/cmd/diffm@latest

Custom Grammar Build Targets

Diffmantic supports embedding different sets of Tree-sitter grammars via Makefile targets:

Makefile Command Description Binary Size
make build Default: Embeds 16 fully supported core languages ~13.06 MB
make build-core Embeds ~100 core languages from gotreesitter ~22.37 MB
make build-all Embeds all ~206 languages available in gotreesitter ~29.12 MB

Building a Custom Language Subset

If you only need a specific set of languages (for example, Go, Python, and Rust), you can compile a minimal binary using gotreesitter build tags:

# Pass 'grammar_subset' plus 'grammar_subset_<lang>' tags
go build -tags 'grammar_subset grammar_subset_go grammar_subset_python grammar_subset_rust' -ldflags="-s -w" -trimpath -o diffm ./cmd/diffm

Built with gotreesitter for pure Go Tree-sitter AST parsing with zero C compiler or CGo runtime dependencies.

Usage

Git Status Mode (default in a repo)

# Launch the interactive TUI in any Git repository
diffm

# Show only staged changes
diffm --cached

Git Revision Diffing

# Diff working tree against HEAD
diffm HEAD

# Diff between two commits, tags, or branches
diffm HEAD~1 HEAD
diffm main...feature-branch

File-to-File Diff

# Interactive TUI (default when a terminal is attached)
diffm diff before.go after.go

# JSON output for editor plugins and automation
diffm diff before.go after.go -f json

# Fast UI mode (line alignment and highlight spans without action tree)
diffm diff before.go after.go -f json --ui

# Full envelope (actions, line alignment, and highlight spans)
diffm diff before.go after.go -f json --full

# Human-readable action list
diffm diff before.go after.go -f actions

How It Works

diffmantic matches ASTs in four phases, combining the GumTree algorithm, Zhang-Shasha tree edit distance, and Chawathe edit script generation:

  1. Top-Down Matching. We look for identical subtrees by height. When we find an exact match, all nodes in the subtree get mapped together.
  2. Bottom-Up Matching. For unmatched nodes, we look for counterparts of the same type that share already-matched children. If the Dice similarity score is high enough, we match them.
  3. Recovery. Inside matched containers, we run LCS alignment on unmatched children (first by label, then by structural shape). For small subtrees, Zhang-Shasha (1989) tree edit distance is used as a precise fallback.
  4. Action Generation & Post-Processing. We produce a raw edit script (insert, delete, update, move) using Chawathe et al. (1996) edit script generation and then refine it. Child edits get collapsed into clean subtree operations, comment changes get normalized, and related moves get grouped.

Editor Integrations

Neovim

diffmantic.nvim is the Neovim plugin that started this whole project. It currently ships with its own embedded alpha engine and is being migrated to use the diffm CLI as its backend via JSON output.

VS Code

Planned. The JSON output is built to support editor integration, so if you want to build one, the plumbing is there.

JSON Schema

diffm diff -f json outputs a stable v1 schema with child-index paths. Take a look at diffm diff file-a file-b -f json to see the full structure.

License

MIT. See LICENSE.

Acknowledgements

The engine is based on foundational research in AST differencing, tree edit distance, and edit script generation:

About

Stop Diffing Text, Start Diffing Logic

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages