Skip to content

▶ Riffle

Riffle

Changelog

Every Riffle release, what's new, what improved, and what got fixed.

Latest · Version 2.3.2

v2.3.2 Latest

Build 64

New

  • Drag tabs between windows. Pull a tab down out of the strip and drop it onto another Riffle window's tabs to move it there, at the spot you choose, with its edits and undo history intact. Drop it anywhere else and it gets a window of its own, right where you let go. Dragging a window's only tab moves the whole window, and dropping it onto another window's tabs merges the two.

v2.3.1

Build 63

Improved

  • A change map in the merge window. The strip down the right edge that a diff has now comes to merges too. It marks every change in the merge, colored like the gutter (unresolved conflicts in amber), highlights the one you're on, and shows where your search matches are. Click or drag it to move through the merge, and all three panes follow.

Fixed

  • Closed comparisons give their memory back. A closed diff or merge could stay in memory after its window was gone, holding its text and layout, so opening and closing large files repeatedly kept adding to Riffle's memory use. A comparison now clears itself out as soon as it closes, and its window disappears first rather than waiting for the cleanup.

v2.3.0

Build 62

New

  • Hide unchanged lines in merges. The merge window can now fold long runs of unchanged lines, just like a 2-way comparison. Folds open and close together across the local, result and remote panes, and their seams stay level as you scroll. Click a seam or use the gutter chevrons to open or close one fold, ⌥-click to open them all, or use the new footer toggle and the "lines hidden" count. It follows your Hide Unchanged Lines preference, and Find reaches into folded lines and opens the fold around a match. In the result pane, typing or moving the caret into a fold opens it rather than editing lines you can't see.

Improved

  • Much faster on large files. Reloading a large comparison after scrolling through it, whether from a fold toggle, ⌘R, a whitespace or view-mode change, or a file changing on disk, no longer freezes the window. On a 60,000-line file this went from 19 seconds to under a second. Jumping deep into a large file is now instant: change bands and line numbers appear immediately, and the text follows a moment later.
  • Faster, smoother large merges. A 40,000-line merge opens more than ten times faster and now scrolls smoothly, where it previously stalled.
  • Faster folding and syntax setup. Opening or closing a fold on a very large comparison is up to 18 times faster, and syntax highlighting starts sooner on large files.

Fixed

  • Text stays aligned with its line numbers in large files. In the unified view and the merge result, text deep in a large file could drift thousands of rows away from its line numbers and change bands. It now stays exactly in line.
  • Rows line up in fonts with extra line spacing. In fonts such as Inconsolata, blank lines were drawn slightly too tall, so text slowly drifted away from its line numbers and change markers further down a file. Rows are now exact in every font, and the text sits where it always did.
  • Five-digit line numbers fit the merge result's gutter. The first digit is no longer cut off in files with 10,000 lines or more.
  • Tab width in soft-wrapped panes. The unified and merge result panes now use your tab width setting when soft wrapping.

v2.2.4

Build 61

Improved

  • Faster opening and smoother rendering of large comparisons. Wrapped files avoid unnecessary layout work while the window is being sized, and syntax highlighting for distant lines is prepared in the background to keep the interface more responsive.

Fixed

  • Closing the last comparison closes its window. You no longer need a second ⌘W to dismiss the startup screen. Unsaved-change prompts still apply, and clicking Riffle in the Dock with no open windows brings the startup screen back.

v2.2.3

Build 60

Fixed

  • External comparisons no longer open with a blank editor. Fixed a startup case that remained after 2.2.2, where an invisible window could take the editor from the visible comparison. This affected files opened from Git clients such as Sourcetree, Tower, and GitKraken, and could also leave subsequent clipboard comparisons blank until Riffle was restarted.
  • More reliable window ownership. Hidden and closing windows no longer interfere with the active editor. Moving comparisons between windows continues to preserve edits and undo history.

v2.2.2

Build 59

Fixed

  • Comparisons stay visible after reopening Riffle. Closing the last window could leave an invisible window alive that took the editor away from a newly opened comparison. This could make pasted text or files opened from an external tool appear blank even though the change count was correct. Closed windows now release their editor ownership correctly.

v2.2.1

Build 58

Improved

  • One choice for both unsaved files. When both sides of a comparison have edits, a single dialog lists the files and offers Save All, Discard All, or Cancel.

Fixed

  • Closing an edited comparison no longer leaves stuck dialogs. Fixed a window-delegate lifetime bug that could leave save prompts unresponsive. Repeated close requests cannot stack additional prompts while a decision is pending, and cancelling or encountering a failed save keeps your edits open.
  • Reopening Riffle creates only one welcome window. Clicking the app after closing its last window no longer opens two startup windows.

v2.2.0

Build 57

New

  • Independent comparison windows. Open a new window with ⇧⌘N, move a tab into its own window from the File menu or the tab's context menu, and choose Tabs or Windows as the default in General settings. Moving a comparison preserves unsaved edits, undo history, search state, and scroll position.
  • Paste to Compare. Press ⌘V on the welcome screen to start a comparison with clipboard text on the left, or use ⌘N for an empty comparison. Both options sit together beside the familiar file-comparison and merge actions.
  • Dim unchanged lines. Unchanged text now draws at half opacity in Blocks, Fluid, and Unified comparisons, keeping real changes easier to spot. Enabled by default; turn it off in General settings if you prefer equal contrast throughout.
  • A clear signal when change navigation wraps. A large loop icon briefly appears in the center of the diff area when stepping from the last change to the first, or back again.

Improved

  • A footer that fits narrow comparisons. File and change counts shorten to compact numbers, then disappear when space runs out. The hidden-lines label also adapts, so the footer stays one line tall when a review sidebar leaves little room.
  • Window-aware file opening and integrations. Riffle reuses comparisons already open in another window. Save As, folder drill-down, review history, and waiting command-line merge jobs continue to follow a comparison when it moves.
  • Safer closing and quitting. Closing a window checks all its tabs for unsaved work; quitting checks every window. Cancelling a prompt or encountering a failed save keeps the comparisons open.

