Skip to content

Open copied-file diffs in an external diff tool - #58

Merged
sapsaldog merged 3 commits into
mainfrom
feat/copied-file-diff-tool-handoff
Jun 19, 2026
Merged

sapsaldog merged 3 commits into
mainfrom
feat/copied-file-diff-tool-handoff

Conversation

@sapsaldog

@sapsaldog sapsaldog commented Jun 18, 2026 •

Copy link
Copy Markdown
Owner

Summary

Replaces the in-app inline diff for .worktreeinclude copied files with a hand-off to an external diff/merge tool. Clicking a copied-file chip (detail pane) or row (the "View all" browser) opens that file's main↔worktree pair in the user's chosen tool, selected from a picker shown in three places and remembered as a persisted default.

Implements the Claude Design prototype (Oh My Worktree.html / diff-concepts.jsx), which lands the copied-file diff experience on external hand-off (App.jsx: "Hand a copied file off to the chosen external diff tool (no in-app diff).").

What changed

  • DiffTool — pure, table-driven catalog of five tools (Araxis Merge, Kaleidoscope, Beyond Compare, VS Code, FileMerge) with launch-argument assembly and installed/effective resolution. Unit-tested to 100%.
  • DiffToolLauncher — detects installed tools (CLI/bundle probe) and launches the process on the file pair. Coverage-excluded, like ExternalToolLauncher.
  • DiffToolMenu — reusable picker in the Copied files detail header, the View all browser header, and Settings → General. Not-installed tools are disabled with a "Not installed" hint; the selection persists via @AppStorage("diffToolID") and falls back to the first installed tool.
  • Every copied file is openable — clicking any chip/row (including identical) hands off to the diff tool (it just shows no differences). The status-based isClickable gate was removed; isChanged now only drives the dimmed styling, the changed-count, and the "Changed only" filter.
  • Removed the in-app UnifiedDiffView and the apply-to-main / copy-to-worktree actions (from CopiedFileDiffer, the view model, ContentView, and the confirm alert). CopiedFile.classify / CopiedFileDiffer.compare stay — chips still show status and +N −N counts.

Design + plan: docs/superpowers/specs/2026-06-18-copied-file-diff-tool-handoff-design.md, docs/superpowers/plans/2026-06-18-copied-file-diff-tool-handoff.md.

Test Plan

  • swiftlint lint — clean
  • Test scheme — 492 tests across 45 suites pass (incl. new DiffToolTests)
  • scripts/coverage.sh — strict 100% gate passes (DiffTool.swift at 100%; CopiedFile.swift / CopiedFileDiffer.swift still 100% after the removals)
  • Manual: pick a tool in each of the 3 menus; click any chip — modified / new / missing / identical — and confirm it opens in the tool; check the "No diff tool" state when none installed

🤖 Generated with Claude Code

sapsaldog and others added 3 commits June 18, 2026 17:32
Replace the in-app inline diff for .worktreeinclude copied files with a
hand-off to an external diff/merge tool. Clicking a copied-file chip (detail
pane) or row (the browser) opens its main↔worktree pair in the chosen tool.

- Add a pure DiffTool catalog (Araxis Merge, Kaleidoscope, Beyond Compare,
  VS Code, FileMerge) with launch-argument assembly, unit-tested to 100%.
- Add DiffToolLauncher to detect installed tools and run the process.
- Add a reusable DiffToolMenu picker in the Copied files header, the
  "View all" browser header, and Settings → General; the selection persists
  via @AppStorage("diffToolID") and falls back to the first installed tool.
- Remove the in-app UnifiedDiffView and the apply-to-main / copy-to-worktree
  actions; CopiedFile.classify / CopiedFileDiffer.compare stay for the chip
  status and +N −N counts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every copied file now hands off to the external diff tool, identical ones
included — the tool just shows no differences. Removes the status-based
isClickable gate (chips/rows are always buttons) and keeps isChanged only for
the dimmed styling, the changed-count, and the "Changed only" filter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The picker was added to GeneralSettingsView, which only renders inside the
legacy SettingsView window — never opened (showOrCreateSettingsWindow is dead
code) — so it never showed. Move it to SettingsSheetContent's General tab (the
live in-app settings sheet, opened via isShowingSettings) as the top row, and
revert the dead-code addition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sapsaldog
sapsaldog merged commit 93de9ea into main Jun 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant