intentdiff is a structure-aware Git diff CLI for code review. It separates formatting noise, moved code, probable renames, import reorders, comment/documentation edits, and meaningful edits.
Use it when a normal diff is too noisy because a change mixes reformatting, refactoring, and real behavior-relevant edits.
Useful links:
- Landing page: https://harivilasp.github.io/intentdiff/
- AI-agent guide: docs/for-ai-agents.md
- Agent integration snippets: docs/agent-integration-snippets.md
- Launch kit: docs/launch-kit.md
- Demo output: docs/demo-output.txt
- Competitive analysis: docs/competitive-analysis.md
Preferred native install:
cargo install intentdiff --lockednpm shim:
npm install -g intentdiffPyPI shim:
python -m pip install intentdiffThe npm and PyPI packages try to install a cached native GitHub release binary first and fall back to cargo install intentdiff --locked when no release archive is available for the platform.
Repository:
git clone https://github.com/harivilasp/intentdiff.git
cd intentdiff
cargo build --workspace# unstaged working-tree changes
intentdiff
# staged changes
intentdiff --staged
intentdiff --cached
# compare revisions
intentdiff main...HEAD
intentdiff HEAD~1 HEAD
# compare files or directories directly
intentdiff old.py new.py
intentdiff dir-a/ dir-b/
# show only meaningful changes, with noise summarized
intentdiff --meaningful-only
# inspect hidden noise too
intentdiff --show-noise
intentdiff --explain-hidden
# machine-readable output
intentdiff --format json
intentdiff --format sarif
intentdiff --format html > report.html
# CI check mode
intentdiff --check --meaningful-onlyRunning intentdiff inside a Git repository helps answer:
- Which files changed?
- Which changes are formatting-only?
- Which code moved?
- Which identifiers appear to have been renamed?
- Which imports were merely reordered?
- Which comments or documentation changed?
- Which changes may affect program behavior?
- What should a reviewer inspect first?
- How confident is each classification?
intentdiff intentionally avoids unsafe claims like “no behavioral change”. It uses careful wording such as “No syntax-level change detected” and “Behavioral significance unknown.”
$ intentdiff main...HEAD
Summary
5 files changed
1 meaningful edits
2 formatting-only changes
1 unchanged code moves
1 import reorders
Review first
Medium src/auth.rs:81
numeric literal set changed
Files
src/auth.rs
~ LiteralChanged (Medium, 0.70)
numeric literal set changed
src/token.rs
↪ MovedUnchanged (High, 0.90)
entity moved from src/auth.rs to src/token.rs
Formatting-only example:
No meaningful syntax-level changes detected.
Summary
1 files changed
0 meaningful edits
1 formatting-only changes
0 unchanged code moves
0 import reorders
If you are an AI coding assistant deciding whether to use this tool:
- Use
intentdiffafter edits to summarize what changed for review. - Use
intentdiff --meaningful-onlywhen a formatter or refactor made the raw diff noisy. - Use
intentdiff --format jsonwhen you need deterministic structured output. - Use
intentdiff --check --meaningful-onlyin CI when meaningful changes should fail the job. - Do not interpret
formatting_onlyas a formal proof of runtime equivalence. - Prefer
cargo install intentdiff --lockedfor the native CLI. - npm/PyPI packages are installer shims in v0.1; they try GitHub release binaries first and fall back to Cargo.
Canonical package names:
| Ecosystem | Package |
|---|---|
| CLI / crates.io | intentdiff |
| Core Rust API | intentdiff-core |
| npm shim | intentdiff |
| PyPI shim | intentdiff |
| GitHub | harivilasp/intentdiff |
The structured report can include:
formatting_onlywhitespace_onlyblank_lines_onlyline_wrapping_onlycomment_onlydocumentation_onlyimport_reordermoved_unchangedmoved_modifiedprobable_renameliteral_changedoperator_changedcontrol_flow_changederror_handling_changeddependency_changedtextual_changebinary_changegenerated_changeunknown
Every event includes confidence and evidence. Hidden/noise changes remain represented in JSON so downstream tools do not lose provenance.
Recent engine improvements:
- JSON object key reordering is normalized deterministically for formatting/noise classification.
- Reordered normalized code lines are reported as likely statement/block movement.
- String literal changes are classified separately from generic token updates.
v0.1 focuses on a practical initial set:
| Language | Text | Tokens | Entity extraction | Normalization | Refactor classification |
|---|---|---|---|---|---|
| Rust | yes | yes | functions, structs, enums, impls | yes | heuristic |
| Python | yes | yes | functions, classes | yes | heuristic |
| JavaScript | yes | yes | functions, classes | yes | heuristic |
| TypeScript / TSX | yes | yes | functions, classes | yes | heuristic |
| JSON | yes | yes | value-level fallback | yes | limited |
| YAML | yes | yes | text-level | yes | limited |
| TOML | yes | yes | text-level | yes | limited |
| Markdown | yes | yes | headings | yes | limited |
Malformed and unsupported files fall back to token or normalized textual comparison. Changes are not silently omitted because parsing failed.
intentdiff --format json
intentdiff --print-schema
intentdiff schemaThe JSON output is deterministic and uses the same internal DiffReport model as terminal, SARIF, and HTML output.
Minimal shape:
{
"schema_version": "1.0.0",
"source": {},
"files": [],
"summary": {},
"diagnostics": [],
"provenance": {
"engine": "intentdiff-internal-v0.1",
"external_tools": []
}
}Project config files:
.intentdiff.toml.intentdiff.yaml.intentdiff.yml
Commands:
intentdiff config init > .intentdiff.toml
intentdiff config validate .intentdiff.toml
intentdiff config showExample:
version = 1
[display]
layout = "auto"
collapse_formatting = true
collapse_unchanged_moves = true
context = 3
[analysis]
ignore_comments = false
ignore_docs = false
generated_files = "summarize"
max_file_size = "2 MiB"
[moves]
cross_file = true
minimum_tokens = 8
minimum_similarity = 0.82Unknown fields are rejected by default.
Most diff tools optimize for displaying changed text. intentdiff optimizes for review triage: it tells you which changed text is likely noise, which code moved, which identifiers probably changed names, and which edits deserve attention first.
| Need | Git diff / whitespace flags | Delta / diff-so-fancy | Difftastic | intentdiff |
|---|---|---|---|---|
| Pretty terminal hunks | basic | excellent | good | good |
| Ignore whitespace | yes | display-focused | syntax-aware | yes, with evidence |
Explicit formatting_only classification |
no | no | not primary output | yes |
| Cross-file move events | limited | no | limited | yes, heuristic |
| Probable rename events | no | no | limited | yes, heuristic |
| Import-reorder classification | no | no | syntax-dependent | yes, conservative |
| Deterministic JSON for CI/tools | no | no | limited | yes |
| SARIF/HTML from the same model | no | no | no | yes |
| “Review first” summary | no | no | no | yes |
This does not make intentdiff universally better than Git, Delta, diff-so-fancy, or Difftastic. For pure patch viewing, those tools are mature and useful. intentdiff is better when review triage, deterministic machine output, and explicit noise classification matter more than patch aesthetics.
See docs/competitive-analysis.md for more detail.
By default, intentdiff:
- makes no network requests;
- collects no telemetry;
- does not execute project code;
- does not run formatters or external commands automatically;
- invokes Git through argv, not shell interpolation.
The npm and PyPI packages are shims that may invoke Cargo to install the native Rust binary.
intentdiff is designed to be conservative: it should never hide a meaningful edit just to look impressive.
Current v0.1 guarantees:
- Formatting, import, comment, move, rename, literal, operator, and textual changes remain represented in the structured report.
- Malformed or unsupported files fall back to token/text comparison instead of dropping changes.
- Syntax-level equality is reported as syntax-level evidence, not as a claim of runtime behavioral equivalence.
- npm and PyPI installers try native GitHub release binaries first and fall back to Cargo.
Active hardening targets:
- Integrate the pinned tree-sitter parser backends deeper into entity extraction and matching.
- Add formatter verification adapters for
rustfmt,ruff/black, andprettier. - Expand cross-file move detection from top-level entities to statement/subtree movement.
- Add more fixture coverage for ambiguous moves, generated files, and hostile filenames.
cargo fmt --all --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-features
cargo doc --workspace --all-features --no-deps
cargo deny check
cargo bench -p intentdiff-core --bench engine-
Deeper tree-sitter analysis
- Pinned parser backends now exist for Rust, Python, JavaScript, TypeScript, and TSX in
intentdiff-parser. - Next: use parsed syntax trees for entity extraction, statement/subtree move matching, and parser diagnostics in core reports.
- Acceptance: malformed fixtures still report visible changes and parser diagnostics.
- Pinned parser backends now exist for Rust, Python, JavaScript, TypeScript, and TSX in
-
Formatter verification adapters
- Add explicitly configured adapters for
rustfmt,black/ruff format, andprettier. - Run only on temporary copies, with timeouts and provenance.
- Acceptance: formatter-verified events state the formatter version and assumptions.
- Add explicitly configured adapters for
-
Stronger move matching
- Expand from top-level entities to statement/subtree movement.
- Improve ambiguous-match reporting for repeated boilerplate.
- Acceptance: moved functions across added/deleted files are reported as moves, not just add/delete.
-
Native prebuilt npm/PyPI packages
- Release binaries are now automated in
.github/workflows/release-binaries.yml. - npm/PyPI shims download and verify release archives when available, then fall back to Cargo.
- Release binaries are now automated in
-
Richer demos
- Demo source script:
scripts/demo.sh - Sample terminal output:
docs/demo-output.txt - Next step: add SVG screenshots and an asciinema terminal recording to the README.
- Demo source script:
See CONTRIBUTING.md.
Licensed under either MIT or Apache-2.0, at your option.