Fixed

  • Identical pasted text could show false differences. Blank lines are now preserved when pasting into an empty or padded pane. Empty panes in Blocks view also reliably accept clicks for pasting.
  • Inline highlights now respect whitespace settings. Ignore Trailing and Ignore All apply to highlights and insertion markers inside changed lines, including merge input panes. Real edits stay highlighted, with correct positioning after Unicode text.
  • Undo and Redo follow the active editor. Text edits and merge-result history remain available after moving a comparison to another window, including through the Edit menu.
  • Accurate licensing errors. An unavailable licensing endpoint is reported as a server problem rather than incorrectly claiming a valid license key does not exist.

v2.1.1

Build 56

Fixed

  • Your external drives get their own icons back in the Finder sidebar. With the Finder extension switched on, an external drive could turn up in Locations wearing Riffle's app icon instead of a disk — and stay that way through an unplug, a remount, even a reformat, because nothing was ever written to the drive to undo. The extension has to tell Finder which directories to consult it about, and it had been naming every mounted volume individually, on the reasonable-sounding theory that a drive plugged in later would otherwise have no Riffle item in its menus. But a claim on a volume's own root is how a sync client tells Finder it manages that drive, and Finder decorates the sidebar accordingly — the same badge Dropbox or Google Drive earns for the folder it owns. Riffle owns nobody's drive. It now claims /Volumes and lets the claim reach the items inside, which is all it ever needed: Compare with Riffle still appears on two files anywhere, and your drives look like drives

v2.1.0

Build 55

New

  • Find (⌘F), and it searches the whole comparison rather than a pane of it. One field, one count, one set of chevrons — matches from both sides go into a single list ordered by the row they sit on, so ⌘G reads down the window instead of walking one pane to the bottom and starting over at the top of the other. The counter says "3 of 41" and the badge beside it says which side you are standing on. Two separate find bars with two separate counts would have left you doing the interleaving in your head, which is the part a diff tool is supposed to do for you. It is in the Edit menu with the shortcuts you already know — ⌘G and ⇧⌘G to step, ⌘E to search for what you have selected, Escape to put it away — and there is a magnifying glass in the toolbar for when you would rather click
  • In a review, it searches every changed file, not the one you are looking at. A review is a set of files you are reading as one thing, so "where does this appear?" is a question about the review — and the answer is usually mostly in the twenty-eight files that aren't on screen. The bar spans the whole review window, the counter reads "3 of 41 · 6 files", and every row of the file list wears the number of matches inside it, folders included, so a collapsed directory still says what it is hiding. Stepping crosses into the next file the way ⌘↓ already does. Files you have never opened are searched too — the search reads them itself rather than waiting for a diff to be run over them
  • It reaches into collapsed runs, and opens them to get to a match. A long file arrives with its unchanged stretches folded, which is precisely the file you most need to search — a find bar that stopped at the "47 unchanged lines" seam would come up empty on the ones it exists for. Riffle searches every line, and stepping onto a match inside a fold opens that run and scrolls to it, rather than landing you on the seam and leaving you to work out that the line is in there somewhere
  • The three-way merge has it too, result pane included. Local, result, and remote are one search, and the result is searched as it stands right now rather than as it was when the merge opened — it is the file you are writing, so anything else would be answering a question about a file that no longer exists
  • Matches show up in the change map. The strip down the trailing edge already tells you where the rest of the file's changes are; now it tells you where the rest of the matches are as well, with the one you are on drawn full width. Three hits clustered at the top of a thousand-line file looks nothing like three spread through it, and until now you had to scroll the length of it to find out which you had
  • Match highlights come from your theme. Nearly every theme in the gallery already says how it wants find matches drawn — it is one of the colours a VS Code theme carries — so Riffle uses the theme's own rather than dropping a fixed yellow box on top of it. A theme that says nothing gets Riffle's amber pairing, and one that names only the current match has the rest derived from it, so you never end up with a themed highlight sitting next to a stock one
  • Match case, whole words, and regular expressions, behind one glyph in the field so the bar stays a field and two chevrons. The glyph tints when any of them is on, because otherwise a count on screen is quietly the answer to a narrower question than it looks

Fixed

  • Jump-to-comment lands on the right line in fluid and unified. It mapped a comment's line number through the blocks-mode alignment whatever mode was showing, so in the other two it scrolled to whichever row happened to share the number. The three modes count rows differently — blocks pads the shorter side of every hunk, fluid has one row per line, unified interleaves both files — and there is now one path from "a line of the file" to "a row on screen" that knows the difference. The find bar uses it too

v2.0.11

Build 54

Fixed

  • A comparison with wrap off really does open at the first column now. 2.0.10 fixed half of this and reported the whole of it. A pane's line numbers are drawn over the text's own scroll area rather than beside it, so the leftmost position that shows the start of a line is one gutter to the left of zero — and a pane opened at zero, which is a gutter short. Every comparison therefore arrived with the first few characters of every line already behind the gutter, before blame or a long file's extra digit had widened anything. What 2.0.10 corrected was the gutter growing after the fact, and it did that by holding the pane's offset steady as the gutter moved — faithfully preserving an offset that had been wrong since the moment the comparison opened. So it stopped the problem getting worse and left what you actually saw. A pane now asks the framework where its own first column is and opens there, which also covers the case the old arithmetic would have missed: a comparison that opens with blame already showing. A re-diff of a file you are editing still keeps the column you were reading
  • A side with no blame no longer holds a blame column's worth of nothing. The column reserved its width the moment blame was switched on, so that the text beside it would not reflow when a slow read finally landed. That is right while it is loading and wrong once it has: only one side of a comparison usually has a history to read — a git client hands over its own temp copy of the other side, and a temp copy cannot be blamed — so the empty side sat holding 180 points of blank gutter, a third of a pane on a normal window. The width is still held while the read is running, and afterwards only by a side that actually has attributions

v2.0.10

Build 53

