Full release details: CHANGELOG.md
Ordered by priority, last verified 2026-10-10 (v3.12.1 shipped 2026-10-10 with the seventeen-plus PRs merged since v3.12.0, the v3.12.x merge-back fix included; the 2026-10-08 changelog scan inserted Agent Control, the worktree audit widened it into Agent Workspaces and added a v3.12.x merge-back fix; on 2026-10-10 Agent Workspaces was split in two, part I moved ahead of Stacked Branches as v3.13.0 — it completes the v3.12.x fix and unblocks Dendreo's teardown — and part II became v3.16.0, so Stacked Branches, Combined Diffs and Voice Input each moved one minor later). The thread: the measured-accuracy engine re-founds the trust every later auto-apply feature spends, then make the app reactive and fast (Live Repo), close the resolution loop (preview-to-apply, whose confidence threshold is only meaningful because of the accuracy work), then workflow & comparison primitives, experimental voice input, and the v4.0 code-intelligence headline. Full renumbering history: git log -p -- roadmap.md.
| Version | Codename | Why now |
|---|---|---|
| v3.13.0 | Agent Workspaces I — Lifecycle & merge-back | Worktrees as provisioned environments (repo-defined setup/teardown hooks) and the real merge-back through preview→apply: the interim v3.12.1 fix refuses as soon as main moved, which is the normal case for a long agent task; Dendreo's bin/worktree shows what a real team needs |
| v3.14.0 | Stacked Branches | Native stacked PRs, sequenced after v3.11 (leans on preview→apply) |
| v3.15.0 | Combined Diffs | Multi-commit, non-contiguous aggregated diff |
| v3.16.0 | Agent Workspaces II — Agents & parallel work | Live agent status, in-app permission requests, agent picker, worktrees view, cross-worktree conflict prediction, merged-PR cleanup — GitKraken 12.x, VS Code 1.141 and Conductor shipped parts of it |
| v3.17.0 | Voice Input | Experimental — local dictation via embedded Whisper |
| v4.0.0 (candidate) | Blast Radius | Code-graph impact before merge — the code-intelligence headline |
v3.12.4 (Windows build no longer needs the VC++ runtime), v3.12.3 (reset --keep, opt-in auto fast-forward, tracked-but-ignored warning, diffs that keep --/++ lines, file history compare across renames, PR comment actions, in-house Markdown, GPU rendering on Linux), v3.12.2 (AI context for PRs and release notes, AI branch creation, AI language and model fixes), v3.12.1 (merge-back no longer loses data, security hardening, full-screen Settings, WIP as a Git Tree row, per-project identity), v3.12.0 (built-in terminal renderer, WIP in the Git Tree), v3.11.2 (Finder-like folder navigation), v3.11.1 (History-aware LLM fallback) and v3.11.0 (Merge preview-to-apply) shipped; see Shipped below and the full detail in CHANGELOG.md.
From the 2026-10-08 changelog scan and worktree audit. GitKraken 12.1→12.5 shows each agent session's live status, answers Claude Code / Codex / Copilot CLI permission requests from its panel and runs per-repo setup commands before an agent starts; VS Code 1.141 cleans up agent worktrees by disk use and merged PR; Conductor gives each workspace setup/archive scripts and a port range; Strand snapshots a worktree before removing it. Dendreo's own bin/worktree (~1,700 lines) shows the real need: a worktree is a running environment — its own containers, subdomain, tenant, test databases and reserved Vite port — that must be provisioned on create and torn down on delete. GitWand today creates and removes the git worktree only (WorktreeManager.vue, scratch.rs), launches Claude Code only, and then loses sight of the session.
Split on 2026-10-10: this part makes a worktree a provisioned environment and brings agent work back for real; the agent-facing half (status, permissions, parallel-work prediction) is v3.16.0 below.
Lifecycle hooks (the foundation) — a worktree section in .gitwandrc, so the repo, not GitWand, says how to bring an environment up and down:
worktree:
dir: .claude/worktrees # default stays configurable; Claude Code / Dendreo convention
include: [.env, auth.json] # or a .worktreeinclude file (Claude Code / Conductor / Strand)
setup: bin/worktree provision {name}
teardown: bin/worktree teardown {name}
url: bin/worktree url {name}setupruns after creation, streamed into a terminal tab;teardownruns before any removal (manual, merge-back, cleanup), and a failed teardown blocks the removal instead of orphaning containers, volumes and databases — what happens today when a Dendreo worktree is removed from GitWand- name, path, branch and base exported as
GITWAND_WORKTREE_*variables;urloutput shown on the worktree card and openable includecopies ignored files only (same semantics as.worktreeinclude); symlink vs copy per entry, for agent config (settings.local.json,mcp.json) and shared dependency folders
Creation
- Base on the freshly fetched remote default branch by default (Claude Code, Dendreo, Conductor), not the local
HEADas AI tasks do today
Bringing work back
- Merge-back becomes a real merge or rebase through the v3.11 preview → apply flow (completing the v3.12.1 interim fix; the agent's terminal processes are stopped first — on Windows too, where v3.12.1 only kills the leader, and including a shell's background jobs,
setsidprocesses and a foreground job whose leader already exited, which surviveterminal_closetoday): conflicts previewed, auto-resolved by the engine, agent commits kept, snapshot taken
Removal
- Snapshot before removal (v3.8 Time Machine), restorable as a new worktree (Strand)
- Never touch a worktree that is locked, marked
.worktree-keep(Dendreo's guard against Claude Desktop's cleaner), or owned by another orchestrator
A differentiating feature: stacked PRs workflow without an external CLI (Graphite, ghstack…). Sequenced after v3.11.0 on purpose: Restack leans on the conflict preview → apply flow.
The paradigm: short stacked branches (feat/step-1 → feat/step-2 → feat/step-3), each with its own PR targeting the previous one.
Visualization — The DAG automatically identifies stacks; a "Stack" banner in the sidebar; a "Stacks" tab in Today
Creation — "Stack a branch" button in the context menu; ⌘⇧S shortcut from the commit area
Restack — Automatic detection when the base has moved; one-click "Restack" button (cascading git rebase --onto); conflict preview before execution (v3.11.0 preview-to-apply)
PRs — "Submit stack": creates or updates GitHub PRs for each layer; automatic retarget when a layer is merged
Merged-PR detection (from the 2026-10-08 changelog scan, Tower 17 / Windows 14) — "is this layer merged?" cannot rely on git_branch_merged (read.rs, git branch --merged): a squash- or rebase-merged PR leaves no ancestry, so the layer is never seen as merged and the retarget never fires. Ask the forge (merged PR whose head is this branch), fall back to a patch-id comparison against the target (git cherry). The same signal feeds the v2.12 Archived Branches: a "merged" hint with a one-click Archive on branches whose PR is merged
Stale-head guard (from the same scan, Conductor 0.89) — a layer is merged only if the PR's head is still the commit reviewed locally: pass the expected sha to the forge merge endpoint (rest_merge_pr sends only merge_method today; GitHub refuses with 409 on mismatch, GitLab has the same parameter), and say so instead of merging commits nobody looked at. Applies to every in-app PR merge, not only stacks
Implementation — Metadata in .gitwand-workspace.json; no external CLI dependency. Cascading Restack and per-layer Submit-stack progress stream via tauri::ipc::Channel (v3.10.0 pattern) rather than a new global emit() broadcast
Inspired by GitBlade. A comparison primitive we lack: one aggregated diff across several commits, even non-consecutive — review scattered work as a single change.
Today's baseline — getGitFileDiff(from, to) and folderDiff(refA, refB) compare exactly two points; CommitGraph.vue is single-select; file history / split commit / fork point don't cover "these 3 commits together".
- Multi-select in the Git Tree —
⌘-click /⇧-click commit selection, selection chip ("3 commits selected → Combined diff") combined_diffTauri command — Rust-side aggregation of the selected commits' patches into one virtual diff (per-file hunk merge, conflict-free since same-history)- Combined viewer — standard DiffViewer rendering + per-hunk commit attribution (gutter badge → jump to commit)
- Entry points — Git Tree context menu, file history ("combine these versions"), PR review (subset of commits)
- Optional AI summary — "what these N commits do together" (what/why/affected areas) via
useAIProvider, reusing the v3.5.0 PR-summary prompt
Second half of Agent Workspaces (split 2026-10-10), on top of the v3.13.0 lifecycle and merge-back. Sequenced after Stacked Branches (v3.14.0), whose merged-PR detection drives the cleanup below.
Creation
- Start from a branch, a remote branch, a PR (
pull/<n>/head) or a Launchpad issue (GitKraken 12.4): branch named after it, issue body as the starting prompt - Agent picker (Claude Code, Codex, Gemini, opencode… — the providers GitWand already knows), not Claude Code hard-wired
Visibility
- A worktrees view, sortable and filterable, replacing the modal: branch, dirty count, ahead/behind, last activity, disk use, PR state, env URL, agent status
- One WIP row per dirty worktree in the Git Tree (GitKraken 12.3), building on the #224 WIP-as-Git-Tree-entry work
- Recognise worktrees created by other tools (
.claude/worktrees/, Conductor, Superset…) and identify an agent session by its process, not by the presence of a.claude/folder —detect_agent_toolflags every worktree of a repo that commits.claude/, GitWand's own included
Agent status
- Live status — per session: running, waiting for input, idle, exited. Baseline with no integration: PTY output activity + process state (works for any CLI); richer states from each CLI's own hook mechanism where it has one, starting with Claude Code hooks. Shown on terminal tabs, in the worktrees view and as an OS notification when a background agent starts waiting
- Permission requests in-app — when the CLI exposes it (Claude Code hooks first), surface the pending tool call with the exact command, Allow / Deny from the panel. Never auto-allow; an unanswered request stays pending in the terminal exactly as without GitWand
Parallel work — where the engine pays off
- Cross-worktree conflict prediction — run the Conflict Predictor between parallel tasks and against the target before anything lands: "task A and task B will conflict on
useRepo.ts, 3 hunks, 2 auto-resolvable". Strand only warns that two worktrees touch the same files; nobody predicts the actual conflicts. The headline of this release - Compare two attempts at the same task side by side, keep one (Strand)
Cleanup
git worktree lockwhile an agent runs (Claude Code does the same), unlock when it exits- Clean up once the PR is merged (v3.14 merged-PR detection) or after N days inactive, single or batch (Dendreo's
clean --merged), always throughteardown
- Local dictation: microphone button in the commit panel — transcription via embedded Whisper (
whisper-rsRust) — zero cloud - Optional AI enrichment: pass dictated text through
useAIProviderfor conventional commit formatting - Models:
tinyorbasedownloaded on demand, stored locally - Multilingual: Whisper auto-detects the language
- Graceful fallback: clear message if microphone access is denied by macOS TCC
Inspired by Snipara's project-intelligence layer. Before a merge/rebase, answer: "what does this operation risk breaking?" — the natural extension of Conflict Predictor + postMergeRisk (v2.4.1), and a headline differentiator. The same graph also answers the question one step later: "did it actually break something a text merge couldn't see?"
Today's baseline — packages/core already embeds tree-sitter (TS/JS/Python/Go/Rust WASM grammars), an ES/CJS import parser (resolvers/imports.ts) and parse-tree validation (validate-parse-tree.ts), but no dependency graph, caller discovery, or test mapping.
- Early exit before parsing —
git diff --name-statuson the two branches first: if every path is either newly added with noimport/requireline referencing a symbol the other side changed, or matches an asset/doc extension (.css,.png,.md, …), the engine declares no possible semantic collision and returns without loading tree-sitter. Same spirit as.gitwandrc'sgeneratedFilesskip. Cheap, not literally free — an added file's imports still get scanned against the other side's changed-symbol list, since a new file can call into a renamed export it never touched in the diff - Import graph —
packages/core/src/codeanalysis/: tree-sitter queries build the module adjacency graph (browser-safe, incremental). Cached locally, content-addressed by blob SHA (git's own object model, no external index format): a file's parsed edges are only recomputed when its blob changes, so re-running against an unchangedmaincosts nothing. Considered and dropped: downloading a prebuilt LSIF/SCIP index from CI — real repos rarely have one, and it would pull in exactly the cloud/infra dependency the local-first positioning avoids elsewhere on this page - Reverse dependencies — for each file touched by the operation: who imports it, which exported symbols changed
- Shallow parsing on dependents — full AST only for the files a branch actually changed; on unmodified files reached through the reverse-dependency edges, tree-sitter queries pull import declarations and call expressions only, function bodies/loops/local variables are never walked unless the file itself was touched. Keeps the cost proportional to the blast radius, not to the repo
- Silent conflict detection (
detect_silent_conflict) — the case git's text merge never flags because the two sides touched different files: branch A renames a symbol or changes its signature, branch B keeps calling the old shape somewhere the line-level diff never intersects. Runs the same import graph against the merge's actual result (localgit merge --no-commit --no-ff, zero side effects, same discipline asgitwand_preview_merge) instead of the pre-merge diff. A scored pattern registry (renamed_export_vs_import,signature_change_vs_unchanged_call,deleted_variable_vs_scoped_reference) reports a traced collision —files_involved,confidence, atracebuilt only from real symbol/line names, never a paraphrase — and never auto-fixes it. Mirrors the text engine's own rule (acomplexhunk is never silently applied, v3.9.0) one layer up, at the symbol level instead of the line level - Probable-test detection — heuristic mapping (
*.test.*/*.spec.*naming + import edges) → "these 12 tests likely cover the changed code" - Co-change analysis — "these files historically change together" mined from local
git log(zero cloud, cheap); a second impact signal complementing the static import graph, exactly the history hop Greptile does server-side - Blast Radius panel — new tab in
MergePreviewPanel: impacted files ranked, affected symbols, suggested test scope; feeds ablastRadiusdimension alongsidepostMergeRisk - Review ordering — blast radius reused in the PR review (v3.5.0): files ranked by impact, "start with these 2 files"
- Feedback loop — rejected impact predictions / auto-resolutions lower the pattern's confidence (extends
useResolutionMemory), the local analog of Greptile v4's false-positive reduction; the Engine Accuracy release's lot F (derive the repo's conventions by replaying its own history) is the active, measured form of the same idea — the two should share one store - Agents too — exposed via
@gitwand/mcp(gitwand_blast_radius,detect_silent_conflict) and CLI only, never the/agentWebMCP page, which by design never touches a real repository or its history. Positioning: Greptile sells this as a paid API ("Genius API", $0.45/req) — ours is local, free, open source - Package-graph pre-filter (optional) — when the repo already has an Nx, Turborepo or Bazel project graph, use it as a coarse first pass: if
main's changed package isn't a dependency of the PR's changed package, declare a pass without loading tree-sitter at all. Falls back to thepnpm-workspace.yaml/package.jsonworkspace graph GitWand already reads when none of the three is present, so this works the same on GitWand's own repo (plain pnpm workspaces, no Nx/Turborepo/Bazel) as anywhere else. Package-level only — two files inside the same package still go through the full reverse-dependency graph, since that's whererenamed_export_vs_importactually lives - CI/CD gate —
detect_silent_conflictdoubles as a CLI check (gitwand check-semantic,packages/cli), runnable as a GitHub Actions / GitLab CI job against a PR's would-be merge (fetch base + head, no working-tree side effects). Ships advisory first — inline PR annotations — following thegitwand scanprecedent (v3.5.0: non-blocking badge, opt-in pre-commit hook before anything blocked); becomes a hard-blocking gate only once its false-positive rate is measured and cleared, the same discipline that kept--regenerateCLI-only at 38.5% agreement against an 80% bar (Engine Accuracy, v3.9.0).benchmark-gate.ymlis the existing precedent for a hard block already living in this repo's own CI - Opt-in & lazy — computed post-preview, never blocking the merge flow; enabled in Settings
Competitive scan from 2026-06-24 across 6 clients/tools (Snipara, GitDriv, GitUp, GitX-dev, Aurees, GitBlade), updated 2026-07-20. High-signal leads were promoted into the versioned sections above after a code audit — PR Review 2.0 (inspired by Greptile) → v3.5.0 (shipped), Commit Review (inspired by git-lrc) → v3.7.0 (shipped), global snapshots/undo → v3.8.0, Live Map + libgit2 phase 1 → v3.10.0, editable diff + merge preview-to-apply → v3.11.0, Combined Diffs → v3.15.0, code graph/blast radius → v4.0.0 (candidate). Discarded leads (GitDriv = beginner web drag-and-drop, GitX-dev = near-dead fork, GitBlade = parity only, abandoned since 2019) bring nothing advanced.
2026-07-09 scan — three serious new competitors (all post-dating v2.15.0), now folded into the Competitive landscape table above: Strand (strand/0.5.0, agent workspaces via worktrees), GitComet (gitcomet/0.1.15, pure Rust+GPUI perf), RelaGit (relagit/0.16, design/SolidJS).
Synthesis: none of the three addresses structured conflict-resolution AI (Strand = agent workspaces, GitComet = perf, RelaGit = design) — GitWand's moat (auto-resolve + multi-repo Launchpad + extensible CLI/MCP) stays intact. Worth cultivating: the v3.8–v3.11 pipeline (preview-to-apply) + v4.0 code graph to widen the gap. Worth borrowing from their respective strengths: published a11y/perf baselines (Strand, → v3.10 benchmark pass), SolidJS vs Vue 3 benchmark on heavy diffs (RelaGit, → v3.10 perf pass).
2026-10-08 scan — Multi-Git (AnthonyKopri/multi-git, MIT, Electron/Node): multi-account SSH, safety net, coding-agent launcher, JSON CLI + MCP. No conflict AI (ours/theirs/manual only). Most of its safety layer is already covered: Recovery Points / Recently Discarded ≈ Time Machine (v3.8.0), "behind upstream" fast-forward ≈ v3.6.0, MCP dry_run + structured refusals ≈ design principle 6. Two leads kept, in Later (unscheduled): SSH routing on identity profiles and opt-in auto fast-forward after fetch. Discarded: passphrase vault (the system agent/keychain does the job), parity features (bisect, notes, LFS, patches).
2026-10-08 changelog scan — April→October release notes of GitKraken, GitButler, Tower, Fork, Sublime Merge, GitHub Desktop, Strand, GitComet, RelaGit, GitSquid, plus Zed, VS Code, lazygit, Conductor, Nimbalyst and the jj GUIs. Promoted: Agent Control → Agent Workspaces after the worktree audit (split on 2026-10-10 into v3.13.0 and v3.16.0); merged-PR detection and stale-head merge guard → Stacked Branches (v3.14.0). Gitoryx (gitoryx.com, v1.0.1, 2026-10-06) added after the scan: only gaps worth taking are guided bisect and the tracked-but-ignored warning (both in Later); sprint view, GitFlow and gitmoji discarded, changelog generation ≈ our tag-triggered release notes. Already covered or planned: cherry-pick/revert conflict indicator (Fork 2.66 ≈ Conflict Predictor v2.20), combined diff (Tower 14.1 ≈ v3.15), stacked PRs (GitButler 0.22, VS Code ≈ v3.14), Forgejo, file history, pickaxe search. Moat alert: GitButler 0.21 ships AI-assisted conflict resolution and but resolve (0.22), Gitoryx an auto-resolve "wand" for identical blocks (0.0.31) and AI conflict resolution (0.0.42), IntelliJ 2026.2 a "streamlined conflict resolution flow" — "nobody else does conflict AI" no longer holds for GitButler; the measured-accuracy benchmark (v3.9) is the answer to keep forward.
Still watching:
- Per-hunk commit attribution for parallel agents (Nimbalyst 0.75) — when several sessions edit the same file, each commits only its own hunks. Interesting once Agent Workspaces (v3.16) knows which session wrote what; speculative before.
GitUpKit(gitup.co) — their SDK for building Git clients, worth studying.- libgit2 phases 3-4 — migrate
git_log/git_show(revwalk, the real win on 40k commits — but the object-fetch loop needs optimizing first) thengit_file_log(--follow/rename tracking to reimplement). To schedule once phases 1-2 (v3.10/v3.11) are validated.gixas an alternative to be re-evaluated at that point. - libgit2 for
list_repo_tree(candidate, 2026-10-01) — the File Explorer panel's one-shot tree isgit ls-files --cached --others --exclude-standard, capped at 20,000 entries. It could read the index directly and classify untracked entries withis_path_ignored, the way v3.11.2'slist_repo_dirdoes (66 ms for a 6,000-entry directory against 1.6 s withgit check-ignore). Next step: retirelist_repo_tree(no frontend caller since v3.11.2, when the panel moved ontouseLazyRepoTree) or migrate it to libgit2 if a caller returns. Same rule as every libgit2 migration: measure first, keep the CLI fallback, cover it with parity tests. libgit2 stays off anything that runs filters, hooks or external config (LFS, signing, credentials), off writes, and off algorithms it implements differently (blame, histogram/patience diffs). - Verification Plans attached to handoffs (Snipara) — every PR/change carries the checks it must pass; overlaps with the CI annotations (v2.18.0).
- Greptile (greptile.com) — largely absorbed into the plan (2026-07-02): multi-hop pre-review + confidence scores → v3.5.0 (shipped), hot index → v3.10.0, LLM-fallback historical context → v3.11.0, local code graph + co-change + feedback loop → v4.0.0. Still watching: their public AI-reviewer benchmark (reusable for the v3.5.0 benchmark work) and how the Genius API evolves.
- git-lrc / LiveReview (HexmosTech) — concept absorbed in v3.7.0 (Commit Review). Still watching: their LiveReview team offering (dashboards, org policies, review analytics) — if the
GitWand-Reviewtrailer catches on, a cross-repo rollup in Today/Dashboard would be the local equivalent. - FinderGit — UX worth borrowing (file-tree first), macOS-only today; the Finder-like sidebar concept has been promoted to v3.11.0. Cross-platform via Tauri is a structural advantage over FinderGit's solo-dev status.
-
Follow-ups from the #234–#239 reviews (2026-10-09):
- explicit force pushes (reset, rebase, undo, the Force Push menu item) still use a bare
--force-with-lease, which the 30 s background fetch defeats — pass the expected sha as the #239 auto path does - #239 treats a pull later undone by a local reset as a local rewrite (the collaborator's commit was once a local tip), so Force Push is offered and would drop it; and with
push.default=upstream+ a differently named upstream the auto force push can never succeed — judge against@{push}and lease that ref - #234: on Windows,
gh/glabreceive the PR body on the command line (≈32K limit) — send JSON on stdin (--input -); a background revalidation racing a save can briefly show the old title/body - #237: the Rust model-listing commands (
codex debug models,copilot help config,agy models, opencode) have no process timeout of their own (the frontend gives up after 30 s, the child lingers)
- explicit force pushes (reset, rebase, undo, the Force Push menu item) still use a bare
-
Follow-ups from #244 (security hardening) (2026-10-09, updated after its review rounds on 2026-10-10):
- Copilot is unverified (not installed when the follow-ups were written): its run directory, stdin support and lockdown; Antigravity (
agy1.0.13) still gets the prompt on argv, and its tools are not restricted - the user's own MCP servers still load for Codex and opencode (no confirmed switch:
-c 'mcp_servers={}'does not remove them) ai_http_requestwithauth: "none"(Ollama) still reaches any http(s) URL through the backend — limit it to the configured Ollama URL- Windows: a grandchild of the
claude --helpprobe can outlive it once the direct child has exited (needs a Job Object) - Claude Code still creates one empty
~/.claude/projects/<run-dir>/folder per run (no flag avoids it;--no-session-persistencealready drops the transcript) - the
ai-runssweep (24 h, at base setup) could remove a run directory still in use by a run older than that in another GitWand process - flaky tests seen on 2026-10-10:
pullAutostash.git.test.tscleanup (rmSynchitsENOTEMPTYon.git, retry it),merge_back_without_a_recorded_base_still_worksunder full-suite load - an XSS in the webview still drives every IPC command: scope commands per window/capability, and give
read_file/write_filea registry of repositories the user opened rather than the.git-ancestor check (a dotfiles repo at$HOMEpasses it) img-srcstayshttps: http:for self-hosted forge avatars — proxy or allowlist avatar hosts, then tighten it- parity-probe dispatch entries for
read_commit_templateandai_http_request(noneauth against a local fixture server) usePrPanel-cli-missing.test.tsfails on a machine whose locale is not English (asserts the English timeout string) — pin the locale in the test
- Copilot is unverified (not installed when the follow-ups were written): its run directory, stdin support and lockdown; Antigravity (
-
SHA-256 / reftable repositories (2026-10-08 scan: GitButler 0.19.10, Sublime Merge 2130, Zed) — git handles them, but a few GitWand parsers assume 40-hex ids (
git/libgit2.rs:754,dev-server.mjs:4165). Audit every such assumption and add a SHA-256 fixture repo to the parity tests. -
Guided bisect (Gitoryx) —
bisectexists only as an in-progress operation GitWand can abort (ops.rs). Add a start flow (pick good/bad from the Git Tree), Good / Bad / Skip on the current commit, remaining-steps counter, culprit commit opened at the end; optionalbisect runwith a user command. -
Per-project identity everywhere (from the #246 review) — the project's identity (
commitIdentityFor) reaches plain commits and custom automations only; amend, split,--no-ffmerge, revert and cherry-pick still use git's config, so the committer (and for merge/revert/cherry-pick the author) can differ inside one project. Route every commit-creating command through it. Also keyidentityOverrideByRepoon a canonical path (case-folded on case-insensitive filesystems, worktrees resolved to their main repo), so the same project opened through another spelling or a linked worktree keeps its identity -
SSH routing on identity profiles + wrong-account guard (from the 2026-10-08 Multi-Git scan) — the v2.12 profiles (
useIdentity.ts) only injectuser.name/user.emailat commit time; authentication still goes through the global SSH config. Add an optional SSH key per profile, routed per operation viaGIT_SSH_COMMAND(fetch/pull/push/clone), auto-select rules on the origin URL (github.com/acme/→ Pro), and a pre-push check: the account the key actually signs in as (ssh -T, remembered per key) vs. the one the remote expects; on mismatch, block with an explicit override, force-push included. Real pain for anyone juggling work and personal accounts, and author + key always switch together, so a repo can no longer push as one account and commit as another. -
Follow-ups from #260–#265 (2026-10-14):
- #262: PR reads (detail, review threads, comments, reviews) and comment/review writes still resolve the PR via
get_pr_json, origin first — on a fork with a same-numbered PR they act on the fork's PR. Movingget_pr_jsonitself to the base repo fixes every caller at once - #262: the tokenless merge (
gh pr merge,gh_merge_pr_inner) passes no--repo, unlikegh pr ready - #265: a bisect in progress is invisible to the status, so the tooltip shows it only after a fast-forward attempt; a stale block reason can linger up to one fetch tick (30 s); a branch literally named
HEADorunknownis treated as detached - #264:
git_untrack_pathsneeds git ≥ 2.25 (--pathspec-from-file) - #263: the fr/es/pt-BR/zh-CN strings for the Keep mode were not read by a native speaker
- #262: PR reads (detail, review threads, comments, reviews) and comment/review writes still resolve the PR via
-
Follow-ups from #258 (command registry covers the forge wrappers) (2026-10-14):
- on a fork, dev-server
/api/gh-pr-comment(POST, PATCH, DELETE) targets origin viagetRepoNwo, while the Rust commands resolve the PR elsewhere; the PATCH and DELETE web branches ofghPrUpdateComment/ghPrDeleteCommentdo not even send the PR number. dev:web QA of review-comment edits on a fork is not representative - 97 forge commands are registered as
GAP:(Azure DevOps and Bitbucket PRs, GitLab MRs beyond auto-merge and issues, Gitea beyond the 8 read routes, and some GitHub PR actions, reactions and auth flows) — dev:web cannot exercise them
- on a fork, dev-server
-
Follow-ups from #269–#270 (file history compare, diff parsers) (2026-10-14):
- a file history entry outside the loaded history (line-range result, rebased commit) has no known name before a rename; the Compare tab says so instead of guessing — load more history, or have
git log -Lresults carry names - CRLF: Rust strips
\rfrom diff line content, the dev-server keeps it (also true ofgit_diff) - file status (added/deleted/renamed) is still derived in several places with different coverage (
parse_diff_hunks,parse_multi_file_diff,devParseDiffHunks, the dev-servergit-showloop) - combined
@@@hunk header numbers differ (Rust old 1,1 / new 0,1; core and the dev-server 0,1,0,1), andisPureMoveon a combined hunk - strict hunk counts cut a hunk whose header undercounts its body; no forge path in the app sends such diffs today
- a file history entry outside the loaded history (line-range result, rebased commit) has no known name before a rename; the Compare tab says so instead of guessing — load more history, or have
-
Follow-ups from #257 (GPU-first rendering on Linux) (2026-10-13):
- the software fallback is untested on the setups it is for: only the #135 (Ubuntu 26.04, native Wayland) and #139 (Mint 22
.deb) reporters can confirm that the second launch recovers. Ask them once it ships - the first launch that hits the EGL abort still shows nothing; only the next one switches to software. A launch that hangs without aborting is not detected
- remove the shim (
commands/render_fallback.rs, its two commands and the Settings row) once the EGL abort is no longer reported. It is not tied to a build host: #135 was on 26.04
- the software fallback is untested on the setups it is for: only the #135 (Ubuntu 26.04, native Wayland) and #139 (Mint 22
-
Move the Linux build host to ubuntu-24.04 (around April 2027, when 22.04 leaves standard support) — release and bundle builds run on ubuntu-22.04 so the
.deb/AppImage keep working on glibc 2.35 (22.04, Mint 21.x, Debian 12). Moving drops those systems, so announce it one release ahead. -
Test the log view epoch (follow-up to v3.12.0, #214) — the filter/scope change that drops in-flight log pages and the forced-reload depth (
forcedReloadDepth) have no test; auseGitRepotest for "filter change while a page is in flight" would lock them in. -
Re-list loaded folders without the watcher (follow-up to v3.11.2) — the File Explorer panel re-lists a loaded folder only on a watcher event. With Live Repo off, or with the watcher unhealthy (network mounts, for instance), new and deleted files never appear in a folder already loaded, while the folder badges, fed by status polling, do change, so the tree and its badges disagree. Add a Refresh action, or re-list the loaded folders whenever the
repoFilespath set changes and the watcher is not healthy. -
Snapshot rebase/cherry-pick state — v3.8 restores
MERGE_HEADbut not.git/rebase-merge/or.git/sequencer/, so restoring a snapshot taken mid-rebase or mid-cherry-pick brings the files and index stages back without the in-progress sequence. Restoring those is a directory copy rather than a plumbing call, which is why it was left out of the first pass. Revisit if users report rewinding mid-rebase. -
Snapshot cost on very large working trees — each snapshot runs
git add -Ainto a scratch index, which is O(worktree) on a cold cache. Fine on normal repos, unmeasured on a 100k-file monorepo. Benchmark alongside the v3.10 FS-watcher work, where the same walk gains a second consumer. -
Snapshot refs are visible to a bare
git log --all— GitWand excludes them from every traversal it runs, but any ref underrefs/is by definition part of--all, so a user typing it in a terminal sees snapshot commits, exactly as they seerefs/stash. Nothing to fix short of abandoning refs entirely (which would letgceat the snapshots); documented here so it is a known property rather than a surprise. -
libgit2 phase 2: stage/unstage (moved out of v3.11.0, 2026-09-14, measured and declined): the plan was index-level
git2staging behind a CLI fallback, mirroring the v3.10git_diffmigration. Measured before building, and the numbers say not to. Perf: the win is a flat ~15 ms, which is the subprocess spawn and nothing else, because both paths pay the same hashing cost.git addagainst libgit2, median of 7 runs: 1 file 17.1 vs 1.8 ms, 100 files 79.7 vs 64.1, 1000 files 926.7 vs 874.7, 5000 files 4997 vs 4487. Staging is batched (one call for N paths), so that 15 ms is per user action, and everystageFilesis followed by arefresh()whosegit statusalone costs 20 ms on a 1000-file repo and 31 ms on 5000. The saving is smaller than the refresh that immediately follows it. Correctness: 8 of 9 scenarios write a byte-identical index (modified, untracked, deleted, CRLF undertext=auto+core.autocrlf, exec bit, symlink, conflicted-resolve, andunstageviareset_default). The ninth diverges: libgit2 implements the built-in CRLF filter but executes no externalfilter.<name>.cleanprocess, which is exactly the Git LFS mechanism. A probe with a filter rewritingSECRETtoREDACTEDhad the CLI storevalue=REDACTEDand libgit2 storevalue=SECRET; on an LFS repo that is the raw binary in the index instead of the pointer, and git then reports the file asAMrather thanA, so it reads as "still modified" rather than as corruption. A guard is possible (repo.get_attr(path, "filter")to detect filtered paths and defer to the CLI), but a fast path plus a detector plus a fallback plus parity coverage, all for 15 ms, does not pay for itself. Revisit only if staging latency becomes a real complaint, in which case the measurement points at the post-actionrefresh()rather than atgit add, and the v3.10 watcher is already the infrastructure for that. -
libgit2 blame (moved out of v3.11.0, 2026-09-14, because it cannot be completed on demand):
git_blame's fast path was written, tested and then left disabled in v3.10.0.blame_attribution_matches_the_cli_on_a_moved_blockexposed a git-version-dependent attribution divergence on a moved block between libgit2's bundled Myers xdiff and the CLI's histogram blame: green against git 2.50.1, red against 2.55.0. This is a disagreement between two algorithms, not an unfinished task, so it has no estimate and no owner action short of resolving the divergence upstream or reimplementing the attribution. Blame attribution is user-visible, so the CLI stays authoritative.libgit2_blameand its tests stay in tree as the regression guard; re-enabling it means resolving the divergence first, not deleting the test. -
Linux inotify validation (moved out of v3.11.0, 2026-09-14, same reason): the v3.10 watcher registers inotify watches across the working tree, and registration cost on a
node_modules-sized checkout was never measured on real Linux hardware, the work having been done on macOS where FSEvents has a different cost model. It is a measurement, not a change: the outcome may be "nothing to do" or "the watcher needs rework", which is precisely why it cannot sit on a release's critical path. Needs doing before the watcher is leaned on any harder, and before the v4.0 indexer becomes its second consumer. -
Rebase preview loses commit provenance (deferred from v3.11.0 lot A1):
preview_rebasereplays each commit of the stack separately, then deduplicates the results per file keeping the strongest conflict signal (read.rs, theby_filefold). Which replayed commit actually produced a given conflict is discarded in that fold, so the panel cannot say "this conflicts at commit 3 of 5", and a future per-commit "stop here" apply cannot be driven from the payload. Fixing it means a new field on the serializedFileMergePreview, which ripples into the dev-server route and the parity normalization, so it was left out of the release that added the routes. The scratch-file race and the missing-Llabels in the same function were fixed; this one is purely an enrichment. -
Multi-forge PR-freshness signal parity — follow-up to the branch-badge background-prefetch/cache work (PR #125): GitLab/Bitbucket/Azure already get the breadth fix (background drain past the first page), but not the cheap freshness-signal instant-cache-restore fast path — GitHub-only today, since the other three don't yet have an equivalent cheap "most-recently-updated PR" query built. Deferred until there's real non-GitHub usage pressure.
-
Cursor-based PR-list pagination (Rust) — already flagged in-code as Phase 2/v2.9 (
gh_list_prs_inner/rest_list_prscomments, predates PR #125): replace the naive offset+limit re-fetch, which re-walks from the start on every page, with a cursor-basedgh api graphqlquery. Removes the quadratic re-fetch cost for repos with very large open-PR counts; most repos stay well under the current 300-PR prefetch ceiling, so this is scalability hardening, not an urgent fix. -
Commit Review "Fix with agent" in a scratch worktree — follow-up to v3.7.0: the originally-planned "optionally in an AI-task scratch worktree" variant was cut after manual QA against real
claude/codexCLIs found a brand-new scratch worktree always hits a first-run "trust this directory?" onboarding screen that misinterprets the piped prompt as menu navigation (drove a realbrew upgrade --cask codexin testing). Revisit once there's a real fix — pre-trusting the directory before launching the agent, or detecting the onboarding screen before writing. -
Decide the fate of the
explainOnlyoption (follow-up to the v3.7.2 predictor fix): it short-circuitsresolveHunk()before the format-aware dispatch and the confidence gate, so any caller that readsstats.autoResolvedafter using it gets a structural0. That is exactly howgitwand previewand two MCP tools shipped broken. After the fix the option has zero consumers in the monorepo while staying part of the publicGitWandOptionscontract, so it is now a footgun with no user. Either remove it (breaking change for external consumers, if any) or redefine it as "classify and resolve, but do not assemble merged content", which is what every call site actually wanted. -
Let an in-flight AI call survive a hunk renumbering (deferred from the issue #196 work): confirming one hunk renumbers every later one, and the queue's answer to that is to keep its settled suggestions (renumbered) and discard whatever is still running, because a run captured its index in its closure when it was dispatched. Keeping those runs alive means giving each one a token the queue resolves to an index at write time, so a renumbering rewrites the mapping rather than invalidating the work. Worth doing only if batches get slow enough that discarding a few in-flight calls is felt.
-
Hard cancel for an in-flight AI call (deferred from the issue #196 work): cancelling a hunk or a batch marks the entries idle and discards late results, but an already-spawned
claude -pkeeps running to completion. Killing it needs a Rust command holding the process handle plus a way to address it from the frontend, which is its own piece of work. -
Manual pass over the AI hunk queue in the packaged app (outstanding from the issue #196 work). The UI half is done: a run against the real
claudeCLI underpnpm dev:web(4 complex hunks, one file) watched the batch stage 4 answers, confirmed one hunk and saw the other 3 survive renumbered onto the right hunks, saw a rerun re-buy nothing, and saw a cancelled call's late answer land nowhere. What is left is the responsiveness half, and it cannot be checked underdev:web:dev-server.mjsspawns the provider withspawnSync, so it blocks its own single thread for the whole call (measured: an unrelated API request waited 10.1s; the 4-hunk batch took 79s as four serialized calls, never 3 concurrent). The dev-server therefore shows the opposite of what the Rustspawn_blockingchange fixes. The mechanism itself is now pinned by a Rust regression test (commands::ai::tests): three AI commands are put in flight on a deliberately single-worker runtime and a 50ms timer still fires in 50ms, where the same test measured 3.2s before thespawn_blockingchange. What is left is therefore only the human half, in the packaged app: that the window keeps painting and the progress and partial-failure lines read correctly while a real batch runs. -
Commit Review coverage on a content-only restage — v3.7.0's staged-set watcher fingerprints staged file paths + statuses, not content, so editing an already-staged file's content without changing which files are staged doesn't retrigger a coverage/finding recompute automatically (the pre-commit gate still recomputes coverage honestly right before the trailer is written, so the record itself stays accurate — this is a UI-staleness gap between review passes, not a data-integrity one).
-
Retire the frontend's "default to GitHub" forge fallback (follow-up to the v3.7.3 self-hosted-GitLab fix, #168):
useForge.ts'sgetProviderByUrl/usePrPanel.ts's pre-resolutionforgecomputed still assumegithubProviderwhenever detection hasn't resolved yet (no remote,dev:webmode, or a genuinely unrecognized forge) — a deliberate, documented backward-compat default, not an oversight. The Rust-side detection is now forge-agnostic end to end (URL match →glab/gh auth status --hostnameprobe), so the one remaining non-deterministic step is this UI default. Precedent exists for the alternative: Cursor Origin (#165) shows an honest "unsupported forge" state instead of guessing. Doing the same here would need the brief pre-resolution window (beforegitRemoteInfo()returns) to render a neutral/loading state instead of an optimistic GitHub guess — deferred until there's a concrete report of it mattering, since today it never surfaces the wrong forge for supported CLIs. -
Gitea follow-ups (deferred from the v3.11.0 Gitea lot, issue #193): forge-side auto-merge via the merge endpoint's
merge_when_checks_succeed, which Gitea does support; submitting and dismissing reviews (reading them is implemented), check annotations, per-file review history, cross-fork PR creation, and Gitea Actions logs; exact PR counts, sincegitea_pr_countis bounded at 300 because Gitea's real total lives in theX-Total-Countresponse header andcurl_with_statuscaptures no headers at all, so an exact count needs a shared-transport change that would touch every forge;SettingsAccountsTab.vuehas no test file, so the account form's Gitea branch and the two-entry keychain removal are covered only by hand-reading, which is where the frontend-to-Rust join already broke once and would break silently again; and an old Gitea that silently ignores an unrecognised merge field and merges with its own default (HTTP 200) never triggers the legacy-field retry, with nothing in the status code to distinguish that case. Also, from the final review fix wave (2026-09-16): commit links forcehttpsand drop the port, because the frontend-onlyforgeCommitUrlbuilder cannot see the account's base URL, which lives in the keychain, Rust-side only;App.vue'sopenOnForgesends a Gitea repo to github.com, a pre-existing gap it now shares with azure and cursor; the account form can carry a stale username when the forge select is switched mid-form without clearing it; and the dev-server'sgitea-pr-countroute uses the list ceiling where the Rust command uses a dedicated count ceiling, and surfaces an HTTP error where the Rust command degrades to0. -
History-aware prompts for the MCP — align
buildResolveHunkPrompt/gitwand_resolve_hunk_llmwith the v3.11.1 history context (collectHunkHistoryis already exported from@gitwand/core). -
Rename-aware history —
blame -M -C/log --followfor the v3.11.1 history context. -
Dedicated
git_conflict_historyRust command — one IPC round-trip and a real process timeout, if thegitExecround-trips of v3.11.1 prove slow. -
Honor
.gitwandrcllmFallback.model/maxTokenson the desktop — ignored today in favour of the app's AI settings. -
File Explorer follow-ups (out of scope for v3.11.2, spec §10 and its 2026-10-02 addendum). Not done: stage/unstage from the panel, file operations (rename, delete, create), and tree-wide name search beyond type-ahead over the visible rows. Each needs its own design, and search would have to work with a 5,000-per-folder listing cap.
-
Refresh a clean File Explorer tab on an external change. A tab's buffer is read when the tab opens. Since v3.11.2 a clean tab re-reads the disk when it leaves its Diff side, but a tab that stays on File does not see an edit made outside GitWand until it is reopened. The watcher already reports the path, so a clean tab could reload in place, and a dirty one could offer to.
-
Live Repo watcher blind spot on ignored folders. The watcher drops events under
node_modules,target,dist,.venvand__pycache__, so an ignored folder expanded with "Show ignored" in the File Explorer does not refresh live. Collapsing and re-expanding it re-lists it.
GitWand is a native Git client that understands code, resolves trivial conflicts on its own, and makes visible what the terminal hides.
Positioning: neither "yet another Git GUI" nor an IDE. A first-class Git navigation tool — fast, local-first, cross-platform — with a unique algorithmic intelligence for conflict resolution, and a surface for interacting with AI agents (MCP, Agent Sessions, terminal).
Core values: open source (MIT) · native performance (Tauri 2 + Rust) · zero mandatory cloud · every feature optional and explicit.
| Client | Stack | Price | Strengths | Weaknesses |
|---|---|---|---|---|
| Kaleidoscope | macOS native | ~€150/yr | Image diff, folder diff, visual 3-way merge | macOS-only, no Git workflow, no auto-resolve |
| GitHub Desktop | Electron | Free | Simple, GitHub PR workflow, cherry-pick/rebase | GitHub only, basic diff, no AI, no auto-resolve |
| GitButler | Tauri/Rust | Free | Virtual branches, stacked PRs, Agents Tab (Claude Code); MCP server, Series A Apr 2026 | Unfamiliar paradigm, no algorithmic auto-resolve |
| GitKraken | Electron | $8/mo | Agent Mode v12.0, multi-forge, Launchpad, cloud Workspaces, AI commit/PR/merge | Paid, Electron, cloud account required for advanced features |
| GitSquid | Tauri/Rust | €49/yr | Conflict Predictor, scratch worktree, Monorepo Scope, secrets scanner, multi-forge | Paid, no algorithmic auto-resolve |
| Fork | Native | $50 | Fast, clean UI, large repos | No inline PR review, no auto-resolve |
| Tower | Native | $69/yr | AI commits (Claude Code + Codex, v16 May 2026), multi-forge | Paid, no resolve engine |
| Sublime Merge | Native | $99 | Ultra-fast, configurable diff_algorithm |
No PR workflow, no AI, no auto-resolve |
| Strand | Tauri 2 + React | Free/OSS | Agent-native worktree sessions (parallel agent workspaces), full worktree lifecycle (merge+archive+recovery), WCAG 2.1 a11y, published perf baselines | No conflict AI, mono-repo only, no Launchpad equivalent |
| Gitoryx | Native (non-Electron) | Freemium (private repos capped at 30 commits on Free) | Very active (36 releases May→Oct 2026, v1.0 on 2026-10-01): guided bisect, identity profiles per repo, auto-resolve wand for identical conflict blocks + conflict map, AI conflict resolution and commit explanation, changelog generation | Proprietary, conflict handling shallow (identical blocks + LLM), no engine accuracy measurement |
| GitComet | Rust + GPUI | Free/OSS | Zed-level responsiveness, dual GUI+headless (difftool/mergetool), Linux-first, documented perf on Chromium-scale repos | No AI, no worktrees, no multi-repo, no conflict resolution (strategy algo only) |
| RelaGit | Electron + SolidJS | Free/OSS | Fine-grained reactivity (SolidJS), native AI SDK (@ai-sdk/anthropic) for commit suggestions, community theme ecosystem, popout windows |
Electron (heavy), fragile beta, no worktree/launchpad, no structured conflict AI |
Full change details per version: CHANGELOG.md
| Version | Highlights |
|---|---|
| v3.12.4 | Windows app starts without the Visual C++ Redistributable — the C runtime is linked statically (it had been imported since v3.11.2, so winget rejected v3.11.2 to v3.12.3), and the release fails if the exe imports it again · the asset re-upload step looks in the real bundle folder (#273) · SECURITY.md (#272) |
| v3.12.3 | Reset --keep (#263) · opt-in auto fast-forward after fetch (#265) · tracked files matching .gitignore warning + untrack (#264) · PR comment actions on GitHub, in-house Markdown renderer, GPU rendering by default on Linux with an automatic software fallback (#257) · diff parsers bounded by hunk counts keep --/++ lines (#270) · file history compare in the desktop app, across renames (#269) · non_overlapping no duplicate lines under diff3 (#259) · MCP residual-marker check (#260), Bitbucket PR-list pagination (#261), PR write actions on forks (#262), global-shortcut startup (#256) · command registry covers forge wrappers and Rust registration (#268, #269) |
| v3.12.2 | Extra context for AI-written PRs and release notes, create a branch with AI from the branch selector, commit AI language chips translate the current message, one shared frame for AI split buttons (#252) · AI generation follows the chosen language and model again (stale settings write-back), no phantom origin branch and every remote's branches count as remote (#255), identity menu no longer clipped (#252) · modal close buttons aligned, light-theme dividers and minimap visible, larger modal/Help titles (#253, #254) · tests pinned to en-US (#251) |
| v3.12.1 | AI-task merge-back no longer loses data (#233, #247) — squash-merge only when the main checkout's HEAD is in the task's history and the task's starting commit/branch still holds, all or nothing, snapshot first (dry run, so a refusal leaves none); closing a terminal stops the agent's process groups; a cleanup failure closes the task with a warning · Security hardening (#244) — AI CLIs from an allowlisted env, each run in a fresh private directory, Claude with no tools/project settings/MCP, prompts on stdin; AI key in the OS keychain, bound to its endpoint; CSP to fixed hosts; remote images and Gravatar opt-in; telemetry opt-out; file commands confined to git work trees · Full-screen Settings aligned with Help, per-project commit identity with its signing key (#246) · WIP as a Git Tree row (#224) · AI PR-description update and in-place edit (#234), reasoning effort forwarded + provider model lists (#237), unified AI templates with per-repo output language (#238), force push after a local rebase (#239), responsive header (#240), discard keeps staged work (#241), terminal polish (#242), plus graph, stash, rebase and diff fixes (#222–#236, #243, #245) · Dependabot #127/#128 (#249) |
| v3.12.0 | Built-in terminal renderer — xterm.js replaced by GitWand's own VT emulator and DOM renderer (utils/vt) that rebuilds only changed rows, fast even on software GL; bundled Symbols Nerd Font for prompt icons; terminal follows the tab surface and light/dark theme · WIP in the Git Tree — the Changes dock entry becomes a WIP tab glued to the Git Tree, the WIP diff overlays the graph · Cherry-pick as WIP (--no-commit) · reset/checkout refresh the Git Tree immediately (#213) · staged files can be discarded, including staged renames · WIP on the trunk head stays on lane 0 · dependency security pass (rustls 0.23.45, MCP SDK transitive deps, DOMPurify 3.4.16) |
| v3.11.2 | Finder-like folder navigation — the File Explorer panel becomes the file browser (the separate Browse view is gone): lazy per-folder list_repo_dir with in-process libgit2 ignore classification (5 000-entry cap, 66 ms for a 6 000-file folder vs 1.6 s for git check-ignore), live re-listing from the Live Repo watcher, a virtualized keyboard-first role="tree", change badges on every folder above a changed file, per-tab Diff | File with a Working tree | Index switch, context menu (Copy path, Reveal in Finder/Explorer via reveal_in_file_manager, Scope here) · git_diff/write_file go through a filesystem-resolving safe_repo_path · the untracked-file diff gets the 5 MB cap · getGitDiff stops dropping the truncation, untracked-directory and nested-repo fields on Tauri · Linux AppImage launcher shipped 0755 (@tauri-apps/cli 2.12, CI mode check) |
| v3.11.1 | History-aware LLM fallback — llm_proposed and "Resolve with AI" now tell the model why each side changed the conflicting lines: the commits since the merge base, with their messages, plus range diffs within a token budget (1 500 by default, 200–8 000). Computed locally through an injected GitRunner, so @gitwand/core stays browser-safe, and collected only for hunks actually sent to a model · an explicit "History unavailable" line instead of a silent gap · a .gitwandrc opt-out that wins over the app setting · shown in the LLM trace panel · fixes: MergeEditor never received the repo path, which had silently disabled custom automations and resolution-memory apply; saving Settings no longer drops unknown llmFallback keys |
| v3.11.0 | Merge preview-to-apply + editable diff — "Merge and auto-resolve" runs the real operation and re-runs the engine against what git produced, applying what passes the gates and stopping on the residual; a numeric confidence bar (minConfidenceScore) ANDed with the label gate across desktop, .gitwandrc, CLI and MCP; per-hunk opt-out; CodeMirror 6 in the merge editor and an editable inline diff · Gitea and Forgejo support (#193) verified against a live 1.27.3 server · Forge-side auto-merge on GitHub, GitLab and Azure, with Bitbucket refusing honestly rather than pretending · Abort and continue tell the truth (#197, #202): one git_operation_action for merge, cherry-pick, revert and rebase, three outcomes instead of two, confirmation before discarding resolution work, and nothing auto-continues · A declared Tauri-to-dev-server command registry with a guard, plus failure parity for 27 write commands — which found and fixed a submodule update that reported success whatever git did, and two routes that 404'd under dev:web |
| v3.10.0 | Live Repo (#178) — a notify filesystem watcher replaces the 2s status poll, which becomes a 15s fallback; raw OS events are coalesced into typed RepoChangeEvents over a scoped tauri::ipc::Channel (SSE under dev:web), one watcher per repo shared by N subscribers, designed as the hook for the v4.0 incremental indexer. libgit2 phase 1 lands on git_diff only (see Later (unscheduled) for why git_blame did not). clone/fetch progress moves off the global broadcast onto per-invoke channels, packages/core resolution moves into a Comlink Web Worker, and the Today inbox stops being read-only: merge, nudge and a direct jump into the resolver. |
| v3.9.1 | No-fast-forward merge option (#177) — the merge-into-current popover gets an "Always create a merge commit" checkbox, forcing git merge --no-ff even when a fast-forward is possible. Off by default · CLI update notice — gitwand checks npm for a newer version at most once every 24h and prints a one-line notice for a global (non-npx) install |
| v3.9.0 | Engine Accuracy — the engine's claims are now measured against ~1,700 real merges instead of asserted (benchmark/, 8 pinned public repos, byte-for-byte comparison with what teams actually committed) · no complex hunk is ever silently applied (format_semantic reclassification, scored and traced) · a resolution that breaks a format invariant (double Unreleased, duplicate JSON key) is retracted · generated files (lockfiles, bundles) decline by default instead of an auto-merge measured wrong ~100% of the time (resolveGeneratedFiles opt-in) · the engine knows what merge it's in (MergeContext) — version-identity conflicts resolve to the target branch, laravel agreement 24 → 83% · package.json/composer.json fragments merge by key instead of line-by-line · gitwand conventions measures a repo's own merge history to derive its policies, always losing to an explicit .gitwandrc · a sandboxed --regenerate tier runs the ecosystem's own installer in a disposable worktree for declined lockfiles, measured at 38.5% agreement against an 80% bar so it stays CLI-only rather than shipping to desktop · benchmark-gate.yml CI check blocks any future PR that regresses agreement on the pinned corpus |
| v3.8.0 | Time Machine — repo snapshots & global undo. Every destructive operation (discard, reset, checkout, branch switch, bulk resolution apply) first captures a restorable snapshot of the working tree (untracked included), the index and conflict stages 1/2/3, written with git plumbing under refs/gitwand/snapshots/ and restored via read-tree so it never refuses on a dirty tree · undo offered where the action happened — a single-slot toast with an Undo button and a ⌘Z hint, since a discard previously gave no feedback at all · global ⌘Z / ⇧⌘Z now rewind and replay repo operations, reporting through that same toast · the existing rewind popover (⌘⇧U) lists snapshots merged with git's reflog instead of the reflog alone, with a full-history modal behind its footer link; restoring is itself undoable via a pre-restore snapshot · retention settings (age + count caps, pruned on repo open) and opt-in AI snapshot labels · snapshot refs excluded from every --all traversal, and every ref move a restore makes carries an explicit reflog message |
| v3.7.0 | Commit Review — micro AI reviews in the Changes panel (inspiration git-lrc, fully local instead of a cloud+browser detour). "Review staged changes" runs the pre-review engine against the staged diff (inline findings, severity badges, n/p/x navigation) · Fix with agent pipes findings into a terminal AI agent session against the current repo (the scratch-worktree variant was cut after manual QA found it could hit a CLI's first-run "trust this directory?" screen and misfire a real command — tracked as a follow-up) · Iterations & coverage tracking bound to HEAD · Review / Vouch / Skip commit-time decision recorded as a GitWand-Review: trailer · per-repo .gitwandrc opt-in overriding the app Setting in either direction · a composable pre-commit hook merging the shipped v3.5.0 secrets section with a new warn-only review reminder · a real focus trap added to BaseModal, fixing a foundational a11y gap inherited by every modal in the app · fixed a core reactivity bug where routine background polling silently wiped findings, plus a dozen smaller findings from a dedicated product/code review round |
| v3.6.6 | Dev loop & CI build times (pure tooling/perf chore, no product surface) — ci.yml's 3-bundle-per-push desktop job replaced by a fast rust-check (fmt/clippy/check/test, now on PRs too) + a path-filtered bundle-smoke job (~230 billed CI min saved/push); Rust cache across all 3 workflows; [profile.ci]/[profile.dev] cut a post-edit cargo build from ~21s to ~6.5s; measured cargo llvm-lines/--timings to rule out the previously-planned gitwand-git crate split; Vitest defaults to environment: "node" instead of global jsdom (setup time @gitwand/core's resolution engine lazy-loaded out of the boot chunk (main bundle −185 KB raw); deduped reqwest (dropped native-tls/openssl-sys, removed libssl-dev from CI); anonymous telemetry gated behind an explicit telemetry Cargo feature with a build-time guard against a telemetry-less release |
| v3.6.0 | Post-checkout "Update branch" prompt — one-click fast-forward (with stash/restore) or "Continue on local branch" when checking out a branch that's behind its upstream with no divergent commits, per-branch mute · Non-blocking rebase-conflict handoff (#128) — an interactive rebase conflict now closes the blocking RebaseEditor modal and hands off to the existing rebase banner + inline MergeEditor instead of trapping resolution behind an overlay; also fixes a UI freeze on very long/minified conflicting lines (word-diff now guards against pathological line lengths) · CommitGraph animation polish (#127) — no more layout shifts/flicker during pagination loading |
| v3.5.0 | PR Review 2.0 — GitHub-standard keymap (J/K/⇧J/⇧K/V/⇧V/T/C/N/P/⌘Enter), viewed-file tracking, pending-review persistence, dismiss review/request reviewers, local opt-in AI pre-review pipeline (multi-hop, confidence-scored findings), PR summary block, unified LineAnnotation gutter model, GitLab review completion, lazy per-file diff loading + virtualized rendering (PR detail hot path 6→3 forge calls) · Pre-commit secrets scanner — zero-network local scanner (AWS/GCP/Azure/GitHub/GitLab/Slack/Stripe/OpenAI/Anthropic/RSA/JWT/high-entropy), non-blocking commit-area badge, .gitwandrc extensible patterns, dual Rust+TS implementation, CLI gitwand scan, opt-in pre-commit hook · PR badges: background prefetch & cache (git-log style) past the first page, plus a real open-PR count on the dock badge · Repo-tab reordering via pointer events (mouse/touch/pen) + keyboard a11y · File Explorer Save button moved next to the lock toggle |
| v3.4.0 | Conflict-engine bundle — token_level_merge pattern (line/token decomposition, never auto-applied, user-confirmed via TokenMergePanel) · 2-way base recovery from the git index (unlocks diff3-only patterns on default-conflictstyle repos, guarded against clobbering manual edits) · ResolutionPreviewPanel + per-hunk "Resolve auto" confirmation · recoverable-before-model metric (summarizeTiers, surfaced in CLI/desktop/MCP + local cumulative stats in Settings, backed by a corpus regression guard + golden-funnel CI gate) · value_only_change extended to diff3 with semver/timestamp-max resolution · deterministic recoverers forced before the LLM path · data-loss fixes (imports resolver emptying hunks, insertion_at_boundary dropping duplicate-line insertions, whitespace_only false positive in string literals, rename detection matching inside strings/comments) · git log pagination/caching fixes. Measured: manual residual halved on a 2000-merge production corpus (5.6%→2.7% of hunks) |
| v3.3.0 | Blame gutter in the File Explorer's CodeMirror editor — opt-in author/date gutter, deduped per commit run, hover tooltip · Telemetry moved to Aptabase — Umami Cloud was silently dropping every launch ping (non-browser User-Agent filtering); replaced with App-Key-authenticated Aptabase, including a self-hosted upstream crash fix (tokio::spawn → tauri::async_runtime::spawn) · Azure DevOps PR base-branch picker now lists server-side branches, not just local refs |
| v3.2.0 | Integrated terminal (WebGL rendering, inline search, clickable links, typed tabs with unread dot, real PTY agent launch, "New AI task" scratch-worktree button) · File Explorer / Editor panel (gitignore-aware tree, CodeMirror 6 editor, lock/undo/save toolbar) · Git Tree (filter mode, branch/author quick-toggles, date-bucket separators, branch autocomplete + #PR search) · Per-project worktree submenu + AI-task worktree management · Submodule update checking/applying · Per-author line churn stats · Antigravity CLI provider · Rebase onto any ref + branch reset · Sidebar unified Changes section · Tauri 2.11 |
| v3.1.0 | Customizable dock & startup view, PR create unpublished-branch warning, customizable release-note templates, anonymous GDPR-compliant launch ping, website screenshot slideshow & lightbox, pnpm 11.9.0 |
| v3.0.0 | Today (triaged action inbox, urgency tiers, state-aware primary actions, Launchpad → Today rename) · VS Code extension on the Marketplace (esbuild bundle, publish-vscode.yml CI, 4 extension bug fixes, CLI validation surfacing) · Dashboard (contributor modal, activity tooltips, fortnight stats, Git-Tree commit navigation) · Branches (top-contributor avatars, pinned section, move uncommitted changes on switch, force-delete prompt) · Fullscreen markdown image viewer · Website hero toggle + clickable platform cards |
| v2.24.0 | Full-screen views & in-app Launchpad — the permanent sidebar/Git-Tree strips give way to a floating bottom-center AppDock; Dashboard, Changes, History, PRs and a first-class full-screen Git Tree each render full-bleed (RepoSidebar gains a pane prop; collapsible, persisted commit composer rail). Launchpad gains in-app issue review (IssueDetailView + useIssuePanel), an action inbox (useLaunchpadInbox / useRepoActionCards), extracted scope (useLaunchpadScope) and internal navigation. The list/tree file-tree toggle extends to the history (commit) sidebar (useFileTree generalised over any { path } entry). Plus a Linux AppImage follow-up: URL openers de-pollute PATH/XDG_* so a spawned xdg-open resolves the system browser instead of silently no-opening (#52), with opener stderr/exit captured. EditCommitOverlay/SplitCommitModal lazy-loaded. Full dev:web parity + 5-locale i18n |
| v2.23.0 | Changes sidebar & rebase polish — list/tree layout toggle for the changes view (collapsible folders, persisted layout + per-section collapse state, auto-expand to the selected file) via a new useFileTree composable; per-file and per-folder stage/unstage/discard fused into an always-visible segmented "action group". Interactive rebase now works in the packaged desktop app (dedicated git_interactive_rebase Tauri command replacing a dev-only HTTP endpoint) and branch pickers list branches by most-recent commit (shared branchSort). Plus a Linux AppImage fix: external links/OAuth buttons route through a robust multi-opener chain. Full dev:web parity + 5-locale i18n |
| v2.22.0 | Advanced conflict resolution — file-level bulk resolution ("Accept all: Current · Incoming · Both" in one click, persistent memorize-rule toast, one-click "Apply rule to N hunks"); tree-conflict resolution for markerless conflicts (modify/delete, both-deleted, add/delete) via get_tree_conflicts/resolve_tree_conflict with a dedicated editor panel + sidebar badge; markerless content-conflict reconstruction (reconstruct_conflict rebuilds the 3-way text from index stages when the working tree lost its <<<<<<< markers). Plus remote-state reliability fixes: false "Publish branch" on already-published branches (remote_branch_exists), false "offline" blocking push/pull (WKWebView spurious events → hysteresis + authoritative confirmOnline probe), and git_remote_info preferring origin (fixes the bogus "unpushed tags" modal). Full dev:web parity + 5-locale i18n |
| v2.21.0 | Monorepo Scope — pick a sub-workspace and scope the commit graph, search & stats to its file tree. Auto-detects 6 workspace formats (pnpm, npm/yarn, Cargo [workspace], nx.json, turbo.json, go.work), parsed natively in Rust with a documented precedence; scope persisted per repo (additive scope field in .gitwand-workspace.json, validated on load); git_log pathspec filtering + a new git_rev_count driving a stable "N commits hidden" badge; sidebar ScopePicker (auto-detected packages + "Custom folder…" ad-hoc), active-scope chip & badge in the graph header. Picker shows only on detected monorepos; full dev:web parity via a mock detect-monorepo route |
| v2.20.0 | Scratch worktree + extended Conflict Predictor — "Resolve in scratch worktree" from the merge preview opens a temporary isolated gitwand-scratch-<timestamp> worktree as a repo tab (resolve away from the active checkout, bring changes back in one click or discard, auto-cleanup, origin-anchored lifecycle); Conflict Predictor extended to rebase (per-commit replay against onto) and cherry-pick — side-effect-free preview_rebase / preview_cherry_pick Tauri commands, MCP gitwand_preview_merge operation param, new gitwand preview CLI command, operation selector + risk badge (low/medium/high) + hunk-by-hunk preview in the panel |
| v2.19.0 | GitHub OAuth & Azure DevOps + cross-fork PRs — "Sign in with GitHub" via OAuth device flow (tokens in the OS keychain, tokenless REST path, no gh CLI required), Azure DevOps as a first-class forge (AzureProvider, Entra ID device flow + auto token refresh, PR list/detail/diff/create/merge/checkout, comments, branch-policy CI checks, reviewer votes), cross-fork pull requests (target-repo selector defaulting to upstream, fork PRs surfaced in the list), and a backend performance pass (async Tauri commands, disk-persisted SWR PR cache, libgit2 git_status fast-path) |
| v2.18.0 | Inline CI Check Annotations — check-run annotations overlaid in the PR diff across the three forges (GitHub check-runs API, GitLab artifacts:reports:codequality, Bitbucket Reports API), gutter icons ❌/⚠/ℹ with hover tooltip, clickable "N annotations" badge in the CI tab, per-file ⚠ count in the diff sidebar, forge-agnostic CIAnnotation type + ForgeProvider.getCheckAnnotations(), lazy one-shot fetch per PR; Copilot CLI as a fourth AI provider (text-only sandbox) |
| v2.17.0 | opencode provider + per-CLI model picker — opencode-cli as a first-class AI provider (opencode run, binary discovery, Settings status), second model select under the provider picker for the three CLI agents (opencode enumerates via opencode models, Claude Code aliases, Codex free-text), aiModelByProvider persisted per provider, --model threaded through all three CLIs |
| v2.16.0 | PR Activity Notifications — background Launchpad poller, zero-network snapshot diff (useLaunchpadNotifications) for CI flips / review requests / new comments / merge-close, native OS notifications via tauri-plugin-notification (background-only), Settings granularity (All · Reviews & comments · CI failures only · None) + "by people" bot filter, enriched workspace_prs_all (CI/review/comment fields) |
| v2.15.1 | Git Tree polish & quick actions — Force push (branch context menu + protected-trunk/diverged-remote guard), Quick Stash ⌘⇧, (instant, AI label) + pending badge in the commit area, Submodules in the Git Tree (branch-picker section, per-commit pointed-SHA badge, click-to-navigate) |
| v2.15.0 | Git Tree multi-branch — Git Tree as primary view, Log panel removed, unified context menus, stash/branch/tag management from the graph, DAG trunk-pinning, WIP node, search bar |
| v2.14.0 | Forge completeness — GitLab updateComment/deleteComment/CI checks, complete Bitbucket stubs, forge-agnostic getConflictPreview/getHotspots, multi-account provider |
| v2.13.0 | AI & Review — custom AI prompt presets, GitHub-native inline code suggestions in PRs |
| v2.12.0 | Branch Management & Identity — Archived Branches, Pinned Branches, Multiple Committer Identities, Commit Templates |
| v2.11.0 | Large-scale performance — backend.ts domain split, Fork Point visualization, transparent command log (⌘⇧L), real-time clone progress, CommitLog pagination |
| v2.10.0 | Forge integrations + MCP catalog — GitLab MRs, Bitbucket PRs, multi-account, in-app MCP catalog (Settings > MCP, one-click install) |
| v2.9.0 | Launchpad — cross-repo PRs/Issues/WIP/Team dashboard, pin/snooze, ⌘L, lazy Team, 95 green tests |
| v2.8.0 | Agent Sessions View + Scheduled AI tasks — Agents panel, active MCP sessions, launch Claude Code from GitWand |
| v2.8.2 | Performance hardening — lazy-load 20 panels, bundle −150 KB, libgit2 fast-path, consolidated polling, lib.rs split into 6 domains |
| v2.7.0 | Multi-repo Workspaces + Hooks manager + Worktree first-class — tab=worktree, quick-create "New task" (⌘⇧N), cross-worktree status |
| v2.6.0 | @gitwand/core Refactoring-aware merge — rename/move detection, opt-in via .gitwandrc |
| v2.5.0 | LLM fallback opt-in — llm_proposed pattern, resolveAsync(), audit trail, desktop+CLI+MCP tie-in |
| v2.4.1 | Semantic post-merge validation — tree-sitter parse-tree validity, opt-in tsc --noEmit, postMergeRisk dimension |
| v2.3.0 | Tree-sitter structural dispatcher — entity-by-entity merge for TS/JS/Python/Go/Rust, +20-30% auto-resolution |
| v2.2.0 | Format profile registry + JSON Patch arrays — /dependencies, /scripts, RFC 6902, +10-15% on JSON/YAML |
| v2.1.0 | Histogram diff & block-move detection — Patience++, Rabin-Karp rolling hash |
| v2.0.0 | Distribution & polish — Clone & Fork from the UI, Codex CLI provider, native macOS menu bar, Contributors Dashboard |
| v1.9.0 | Git 2.54 suite — commit context menu (checkout/reset/revert/branch/tag/cherry-pick), Trailers, Blame diff algorithm, File history line-range + pickaxe, Tags panel, Conventional Commits prefixes |
| v1.8.0 | Design system & modal foundations — AppHeader split, BaseModal, merge editor line numbers + minimap, PR description markdown |
| v1.7.0 | Split commit by hunks — line-by-line selection, integrated into interactive rebase |
| v1.6.x | Folder diff, Image diff, Submodules & Worktrees, @gitwand/core/@gitwand/cli/@gitwand/mcp published on npm + MCP Registry |
| v1.5.x | Hardening, performance & English-first — XSS, LCS O(min), CI Rust↔Node parity, macOS TCC fix |
| v1.4.0 | Pattern registry — reorder_only, insertion_at_boundary, desktop auto-update |
| v1.3.0 | AI Everywhere — branch naming, PR writing, hunk review, conflict explanation, commit search, release notes |
| v1.2.0 | Interactive Rebase, Absorb, AI commits, Undo stack |
| v1.1.0 | MCP server (@gitwand/mcp) — 5 tools, 3 resources, Claude Code slash commands, enriched CLI JSON |
| v1.0.0 | Full Git client + resolution engine — 8 patterns, diff3 LCS, format-aware resolvers, PR workflow + integrated Code Review |
- Intelligence first — Every screen should offer more than the terminal.
- Native performance — Tauri 2 + Rust. Sub-1s startup, smooth on 100k+ commits.
- Progressive — Works immediately for simple cases. Advanced features are discovered naturally.
- Cross-platform — macOS, Linux, Windows. Same quality everywhere.
- Free and open source — Core and desktop under MIT.
- Refusal is structured, not silent: any tool that declines to decide (a pending hunk, a detected silent conflict) hands back
agent_guardrailsbuilt only from facts it actually computed (the diff, the signature, the missing argument), never inferred domain judgment like "this is security-critical." Applies everywhere a@gitwand/mcptool can refuse (gitwand_resolve_conflictstoday,detect_silent_conflictin v4.0.0); the/agentWebMCP page has no repository to reason from, so it never carries this.