semantic-diff 0.5.0

A terminal diff viewer with AI-powered semantic grouping (Claude CLI / Copilot)
Documentation

semantic-diff

Crates.io Homebrew

A terminal diff viewer with AI-powered semantic grouping. Built with Rust and ratatui.

Groups your git changes by meaning — not just by file path. Designed to run as a cmux split pane alongside Claude Code, giving real-time visibility into what's being changed and why.

Why

AI coding agents like Claude Code, Cursor, and Copilot generate code faster than you can review it. The bottleneck has shifted from writing code to understanding what changed.

"Claude Code has absolutely zero features that help me review code or do anything else than vibe-coding and accept changes as they come in"Hacker News

"You can't review code being generated faster than you can read it"Hacker News

"The diff shows what changed, but not why"Hacker News

"CLI based tools (eg. git diff) are just generally inferior to visual integrated code review tools"Hacker News

Developers moving to terminal-first workflows (Ghostty + tmux + Claude Code) gain speed but lose the review capabilities IDEs provide. semantic-diff fills that gap — a terminal-native TUI that groups your changes by intent, not just by file.

How semantic-diff is different

Tool Semantic grouping Terminal TUI AI-powered Review-time
semantic-diff Yes Yes Yes Yes
Difftastic No Yes No Yes
Delta No Yes No Yes
Deff No Yes No Yes
Crit No Yes No Yes
Gnosis Yes No (Electron) Yes Yes
VibeGit Yes No Yes No (commit-time)
LightLayer Yes No (web) Yes Yes
Plandex No Yes Yes Yes

No other tool combines semantic grouping by intent + terminal-native TUI + AI-powered analysis at review time.

Demo

https://github.com/user-attachments/assets/49f7f3cf-a72c-47f6-9313-fdf0e2000db8

Features

  • Hunk-level semantic grouping — AI clusters related hunks across files by intent (e.g. "Auth refactor", "Test coverage"), not just file-level grouping
  • Multi-backend AI — Supports Claude CLI and GitHub Copilot CLI (copilot --yolo), with configurable preference and automatic fallback
  • Configurable~/.config/semantic-diff.json with JSONC comment support, model selection, and intelligent cross-backend model mapping
  • Grouping cache — Cached in .git/semantic-diff-cache.json keyed by diff hash; instant reload when nothing changed
  • Syntax-highlighted diffs — Powered by syntect with word-level inline highlighting
  • Collapse/expand — Toggle files, hunks, and semantic groups
  • File tree sidebar — Changed files organized by semantic group with per-hunk stats
  • Group-aware diff filtering — Select a file or group in the sidebar to filter the diff view to only those changes
  • Hook-triggered refresh — Auto-updates when Claude Code edits files (via SIGUSR1)
  • cmux integration — Auto-opens in a right split pane
  • Help overlay — Press ? to see all keybindings
  • Text wrapping — Long diff lines flow with the terminal width
  • Progressive enhancement — Shows ungrouped diff immediately, regroups when AI responds
  • Graceful degradation — Works without any AI CLI (falls back to ungrouped view)

Install

Homebrew (macOS)

brew install alankyshum/tap/semantic-diff

Cargo (crates.io)

cargo install semantic-diff

Build from source

git clone https://github.com/alankyshum/semantic-diff
cd semantic-diff
cargo build --release
# Binary at target/release/semantic-diff

Usage

# Run in any git repo with uncommitted changes
semantic-diff

Keybindings

Key Action
j/k, ↑/↓ Navigate up/down
Enter Sidebar: select file/group · Diff: toggle collapse
Tab Switch focus between tree sidebar and diff view
/ Search/filter files
n/N Next/previous search match
g/G Jump to top/bottom
Ctrl+d/u Page down/up
? Show shortcut help
Escape Clear filter / quit
q Quit

Configuration

On first run, a default config is created at ~/.config/semantic-diff.json:

{
  // Which AI CLI to prefer: "claude" or "copilot"
  // Falls back to the other if preferred is not installed
  // "preferred-ai-cli": "claude",

  "claude": {
    // Model: "sonnet", "opus", "haiku"
    // Cross-backend models mapped automatically (gemini-flash → haiku)
    "model": "sonnet"
  },

  "copilot": {
    // Model: "sonnet", "opus", "haiku", "gemini-flash", "gemini-pro"
    "model": "sonnet"
  }
}

Claude Code Integration

semantic-diff is designed to work as a live diff viewer alongside Claude Code.

Setup

  1. Copy the hook script (an example is provided in .claude/hooks.example/):
mkdir -p ~/.claude/hooks
cp .claude/hooks.example/refresh-semantic-diff.sh ~/.claude/hooks/
chmod +x ~/.claude/hooks/refresh-semantic-diff.sh
  1. Add to your Claude Code settings (~/.claude/settings.local.json):

Note: Add this to your global (~/.claude/settings.local.json) or user-level settings, not the project-level .claude/settings.local.json. Adding it to the project settings will cause the hook to trigger within the semantic-diff repo itself, repeatedly opening new semantic-diff instances.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/refresh-semantic-diff.sh",
            "async": true,
            "timeout": 10
          }
        ]
      }
    ]
  }
}

How it works

  1. Claude Code edits a file (Edit/Write tool)
  2. PostToolUse hook fires refresh-semantic-diff.sh
  3. If semantic-diff is running: sends SIGUSR1 to refresh the diff
  4. If not running: opens a cmux right-split pane and launches semantic-diff
  5. AI groups the changed hunks by semantic meaning
  6. You see real-time, grouped changes without leaving the terminal

Changelog

v0.5.0

  • Drop-in git diff replacement — Use semantic-diff as a direct replacement for git diff with the same CLI arguments (--staged, --cached, revision ranges, path filters). Configure as git config diff.external for seamless integration.
  • Incremental grouping — Files are grouped progressively as LLM responses stream in, so you see organized results immediately instead of waiting for all files to be analyzed.
  • Clippy lint fixes — Clean up uninlined format args and ptr_arg warnings.

v0.4.0

  • Adaptive dark/light theme — Auto-detects terminal background color via OSC 11 protocol (supports iTerm2, Ghostty, kitty, WezTerm, Alacritty, xterm, VS Code terminal). Falls back to COLORFGBG env var. Override with "theme": "dark" or "light" in config.
  • Light theme — Full light-background palette with pastel diff colors, dark text, and blue accents for readability on white/light terminals.
  • Terminal detection guards — Skips background detection in CI, piped stdin, and TERM=dumb environments for zero startup overhead.

v0.3.0

  • Security hardening — Secure PID file management with atomic writes and ownership validation, path traversal protection in diff parser and config/cache paths, bounded LLM response reading with validated deserialization, UTF-8 safe truncation.
  • Stdin-piped LLM invocation — Prompts sent via stdin instead of command-line arguments to prevent process table exposure.
  • Secure log file location — Log file moved to a secure directory with restricted permissions.
  • Integration test suite — Added diff rendering, SIGUSR1 signal handling, large diff stress tests, and LLM integration tests.

v0.2.3

  • Fix — Resolve clippy warnings in config and LLM modules.

v0.2.2

  • Fix — Account for line wrapping in scroll offset calculation.
  • Badges — Added crates.io and Homebrew version badges to README.

v0.2.1

  • Fix — Remove non-functional cmux resize-pane call from hook.
  • Docs — Embed demo video in README.

v0.2.0

  • Hunk-level semantic grouping — Groups related hunks across files by intent, matching GitHub Copilot's content-level approach. A single file's hunks can appear in different groups.
  • Multi-backend AI support — Added GitHub Copilot CLI (copilot --yolo) as a fallback when Claude CLI is not available.
  • Configuration file~/.config/semantic-diff.json with JSONC comment support. Configure preferred AI backend, model per backend, with intelligent cross-backend model mapping (e.g. gemini-flashhaiku).
  • Grouping cache — Results cached in .git/semantic-diff-cache.json keyed by diff hash. Instant startup when diff hasn't changed.
  • Group-aware diff filtering — Selecting a file in the sidebar filters the diff to its entire group. Selecting a group header toggles the filter.
  • Help overlay — Press ? to see all keybindings in a centered popup.
  • Text wrapping — Long diff lines wrap with the terminal width instead of being truncated.
  • Improved key responsiveness — Accept Repeat key events on macOS for smooth held-key navigation.
  • Scroll-to-top on file select — File header pinned to top of viewport when selected from sidebar.

v0.1.0

  • Initial release with file-level semantic grouping, syntax highlighting, collapse/expand, file tree sidebar, and Claude Code hook integration.

Requirements

License

MIT