Fixed

  • A comparison with wrap off no longer opens scrolled sideways. With Wrap Lines set to Never, a file with long lines could open part-way across instead of at the start of the line — reported after comparing from Fork, and just as true from anywhere else. The gutter was the cause: a pane's text is held clear of its line numbers by the scroll position itself, and when the gutter grew after the comparison was already up — which is what happens every time blame arrives, since the blame column is as wide as a commit, an author and a date — the text stayed where the narrow gutter had left it and the start of every line ended up behind it. The two panes then made it worse: they mirror each other's scrolling, and they were doing it by raw position, so a side whose blame is wider than the other's dragged its counterpart off by the difference. Both panes now hold their place against their own gutter, so a comparison opens at the first column and stays there — and a reader who has scrolled sideways keeps the column they were reading when blame appears

v2.0.9

Build 52

New

  • Read any file's history from a review, not just the changed ones. A review is built from a diff, so its file list could only ever hold files with something pending — and the file-history rail with it. The sidebar now has a second list beside Changes: every file the repository tracks, arranged flat, grouped or as a tree by the same control, with a filter of its own and a mark against the files this review is about. Pick one with nothing pending and it opens on its newest commit beside the one before it — a real comparison rather than a file against itself — with the history beside it, ready to step back through. Pick one the review is about and you get the review's own diff of it, staging state and all
  • File history in an agent-changes review. A review built from a manifest — a coding agent's own edits, a build's outputs — refused the history rail outright, on the grounds that a manifest can name files that are in no repository. True of the manifest, not of the files: the right-hand side is the real file the producer pointed at, so Riffle now finds the repository behind it the same way a plain 2-way diff of that file would. The rail opens on those rows, and the file browser comes with it, listing the repository the files were found in. Files that really are outside a repository get no rail, which is the honest answer rather than a rule
  • File history beside a merge. The merge window was the one place in Riffle with no way to read a file's history — and the reasoning was only half right. A merge's three inputs really are temp copies a client handed over, with no history to speak of, but the file being written is the real one in your working tree. That is the file the rail now reads, so mid-conflict you can see what else has happened to it lately without leaving the merge. Clicking a commit opens it in a tab of its own rather than replacing a merge you are part-way through

Improved

  • The file-history rail stays open as you move between files. It was a per-file switch, so reading a repository file by file meant reopening the same panel at every click. It is now a view preference like the blame column: open it once and it is there for the next file, and the one after that

v2.0.8

Build 51

Fixed

  • A conflict with no common ancestor opens. When the same file is added on both branches — git calls it add/add — there is no base version to merge against, and clients say so in their own way: git names an empty temporary file, Fork and Tower pass an empty --base, and others name a file they have already removed. Riffle refused all but the first, and because it said so on standard error, which a git client throws away, sending that kind of conflict to Riffle from Fork or Tower did nothing at all — no window, no error, nothing to go on. All three now mean the same thing, and Riffle merges against an empty base, which is what git does with it too
  • The command line stops blaming your installation. A job it couldn't act on reported "could not launch Riffle. Is Riffle installed?" whatever the real reason was. It now names the file that wasn't there, and recognises a placeholder like $MERGED that a client never filled in — usually a sign the arguments are in the wrong tool's field, since $BASE and $MERGED belong to a merge tool and $LOCAL and $REMOTE to a diff tool

v2.0.7

Build 50

Fixed

  • Merging from Fork works. Fork hands its three inputs to a merge tool and then clears them away almost immediately — git mergetool waits for the tool to finish, so Riffle was built expecting the files to last, and from Fork the merge window opened on "couldn't be opened because there is no such file" instead. Riffle now takes its own copy of a merge's inputs the moment the job arrives, before the window even exists, so a client is free to clean up on whatever schedule it likes. The result is still written to your real file, the copies go when the merge closes, and a merge over files you own — which is what git mergetool hands over — is still read live rather than duplicated. Fork's diff side was never affected

v2.0.6

Build 49

New

  • Close every tab, or every tab but one. A tab's right-click menu now carries Close Other Tabs and Close All Tabs beside Close Tab, so clearing a strip that filled up over an afternoon is one click rather than twenty. Unsaved work is still asked about before anything closes — pane edits across the whole set in a single prompt, an unfinished merge on its own terms so git still hears merged or aborted — and cancelling any of those prompts leaves every tab exactly where it was rather than closing half of them

v2.0.5

Build 48

New

  • Folder comparison respects .gitignore. Compare two checkouts of the same project and you get the project, not its build output. Riffle reads the ignore files the way git does: per folder and layered, so a .gitignore deeper in the tree governs its own subtree and overrides a shallower one, ! puts back what an earlier line took out, and each side's .git/info/exclude is read at the top. Both folders are consulted, so anything either checkout ignores is left out — which is what you want when the ignore file is one of the things that changed. Excluded folders are never descended into rather than scanned and then hidden, so this makes a large comparison faster as well as shorter. On by default; your global core.excludesFile is not read
  • A Folders tab in Settings, for what a comparison leaves out. The exclusion rules were always there but had no way in short of a defaults write. Settings ▸ Folders now holds the .gitignore toggle, a node_modules toggle for the projects where a .gitignore doesn't already cover it, and a list of your own patterns in the same syntax. .git, .hg, .svn and .DS_Store stay excluded always and need no pattern
  • Every folder comparison says how much it left out. The toolbar carries the count of excluded entries, and its menu turns exclusions off for that one comparison and rescans, so "why isn't that file here?" is answered in a click rather than a trip through Settings. A folder compare that quietly drops files is one you can't take at its word, so the number is always on screen when there is one

Improved

  • Settings stops resizing itself. Every tab set its own window size, so switching to Integration widened the window and switching away snapped it back. They all share one size now, a little wider than before, which also gives the row of tabs room to breathe

Fixed

  • Riffle finds the GitHub CLI wherever it lives. Reviewing a pull request runs your own gh, so it inherits whatever gh auth login already set up and Riffle never holds a credential of yours. Locating that binary used to mean four hardcoded paths, which told anyone whose gh came from MacPorts, mise, asdf, nix, or a personal ~/.local/bin to install a gh they already had — a wrong answer rather than merely an unhelpful one. When none of the known locations match, Riffle now asks your login shell where gh is and gets the same answer your own PATH would give. It only asks as a last resort and remembers the reply, so an ordinary Homebrew install pays nothing for it, and a shell held up by a slow profile is dropped after five seconds rather than stalling the review

v2.0.4

Build 47

Improved

  • The icon gets its fan back. The 2.0 icon tucked its cards in close and traded the blue for coral, and the result read as less distinctive in a full Dock. The 1.x look returns — the dark slate tile, the green and blue cards splayed wide behind the front one — keeping the 2.0 front card with its two-column diff and centre hairline. Every rendition comes from the one generator: the Dock icon, the macOS 26 layered form, the welcome panel, and the copies the website shows

v2.0.3

Build 46

New

  • Pipe a diff straight into Riffle. git diff | riffle opens the diff as a review — file list beside the changes — and so does any other unified diff: jj diff --git | riffle, svn diff | riffle, plain diff -u output, or a saved patch via riffle --patch fix.patch. Riffle rebuilds each file's before and after from the hunks; the stretches a patch doesn't carry appear as a shared "⋯ N unchanged lines ⋯" row, so pipe git diff -U9999 when you want full context. The snapshots are Riffle's own renderings of the pipe, so they open read-only and never land in Recents
  • Jujutsu (jj) one-click setup. Settings → Integration grows a jj section beside Git: one click runs jj config set --user so jj diff --tool riffle opens a change as a folder comparison and jj resolve sends conflicts to the merge window — with the same copyable manual commands the other integrations offer

Fixed

  • riffle --version reports the app's version. The CLI carried its own version string, which had quietly stopped moving; it now reads the version out of the app bundle it ships inside, so the two can never drift apart again

v2.0.2

Build 45

New

  • Apply a change across a 2-way diff. A pair of chevron buttons sits centred between the panes, dressed like the merge window's resolving cluster: apply the change you are standing on to the left or to the right, making that side match the other one there — BBEdit's [← Apply] / [Apply →], for people who reached for it and found it missing. Edit ▸ Apply Change to Left / Right carry the same motion on ⌥⌘← / ⌥⌘→, and applying walks you to the next change, so apply, apply, apply reads a file the way ⌘↓ does. An apply is an edit, not a save: the receiving pane takes the lines as unsaved work with everything that already protects one — encoding and line-ending preservation, Revert, the close guard — and ⌘S writes it. A side that can't be written (a git revision, a review snapshot, a read-only file) offers no arrow at all, and typing in a pane parks the arrows until the comparison catches up

Improved

  • Identical files stay on screen. The full-window "Files are identical" placard is gone from 2-way text diffs: the panes stay up with nothing marked — the visual proof — and a slim banner above them says it in words. Working a comparison down to no differences no longer takes the files away at the finish, and when whitespace is being ignored the banner says "No differences" rather than claiming a byte-equality it didn't check

v2.0.1

Build 44

New

  • Paste an image into an untitled comparison. ⌘V an image into either side of a New Empty Comparison and that side becomes the image — a copied file is used in place, a screenshot or a Copy from Preview is kept with the comparison. With one image in, the other side invites the second: paste it, choose a file, or drop one, and the two open as an image comparison. Text pastes are untouched, including the ones that sneak an image rendering along for the ride

Fixed

  • Dragging image files onto the welcome panel works. The drop zone was refusing images while accepting everything else; any file Riffle can compare now lands

v2.0.0

Build 43

New

  • Stage, unstage and discard from a review. A working-tree review can now change the index: whole files from the file list's right-click menu, or one hunk at a time from the footer of the diff. The unit is git's own hunk rather than Riffle's change block, so what gets staged is exactly what git add -p would have staged. Discarding always asks first, and sends the file to the Trash rather than deleting it
  • The review file list is organised. Files now group by directory — flat, grouped, or a full tree, whichever you pick — with the common root named once above the list instead of repeated down every row. There is a filter field, per-status counts, and a dot on each row showing whether it is staged, unstaged, or partly both
  • A file's history, beside its diff. Every commit that touched the file you are looking at, newest first, with the author, the short SHA, the subject and the date. Click one to load that revision into the left pane and read the file as it was against the file as it is; the two revisions on screen are marked A and B. Open it from the clock in the toolbar, from Navigate ▸ Show File History (⌥⌘Y), or from Open Git File History in a review's file list. A revision is read-only, always — it is a copy of a git object, not your file, and Riffle will not let you type into history
  • Blame, per line, beside the diff. A column between the line numbers and the text showing who last touched each line, with runs of consecutive lines from one commit drawn as a single block labelled once. Click a block to open the commit behind it. Off by default; toggle it from the toolbar or View ▸ Show Blame (⌥⌘B). Each pane blames its own revision — a working file blames the working tree, a revision loaded from history blames that object, and a range review's base side blames the base
  • The commits behind a changeset. A branch, commit or pull request review now has a Files ⇄ History toggle. History lists the commits in the range with a detail pane for the selected one — who, when, the full message, and the files it touched — and Open Changeset opens any of them as a review of its own
  • Step through every change in a review, across files. ⌘↓ at the last change of a file now moves to the next file's first change, and ⌘↑ is symmetric. The footer says where you are — "File 3 of 12 · Change 2 of 5". It follows the list's own order, so a tree traverses in tree order; it honours the filter, because the filter means what it says; and it stops at the last change of the last file rather than wrapping, because wrapping loses your place
  • Riffle can tell you when something lands. Leave a review Live, go do something else, and get a notification when the repository moves — "3 files changed", "The branch moved", "A merge is in progress". Clicking it brings the review forward and selects the file. It never fires while Riffle is the app in front, never for a review that isn't Live, and a burst of a hundred changes is one notification rather than a hundred. Off until you switch it on in Settings ▸ Notifications, which is also when macOS is asked for permission; right-click the Live toggle to silence a single review
  • A pixel inspector for image comparisons. Move the pointer over an image comparison and read what is actually there: the coordinate, both sides' colour as a swatch, hex and RGBA, the signed per-channel difference, and a ΔE00 saying whether that difference is one anybody could see. Under it, each file's whole-image range per channel — the thing that explains a "black" PNG that is really 4, 4, 4 — and the colour space each file declares, flagged when the two disagree, which is very often the entire reason two identical-looking images differ in every pixel. Coordinates are on the shared canvas, so a smaller image beside a larger one reads as "outside this image" rather than as transparent black. Click the image to put the colour under the pointer on the clipboard — hex by default, or CSS, the four RGBA numbers, or a SwiftUI Color you can paste straight into code — and right-click for the other side, both sides at once, the coordinate, or to change the format. Toggle it from the eyedropper in the toolbar or View ▸ Show Pixel Inspector (⌥⌘I)
  • Compare what's on the clipboard. New Empty Comparison (in the welcome panel, or File ▸ New Empty Comparison, ⇧⌘N) opens a comparison with two empty sides. Paste into one, paste into the other, and the diff keeps up as you type — no save, no button, nothing written to disk. It is an ordinary 2-way diff in every other respect. The two sides stay the same width while one of them is still empty — it is where you are about to type, not a side that isn't there. To diff a snippet against a real file, Open Left… / Open Right… in the footer point that side at one without disturbing what you pasted into the other. If what you pasted turns out to be worth keeping, File ▸ Save Side As… (⌥⌘S) writes it wherever you like — and an untitled side then carries on as that file
  • 2.0 is a free update if you already own Riffle. Lifetime Access means lifetime access — there is no paid upgrade, and nothing to re-enter. If you are on the free tier, unlimited 2-way file diff stays free and everything above is still the one-time license
  • A new icon. The same riffled fan of cards, with the front card now split down the middle: two columns of lines either side of a hairline. It reads as a diff rather than as a stack of paper, and it is drawn on Apple's real continuous-corner tile so it sits properly beside the rest of your Dock

Improved

  • Say what language a comparison is. A syntax menu in the footer, beside the whitespace controls: leave it on Automatic (which names what it worked out) or pick one outright. For the comparisons where the file name doesn't say — something you pasted in, a file with no extension, a .txt that is really JSON — which is every comparison detection was never going to get right
  • Fold and unfold any stretch of agreement, whenever you like. Hovering a run of hidden lines turns its count into "Show 19 lines" and the pointer into a hand; ⌥-click opens every fold at once. A chevron in the gutter beside a run's first line shuts it again — and those chevrons are there whether or not the file was folded to begin with, so you can put one long stretch of unchanged code away without hiding everything else first. Every run has one whichever way it is pointing, on the same row shut as open, so opening and closing the same stretch is the same spot twice: click, click, click without moving the pointer. Previously opening a fold was a one-way door, and collapsing anything at all meant collapsing the whole file
  • Merges undo. ⌘Z now steps back through every resolution — Take Left, Take Both, a region assembled line by line, a hand edit — wherever the window happens to be focused. Previously undo was only live while the caret was in the result pane, which meant resolving from the footer buttons left nothing to undo at all. A merge also opens with the caret already in the result, and Revert the Whole Merge in the Merge menu (and the footer's ⋯) puts every change back to how the merge opened, itself a single undo away
  • Taking a side moves on to the next change. Resolving from the footer buttons now steps to the next conflict still needing a decision, or simply to the next change once they are all settled. It stops at the last one rather than wrapping back to the top
  • The resolving controls sit over the pane they write into. Five icon buttons — everything from the left, this from the left, both, this from the right, everything from the right — centred on the result pane rather than wherever the footer's other text left room, with the ⋯ menu at the pane's right edge. The arrows point inward, at the result, because that is where the lines are going; hover any of them for the words. Take All used to be two chevrons up in the window toolbar, a long way from the decision they were about and drawn in a different language from the buttons they doubled. The ⋯ is grouped and spelled out now — the ordering variant of Take Both, the base, and the ways back out of a decision — so it is clear why each is in there rather than out here

Fixed

  • The welcome window's Recent panel reaches the top. Its tint carries on up through the titlebar band, behind the traffic lights, instead of stopping a titlebar's height down the window and reading as a panel that fell short
  • The previous / next change buttons no longer look switched off. They were drawn as unlit toggles — a dim glyph on no background, which is how macOS draws a control you can't press. They are bordered buttons now, in both the diff and merge footers, matching the resolving buttons beside them
  • The tab strip takes a two-finger swipe again. With enough tabs open to overflow the window, the strip scrolls to a trackpad swipe or a mouse wheel as well as to its chevrons
  • The pointer over a fold is a hand, not a text cursor. The text view's own I-beam was winning over the fold's, so a row that takes a click looked like a row you could type in
  • The hover tint on a fold is much lighter. A fold's gap is three rows tall, and a wash that looks gentle on one row was reading as a grey slab dropped into the file

v1.6.3

Build 42

Fixed

  • Tabs keep their width again. With several comparisons open the tabs were squeezing narrower and narrower instead of running past the edge of the strip, and the ‹ › buttons for reaching the ones out of view never appeared, because from the strip's point of view nothing had overflowed. They take their full width and scroll again, and opening a comparison scrolls its tab into view
  • Reordering tabs by dragging works on macOS Sequoia. A tab could be picked up and nothing would happen. Dragging one is a plain drag now rather than a trip through the system's drag-and-drop machinery, which on Sequoia never delivered it. A click is still a click: the reorder only begins once the pointer has actually moved
  • The colours in a tab's right-click menu are visible on macOS Sequoia. The eight colour circles were missing there, leaving a list of colour names with nothing to tell them apart

v1.6.2

Build 41

New

  • Hide unchanged lines. A long file with a few changes in it is mostly agreement, and scrolling past the agreement is the work. Riffle now folds the long runs both files agree on behind a single seam saying how many lines are in there — click it to open that run, or the count in the bottom bar to open them all. Three lines stay either side of every change, so a fold never costs you the context that tells you what a change is. On by default for files long enough that it pays, off for files you can already take in whole; Settings ▸ General sets the policy and how much context to keep, and the bottom bar overrides it for the comparison in front of you
  • A change map down the trailing edge. Every change in the file as a mark on a narrow strip, so a file with three changes clustered at the top reads differently from one with changes spread all through it — before you have scrolled a line of either. It is the panes' scrollbar as well: drag it to scrub, and the block showing what is on screen is the knob. In two-pane, unified, and the diffs inside a review

Improved

  • A file that was added no longer spends half the window on nothing. The "before" side of a new file is empty, and it was taking half the width to show that. It keeps a narrow column now, and the file you are actually reading takes the rest
  • The icons in a review's toolbar match the ones beside them. A review's editor button was drawn half again the size of the diff's own icons, in a different style — and its terminal button and open-with menu were missing entirely, all three collapsed into one oversized control. The pane headers' save, revert, and reveal glyphs also agree on a size and stroke again

Fixed

  • Tabs respond to the mouse on macOS Sequoia. A tab showed no hover state and took no clicks — the strip was plainly there and completely inert, while the + button three inches to its right worked fine. The tabs were inside a horizontally scrolling container and the + button was not, and on Sequoia that container swallowed everything aimed at what was inside it. The strip scrolls itself now, so the tabs sit in the same place the + button always did. Double-clicking still renames, reordering by drag still works, and the chevrons at the right reach tabs that have scrolled out of view

v1.6.1

Build 35

Fixed

  • Clicking a tab switches to it again. 1.6.0 gave tabs a double-click-to-rename, and a tab is also a drag handle for reordering, so a single click had to wait for the double click to be ruled out before it counted — and a click that drifts a pixel during that wait is taken as the start of a drag instead. On a mouse, which drifts far more readily than a trackpad, the result was a tab strip that looked fine and did nothing. Selecting is a plain click again, with renaming alongside it rather than in front of it
  • The red button closes the window. It used to close the front tab and never the window, which is not what that button means anywhere else on the Mac. Now it closes the window, Riffle keeps running, and the dock icon — or the next comparison arriving from the CLI, Finder, Tower or an agent — brings the window back with every tab still in it. ⌘W closes a tab, as it does in any tabbed app, and falls through to closing the window when there are no tabs left. Anything unsaved in any tab is asked about first, not just the tab you happen to be looking at
  • The close button on a tab sits at the tab's trailing edge instead of trailing the last letter of its name, so it is in the same place on every tab

Improved

  • Switching tabs is fast on large files. Coming back to a tab rebuilt its panes, and most of that time went to re-measuring how each line wraps — around a third of a second per pane on a four-thousand-line file, for an answer that had not changed. That measurement is now remembered, so returning to a tab, changing theme, and switching between blocks and fluid are all near-instant on files where they used to stall. Opening a comparison for the first time is unchanged: that measurement is real work and still gets done
  • Close Window joins the File menu on ⌘⇧W, beside ⌘W's Close

v1.6.0

Build 34

New

  • Fix it where you found it. A diff pane whose file is yours is now editable in place. You see the typo, you fix the typo, you press ⌘S, and the diff re-runs from what you just wrote — no round trip to the editor, no coming back to refresh. Each side saves on its own (⌘⇧S writes both), the reader keeps its place across the save, and undo stays inside the pane you typed in
  • Only the files that are actually yours. Riffle is read-only unless it can prove otherwise, because most of what it shows isn't what it looks like. Your own files and both sides of a folder comparison are editable. A git review's two sides are blobs materialized into a temp tree, a git difftool older revision is a copy git is about to delete, and a --pairs manifest's left side is the "before" snapshot the whole review is built on — none of those take a save, and none of them offer one. A manifest's right side, which is the real file being reviewed, does
  • Name a tab, and give it a color. Double-click a tab to rename it, or right-click for Rename and a set of eight colors that tint its icon and wash its background just enough to find across the strip. Useful the moment you have several agent reviews open and the derived names all read alike; "Use Automatic Name" puts a tab back to following its files
  • Tabs land where they should. A tab now advances to the next multiple of the tab width instead of TextKit's 28-point default, which corresponded to nothing in a monospaced font — so tabbed and space-indented lines finally line up in the same column. Settings ▸ General sets the width (2, 4, or 8). It changes what you see, never what is written to a file
  • Revert, beside Save. A pane with unsaved work grows a revert control next to its save glyph, for the edit you made by accident. It puts the file back as one undoable step, so ⌘Z brings your work back if the revert was the mistake

Improved

  • Typing is colored as you type. A line you add is syntax-highlighted like the rest of the file rather than sitting there plain until the next save
  • A new line keeps the indentation of the one it came from, which is the one editing convenience worth having here — landing in column zero inside indented code is wrong often enough to notice
  • Unsaved changes are marked with a slowly pulsing red dot beside the filename, so a modified-but-unwritten file is hard to look past. It holds still when the system asks for reduced motion
  • The save control is a floppy disk. The download-tray glyph it replaced reads as "download", or as a share sheet run backwards; a floppy has meant "write this to disk" for forty years and needs no caption
  • While a pane holds unsaved typing its change bands go faint, and its intra-line boxes and end-of-line marks stand down. They describe the file as it was loaded, and a decoration that isn't accurate any more shouldn't keep looking authoritative — the next save recomputes all of it
  • Changing the view mode, whitespace mode, or soft wrap while you have unsaved work re-runs the diff against what you typed rather than against the file on disk, so nothing you were in the middle of is lost to a display setting. So does swapping the sides, which carries the work across with its file
  • A save writes the file back exactly as it found it: the same encoding and byte-order mark, CRLF where there was CRLF, no trailing newline where there wasn't one, and untouched lines of a mixed-ending file keeping their own terminators
  • Closing a tab, closing the window, or quitting with unsaved pane edits asks first and names the files, the way an unfinished merge already did
  • If something else rewrites a file while you're editing it, Riffle stops reloading and says so in that pane's header, with the two honest ways out: save over what landed there, or reload and drop yours

v1.5.1

Build 33

New

  • Compare two files straight from Finder. Select two, right-click, and choose Compare with Riffle. It's a real Finder menu item, added by an extension that ships inside Riffle and needs switching on once in System Settings — Settings ▸ Integration has a button that takes you to the right place and tells you whether it's on. The first file as the window lists them opens on the left, which macOS gives no way to improve on: it reports the selection in the window's own order, never the order you clicked. The swap button fixes it in a click when that isn't the order you wanted
  • The same comparison, two other ways. Services ▸ Compare with Riffle does the same job from anywhere, including iCloud Drive and a synced Desktop or Documents, where macOS lets no third-party extension add a menu item at all — and it can be given a keyboard shortcut in System Settings. Riffle also appears under Open With now, for a selection of any two files
  • A dark theme on a light Mac, or the other way round. Riffle keeps a theme for each appearance and picked between them by what the system was doing, which is no use if you run macOS light and want your code dark. Settings ▸ General now has a Theme Appearance choice: System, Light, or Dark. It changes the theme only — menus, dialogs and Settings still follow the system, the way every other Mac app does

Improved

  • Reveal in Finder moved into the panes. Each side of a diff now has its own folder button in its header, so it says which file it means — the window toolbar could only ever act on one side, and in a review it ended up showing two identical folder buttons that opened different files. Editor, terminal and the open-with menu stay in the toolbar, and in a review they point at the file in your checkout rather than the temporary copy the diff is drawn from

Fixed

  • Opening files got its two seconds back. Every file handed to Riffle waited to see whether a command-line job was coming for it, including files that obviously weren't — a Finder double-click, Open With, a drop on the icon. Those now open immediately; a riffle command still gets the wait it needs to deliver its files
  • The review window the Claude Code plugin opens is free again. Its license gate was written when git was the only way into a review, so it also locked a review built from a file list, which has no repository in it at all. Anyone past their trial got a "paid feature" placard where 1.5.0 was supposed to give them the same 2-way diffs that are free forever. Git review is still the paid one
  • Side labels from a --pairs manifest reach the diffs. labelA and labelB were read and then dropped, so the panes fell back to labelling themselves from their paths — and since a "before" file is usually a snapshot in a content-addressed store, that meant a pane header reading as a 64-character hash instead of "before the agent"
  • A review's context line no longer runs off the end of the toolbar. A deep path pushed the change count and the Live toggle out of the window; it now loses its middle and keeps its tail, with the whole thing in the tooltip

v1.5.0

Build 17

New

  • Bring your own themes. Riffle ships 60-odd themes, but until now there was no way to add one. Settings has a new Syntax tab that manages them: add a theme file from disk, see what you've added, and remove one when you're done with it. It reads the VS Code / shiki theme JSON that nearly every editor theme is published as, and now also real TextMate .tmTheme files, so a theme you've carried around for years still works. Themes that ship as JSON with comments in them — Cobalt2 and Shades of Purple both do — no longer get turned away
  • A gallery to install from. The same tab browses a catalog of themes and languages published alongside Riffle's updates, with a preview of each theme's colors, who made it and under what license, and one click to install. Because it's a feed rather than something baked into the app, new entries appear without waiting for a Riffle release. It works offline too, showing the last catalog it downloaded
  • Add your own languages. Riffle knows 46 languages; now it takes more. A language is a JSON file naming the file extensions it claims plus its keywords, comment markers and string delimiters, dropped in ~/Library/Application Support/Riffle/Languages or installed from the gallery. At its smallest it's four lines pointing an extension at a language Riffle already knows, which is all it takes to color .blade.php as PHP or your in-house .conf dialect as INI. Multi-part extensions work and beat a shorter match, so a Blade definition takes page.blade.php while plain .php files stay PHP. Comparisons you already have open re-read themselves when you add or remove one, so there's no closing and reopening tabs to see it
  • Thirteen languages ready to install from the gallery, including AL for Microsoft Dynamics 365 Business Central, Blade, Liquid, Jinja, Handlebars, PowerShell, Julia, Solidity, F#, Groovy and Jenkins pipelines, Prisma, MDX, and .env files
  • Review a list of files, not just a repository. riffle review --pairs <manifest.json> opens the review window — file list beside an inline diff — over any set of before/after pairs a JSON file names, with no repository involved. Add --watch and Riffle re-reads the manifest whenever it changes, so a tool that rewrites it revises the rows it changed and adds the ones it newly touched, in the window already open rather than in another one. Built for coding agents, and useful to anything that can write a list: a build's before/after outputs, a migration's inputs, a batch of generated files
  • The Riffle plugin for Claude Code uses it. The end of an agent's turn now opens one window listing every file it changed, each against a snapshot taken before the agent first touched it, instead of a tab per file capped at five. Later turns land in the same window. Files you edited yourself are still excluded, which is the whole point of the snapshots. The tab is named after the project, so two agents working in two checkouts stay apart, with the full path and the agent's name in the window itself

Improved

  • Settings ▸ General says less and points better. The theme pickers stay where they were, with a Manage button beside them that opens the new tab, and the paragraph that used to tell you to go find a folder in Finder is gone

v1.4.0

Build 16

New

  • Two shorthands for the review window, spelled the way you'd say them. riffle diff reviews everything you've changed but not committed, and riffle show reviews the commit you just made (riffle show HEAD~1 for the one before it). Both open the same file list beside an inline diff that riffle review opens, and both take every option it takes
  • Reviews can stay live. riffle diff --watch, or the new Live button in the review window, keeps the file list and the diffs up to date as the repository changes, so edits, commits, staging and new files all appear on their own. Leave it open on a second screen beside your editor, or beside a coding agent, and watch the work land instead of reaching for refresh. Files that just changed are marked with a dot, and your place in the file you're reading is kept. Available for the working tree and the staged index: a commit, branch or pull request review compares two fixed commits, so there is nothing to watch
  • Get to the files from any comparison. Every comparison's toolbar has three new buttons, one each for revealing in Finder, opening in your editor, and opening a terminal, all acting in one click on the file you're looking at. The menu beside them reaches every other file the comparison is built from: both sides of a diff, all four files of a merge, either folder and the selected entry in a folder comparison, the repository and the selected file in a review. A review points at the real file in your checkout, not the temporary copy its diff is drawn from, and files that are throwaway copies say so before you edit one
  • Editors follow the file. A Swift file offers "Open in Xcode" and a Markdown file "Open in Zed", because Riffle uses whatever you have set macOS to open each type with, so there is nothing to configure. Open With lists everything else that can open it. Terminals do need a choice, so Settings ▸ General has a picker offering the ones it finds installed, with anything else selectable from disk

Improved

  • Rescanning a review no longer loses your place. Refreshing used to jump the selection back to the top of the file list and rebuild every diff from scratch, so a rescan cost you your scroll position in whatever you were reading. It now keeps the selected file, keeps the diffs for the files that didn't move, and reloads only the ones that actually changed. Those are marked with a dot in the file list for a few seconds so you can see what landed

v1.3.4

Build 15

Improved

  • The paid features have a name. Settings ▸ License read a bare "Licensed", which never said what the tier was called, so the pricing on the website and the status in the app were using different words for the same thing. It now reads "Riffle Pro", the trial counts down a "Pro trial", and the buy button and status line name the tier instead of listing the features twice

v1.3.3

Build 14

New

  • A comparison can now be opened without Riffle coming forward. riffle --background a b puts the diff in a tab and leaves you where you are, which is what a script, a git hook, or a coding agent opening a diff mid-turn usually wants. Without the flag nothing changes, so riffle a b at the prompt still brings the window up
  • File Properties has a Where row, giving the file's folder with your home directory written as ~. Two files with the same name on either side are hard to tell apart from the name alone, and the window title never had room for the path. Hovering a tab shows the same thing as a tooltip, with both sides listed when they differ

Improved

  • A diff that arrives on its own now does so quietly. It no longer lifts the window above what you are reading, and it starts comparing as soon as the tab is created rather than after the tab is drawn, so the content is usually there in the first frame instead of appearing a moment after an empty pane

Fixed

  • A very long path no longer stretches the File Properties panel off the screen. Values wrap to two lines and lose their middle rather than their beginning, keeping the ~/ and the trailing folder that identify a path; the full text is still in the tooltip and can be selected and copied

v1.3.2

Build 13

Improved

  • When open tabs overflow the tab bar, a pair of arrows appears beside the + button to scroll it. A trackpad could always swipe the bar sideways, but a mouse had nothing to grab and dragging a tab reorders it, so tabs off the edge were unreachable — and there was no sign they were there. Each arrow dims when that side is already fully in view, and a click brings the next tab past the edge into view rather than scrolling a fixed distance

v1.3.1

Build 12

New

  • Twig templates are highlighted instead of rendering as plain text. {% %} tags and {{ }} interpolations keep quiet delimiters around their contents, so tag names, word operators, filters, and strings stand out from the markup they are woven through, and {# #} comments read as comments. Tags split over several lines are followed across the break, and page.html.twig is recognised the same as page.twig

v1.3.0

Build 11

New

  • riffle review takes --title, --label-a, and --label-b, so a caller can name a review window ("PR #214 review") instead of being stuck with the derived repository name
  • riffle review --if-changes opens nothing and exits 0 when the chosen scope is empty, so a tool that offers a review after some work no longer opens a window reading "No changes" when that work was already committed

Improved

  • A comparison whose two sides have different file names now takes its window and tab title from --title when the caller passed one. Comparing a file against a temp or content-addressed copy of it used to title the window with both paths, so a diff of retry-policy.ts against a hashed snapshot read as a bare hash. A comparison whose sides share a name is unchanged: that name is still the title, and --title still prefixes the subtitle, so git difftool runs look exactly as before

v1.2.0

Build 10

New

  • Notices when a file under an open comparison is changed by something else. A 2-way diff re-runs itself against the new content and keeps your place; a merge you've already worked in asks first, so a reload never discards your resolutions
  • File → Reload from Disk (⌘R) re-reads the frontmost comparison on demand — a diff, a merge, a folder comparison, or a git review

Fixed

  • Saving a merge no longer overwrites the target file without warning when another tool rewrote it while the merge was open

v1.1.3

Build 9

Improved

  • Checks for updates shortly after launch. Previously the first automatic check could be a day away, so a new install would sit on an old version

v1.1.2

Build 8

New

  • The conversation timeline now includes submitted reviews (Comment, Approve, Request Changes), each with a theme-colored state pill

Fixed

  • A review submitted from Riffle now appears in the conversation immediately, without a manual reload

v1.1.1

Build 7

New

  • PR overview and conversation panel in the review window: the description and reply comments render as GitHub-flavored Markdown, and PR sessions open on the Conversation tab
  • "Open on GitHub" button in the review header for PR sessions

Improved

  • The whole review section (file list, header, drawer, composer) now follows the active theme and re-tints live when it changes
  • The verdict control has distinct per-choice icons and semantic theme colors

Fixed

  • Changed-line text no longer renders blank on first load

v1.1.0

Build 6

New

  • Full pull request review round-trip: leave inline comments on changed lines, build up a draft review, and submit it to GitHub without leaving Riffle
  • Markdown in review comments, with a Write/Preview composer and rendered comments in the review drawer
  • Review receipts and a discoverable Review button in review sessions

Improved

  • Version numbering switched to x.y.z (this release supersedes 1.1)

v1.0

Build 3

New

  • Fast, native 2-way file diff with aligned panes, change ribbons, and step-through navigation
  • 3-way merge with conflict step-through and a fully editable result pane
  • Folder comparison
  • Git review sessions for branches and pull requests
  • Installs as a compare and merge tool for Tower, honors git difftool and git mergetool, and ships a command-line launcher
  • 14-day full-feature trial, and unlimited 2-way diff stays free forever after it ends