Изменения

Все версии, начиная с последней, — те же заметки, которые приложение показывает, когда обновляет само себя. Загрузки — на странице релизов. Более ранние версии показаны на английском.

Новая иконка теперь правильно выглядит в macOS 26. В тёмном стиле стрелка и кольцо больше не сливаются в сплошные пятна, а у головы и ушей кошки ровные края вместо зубчатых.

Закрытие верстака теперь освобождает память, которую занимали заметки о выпуске. Раньше открытая страница заметок о выпуске продолжала работать в фоне, пока вы не выходили из DuoUpdater.

Новая иконка. Свернувшаяся клубком сиамская кошка, чей хвост — стрелка обновления. В macOS 26 и новее она следует выбранному вами стилю иконок: светлому, тёмному или тонированному.

Фоновые проверки ждут, пока вы в режиме экономии данных или в сети с оплатой за трафик, например в режиме модема iPhone. Они запускаются, как только вы вернётесь в обычную сеть. Ручная проверка и установка обновлений работают как раньше.

Проверки, не прошедшие из-за сбоя сети, повторяются один раз через две минуты. Раньше строки с ошибкой и предупреждение оставались до следующей плановой проверки — по умолчанию через шесть часов.

Под капотом. Изображения в заметках о выпуске занимают гораздо меньше места на диске, панель Запросы больше не считает повторно проверенный запрос дважды, а проверка Muse больше не скачивает её страницу входа.

Приложения из Homebrew, которые устанавливаются собственным сценарием установки, например Quark Cloud Drive, теперь обновляются в один клик. Раньше каждая попытка заканчивалась ошибкой о том, что установочного пакета нет.

Приложения из Homebrew, установщик которых нужно запускать самому, теперь показывают обновление со ссылкой, а не завершаются ошибкой. Раньше DuoUpdater скачивал установщик целиком, а затем останавливался с ошибкой.

Распознаётся больше приложений из Homebrew. Приложения, которые Homebrew устанавливает под другим именем, например Visual Paradigm Community Edition, теперь проверяются на обновления, и приложение с похожим названием больше не принимается за них.

Приложениям, чей cask в Homebrew отозван, больше не предлагается обновление, которое Homebrew отказывается устанавливать. Вместо этого они проверяются через собственный канал обновлений приложения, если он есть.

Заметки о выпуске VS Code снова отображаются.

Под капотом. Настройки › Диагностика больше не предупреждает постоянно об Antigravity и OpenLens, когда их обновления находятся другим способом.

Blender, скачанный с blender.org, теперь получает обновления, в один клик. Раньше проверялась только копия, установленная через Homebrew.

Альфа-, бета- и RC-сборки Blender обновляются каждая по своему каналу. DuoUpdater определяет, какая у вас сборка, и сообщает, когда выходит более новая сборка того же вида. Альфе никогда не предлагается стабильная версия, и наоборот.

Обновления Muse снова видны. С тех пор как Muse стал требовать вход для ссылки на загрузку, в его строке показывалась ошибка вместо новой версии.

Под капотом. Всплывающее окно в строке меню и верстак открываются немного быстрее в первый раз после запуска, а duo check теперь показывает приложения, проверка которых не удалась, вместо сообщения, что всё актуально.

DuoUpdater теперь говорит по-итальянски, на традиционном китайском, португальском (Бразилия) и турецком. Всего одиннадцать языков. В немецком, испанском и японском исправлены неверные и обрезанные тексты. «Настройки → Папки» теперь показывает названия папок так же, как Finder на вашем языке.

Приложения, установленные через Homebrew, теперь обновляются через Homebrew. Это касается приложений, установленных через brew, у которых есть и собственный механизм обновления. Раньше DuoUpdater обновлял их напрямую, Homebrew об этом не знал, и следующий brew upgrade заново скачивал и устанавливал версию, которая у вас уже была.

Окна открываются в том пространстве Space, где вы находитесь. Раньше повторное открытие настроек или другого окна DuoUpdater после закрытия могло переключить вас обратно в то пространство, где оно показывалось в последний раз.

Одно обновление — одно уведомление. Некоторые приложения проверяются через два источника, и они могли снова и снова сообщать об одной и той же новой версии.

Журнал релизов больше не показывает релизы с датой в будущем. Если лента разработчика указывает дату позже момента, когда DuoUpdater впервые увидел релиз, журнал использует этот момент.

Когда диск для резервных копий отключён, окно верстака снова помещается на экране, а «Копировать сейчас» объясняет, почему копирование невозможно. Раньше окно могло стать выше экрана, и списки не прокручивались до конца, а «Копировать сейчас» молча ничего не делало.

Бета-версии и релиз-кандидаты Xcode теперь обновляются в один клик. Войдите один раз в свою учётную запись Apple Developer в «Настройки → Xcode», и DuoUpdater будет скачивать и устанавливать новые беты и RC, как любое другое обновление. Раньше он мог только сообщить, что вышла новая.

Устанавливайте любую версию Xcode рядом с уже установленными. В «Настройки → Xcode» перечислены все выпуски Xcode, сгруппированные по версиям, и группа для вашей macOS уже открыта. «Установить» помещает выбранную версию в «Программы» как отдельную копию — например, Xcode-26.6.app — и ничего не заменяет; или сохраните только архив (.xip). Если вы вошли в учётную запись, добавляется собственный список Apple, поэтому новые выпуски появляются в течение нескольких минут.

Вход в Apple Developer поддерживает себя сам. Apple завершает сеанс разработчика примерно через восемь часов; теперь DuoUpdater получает новый в фоне — без окна и без пароля, — пока Apple ещё узнаёт этот Mac. Это можно отключить в «Настройки → Xcode».

Новые выпуски Xcode появляются раньше. По будним дням, в часы, когда Apple обычно публикует выпуски, DuoUpdater проверяет наличие нового Xcode каждые пять минут.

Несколько приложений снова работают после изменений у их разработчиков. CapCut beta и Superconductor nightly снова находятся и устанавливаются, а Superconductor сохраняет свою нынешнюю идентификацию приложения. VLC 3.0.24 и JetBrains Air снова показывают свои примечания к выпуску.

Теперь поддерживается Qoder CN IDE. Версия IDE Qoder для материкового Китая получает проверку обновлений, установку в один клик и примечания к выпуску в окне. Настольное приложение Qoder CN теперь тоже показывает свои примечания к выпуску.

Qoder IDE больше не меняет мнение о последней версии. Qoder выкатывает обновления постепенно, и DuoUpdater теперь спрашивает так же, как ваша копия IDE, поэтому каждый раз получает один и тот же ответ. Раньше предлагаемая версия могла переключаться между двумя выпусками, а установка в один клик могла остановиться на полпути, потому что ответ менялся.

Приложения на Sparkle, скачавшие уже устаревшее обновление, снова можно обновить. Если приложение, которое обновляет себя через Sparkle, скачало сборку, а потом вышла более новая, DuoUpdater теперь удаляет старую загрузку и устанавливает последнюю. Раньше «Обновить» раз за разом сообщала, что установка сейчас будет отменена, и строка не менялась.

duo install сообщает, когда последняя сборка уже ждёт установки. Если собственный механизм обновления приложения уже скачал последнюю версию, команда теперь говорит об этом и предлагает закрыть приложение или выполнить duo restart. Раньше она ошибочно сообщала, что приложение можно только проверить, но не установить.

搜狗输入法 теперь обновляется в один клик. DuoUpdater устанавливает обновление так же, как метод ввода обновляет себя сам — установленный бандл остаётся на месте, — и сначала копирует ваш словарь и настройки, поэтому откат вернёт и их.

Резервные копии на другом диске теперь сохраняют словарь и настройки метода ввода. Раньше на диск для резервных копий переносилось только само приложение, поэтому откат метода ввода оттуда оставлял на месте данные более новой версии.

Больше никаких обновлений, которые невозможно установить. JetBrains Air теперь показывает ту сборку, которую действительно предлагает Toolbox. Приложение из App Store, оставшееся под старым именем после того, как разработчик его переименовал, теперь сообщает, какую копию обновляет App Store, вместо того чтобы предлагать обновление, которое лишь переустанавливает другую копию.

Примечания к выпуску ещё у ряда приложений теперь отображаются с форматированием. Приложения, публикующие примечания в Markdown, теперь получают такой же нативный список, как и остальные. Раньше такие примечания показывались простым текстом.

«Перезапустить» больше не соперничает с собственным установщиком приложения. Когда приложение само скачало обновление, а его резервная копия для отката должна лежать на внешнем диске, перенос теперь ждёт, пока установщик закончит. Раньше он шёл ровно в те несколько секунд, которые macOS даёт установщику на работу.

Резервные копии для отката теперь могут храниться на другом диске. Резервная копия — это целая копия приложения, и на загрузочном диске они накапливаются. В разделе «Настройки» → «Резервные копии» перечислены подключённые диски со свободным местом на каждом; уже сделанные копии можно перенести туда, а новые записываются туда в фоне — если диск отключён, вы получите задержку, а не пропавшую точку отката. У duo backups появились disks, sync, verify и probe.

Теперь поддерживается 千问输入法. DuoUpdater сообщает о выходе новой версии и обновляет этот метод ввода так же, как он обновляет себя сам.

Заметки о выпуске больше не застревают на предыдущей версии. Когда разработчик публикует обновление за несколько минут до того, как оно появляется на странице изменений, старые заметки записывались под новой версией и оставались там навсегда. CleanShot X с самого дня выхода 5.0.1 показывал заметки к 5.0.

Удаление резервной копии теперь действительно освобождает заявленное место. Копии, сделанные прежними версиями DuoUpdater, записывались в виде, который macOS отказывается удалять, поэтому «Очистить» оставлял большую часть копии на диске, засчитывая её как освобождённую.

«Очистить» открывается сразу. Раньше при каждом нажатии каждая сохранённая копия измерялась заново.

WorkBuddy снова показывает свою новейшую версию. Его служба обновлений отвечает следующим шагом цепочки обновлений, а не новейшей сборкой, поэтому все четыре издания WorkBuddy отставали на два выпуска.

Под капотом. Приложение, которое так и не указало, какой двоичный файл оно запускает, — например, Muse от Meta — теперь всё равно раскрывает свои фреймворки и SDK.

Обновления, завершённые через «Перезапустить», теперь можно откатить. Когда приложение уже само скачало обновление и вы нажимаете «Перезапустить», DuoUpdater сначала сохраняет текущую версию, и это обновление появляется в разделе «Откат», как любое другое. Раньше отменить можно было только обновления, которые установил сам DuoUpdater.

Смотрите, что обновление изменило внутри приложения. Для любого приложения с сохранённой предыдущей версией на верстаке рядом с «Заметками о выпуске» появился вид «Различия пакета приложения»: подпись и разрешения, минимальная версия macOS, фоновые объекты и объекты входа, встроенные библиотеки, а также добавленные, удалённые и изменившие размер файлы. duo diff делает то же самое в Терминале для любых двух копий приложения.

«Перезапустить» сообщает, когда собственный механизм обновления приложения не применил обновление. Если приложение закрылось, а обновление так и не установилось, его строка теперь говорит об этом и по-прежнему предлагает «Перезапустить». Раньше индикатор просто молча останавливался.

Cherry Studio снова показывает свою новейшую версию. После того как Cherry Studio переименовал загрузки для Mac, DuoUpdater принимал более старый выпуск за последний: свежие копии считались актуальными, а более старым предлагалась эта старая сборка.

Обновления из App Store больше не застревают из-за неотвечающего помощника. Когда помощник DuoUpdater переставал отвечать, обновление замирало на 0 %, а все обновления из App Store в очереди за ним ждали, пока вы не закроете DuoUpdater.

«Обновить всё» больше не перезапускает приложения, которые вы игнорируете. При включённом «Автоматически перезапускать обновлённые приложения» в конце партии могло закрыться и снова открыться игнорируемое приложение или приложение, скачанную версию которого вы пропустили.

Теперь поддерживаются Tinycast и SuperCmd. DuoUpdater сообщает о выходе новой версии Tinycast или его беты, а также теперь распознаёт исходный SuperCmd с открытым кодом наряду с SuperCmd 2. Заметки о выпуске Kimi Code теперь тоже отображаются.

Заметки о выпуске соответствуют предлагаемой версии. Страница последних заметок о выпуске VS Code оказывалась пустой, а сразу после выхода новой версии панель заметок могла показывать заметки предыдущего выпуска.

Журнал релизов больше не добавляет один и тот же выпуск при каждом запуске. У таких приложений, как Claude, Raycast и Cline, при каждом запуске DuoUpdater появлялась повторная запись.

Боковая панель верстака разделена на вкладки «Приложения», Brew и «Откат». Нажмите на вкладку или проведите по вкладкам, чтобы переключиться; поиск фильтрует все три сразу.

Под капотом. «Перезапустить» и «Откатить» для одного и того же приложения больше не мешают друг другу; лента обновлений больше не может заставить DuoUpdater удалить файлы за пределами папки загрузок; фоновые проверки больше не рискуют вызвать запрос macOS на доступ к данным других приложений; очень большое число в фильтре «Запросы» больше не закрывает приложение; а строка меню теперь учитывает запрос прав администратора, который вы отклонили в duo install.

Обновления iStat Menus теперь определяются правильно. Когда iStat Menus перевыпускал обновление, DuoUpdater мог продолжать предлагать его уже после установки, а повторное нажатие «Обновить» заканчивалось ошибкой.

Теперь поддерживается Memoh Desktop. DuoUpdater сообщает о выходе новой версии и может обновить его в один клик.

«Обновить всё» больше не просит перезапустить приложение из App Store, которое уже открылось снова. Когда App Store закрывает приложение и снова открывает его в новой версии, его строка сразу показывает, что оно обновлено, а не «Перезапустить сейчас» до конца всей партии.

Приложение, которое уже само скачало своё обновление, больше не скачивает его второй раз. Некоторые приложения тихо загружают обновление в фоне и ждут, пока вы их перезапустите. Нажмите «Обновить» в DuoUpdater — теперь он установит копию, которая уже лежит на диске: обновление займёт секунды и не потребует загрузки. Раньше DuoUpdater скачивал тот же выпуск заново.

Теперь поддерживаются Cua Driver и Petex. DuoUpdater сообщает о новом выпуске любого из них, а Cua Driver к тому же обновляется в один клик и показывает примечания к выпуску.

Об одном и том же обновлении больше не приходят уведомления снова и снова. Когда сервер разработчика переключался между двумя версиями, каждая проверка выглядела как новое обновление и присылала ещё одно уведомление.

Только что установленный пакет больше не предлагает установиться снова. Раньше в его строке по-прежнему говорилось, что скачанный пакет будет открыт повторно.

Для DuoUpdater теперь нужна macOS 15 Sequoia или новее. Mac, оставшийся на macOS 14, сохраняет текущую версию, но больше не получает обновлений; любой Mac с Apple silicon можно обновить до поддерживаемой macOS.

Под капотом. Плановые проверки больше не получают ссылки на загрузку заранее — из-за этого, когда сервер загрузки разработчика не отвечал вовремя, рабочая кнопка «Обновить» могла ненадолго пропадать.

Теперь поддерживается Aside. DuoUpdater сообщает о выходе новой сборки браузера Aside и показывает её примечания к выпуску.

Обновления, которые ваша macOS не может запустить, больше не предлагаются, а в строке теперь объясняется почему. Если разработчик указывает, какие версии macOS поддерживает выпуск, DuoUpdater следует этому: после обновления macOS Little Snitch больше не предлагает сборку с ограничением ниже вашей системы; Xcode больше не предлагает сборку, которой нужна более новая macOS, чем у вас; а установочный пакет, чьему приложению нужна более новая macOS, отклоняется, вместо того чтобы установить приложение, которое не откроется. Строки, где раньше был пустой прочерк, теперь показывают «Пока не для этой macOS» или «Нужна новая версия macOS», а подробности — в один клик.

Видно, с каким SDK собрано каждое приложение. Нажмите на значок рядом с названием приложения — в подробностях теперь написано, например, «Собрано с SDK macOS 27.0.». Удобно, чтобы понять, какие приложения уже пересобраны под новейшую macOS.

Приложения Homebrew, которые выходят двумя пакетами — для старых систем и для новейшей, — теперь читаются из нужного. OnyX разделён так для macOS 27, а DuoUpdater смотрел только на пакет для старых систем: либо вовсе не показывал OnyX, либо считал его актуальным по версии, которую Homebrew отказывается ставить на 27. Теперь DuoUpdater следит за тем из двух, который установлен у вас.

Бета-версии TestFlight больше не теряют своё обновление при запуске TestFlight. Бета с ожидающей новой сборкой могла снова стать «актуальной» и оставаться такой, пока вы заново не откроете TestFlight.

Обновление в один клик для Dropbox и ToDesk скачивает правильный файл. На Mac с Apple silicon Dropbox раньше скачивал сборку только для Intel, которую затем отклоняла проверка безопасности; для ToDesk предлагалась сборка раннего доступа, которую получает лишь часть пользователей, вместо общего выпуска.

«Перезапустить» сразу завершает обновление Spotify. Когда Spotify уже скачал собственное обновление, «Перезапустить» раньше крутилось несколько минут, прежде чем обновление применялось.

Бета-сборки переходят к своим выпускам. Бета Xcode получает предложение своего релиз-кандидата вместо статуса «актуально»; беты CotEditor видят его релиз-кандидаты; а бета Carbon Copy Cloner, чей тестовый цикл завершился, получает выпуск, которым она стала, вместо неудачной проверки.

Примечания к выпуску соответствуют вашей версии. Blender 5.2 раньше показывал примечания к 5.1, а Raycast 1.x — к 2.x. «Открыть страницу» у Gemini теперь открывает текущую страницу настольной версии Google вместо ошибки.

Настройки объясняют каждый параметр прямо рядом с ним. Длинные пояснения под целыми разделами заменены короткой строкой под каждым элементом управления, а меню выбора описывают только выбранный вариант.

Приложение теперь пишет своё название как DuoUpdater, как на сайте.

Пакеты Homebrew из tap, которым вы не доверяете, снова видны. Начиная с Homebrew 6, brew при выводе списка установленного молча пропускает пакеты из недоверенных tap, поэтому они без объяснений пропадали из DuoUpdater. Теперь они отображаются как «Не проверено · tap не доверенный», а рядом — готовая к копированию команда brew trust; стоит выполнить её (или обновление) в Терминале, и окно подхватит изменения, как только вы в него вернётесь.

Приложения, которым для самообновления нужен пароль администратора, больше не обновляются дважды. Когда приложение вроде Tailscale уже скачало своё обновление и ждало перезапуска, DuoUpdater этого не видел и всё равно предлагал «Обновить», что могло столкнуться с собственным установщиком приложения. Теперь в строке предлагается «Перезапустить», а «Обновить всё» его не трогает.

Раздел Homebrew теперь умеет обновлять сам Homebrew. Когда выходит новая версия Homebrew, вверху появляется строка, которая запустит за вас brew update. Если у вас задан HOMEBREW_NO_AUTO_UPDATE, строка не показывается.

Неудачное обновление пакета Homebrew теперь показывает настоящую ошибку brew. Раньше в строке был совет, который brew печатает после ошибки, или вообще ничего, так что сообщение вроде «Command Line Tools слишком устарели» до вас не доходило. Кроме того, обновление нескольких пакетов сразу больше не сообщает о завершении раньше времени.

Значок в строке меню считает больше 50. Если ожидало больше 50 обновлений, он раньше застревал на 50.

Заметки о выпуске: у Claude они разбиты на New, Improved и Fixed, как в самом Claude; у Mac Mouse Fix показываются текстом, а не встроенной страницей; у собственного приложения Homebrew теперь тоже есть заметки.

duo check больше не пишет «Everything is up to date.», если на самом деле не смог проверить. Теперь он сообщает, когда не удалось прочитать TestFlight или когда сканирование приложений было прервано.

Заметки о выпуске теперь отображаются на вашем языке, если приложение публикует их сразу на нескольких. Некоторые приложения выпускают заметки в переводе вместе с каждым выпуском, а DuoUpdater брал тот перевод, который приложение случайно перечислило первым или последним, — поэтому заметки одного приложения у всех читались по-немецки, а у другого язык менялся от выпуска к выпуску.

Приложения, у которых появилась версия для Mac, больше не отображаются как «Не поддерживается на этом Mac». Приложение для iPhone или iPad, запущенное на Apple silicon, ошибочно помечалось так в тот самый момент, когда разработчик выпускал для него настоящую сборку для Mac, — то есть из-за изменения, которое делает обновление доступнее, а не наоборот.

Приложение из App Store, бету которого вы также тестируете, больше не принимается за сборку из TestFlight. Когда разработчик переводил бету в выпуск без изменений, у обеих сборок совпадал номер сборки, и ваша купленная копия передавалась TestFlight — так что App Store уже никогда не мог предложить ей обновление.

Обновление из App Store, которому нужна более новая macOS, чем у вас сейчас, теперь так и говорит. Раньше строка всё равно предлагала его установить, а App Store отказывал на последнем шаге, и ничто на экране не объясняло почему.

Окно «Запросы» теперь показывает, насколько далеко в прошлое на самом деле уходит его журнал, и отмечает периоды, которые не может охватить целиком. Раньше выбор «За 30 дней» для журнала, начинающегося всего несколько часов назад, выглядел ровно как выбор «За 24 часа», и ничто на экране не объясняло почему.

Вы сами выбираете, насколько активно DuoUpdater занимается бета-версиями TestFlight, — в «Настройки → Основные». Вариант При обновлении читает то, что TestFlight уже знает, и запрашивает свежий ответ, когда вы нажимаете кнопку обновления списка; Поддерживать актуальность позволяет DuoUpdater спрашивать и по собственной инициативе, поэтому бета из TestFlight, установленная в фоне, больше не висит вопросительным знаком до обновления списка, а ожидающая вас сборка не остаётся незамеченной за словом «актуально»; Выключено не читает ничего и так и сообщает в этих строках, вместо того чтобы гадать. На компьютерах Mac, где полный доступ к диску уже был предоставлен, изначально выбрано При обновлении, у всех остальных — Выключено.

Теперь достаточно самому открыть TestFlight, чтобы DuoUpdater заметил, что тот установил. Бета, установленная вами через TestFlight, раньше висела вопросительным знаком до следующего обновления списка — а на macOS 27, где уведомление TestFlight «Ready to Test» больше не приходит для уже установленных приложений, это могли быть часы.

Cline теперь проверяется на обновления — и на основной линии выпусков, и на бета-линии — и показывает свои заметки о выпуске. До сих пор он стоял с вопросительным знаком вместо версии: он не публикует ленту обновлений того вида, который DuoUpdater умеет читать, и пакета Homebrew для него нет. Теперь DuoUpdater спрашивает тот же адрес, что и собственный механизм обновления Cline, поэтому предлагается ровно то обновление, которое Cline установил бы сам, а бета-сборка остаётся на бета-треке.

Заметки о выпуске, где изменения сгруппированы под заголовками вроде Added и Fixed, теперь сохраняют эти заголовки. Раньше все группы сливались в один общий список, и было не понять, какие изменения — новые возможности, а какие — исправления ошибок.

Mac Mouse Fix теперь предлагает свои бета-выпуски, если в его собственных основных настройках включено «Get Beta Versions». Раньше DuoUpdater видел только обычные выпуски Mac Mouse Fix, поэтому бета-сборка оставалась незамеченной до выхода следующей обычной версии.

Приложения, у которых номер сборки — просто сквозной счётчик, больше не скрывают собственные корректирующие выпуски. Для приложения, сообщающего версию вроде 12.10 со сборкой 282987, выпуск 12.10.1 читался как «уже актуально».

О новой сборке приложения, сохраняющей прежнее название версии, объявляют повторно. Стоило объявить об одной сборке, как все последующие под тем же названием приходили молча: строка загоралась, значок их считал, но баннер так и не появлялся.

«Обновить всё» теперь считает только те приложения, которые действительно обновились. Приложение, открывающее установщик Apple, чтобы вы завершили установку сами, засчитывалось как готовое, пока его окно было ещё открыто, — поэтому «2 приложения обновлено» могло означать, что не изменилось ничего.

Обновление, которое установилось, но оставило после себя остаток, теперь отображается как установленное, а не как «предоставьте управление приложениями». Новая версия уже работала, а строка в это время отправляла вас в Системные настройки.

Остановка «Обновить всё» теперь останавливает и идущую загрузку. Раньше многогигабайтная передача доходила до конца, повторяясь до пяти раз, и только потом замечала, что её отменили.

Заметки о выпуске больше не путаются между двумя приложениями с общей страницей изменений и остаются актуальными после обновления для приложений, чьи заметки лежат на отдельных страницах для каждой версии. Antigravity и Antigravity IDE могли по четверти часа показывать заметки друг друга; Thunderbird, WeChat, Opera и ещё несколько приложений некоторое время после обновления продолжали показывать заметки предыдущей версии.

Поиск по списку приложений не обращает внимания на диакритику — как это уже делал поиск по настройкам. Набрав «cafe», вы теперь найдёте «Café».

На странице «Диагностика» состояние показывается отдельной строкой для каждого канала выпусков. Раньше сломанное правило для беты или предварительной версии скрывалось за исправным стабильным соседом.

Ответ GitHub «доступ запрещён» больше не выдаётся за превышение лимита запросов. Из-за репозитория, ставшего приватным, или токена без нужных прав вам предлагали добавить токен, который всё равно не помог бы.

«Перезапустить» больше не предлагается для приложения, обновляющего себя само, если ожидающая сборка старше уже работающей.

Под капотом. Установка, резервное копирование и проверка пакетов больше не занимают потоки, на которых работает остальная часть приложения, поэтому меню остаётся отзывчивым, пока что-то из этого выполняется; меню также остаётся плавным во время большой загрузки; «Журнал релизов» учитывает каждый выпуск, который поставщик выпускает под одним и тем же названием версии; резервная копия для отката отклоняется, а не сохраняется, если в ней не хватает собственного исполняемого файла приложения; первый запуск на новом Mac больше не пишет в журнал ложные ошибки базы данных; duo verify и duo reconcile теперь сообщают о схлопнувшихся записях в заметках о выпуске и об адресе установщика, который не работает уже несколько дней; зависшая команда duo прекращает сканирование через двадцать секунд, а не висит бесконечно.

Некоторые приложения, которые обновляют себя сами, больше не выглядят актуальными, когда уже вышла более новая версия. Для приложений, чьи сведения об обновлении лежат за медленно обновляющимся сервером загрузок, DuoUpdater мог ещё несколько дней после выпуска видеть старую версию.

Заметки о выпуске Kimi теперь отображаются в DuoUpdater.

Обновления CodeEdit теперь отображаются. Раньше при более новой версии CodeEdit строка оставалась вопросительным знаком вместо предложения обновиться.

Под капотом. Список Homebrew в меню заполняется быстрее, а команды duo запускаются быстрее.

«Проверить снова» для беты из TestFlight теперь даёт настоящий ответ. Раньше строка из-за этого превращалась в вопросительный знак до следующего обновления списка.

Бета-версии из TestFlight сохраняют свой ответ, пока кнопка обновления списка сверяется с TestFlight. Раньше на несколько секунд все они могли превратиться в вопросительные знаки.

Добавлена поддержка super.engineering: проверка обновлений, заметки о выпуске и установка в один клик. Новая ночная сборка появляется в списке вместе с тем, что в ней изменилось, а «Обновить» устанавливает её за вас.

Microsoft Edge Beta мог предложить вам стабильную сборку Edge. Пока лента бета-канала Microsoft ненадолго пустовала, строка называла стабильную версию, а обновление установило бы её поверх вашей беты.

Бета-версии из TestFlight теперь показывают обновления, которые для них предлагает TestFlight, включая бета-версии iPhone- и iPad-приложений. Кнопка обновления списка в фоне сверяется с TestFlight, обновление больше не исчезает через несколько минут после того, как вы его обнаружили, а кнопка TestFlight открывает страницу этой беты.

Если DuoUpdater не может определить, актуальна ли бета из TestFlight, он так и говорит. Строка показывает вопросительный знак, вместо того чтобы называть бету актуальной, — например, если в TestFlight не выполнен вход или вы больше не тестируете эту бету.

Теперь DuoUpdater объясняет, зачем нужен полный доступ к диску, и без него ничто вас не донимает. Без этого доступа DuoUpdater больше не вызывает предупреждения macOS о чтении данных других приложений; если он требуется бете из TestFlight или CotEditor, вам один раз объяснят, зачем он нужен и где его предоставить.

«Перезапустить» исчезает, как только обновлённое приложение завершает работу. Приложение, оставлявшее после выхода работающий вспомогательный процесс, продолжало просить о перезапуске ещё долго после того, как обновление вступило в силу.

Запрос конфиденциальности macOS, оставшийся без ответа, больше не стопорит проверку обновлений. Проверка продолжается, обходясь без настройки этого приложения.

Заметки о выпуске Rockxy и Ollama снова отображаются целиком. Заметки Rockxy охватывают его недавние выпуски, а не только самый новый, и самый свежий выпуск Ollama больше не пропускается.

duo, необязательный спутник для командной строки, лучше работает с TestFlight. --refresh-testflight работает независимо от того, открыт ли TestFlight, и не захватывает ваш экран, а duo check больше не называет бету актуальной, если TestFlight уже объявил о более новой сборке.

Telegram Desktop снова проверяется на обновления. Telegram переименовал файл, который публикует, и строка больше не могла прочитать из него версию — поэтому она показывала ошибку проверки вместо обновления, ожидавшего за ней.

Приложение для iPhone или iPad, установленное через TestFlight, распознаётся именно как таковое. DuoUpdater принимал его за покупку в App Store, поэтому строка называла не того, кто им занимается, а у магазина запрашивалась карточка, которой не существует, — при каждой проверке, всё время, пока приложение оставалось установленным.

Бета из TestFlight помечается собственным значком TestFlight. Строки, которыми занимается App Store, уже несли значок магазина; строки, которыми занимается TestFlight, вместо этого выписывали название — и один и тот же вид строки был помечен двумя разными способами.

Заголовок окна «Сеть» остаётся на месте при переключении вкладок. Две его вкладки размещали заголовок на чуть разной высоте, поэтому переход между ними выглядел как подёргивание окна.

Прокрутка всего списка приложений снова плавная. При быстрой прокрутке полного списка терялись кадры; теперь каждая строка сообщает свою высоту, для чего её больше не нужно сначала собирать.

Заметки о выпуске для приложения из App Store теперь всегда берутся из App Store. Когда собственный запрос магазина по приложению ничего не находил или завершался ошибкой, окно могло откатиться к заметкам другого канала распространения этого приложения — другой сборки, со своей нумерацией версий — и описывало выпуск, который вашей копии никогда бы не предложили.

Windscribe на канале Beta или Guinea Pig получает сборки именно этого канала. DuoUpdater читает, какой канал обновлений вы выбрали в настройках самого Windscribe, поэтому копии, следующей за предварительной линией, больше не сообщают, что она актуальна, пока на этой линии есть более новые сборки. В окне также показываются заметки к этим предварительным сборкам — раньше оно перечисляло только стабильные.

Windscribe теперь проверяется на обновления, вместе с заметками о выпуске. Копия на старой сборке отображается с версией, на которую может перейти, и с тем, что в ней изменилось; раньше у DuoUpdater не было возможности увидеть версию Windscribe вообще. Обновление по-прежнему идёт через собственный установщик Windscribe, который настраивает и части, лежащие вне приложения.

Обновление больше не устанавливается поверх приложения, которое исчезло, пока вы нажимали. Если между нажатием и началом установки приложение удалили, заменили или оно перестало читаться, DuoUpdater теперь останавливается и говорит об этом, а не устанавливает по этому пути всё равно.

duo, необязательный спутник для командной строки, больше не называет установку пакета завершённой раньше времени. При установке приложения, которое поставляется как .pkg, открывается установщик macOS, а остальное остаётся вам — но сводка считала это установленным: «1 installed», когда ещё ничего не было заменено. Теперь это считается отдельно. Вывод --json также помечает каждую строку тем, что произошло с этим приложением, так что скрипту больше не нужно читать английское пояснение, чтобы отличить сбой от намеренного пропуска.

Под капотом. Перепроверка непосредственно перед установкой, которая защищает обновление в один клик, теперь защищает и duo install; а проверки, которые загрузка обязана пройти, прежде чем заменить приложение, собраны в одном месте для обоих путей, которые их используют.

Нажатие «Обновить» больше не остаётся без результата, когда источник обновлений противоречит сам себе. Если проверка, запускаемая в момент нажатия, возвращает версию старее той, что предлагалась в строке, DuoUpdater теперь сообщает об этом и оставляет обновление доступным. Раньше приложение считалось актуальным и исчезало из списка, а то же обновление снова появлялось при следующей проверке.

Обновления Fork снова предлагаются, если в Fork выбран канал Develop. DuoUpdater читал настройку канала Fork наоборот и следил за каналом Stable, который заметно отстаёт, — копия на Develop числилась актуальной, хотя сам Fork уже предлагал более новую версию.

Mac Performance Monitor теперь показывает свои примечания к выпуску. Приложение публикует их в своём репозитории, а не в той ленте, которую мы читаем, поэтому окну было нечего показать.

Добавлена поддержка CotEditor — и основной линии выпусков, и бета-линии. Какой линии следует копия, определяется установленной версией и собственной настройкой CotEditor «Update to prereleases when available», поэтому бета-копии предлагается следующая бета, а не выпуск, который откатил бы её назад.

Приложению, установленному из App Store, никогда не предлагается загрузка из другого источника. Если запрос к магазину не удался или вернулся пустым, строка теперь сообщает, что приложением управляет магазин, — без номера версии. Раньше проверка могла перейти к другому каналу распространения приложения — к другой сборке с собственной нумерацией — и предложить установить её поверх копии из магазина.

Приложению никогда не предлагается обновление, которое откатило бы его на более старую версию. В некоторых лентах стабильный выпуск стоит выше предварительной версии, которая на деле ушла дальше, — установка такого выпуска отбросила бы приложение назад.

Длинная ошибка в строке больше не сдвигает вниз остальной список. Она укладывается в две строки, полный текст показывается при наведении.

Добавлена поддержка ещё четырёх программ: WhatCable, Qoder IDE, Qoder и Yaak. Для каждой работают проверка обновлений и установка в один клик, а заметки о выпуске загружаются в окно как текст, а не как встроенная страница.

Две программы Qoder для Mac теперь различаются. IDE и настольная программа делят название и страницу загрузки, но выходят разными линейками версий, поэтому каждая теперь отслеживается отдельно.

Бета-сборки WhatCable и Yaak отслеживаются на собственном канале. У копии с бета-версией раньше не было вообще никакого источника, и она оставалась на «Ошибка»; теперь ей предлагается следующая бета, а заметки о выпуске отделены от заметок финальных версий. Для WhatCable сюда входит и финальная версия, в которую в итоге переходит бета, — приняв её, копия переходит на финальный канал.

Проверка ваших программ из App Store расходует долю прежнего трафика. Раньше при каждой проверке заново загружалась страница каждой программы из App Store; теперь страницы хранятся час, а магазин опрашивается обо всех ваших программах за несколько запросов вместо одного на программу. При интервале проверки в пять минут это примерно на треть меньше трафика в целом; при интервале по умолчанию в шесть часов страницы всё равно устаревают между проверками, поэтому там экономия меньше.

Повторная проверка одной программы больше не загружает заново все программы из App Store. Одно нажатие «Проверить снова» отбрасывало все сохранённые страницы, и следующая плановая проверка платила за все; теперь обновляется только та программа, о которой вы спросили.

Проверка программ, которые распространяются через GitHub, тоже расходует долю прежнего трафика. Раньше при каждой проверке заново загружалось полное описание каждого выпуска, даже если ничего не публиковалось; теперь у GitHub спрашивается, изменился ли выпуск с прошлого раза, и ничего не загружается, если не изменился. Раз в сутки каждый выпуск перечитывается целиком, поэтому отозванный выпуск обнаруживается в течение дня.

Программы на бета- или ночном канале GitHub теперь запрашивают один выпуск вместо страницы выпусков. Почти всегда ответом оказывается самый новый выпуск, и полная страница загружается только в те заходы, когда это не так.

Проверка обновлений Vorssaint больше не идёт через переадресацию. Репозиторий переименовали, и переход по старому имени молча переводил запрос на анонимный лимит GitHub; теперь проверка обращается сразу к новому имени.

Под капотом. Готовый выпуск теперь собирается, подписывается и нотаризуется на Mac, размещённом у GitHub, с происхождением сборки, которое может проверить любой, а в журнале запросов ответ из кэша отличается от ответа из сети.

Выгруженные журналы запросов больше не содержат имя вашей учётной записи. Для программ, установленных в домашней папке, в каждой строке был полный путь; теперь там ~ — каким бы способом вы ни выгрузили журнал.

Вкладка «Запросы» теперь сообщает, что в неё попадает, а что нет. Она записывает запросы, которые DuoUpdater делает сам. Страница с заметками о выпуске сама загружает изображения и шрифты, а обновления из App Store и Homebrew выполняют отдельные инструменты — ничего этого там нет, и теперь окно об этом говорит, а не оставляет вас догадываться.

«Скопировать URL» теперь экранирует адрес, который отдаёт. Пути с пробелом — среди них загрузки Firefox, Thunderbird и Bartender — копировались как есть: браузер это исправляет, командная строка — нет.

Строка бета-версии CapCut больше не сообщает о неудачной проверке. Между бетами — после того как одна становится финальной и до открытия следующей — разработчик ничего не публикует на этом канале. Это выглядело как красная строка и кнопка «Повторить», которая не могла сработать. Теперь строка просто не имеет ответа из этого источника, пока не появится следующая бета.

Audacity теперь показывает значок того, на чём оно построено. Приложение запускается через небольшой загрузчик, который передаёт управление настоящей программе рядом с ним, а значок считывался с загрузчика — а он не связан ни с чем.

Заметки о выпуске из App Store теперь приходят на вашем языке. Раньше они запрашивались на языке магазина по умолчанию, поэтому на Mac с китайским или японским языком они всё равно были английскими.

Собственные обновления DuoUpdater теперь отображаются под его собственным именем в окне «Сеть». Проверка версии, заметки о выпуске и загрузка значились там с пустым столбцом приложения.

Под капотом. Учётные данные внутри пути веб-адреса теперь удаляются до записи запроса — так же, как это давно происходит с данными в строке запроса.

Окно «Download Traffic» теперь называется «Сеть» и получило вторую вкладку. «Загрузки» — это прежний журнал: во что обошлось каждое обновление как файл. «Запросы» — новое: каждый запрос, который DuoUpdater делает за вас, ради чего он был, к какому приложению относился и сколько стоил, с полем фильтра, чтобы спрашивать журнал, а не пролистывать его. Цифры сверху отвечают на то, что вы отфильтровали, а не показывают итог за всё время.

Проверка обновлений Spotify почти не расходует сеть. Spotify нигде не публикует файл с версией, поэтому проверка читает её из двухмегабайтного установщика-заглушки — и каждый раз скачивала его целиком, круглые сутки. Теперь она сначала спрашивает, изменился ли файл, и не скачивает его, если нет.

PDF Expert теперь находит свои обновления и показывает, что изменилось. Он читал список выпусков, который разработчик перестал пополнять в 2022 году, и поэтому сообщал, что версия актуальна, какая бы ни была установлена. Теперь он следует тому списку, которым пользуется собственный механизм обновления приложения, и теперь показывает заметки и к прежним версиям, а не только к последней.

Предварительные сборки UTM теперь получают собственные обновления, устанавливаются одним нажатием и показывают соответствующие заметки о выпуске. Раньше предварительная копия сравнивалась с финальной веткой и молча получала ответ «установлена последняя версия»; теперь она следует своей линии, а получив финальный выпуск этой линии, возвращается на финальную ветку.

Под капотом. Записанные запросы переехали в то же хранилище, что и журнал загрузок, так что два учёта одной загрузки больше не могут разойтись. Существующий журнал переносится без изменений.

Ещё пятнадцать приложений под наблюдением, и все, кроме одного, обновляются в один клик. AgentsView, AnythingLLM, Chatbox, ChatGPT Classic, DSH Desktop, FluidVoice, GitHub Copilot, Kun, Meetily, Microsoft 365 Copilot, OpenLogi, OpenSuperWhisper, Paseo, T3 Code — на обеих ветках, alpha и nightly — и Vorssaint. Исключение — ChatGPT Classic: проверку мы берём на себя, но у него есть собственный установщик, который обновляет приложение сам, поэтому это обновление остаётся за вами.

Восемь приложений теперь показывают свои примечания к выпуску прямо в DuoUpdater, а не отправляют вас на веб-страницу. Xcode, Antigravity, Antigravity IDE, AnyDesk, AnythingLLM, Chatbox, Headlamp и Helium. У трёх из них отправлять было попросту некуда: страница AnyDesk отвечает проверкой на робота, авторы Helium не публикуют страницу с примечаниями вовсе, а у Antigravity IDE не было никакой ссылки.

Бета-версии Xcode рассказывают, что изменилось в каждой бете. Раньше в строке были только номер сборки и ссылка; теперь она показывает примечания Apple к вашей бете и ко всем предыдущим бетам того же выпуска.

Word, Excel, PowerPoint, Outlook и OneNote теперь замечают, что обновление установлено. Эти пять приложений продолжали предлагать заново открыть установщик, который вы уже завершили, и никогда не доходили до предложения перезапустить — ожидание и повторная проверка не помогали.

Строка, ожидающая перезапуска, снова объясняет себя — в обоих окнах. Когда приложение одновременно опережало то, что публикует поставщик, и ждало перезапуска, строка над кнопкой описывала совсем другое; для строк, ожидающих перезапуска после «Обновить всё», окно и меню к тому же противоречили друг другу.

Метки состояния больше не вытесняют имя приложения в русском языке. Заодно исправлены метки, заимствовавшие формулировки из несвязанных строк во всех переведённых языках.

Заметки о выпуске теперь появляются и для приложений, чей поставщик указывает только дату без времени. Раньше такие выпуски не оставляли следа нигде.

Страница заметок, которую мы отказываемся открывать, теперь называет причину. Раньше она оставалась пустой, что выглядело в точности как приложение, вовсе не публикующее заметок.

Заметки о ночных сборках WeChat DevTools больше не пустые.

Под капотом. Обработка версий и дат выпуска сведена в одно место, поэтому номер сборки уже не может быть прочитан как маркетинговая версия, а хронология выпусков больше не выдумывает время суток, которого поставщик не называл.

Неудачные проверки теперь видны и в окне. Для строки, проверка которой не удалась, окно не рисовало ничего — как и для тех, что вы скрыли, для пропущенных версий и для приложений, которыми управляют App Store, Toolbox или TestFlight. Выглядело это ровно так же, как «обновлений нет». Теперь оба окна говорят об одном приложении одно и то же, и кнопка повтора есть в обоих.

«Проверить снова» в любой строке спрашивает только про это приложение. Заодно заново считывается список запущенных приложений — это самый быстрый способ поправить зелёную точку, которая выглядит неверно.

Пропуск версии и скрытие приложения теперь отменяются из контекстного меню окна. Обе строки предлагали отменить это правым щелчком — в окне, меню которого ничего подобного не содержало.

Фоновая проверка больше не забирает заметки о выпуске, которые вы читаете. Ежечасная проверка выбрасывала все уже загруженные заметки, и открытая панель возвращалась к индикатору загрузки. Теперь всё начинается заново только по вашему запросу на обновление.

Прерванные загрузки проверяются, прежде чем считаться завершёнными. И серверу, приславшему файл заново целиком, и серверу, оборвавшему передачу раньше времени, верили на слово, а беда всплывала шагом позже — установкой из повреждённого архива. Загрузки через некоторые прокси, которые раньше не удавались никогда, теперь проходят.

Обновление одного приложения больше не перечитывает все приложения на диске. Каждое нажатие означало два полных обхода всех ваших программ ради одной, о которой вы спросили.

Заметки о выпуске Chrome больше не могут зависнуть. Обычного изменения оформления блога Google хватало, чтобы застопорить их на минуты; теперь они загружаются быстро, как бы страница ни выглядела.

Уже загруженный установщик больше не выбрасывается ради повторной загрузки. Когда поставщик записывал один и тот же выпуск двумя способами (v1.2.3 и 1.2.3), ожидающий пакет не опознавался, а «Перезапустить» могло ждать замену, которая уже произошла.

Неудачная установка с правами администратора больше не принимается за вашу отмену. Никакой ошибки не показывалось, и это приложение молча переставало предлагать обновление в одно нажатие, пока вы снова не запрашивали права администратора из меню его строки.

Зелёная точка «запущено» теперь замечает каждое приложение. О запуске или завершении некоторых программ macOS не сообщает вовсе, и их точка оставалась неверной, пока её не обновляло что-то постороннее.

Кнопка «Обновить всё» больше не мигает во время проверки, а приложение, обновлённое посреди проверки, не возвращается к предложению уже установленного обновления.

Если проверка не удалась в тот момент, когда вы нажали «Обновить», вам об этом скажут — вместо того чтобы записать это как «делать нечего».

Под капотом. Даты выпуска, записанные в необычных форматах, читаются правильно, проверка адресов страниц с заметками о выпуске охватывает все равнозначные написания, а рутинный учёт больше не обращается к диску каждый раз, когда на вашем Mac открывается или закрывается любое приложение.

Метка Docker теперь описывает интерфейс Docker, а не его фоновую службу. В строке значилось «нативное»; но Docker Desktop — приложение на Electron. Метка читается из бандла приложения, а бандл Docker — это оболочка: программа, которую он называет, — фоновая служба, написанная на Go, собственного фреймворка она не несёт, а приложение, которое на самом деле рисует окна, лежит уровнем внутри. Читалось всё правильно — просто не из того файла. Теперь DuoUpdater заглядывает во вложенное приложение, но только если внешнее само по себе ничего не даёт и содержит ровно одно такое приложение, которое доказывает, на чём оно построено; так что вспомогательный процесс, поставляемый рядом с настоящим интерфейсом, по-прежнему не может одолжить свою личность хозяину. Docker читается как Electron 42.5.0, и из ста сорока шести приложений в списке на машине, где это писалось, меняется только эта строка.

Заметки о выпусках CleanShot X снова читаются — в том числе для 5.0. CleanShot выпустил самое крупное обновление за годы и заодно перестроил страницу с описанием изменений: дата переехала выше номера версии, вокруг него появилось два новых слоя, а в функциональном выпуске между версией и списком изменений теперь вставлены вступление и две ссылки на видео. Правило чтения, которым пользовался DuoUpdater, перестало совпадать хоть с чем-нибудь из этого. Хуже пустой панели было то, что пустой она не выглядела: уже сохранённые заметки предыдущего выпуска остались на экране под заголовком нового — панель говорила «5.0» над изменениями 4.8.10, и нигде об этом не сообщалось.

Заметки, сохранённые до публикации выпуска, теперь перечитываются, а не принимаются на веру навсегда. Это вторая половина той же истории. DuoUpdater узнал о существовании 5.0 за шесть минут до того, как CleanShot опубликовал её содержание, сохранил страницу в том виде, в каком она была, и подшил её под 5.0 — и с тех пор каждая проверка находила уже сохранённое и больше не смотрела. Теперь сохранённые заметки один раз за сеанс подтверждаются у поставщика, прежде чем считаться окончательными, так что версия, чьи заметки пришли позже, дополняет себя при следующем открытии, а не остаётся неверной.

То, что вы открываете из строки меню, теперь открывается с первого щелчка. Выбор «Список изменений» в строке — или Настроек, или журнала релизов — в первый раз не делал ровно ничего и срабатывал только со второго щелчка. Повторное открытие меню снова превращало каждую попытку в «первую», так что для тех, кто открывает меню, щёлкает один раз и ждёт окно, это не работало никогда. Первый щелчок внутри меню уходил на то, чтобы вывести DuoUpdater вперёд, вместо того, на что он был нацелен. Открытое окно теперь ещё и удерживается впереди: его выводили вперёд и в тот же миг задвигали обратно — второй способ, которым всё это выглядело как щелчок без последствий.

Приложение, оставившее собственное имя пустым, теперь всё равно его получает. Eudic (欧路词典) стоял в списке со значком, с версией — и с пустотой там, где должно быть имя. Его бандл действительно объявляет отображаемое имя — и оставляет его пустым, потому что настоящие имена лежат в переводах самого приложения, — а DuoUpdater принимал этот пустой ответ за ответ, вместо того чтобы задать следующий вопрос. Теперь он переходит к другому имени приложения, а затем к имени самого файла приложения, так что ни одна строка не остаётся безымянной. Здесь это касалось одного приложения из ста пятидесяти; суть в том, что сведения всё это время были на месте, просто их пропускали.

Перезапуск теперь сообщает, что приложение отказалось завершиться, а не выглядит как нажатие, от которого ничего не произошло. Если у приложения открыто окно, которое вас ждёт — запрос на сохранение, форма входа, какой-нибудь диалог, — macOS не даст ему завершиться, и с этой стороны сделать нельзя ничего: это окно самого приложения. Раньше DuoUpdater крутился тридцать секунд, а затем без объяснений возвращал ту же кнопку — а это выглядит ровно как сломанная кнопка, и её нажимают снова. Теперь строка говорит, что произошло, и отправляет вас к приложению разобраться с этим окном. Ничего не изменилось, новая версия уже установлена, так что остался действительно только перезапуск — и если вы просто закроете приложение сами в ближайшие десять минут, DuoUpdater это заметит и вернёт его уже на новой версии, без единого нажатия с вашей стороны.

Примечания к выпуску 欧路词典 снова относятся к одному выпуску, а не к шестнадцати годам выпусков. Приложение публикует всю свою историю — каждую версию вплоть до 2.5.0 — внутри примечаний к тому выпуску, который оказался последним, поэтому панель подробностей показывала всё это под заголовком «26.9.0», и до того, что изменилось только что, приходилось прокручивать десятилетие. Теперь каждая версия получает в списке собственную запись — так же, как у всех остальных приложений.

Значок, показывающий, на чём сделано приложение, теперь требует для Tauri доказательства, а не сходства. Tauri не оставляет в бандле ничего, что можно найти, — ни фреймворка, ни собственной папки, — поэтому именно этот значок выводился из того, как приложение упаковано, плюс из того, что оно связывается с веб-представлением Apple. Longbridge подходит под всё это и при этом не Tauri: свои окна оно рисует тем же движком, что и Zed, а веб-представление встраивает лишь в один угол интерфейса. Теперь DuoUpdater, прежде чем это утверждать, читает из двоичного файла собственный отпечаток Tauri — так что приложение называется Tauri тогда, когда оно им является, а Longbridge читается тем, чем оно и есть: нативным приложением для Mac.

CapCut больше не краснеет из-за того, что у серверов ByteDance выдалась неудачная полусекунда. Точка доступа, у которой DuoUpdater спрашивает версию CapCut, отвечает кодом успеха, а затем примерно в одном случае из пятидесяти — объектом ошибки вместо ответа: это тайм-аут внутри собственной инфраструктуры ByteDance, около 390 байт там, где ожидалось 436 килобайт. С этой стороны отличить такое от того, что CapCut изменил форму своего ответа, было невозможно, и строка сообщала о неудачной проверке — а это читается как «сломалось, кто-то должен починить» применительно к тому, что само проходит со следующей попытки. Теперь эта конкретная форма распознаётся как то, чем она является: запрос немедленно повторяется, и о нём сообщают как о настоящей проблеме, только если он держится пять дней.

Каждое приложение в списке теперь говорит, на чём оно сделано. Строка приложения из App Store всегда несла значок магазина, а все остальные выглядели одинаково — приложение на Sparkle, приложение на Electron и нативное было не отличить. Теперь рядом с каждым именем стоит знак самой технологии: нажмите — увидите название и одну фразу, наведите — подсказку: Electron, Tauri, Flutter, Qt, Java, Chromium, Mac Catalyst, приложение для iPhone на Apple silicon или нативное приложение для Mac — вместе с версией среды там, где её можно прочитать как факт (Electron 42.4.1, Qt 6.2, встроенный в приложение Chromium, тот Tauri, на котором оно собрано). Всё это читается из самого пакета — фреймворка, который пришлось положить сборщику, среды, нужной запускающему файлу, библиотек, с которыми слинкован бинарник, — то есть это факт о том, что установлено, а не догадка по имени приложения. Когда длинное имя не оставляет места, знак уступает, а не выталкивает имя на вторую строку: строка принадлежит имени. Выключается всё это в Настройках → Основные.

LibreOffice больше не заявляет о переходе на версию, которая у вас уже стоит. Его индекс загрузок публикует версии из трёх частей (26.8.0), тогда как установленная копия сообщает о четырёх (26.8.0.3), и заполнение недостающей части нулём делало установленную копию новее — из-за чего в строке появлялась приглушённая заметка «поставщик отстал от вас» о приложении, которое было в точности актуальным. Источник, публикующий меньше частей, чем сообщает приложение, теперь читается как описание того же выпуска, а не более старого; настоящий откат по-прежнему называется своим именем.

Настройка, добавленная обновлением, теперь один раз указывает на себя. Новый параметр посреди окна настроек — это параметр, которого никто не найдёт. После обновления, которое его добавило, на шестерёнке в строке меню появляется синяя точка, на нужной странице — точка в боковом списке, и на самом элементе — пока вы на него не посмотрите. Только для тех, кто действительно обновился до него: новую установку не встречают точками на возможностях, которые для неё просто часть приложения.

Приложения на Electron, добавленные в прошлом выпуске, теперь действительно обновляются одним нажатием. В 0.3.75 DuoUpdater научился читать файл, который такие приложения носят внутри себя, — и он его читал: определял новую версию, нужную именно вашему Mac загрузку и контрольную сумму для её проверки. Только отправить всё это было некуда. Кнопка установки не появлялась никогда, а duo install объяснял отказ причиной, которая не была настоящей. В этом выпуске путь установки подключён. На практике вы можете не увидеть никакой разницы: это чтение стоит позади каждого написанного вручную правила, поэтому оно говорит только за приложение, которое больше ничем не покрыто, — а сегодня, на машине, где это собиралось, таких нет ни одного. Это важно для приложения, которое вы установите завтра и для которого правила ещё никто не написал.

Загрузка, которая увела бы вас с нативной сборки, теперь отклоняется. Apple Silicon по-прежнему может выполнять приложения Intel через трансляцию — значит, загрузка только для Intel проходила проверку «запустится ли это на вашем Mac» и устанавливалась без единой жалобы, оставляя вас с транслируемой копией приложения, которое до этого работало нативно; тихо, и повторяя то же самое при каждом следующем обновлении. Теперь любая установка на месте сравнивает то, что у вас есть, с тем, что пришло, и отказывается от такой замены. В обратную сторону, а также с универсальной сборки на сборку для Apple Silicon, — обычное дело и по-прежнему разрешено.

Когда доказать архитектуру загрузки нельзя, теперь следует отказ, а не догадка. Некоторые поставщики публикуют сборку для Apple Silicon рядом со своей загрузкой по умолчанию, и единственный способ понять, что по умолчанию идёт сборка Intel, — заметить, что существует вторая. Если эта вторая проверка не возвращается чисто — сервер поставщика её отклоняет, соединение обрывается, или обе расходятся в том, какая это версия, — DuoUpdater больше не принимает это молчание за ответ. Он сообщает версию и не предлагает установку; это честный исход.

Сломанное правило больше не может исчезнуть из «Диагностики». Для приложений, покрытых одновременно написанным вручную правилом и новым чтением — а таких большинство, и это сделано намеренно, — сбой правила гасился успехом чтения сразу следом, и приложение с действительно сломанным правилом продолжало выглядеть исправным. Теперь они записываются раздельно. Кроме того, новое чтение впервые сообщает о собственных сбоях: на машине, где это собиралось, три приложения указывали на адреса, которые уже некоторое время отвечают «не найдено», и до сих пор об этом ничто не говорило вслух.

Строки, которые видят обновление, но не могут его установить, теперь предлагают одно и то же в обоих местах. В строке меню показывалась кнопка «Открыть», открывавшая Finder, а в окне для той же строки не показывалось ничего.

Приложения на Electron теперь распознаются без того, чтобы кто-то заранее вносил их в список. Очень многие приложения для Mac носят внутри себя небольшой файл, где указано, где искать их обновления. До сих пор DuoUpdater знал только те, для которых кто-то вручную написал правило, — все остальные стояли в списке без номера версии, и сообщить вам о новой сборке было нечем. Теперь он читает этот файл напрямую, ровно так же, как всегда читал файл Sparkle. Благодаря этому подобное приложение оказывается охвачено в тот день, когда вы его установили, а не в тот, когда до него дошли руки.

Приложения, для которых правило уже было написано вручную, остаются как были. Новый способ чтения стоит позади них, поэтому он способен лишь закрыть пробел и никогда не перехватит то, что и так работало.

Правильность предлагаемой загрузки решают две детали, и обе выяснены на настоящих приложениях, а не приняты на веру. Одни поставщики помечают сборку для Intel как «основную» загрузку, хотя рядом публикуют и сборку для Apple Silicon; другие дают сборке для Apple Silicon имя файла, ничем не отличимое от интеловского, так что по имени ничего не понять. DuoUpdater выбирает по архитектуре, а там, где он не может быть уверен, что загрузка запустится на вашем Mac, он называет версию и не предлагает установку — вместо того чтобы вручить вам нечто, что установится без единой заминки, а потом не откроется.

Если вы пользуетесь бета-версией, релиз-кандидатом или ночной сборкой приложения, DuoUpdater всё это время незаметно следил не за той веткой. Он определяет вашу ветку, находя вашу сборку в списке выпусков самого разработчика, — но предварительная версия обычно сохраняет тот же публичный номер, что и стабильный выпуск, из которого она выросла, и для предварительной версии это совершенно обычное поведение. В итоге совпадение приходилось на стабильную запись. Ошибка была беззвучной: на экране ничего не выглядело неправильным, вы просто переставали узнавать о следующей сборке своей ветки, а показанные примечания к выпуску относились к стабильной линии. Это выяснилось, когда реальные предварительные сборки Supacode и TypeWhisper были установлены и проверены в деле; теперь обе следуют той ветке, на которой действительно находятся.

Бета CapCut показывала версию, которой у вас нет. В строке значилось «9.3.4545 → 9.4.0-beta6», тогда как сам CapCut, Finder и любой другой инструмент обновления называли вашу копию 9.4.0-beta5. Некоторые приложения записывают настоящую версию не в то поле, что большинство, и DuoUpdater со своей стороны стрелки читал более опрятное на вид значение, а со стороны разработчика — настоящее. Предлагаемое обновление всегда было верным: неверной была только подпись. Теперь обе половины строки берутся из одного места — и для CapCut, и для семи других приложений, устроенных так же.

MacWhisper, GitHub Copilot for Xcode, TypeWhisper и OpenUsage теперь показывают примечания к выпускам. У всех четырёх панель примечаний оставалась пустой: в их лентах обновлений примечаний нет вовсе, и это не замечали, пока каждую не сверили с тем, что разработчик публикует на самом деле. Теперь DuoUpdater читает собственную страницу примечаний MacWhisper, файл изменений Copilot и сайт изменений TypeWhisper, а OpenUsage направляет к его списку выпусков.

Helium теперь обновляется через собственную службу обновлений, что даёт бета-канал и заметно меньшие загрузки. Раньше он отслеживался по публичному списку выпусков, где появляются только стабильные сборки, — то есть тем, кто пользовался бетой Helium, выдавалась стабильная версия. Собственная служба публикует ещё и патчи, поэтому обычное обновление весит около 40 МБ вместо повторной загрузки на 124 МБ. Проверено на стабильной и на бета-сборке, а загрузка сверяется с ключом подписи внутри вашей установленной копии, прежде чем что-либо будет заменено.

Бета-, developer- и nightly-выпуски Firefox и Thunderbird теперь отслеживаются как надо — до сегодняшнего дня ни одна из этих пяти линий выпуска ни разу не сообщила об обновлении. Их читали из открытого файла версий Mozilla, где публикуется только та версия, которую вам показывают, а при установке беты «b5» с неё срезается: бета Firefox весь цикл называет себя 155.0, так что единственный задаваемый вопрос звучал как «155.0b5 новее, чем 155.0?», и ответ — нет. С nightly было ещё хуже: Mozilla выпускает по одной каждый день, и все они называются 157.0a1, поэтому четырёхнедельный цикл не давал ровным счётом ничего. Теперь DuoUpdater обращается к собственной службе обновлений Mozilla — по тому же адресу, которым пользуется встроенный апдейтер Firefox и который приложение хранит внутри себя, — и сравнивает идентификатор сборки, который есть у обеих сторон. Перед выпуском это сверили с настоящими загрузками по всем пяти линиям: идентификатор, который сообщает эта служба, побайтно совпадает с тем, что лежит внутри вашей копии; бета, отставшая на одну сборку, теперь показывает обновление, и nightly, собранный раньше в тот же день, тоже. Стабильный выпуск и ESR никогда не были затронуты и остались без изменений. Одно ограничение стоит назвать прямо: эта служба не публикует дату выпуска, поэтому для этих пяти линий журнал релизов по-прежнему фиксирует, когда DuoUpdater впервые увидел сборку, а не когда её выпустила Mozilla.

Wispr Flow, AionUi и Devin теперь обновляются в один клик, а не просто сообщают, что вышла новая версия. Все три и раньше видели свои обновления, но ни одно не могло его применить — с формулировкой, что поставщик выпускает отдельные сборки для Intel и Apple Silicon, а у DuoUpdater нет способа выбрать нужную. Проверка вместо предположения показала, что причина не выдерживает: конечные точки, из которых читаются эти три приложения, и так предназначены для Apple Silicon, а сам DuoUpdater работает только на Apple Silicon — выбирать было не из чего. Каждую загрузку получили и проверили до того, как подключить: внутри нужное приложение, подписанное тем же разработчиком, что и ваша копия, заверенное Apple, а у AionUi — ещё и сверенное с контрольной суммой, которую публикует его собственный манифест. Затем каждое действительно установили поверх более старой копии и убедились, что оно вернулось на новой версии.

Grok Bot теперь отслеживается — новые версии и обновление в один клик. Настольное приложение xAI собирает и подписывает Anysphere, компания, стоящая за Cursor, и обновляется оно через собственный сервис выпусков Cursor. Именно поэтому ни один из обычных путей не отвечал за него: нет ленты Sparkle, нет карточки в App Store, нет публичного репозитория релизов, а cask в Homebrew возвращает обновление самому приложению. Вместо этого DuoUpdater читает собственную конечную точку версии у поставщика. Были ещё две, и обе оставлены в стороне по названным причинам: та, что за кнопкой загрузки на x.ai, вообще не публикует номер версии, а та, которой пользуется собственный апдейтер приложения, отвечает пустым телом, когда у вас уже актуальная версия, — молчание, неотличимое от сломанной конечной точки. Загрузку проверили до того, как её подключить: в образе диска лежит нужное приложение, подписанное тем же разработчиком, что и ваша копия, и заверенное Apple. Одного он намеренно не предлагает — примечаний к выпуску: xAI не публикует их для этого приложения, а единственный changelog, который есть, относится к другому продукту.

Comet и Msty Studio теперь тоже обновляются в один клик, а новая проверка следит за приложениями, которые могли бы, но не обновляются. Это были последние двое из той группы, кто видел обновления, но не мог их применить, — и ни одному не понадобилось ничего нового: достаточно было внимательнее посмотреть, что именно присылает поставщик. Ссылка на загрузку Comet подписана и живёт час, поэтому кнопка обновления указывает на собственный шлюз Perplexity, а ссылка создаётся в момент нажатия, а не часами раньше, при проверке. Msty публикует четыре загрузки в одном файле, версия для Intel идёт первой, и отпечаток для проверки загрузки брался именно из этой первой записи; теперь он привязан к той сборке для Apple Silicon, которая действительно скачивается, — а заодно выпуск, вышедший между проверкой и нажатием, в большинстве случаев будет замечен, а не установлен молча. Обе загрузки перед выпуском были скачаны и проведены через настоящие установочные заслоны. Более общий вывод не касается ни того, ни другого приложения: ничто в DuoUpdater не могло заметить, что приложение осталось только для обнаружения по причине, которая давно перестала быть верной. Теперь ночной обход рецептов сообщает, когда приложение, за которым мы лишь наблюдаем, уже протягивает нам установщик.

QQ音乐 теперь отслеживается — новые версии, обновления одним кликом и его заметки о выпуске прямо в окне приложения. Ни один из обычных путей не отвечал за него. Он не публикует Sparkle-поток и вообще не несёт фреймворка Sparkle; его cask в Homebrew возвращает обновление самому приложению; а конечная точка обновлений, которую называет по имени его собственный бинарник, отвечает 200 и пустым телом на всё, что бы мы её ни спросили, — молчание, неотличимое от сломанной конечной точки, поэтому её оставили в стороне. Вместо неё DuoUpdater читает файл данных, из которого строится собственная страница загрузки поставщика: эта страница отдаётся пустой оболочкой и заполняется из этого файла — он же единственное место, где вообще существуют заметки о выпуске: нет ни блога, ни appcast, ни отдельной страницы на каждую версию. Поэтому заметки читаются прямо из него и отображаются в собственном окне DuoUpdater, а обновление устанавливает нотариально заверенный образ диска, названный в том же ответе. Одна ловушка стоит того, чтобы её записать: этот файл до сих пор несёт рядом с текущей записью вторую, шестилетней давности запись для Mac, поэтому оба правила опираются на версионированное имя файла загрузки для Mac, а не на само слово «Mac». И одно ограничение стоит назвать прямо: файл публикует ту версию, которую вам показывают, но никогда — номер сборки под ней, поэтому переупаковка версии, сохранившей своё имя, здесь невидима. Приложение не выдумывает обновление, которого нет, — оно просто не способно увидеть этот один тип.

TimeMachineEditor теперь отслеживается — новые версии и обновления одним кликом. Ни один из обычных путей не отвечал за него: нет ленты Sparkle (в приложении нет ни адреса ленты, ни фреймворка, который мог бы её использовать), нет карточки в App Store, нет публичного репозитория релизов, а cask в Homebrew возвращает обновление самому приложению. Зато у него есть небольшой сайт поставщика, единственная ссылка на загрузку которого называет версию прямо в своём тексте, — та же страница, прочитанная тем же способом, на который опирается собственная проверка версии в Homebrew, так что это та поверхность, которую и подразумевал поставщик, а не догадка. Обновление устанавливается как собственный пакет установщика поставщика, а не как простая замена приложения, и это сделано намеренно: загрузка также кладёт снаружи самого приложения фоновый планировщик, инструмент командной строки и launch daemon, поэтому замена одного лишь приложения оставила бы новую копию рядом с устаревшим планировщиком, и ничто не заметило бы несовпадение.

Little Snitch теперь отслеживается — и на стабильных, и на ночных релизах. Object Development публикует файл версии, на который опирается собственный апдейтер приложения, — тот же файл читает Homebrew, — и DuoUpdater читает его напрямую, потому что Little Snitch не публикует ленту Sparkle, а его cask возвращает обновление самому приложению. Оба релиза несут одну и ту же идентичность, из-за чего их обычно невозможно отличить друг от друга; но этот выдаёт себя в самой строке версии: ночная сборка пишет слово полностью («6.5 nightly (7301)»), тогда как стабильная сборка читается как простое «6.4.1». Стоит сказать прямо, чего это намеренно не делает: оно не устанавливает обновление за вас. Little Snitch запускает вместе с приложением системное расширение и привилегированную фоновую службу, а сохранится ли это в целости при простой замене приложения — не проверялось на настоящей машине, поэтому DuoUpdater сообщает вам, что вышла новая версия, и отправляет вас к собственной загрузке поставщика, вместо того чтобы гадать с сетевым фильтром.

Carbon Copy Cloner теперь отслеживается, и он не станет пытаться перевести вас между старшими версиями. Bombich одновременно поддерживает живыми три поколения — CCC 5, 6 и 7 — и все они сообщают системе одну и ту же идентичность, из-за чего вопрос «есть ли что-то новее?» оказывается хитрее, чем кажется: 7.1.6 действительно сортируется выше 6.1.13, но переход между ними — это отдельная покупка, а для CCC 7 нужна более новая macOS, чем та, что вообще может стоять на машине с CCC 5. Ответ по одному лишь номеру версии говорил бы каждому владельцу CCC 5 и 6, что его ждёт бесплатное обновление, — вечно, и каждый раз неверно. Поэтому DuoUpdater читает каждое поколение с его собственного адреса и предлагает только следующий релиз внутри того самого поколения, которое у вас действительно установлено. Бета-релизы тоже подхватываются — для тех, кто включил их прямо внутри CCC. Пока это только обнаружение — CCC устанавливает рядом с приложением привилегированный помощник, а это более серьёзная заявка, чем уже имеющиеся здесь обновления в один клик, — и стоит записать, почему раньше эти обновления вообще не были видны: собственная лента обновлений приложения успешно отвечает на каждый запрос совершенно пустой страницей.

Обновление, которое ваш Mac на самом деле не может запустить, больше не загружается и не устанавливается. Каждый бандл приложения указывает самую старую macOS, на которой оно запустится, а некоторые поставщики называют и самую новую — «эта сборка не для настолько новой ОС», это именно то, как приложение, ещё не угнавшееся за macOS 27, об этом сообщает. DuoUpdater не читал ни то, ни другое. Для приложений, отслеживаемых через ленту Sparkle, нижняя граница уже соблюдалась, но таких меньшинство: среди приложений на типичном Mac те, что читаются из собственной конечной точки поставщика или из релизов GitHub, составляют большую половину, а релиз GitHub вообще нигде не публикует требование к macOS. Так что приложение, ушедшее на более новую macOS, чем ваша, могло быть предложено, полностью загружено, подставлено на место — а затем просто не открыться. Теперь DuoUpdater читает это требование прямо из загруженного приложения, рядом с уже существующей проверкой того, что оно собрано под ваш процессор, и отказывается от замены, вместо того чтобы заменить рабочую копию той, что не запустится. Верхняя граница, названная поставщиком, тоже соблюдается там, где её публикует лента, поэтому сборка, которую разработчик пометил как не предназначенную для вашей macOS, вообще не предлагается. Три ограничения стоит назвать прямо. Чтение требования из загрузки означает, что загрузка уже состоялась, — это предотвращает сломанную установку, а не сам трафик, потому что для большинства приложений раньше спросить попросту негде. Приложение, чью новейшую версию ваш Mac не может запустить, будет и дальше показывать это обновление и дальше отказываться его устанавливать; отказ теперь называет нужную версию macOS, но DuoUpdater пока не запоминает этот ответ и не перестаёт предлагать обновление. И проверка охватывает только те пути, где DuoUpdater сам подставляет бандл приложения на место: пакет установщика передаёт файл macOS, которая сама следит за требованиями пакета, а Homebrew и App Store сами выбирают нужные им сборки; приложения, пришедшие из раздела App Store для iPhone и iPad, пропускаются намеренно, поскольку указанная в них версия — это версия iOS, и сравнивать её с macOS было бы хуже, чем вовсе не проверять. Одну вещь это пока не проговаривает вслух: там, где разработчик пометил сборку как не предназначенную для вашей macOS, это обновление попросту не предлагается, а приложение читается как актуальное, вместо того чтобы объяснить почему. Для более старого Mac это само собой разрешается в день, когда вы обновите macOS. Для Mac, который слишком новый, — нет, и здесь причитается ответ получше, чем молчание.

百度网盘 теперь отслеживается — новые версии, обновления одним кликом и его заметки о выпуске прямо в окне приложения. Ни один из обычных путей не был открыт. Он не публикует Sparkle-поток; Homebrew cask ничего не знает о копии, установленной вручную; а манифест обновлений, который его собственный бандл называет по имени, перестал отвечать — этот файл, его arm64-версия и каталог, в котором лежит всё это, возвращают 404. Поэтому DuoUpdater читает конечную точку, на которой построена собственная страница загрузок поставщика, и устанавливает нотариально заверенный образ диска arm64, указанный в том же ответе. Заметки о выпуске приходят тем же путём: на странице «版本更新» есть вкладка Mac版, но сама страница отдаётся пустой и заполняется из API, поэтому DuoUpdater читает этот API напрямую и показывает в своём окне последние сорок релизов. Одно ограничение стоит назвать прямо: этот поток публикует ту версию, которую вам показывают, но никогда — номер сборки под ней, поэтому переупаковка версии, сохранившей своё имя, здесь невидима. Приложение не выдумывает обновление, которого нет, — оно просто не способно увидеть этот один тип.

Проверка, которая не прошла, теперь так и говорит, вместо того чтобы показывать пустоту. У приложения, версию которого может назвать только собственная конечная точка поставщика, был один способ сказать «нет ответа»: пустое тире — точно так же выглядит и приложение, которое вообще ничем не охвачено. Поэтому истечение времени ожидания у конечной точки поставщика или её переезд читались ровно как «DuoUpdater не отслеживает это приложение» — вердикт, выглядящий постоянным, без предложенной кнопки Повторить и без места в счётчике «приложения не проверены». Теперь это неудачная проверка, чем она и является: кнопка Повторить, место в счётчике и названная причина. Намеренно не всё: положение, с которым ваш Mac попросту ничего не может поделать, — нет рецепта для трека выпуска, на котором вы сидите, конечная точка требует идентификацию, которой у этой машины нет, — по-прежнему остаётся тем же тихим тире, каким было всегда, а проверка, три раза подряд закончившаяся неудачей, всё равно выходит из баннера, а не закрепляется в нём навсегда. Приложение, которое устанавливает JetBrains Toolbox, тоже сохраняет свою кнопку «открыть Toolbox», когда чтение версии за ней проваливается, — ведь открыть Toolbox было ответом в любом случае.

Напоминание «перезапустите, чтобы применить» теперь исчезает, как только вы перезапустились. Когда собственный апдейтер приложения загружал сборку в фоне, DuoUpdater сообщал вам об этом и предлагал в уведомлении кнопку Перезапустить. Нажатие её срабатывало — приложение возвращалось на новой сборке и говорило «Теперь запущена версия 1.0.» — но напоминание, которое оно заменило, оставалось лежать в Центре уведомлений под ним, по-прежнему прося перезапустить то, что вы только что перезапустили. DuoUpdater следил за тем, когда напоминание перестанет быть актуальным, а момент, в который он это проверял, был как раз тем моментом, который уже был учтён. Теперь он убирает напоминание, как только не остаётся ожидающего перезапуска, — это заодно убирает и то, что оставило приложение, применившее собственное обновление, пока DuoUpdater не был запущен.

Приложения, которые выпускают много сборок под одним номером версии, теперь везде обрабатываются правильно. Приложение для Mac несёт две версионные строки: ту, что оно вам показывает («1.0»), и номер сборки, который действительно растёт. Большинство приложений меняют обе. Некоторые меняют только сборку: Amp выпустил за один день десять сборок, и все они назывались 1.0; Surge выпустил четыре отдельных релиза под номером 6.9.0; предварительные сборки JetBrains делают то же самое. DuoUpdater решал вопрос «изменилось ли это?», сравнивая показываемую версию примерно в дюжине мест, а для таких приложений это сравнение способно ответить только «нет» — или, там, где спрашивалось «это одно и то же?», только «да», — что бы на самом деле ни произошло. Дальше идёт то, что это ломало. Это одна-единственная ошибка, обнаруженная потому, что Amp сделал её видимой.

Перезапуск больше не выглядит зависшим на три минуты, а затем не сообщает о сбое, которого не было. Нажатие Перезапустить у приложения, чей собственный апдейтер уже держал наготове сборку, крутило спиннер три минуты, а затем говорило, что попытка провалилась, — хотя на самом деле обновление применилось за секунду-две, и приложение уже успело открыться заново на новой сборке. DuoUpdater ждал у показываемой версии изменения, которое просто не должно было наступить. На Amp это измерили: 189 секунд спиннера ради замены, занявшей меньше секунды. Теперь это укладывается в куда меньше секунды, а настоящий сбой по-прежнему сообщается как сбой.

Перезапуск больше не предлагает вам сборку, которая уже устарела. Когда апдейтер приложения уже загрузил одну сборку, а разработчик с тех пор опубликовал другую, DuoUpdater всё равно предлагал Перезапустить — так что вы перезапускались и сразу же оказывались на сборку позади, а ведь именно это должна была предотвращать эта проверка. Теперь такие строки вместо этого предлагают Обновить, что подтягивает актуальную сборку.

Пропуск версии больше не заставляет приложение молчать навсегда. Вот это стоит знать особо. «Пропустить эту версию» должно отклонять один релиз и пропускать следующий. Оно записывало только показываемую версию, поэтому для приложения, которое сохраняет одно имя версии между сборками, однократный пропуск отклонял каждый будущий релиз — постоянно, переживая перезапуски, и на экране не было ничего, что говорило бы, что приложение замолчало. Теперь пропуск записывает ту сборку, которую он отклонил. Одно следствие этого исправления: версия, пропущенная более старой версией DuoUpdater, будет предложена вам ещё раз, потому что старая запись не может сказать, какую сборку она имела в виду. Пропустив её заново, вы запишете это уже правильно.

Откат снова доступен для обновлений, которые выглядели так, будто ничего не изменили. Верстак скрывает откат, который ничего бы не сделал, — а для этих приложений каждый откат выглядел именно так, будто он ничего не сделает, поэтому строка исчезала после настоящего обновления, хотя на диске лежала полная резервная копия, до которой не было способа добраться.

Напоминание о перезапуске снова объявляется один раз на сборку — и переживает публикацию разработчиком ещё одной. В 0.3.69 напоминание, повторявшееся каждые пять минут, заменили на такое, которое говорит один раз за подготовленную сборку, — но сборку в нём определяли по имени, поэтому для таких приложений оно объявляло первую сборку, а затем молчало по поводу каждой следующей. Это исправлено. Отдельно: если приложение отказывается закрываться из-за несохранённой работы, DuoUpdater хранит заметку, чтобы открыть его снова, как только вы ответите. Раньше эта заметка выбрасывалась, если разработчик публиковал ещё одну сборку, пока вы раздумывали, — и приложение оставалось закрытым после замены, и ничто не открывало его снова. Теперь она следует за новой сборкой.

Неудачное обновление из App Store больше не тихо записывается как успешное, а загруженный пакет установщика больше не считается тем, что сейчас предлагается, если это более старая сборка. Оба случая происходили из одного и того же сравнения. История релизов тоже засчитывала десять сборок приложения как один релиз; отныне они считаются отдельно, хотя уже записанную историю восстановить нельзя.

Сама строка теперь говорит, какую сборку применит перезапуск. Она читалась как «1.0 → 1.0» — строка, не называющая никакой разницы. Теперь она читается как «1.0 (129) → 1.0 (130)», и только тогда, когда изменилась именно сборка; там, где имена версий уже отличаются друг от друга, строка не меняется. То же исправление коснулось подсказок у Перезапуска, уведомления, заметки, объясняющей, почему установка была отложена, и отказа duo install.

微信输入法 и 豆包输入法 снова можно обновлять одним кликом — и обновляются они именно так, как обновляют себя сами. Обновление методов ввода одним кликом было отозвано в 0.3.25 в тот же день, когда вышло, после того как у кого-то пропали настройки метода ввода. Проблема была в форме установки: она заменяла всё приложение целиком, как это делает установщик при первой установке. Метод ввода регистрируется в macOS по расположению своего приложения, а оба этих приложения обновляют себя, не трогая это расположение, — они сохраняют само приложение и меняют лишь то, что внутри него. Теперь DuoUpdater делает то же самое, поэтому после обновления зарегистрированное приложение остаётся тем же самым приложением, а сбой на любом этапе оставляет ту копию, которую вы запускали, ровно там, где она была. И ни то, ни другое больше не просит ваш пароль.

Перед тем как обновить любое из них, сначала копируется всё, чему они успели научиться. Ваш словарь, ваши настройки и состояние учётной записи живут не внутри приложения, поэтому копия для отката, которую DuoUpdater уже хранил, не могла отвечать за них. Теперь перед каждым обновлением метода ввода с них снимается снимок, который возвращается вместе с откатом, а сама копия обходится почти бесплатно — 578 МБ одного из них занимает десятую долю секунды и почти не расходует место на диске. Это скорее страховочная сеть, чем исправление: то, что приложение решит сделать с вашими данными при следующем запуске, — это код самого приложения, и этому ничто не может помешать. Но теперь есть, к чему вернуться.

Обновление больше не отнимает у приложения тайком возможность обновлять само себя. Когда DuoUpdater требовались права администратора, чтобы заменить приложение, он восстанавливал, кому принадлежит приложение, но не разрешения, с которыми оно было установлено, — а загруженная копия обычно распаковывается с более узкими разрешениями, чем те, что задаёт установщик. Для обоих методов ввода это разница между тем, способен ли их собственный апдейтер завершить следующее обновление, и тем, что он не может убрать за собой. Теперь разрешения, с которыми приложение было установлено, переносятся на копию, которая приходит ему на замену.

DuoUpdater перестаёт просить вас перезапускать одно и то же приложение каждые пять минут. Приложение, которое обновляет само себя, кладёт новую версию на диск и ждёт, пока вы его закроете. DuoUpdater замечал это при каждой проверке и каждый раз выпускал напоминание заново, поэтому сборка, которую вы решили пока не перезапускать, продолжала докучать вам столько, сколько вы её оставляли. Теперь каждая сборка объявляется один раз: перезапустите её, пропустите или проигнорируйте приложение — и оно останется тихим, а следующая сборка объявит о себе как обычно.

Приложение, ожидающее перезапуска, теперь считается обновлением, а игнорируемое — вообще не считается. Новая версия, уже лежащая на диске, и есть обновление — она просто загрузилась заранее, — поэтому теперь она учитывается в значке и в строке «N обновлений», а не в отдельном счётчике рядом с ними. С игнорируемыми приложениями было наоборот: приложение, которое вы проигнорировали, могло зажечь значок, хотя его строка показывала приглушённый ярлык «Игнорируется» и не давала никакой кнопки нажать, — так что число указывало на то, на что вы не могли повлиять. Теперь «игнорировать» и «пропустить» означают одно и то же на всех трёх поверхностях — в напоминании, в значке и в списке.

搜狗输入法 теперь отслеживается — DuoUpdater спрашивает его собственный апдейтер, а не читает сайт. Страница со списком изменений Sogou публикует версии из трёх сегментов, тогда как установленная копия несёт четыре, поэтому сравнение с ней потребовало бы сперва обрезать настоящую версию. Собственная проверка обновлений отвечает в родной нумерации бандла. DuoUpdater обращается к этой конечной точке так же, как это делает само приложение, и читает из неё релиз целиком, все четыре сегмента, поэтому переиздание, меняющее только последний из них, становится видимым. Это только обнаружение: апдейтер Sogou делает намного больше, чем просто меняет приложение, — он заново регистрирует генератор QuickLook, переносит ваши данные на новое место и принудительно завершает метод ввода, — поэтому само обновление по-прежнему остаётся за ним. Ещё одна вещь, которую стоит знать, и это особенность самого Sogou, а не наша: их конечная точка отвечает в зависимости от версии macOS, которая спрашивает, и Mac на macOS 28, спрашивающий сам за себя, получает в ответ сборку из 2023 года. DuoUpdater не спрашивает от своего имени, поэтому на каждом Mac вам показывается актуальная версия.

Заметки о выпуске, которые более позднее исправление прочитало бы правильно, теперь перечитываются, а не остаются неверными навсегда. Заметки кэшируются по версии, исходя из того, что заметки уже вышедшей версии не меняются. Это верно для самих заметок, но не для того, что DuoUpdater умеет из них извлечь, поэтому приложение, чьи заметки вышли искажёнными, оставалось таким для этой версии, сколько бы исправлений парсинга ни выходило потом. Теперь каждая запись в кэше хранит, каким поколением логики извлечения она была написана, а запись, написанную более старым поколением, загружают заново. Так поступают оба кэша — и для журналов изменений приложений, и для заметок формул Homebrew.

Проверка, провалившаяся на чьём-то CDN, теперь переспрашивается ещё раз, прежде чем считаться сломанной. 502, 503 и 504 означают, что промежуточный узел не смог достучаться до сервера за собой: запрос попросту не дошёл, поэтому тот же самый запрос мгновением позже обычно срабатывает. Проверка Headlamp умерла ровно на этом — GitHub ответил 504 вообще без заголовка ограничения частоты запросов. Теперь для этих трёх кодов делается один повтор — спустя восемь десятых секунды. Намеренно только для этих трёх: 500 означает, что отказал сам сервер, и повтор в большинстве случаев просто воспроизведёт тот же отказ, а повтор при ограничении частоты тратит как раз тот бюджет, на нехватку которого оно и жалуется.

Заметки о выпуске формулы Homebrew теперь следуют за той версией, которой принадлежат. Заметки запоминались по формуле, а не по версии, поэтому стоило заметкам однажды загрузиться, каждый следующий взгляд на формулу до конца сессии показывал заметки той самой первой версии — даже после появления более новой. Их чтение к тому же занимало ту же очередь, которую ждал весь остальной список формул, так что медленный brew info мог застопорить список вокруг себя.

Щёлкните правой кнопкой по приложению в боковой панели Workbench, чтобы его открыть. То же самое «Открыть», которое всегда предлагали строки в строке меню, — теперь и в окне, где вам это, вероятнее всего, и нужно.

Отказ от загруженного установщика забирает с собой и оставленную им ошибку. Выбрасывание подготовленного пакета уже возвращало строку в состояние «Обновить», но красная ошибка от только что отменённой попытки оставалась висеть на ней — и ничто никогда не убрало бы её, ведь ошибка снимается только тогда, когда строка становится актуальной, а строка, всё ещё предлагающая обновление, этого никогда не сделает. Теперь она уходит вместе с загрузкой.

duo, необязательный компаньон для командной строки, перестаёт неточно описывать сам себя. --timeout исчез — он принимался, документировался и никем не читался. --budget впервые задокументирован, и единственное сообщение, которое его упоминает, теперь называет настоящее число минут, а не всегда «15». --max-calls заявлял значение по умолчанию 20, хотя на деле это 6. Числовому флагу, которому передали не число, теперь сообщается об ошибке: duo verify --max-concurrency 1x раньше просто игнорировался и заменялся значением по умолчанию — четыре, что прямо противоположно тому, чего хочет человек, намеренно замедляющий проверку. И duo verify теперь считает запросы, которые реально были сделаны: канал, ответивший 502 и успешно сработавший при повторе, больше не отчитывается чистым ok, втихомолку спросив на самом деле дважды. -h работает везде, где работает --help.

Ещё четыре приложения теперь отслеживаются, ещё два канала выпуска, и каждое из них обновляется на месте. CapCut, Canva и WorkBuddy — на обоих сайтах, с которых они распространяются: международный и китайский ведут независимые линии релизов, поэтому установке предлагаются только версия и заметки, принадлежащие именно её собственному сайту. Termius и VSCodium получают свои каналы Beta и Insiders в дополнение к уже охваченным стабильным сборкам. Второй трек CapCut — самый неудобный: он выбирается переключателем внутри самого CapCut и никак не отражается в номере версии, поэтому то, на каком треке вы находитесь, читается из копии на диске, а не угадывается по той сборке, которую вы случайно запустили. Стоит знать, если вы включаете этот переключатель: DuoUpdater предложит вам самую новую бету, как только она появится, а это может опережать ту точку, до которой вас довёл бы собственный поэтапный выкат обновлений CapCut.

Каналы предварительных версий Android Studio больше не предлагают вам сборку старше той, что у вас уже есть. Google перечисляет свои релизы в порядке публикации, а не по версии, и DuoUpdater перебирал этот список три раза по отдельности — один раз ради версии, один раз ради даты, один раз ради загрузки, — поэтому кандидат в релизы, опубликованный позже более новой canary-сборки, мог отдать версию из одной записи, а файл — из другой. 26 августа канал Canary ответил версией 2026.1.4 RC 2, хотя 2026.2.1 Canary 2 уже вышла. Теперь оба этих ответа обязаны приходить из одной и той же записи.

Переизданный релиз больше не устанавливает копию, которую он должен был заменить. Когда проект пересобирает релиз, не меняя его версию, оба файла остаются под одним и тем же тегом — KeePassXC публикует KeePassXC-2.7.11-1-arm64.dmg рядом с исходным KeePassXC-2.7.11-arm64.dmg, — и DuoUpdater брал тот, что был перечислен первым. Этот порядок алфавитный, и в этот раз он случайно поставил пересборку первой, а в следующий раз поставил бы её последней. Внешне это никак не было заметно: версия в строке была правильной, ошибался только файл за ней. Теперь верный файл выбирается по тому, что говорит само имя файла.

Ночные и снапшот-сборки теперь распознаются как те предварительные сборки, которыми они и являются. Ночная сборка VLC, снапшот KeePassXC и ночная сборка Freelens — все они устанавливаются под именем и идентификатором бандла стабильного приложения, поэтому единственное, что их выдаёт, — это строка версии, а её как раз и не читали. Они засчитывались как стабильные установки, а именно так ночная сборка в итоге получает предложение перезаписать себя обычным релизом. Ночная сборка DB Browser for SQLite по той же причине читается из собственного имени файла приложения, и там проблема была реальной, но скрытой: её замороженная версия сортируется выше текущей стабильной только до тех пор, пока стабильная не догонит её, а после этого каждая установка с ночной сборкой тихо получила бы стабильную сборку.

Перезапуск приложения теперь сообщает о том, что произошло на самом деле. Несколько приложений несут внутри собственного бандла второе приложение — например, Surge хранит там свою панель Dashboard, — и когда перезапустить требовалось только этому внутреннему приложению, DuoUpdater сообщал, что перезапущено внешнее приложение, хотя ничего не происходило. Теперь он сообщает о результате именно внутреннего приложения и больше не выдаёт уведомление о перезапуске для перезапуска, которого на самом деле не было.

Обновление, которое уже загрузилось, теперь сообщает об этом, и его можно вернуть обратно. Строка с уже полностью загруженным пакетом установщика показывала синюю кнопку «Установить» — и ничего больше: ничто не говорило, что загрузка уже завершена или что кнопка заново откроет установщик, а не начнёт обновление с нуля, и не было способа передумать. Теперь это видно прямо в строке, а не спрятано в подсказке, а пункт «Удалить загруженный установщик» в контекстном меню строки выбрасывает загрузку и возвращает строку в состояние «Обновить». Отмена загрузки во время уже идущей установки того же приложения раньше могла заодно выбросить пакет, который только что закончил загружаться, — теперь так уже не получится.

Кнопки заметок о выпуске, которые вели на упразднённые страницы, снова открывают действующие. Microsoft переименовала корпоративные страницы заметок о выпуске Edge, а Termius перенёс свой список изменений, поэтому три канала Edge и Termius отправляли вас на страницу, которой больше не существовало. Раньше никто и никогда не проверял, остаются ли эти страницы на месте, поэтому они могли сколь угодно долго протухать, пока всё остальное выглядело здоровым, — теперь их проверяют по расписанию. У канала Edge Dev кнопки вообще не будет: Microsoft перестала публиковать для него заметки, а все страницы, которые всё ещё существуют, принадлежат другой линии релизов.

Raycast теперь отслеживается вплоть до версии 2 — но только на тех Mac, которые способны её запустить. Raycast 2 требует macOS Tahoe и Apple silicon. Mac, который этому не соответствует, остаётся на линии версии 1 и больше не узнаёт о релизе, который он всё равно никогда не смог бы установить. Теперь у обеих линий свои собственные заметки о выпуске, поэтому установка версии 1 читает историю именно версии 1, а не версии 2.

Заметки о выпуске теперь отображаются в собственном окне DuoUpdater для большего числа приложений. BetterDisplay — на всех трёх его треках, Shotbase и WorkBuddy — на обоих сайтах. Заметки BetterDisplay больше не заканчиваются сырой разметкой его кнопки загрузки и больше не повторяют список участников проекта в каждом отдельном релизе.

duo, необязательный компаньон для командной строки, теперь отказывается принимать командную строку, которую не понимает. Опечатанный флаг раньше просто игнорировался, а проигнорированный флаг выглядит так, будто вы его и не передавали, — поэтому duo verify --githubb тихо проверял вообще все рецепты вместо того одного, который вы просили. Неизвестные флаги, флаг, оставшийся без значения, и лишние аргументы теперь являются ошибками, которые называют, что команда на самом деле принимает, а --help работает после любой команды.

Предварительные и внутренние сборки BetterDisplay теперь предлагаются тем, кто их и просил. BetterDisplay ведёт все три свои линии релизов в одном-единственном фиде обновлений и выбирает между ними двумя переключателями в собственных настройках. DuoUpdater мог только угадывать вашу линию по той сборке, которую вы случайно запускали, а это ничего не говорит о переключателе, который вы включили, но по которому ещё не успели ничего получить, — поэтому тот, у кого включены оба переключателя, но кто сидит на стабильной сборке, получал сообщение, что он в курсе всех новостей, хотя собственный апдейтер BetterDisplay в это время предлагал версию, опережающую его на четыре релиза. Теперь ваш настоящий выбор считывается прямо из BetterDisplay, включая случай, когда включение внутренних сборок не отменяет и обычные предварительные версии. Его предварительные сборки только для Apple silicon намеренно оставлены в стороне, поэтому Mac на Intel никогда не предложат ту, которую он не сможет запустить.

Переключение канала выпуска приложения дважды подряд больше не оставляет строку висеть на старом ответе. Переключение канала отправляет DuoUpdater перепроверять это приложение, и второе переключение, случившееся, пока ещё выполнялась первая проверка, раньше просто отбрасывалось — строка продолжала предлагать бета-версию тому, кто только что отключил беты, пока что-нибудь постороннее не запускало ещё одну проверку. Теперь более новое переключение перехватывает управление у более старого, а проверка, прерванная на середине, помечает не охваченные ею приложения для следующего прохода вместо того, чтобы записать их как уже обработанные. Строки также теперь переходят в состояние проверки быстрее после переключения, так что остаётся меньше времени, в течение которого ответ на экране уже опровергнут вашим собственным переключателем.

Приложение, живущее внутри другого приложения, теперь закрывается и открывается заново вместе с ним. Несколько приложений несут внутри собственного бандла второе, полноценное приложение — например, Surge хранит там свою панель Dashboard. macOS считает его отдельным приложением, поэтому ничто не закрывало его, когда обновление применялось к приложению вокруг него: оно продолжало работать со сборкой, которую только что заменили, из копии, которая уже была не там, где оно думало, и из-за этого не могло связаться с приложением, которому принадлежит. Теперь такие приложения закрываются вместе с приложением, в котором живут, и открываются заново после него, а то окно, с которым вы на самом деле работали, оказывается тем, что возвращается на передний план. Так обрабатываются только те приложения, которые вы могли бы открыть сами; невидимые вспомогательные процессы, которые приложение запускает для себя, никто не трогает.

Точки отката, которые незаметно перестали создаваться, снова создаются. Приложение может заблокировать один из собственных файлов так, что его ничем не удалить, — а копия, хранившаяся для отката, унаследовала эту блокировку, поэтому её никогда не мог заменить следующий откат, и единственная прерванная попытка могла оставить после себя копию, которую ничто не могло убрать. После этого каждое обновление такого приложения проходило без пути назад — и сообщало об этом одной строкой, вообще не называющей причину. Одно приложение на собственном Mac разработчика находилось в этом состоянии два дня. Копии, хранимые для отката, больше не наследуют блокировку, установленное приложение остаётся ровно таким, каким его настроил разработчик, а застрявшая копия больше не может блокировать ту, что должна была её заменить.

Обновление, которое прошло успешно, больше не сообщает о сбое. macOS способна поставить новую версию на место, а затем дать сбой при удалении той, которую она вытеснила. Это принималось за чистую монету: DuoUpdater мог сказать, что приложение не обновилось, хотя оно обновилось, или что точки отката нет, хотя в хранилище резервных копий лежала полноценная, — и в первом случае вас отправляли выдавать разрешение, которое вы уже выдали и которое всё равно ничем не могло помочь. Теперь перед тем, как что-либо сообщить, проверяется, что на самом деле произошло на диске.

Строки версий больше не повторяют цифры, которые версия уже содержит. Когда приложение ждёт перезапуска, строка показывает версию, на которой вы сейчас работаете, и ту, на которую вас перенесёт перезапуск. Обе стороны несли номер сборки — именно он делает разницу читаемой, когда разработчик выпускает несколько сборок под одним именем версии, — и превращается в чистый шум, когда версии и так уже различаются. Строка Chrome тратила всю свою ширину на печать «151.0.7922.174 (7922.17…» и обрывалась ещё до цифр, которые на самом деле изменились. Теперь номера сборок появляются только тогда, когда изменилось именно это.

Теперь для повторного открытия приложения, чтобы завершить его обновление, используется одно и то же слово. Приложение, чей собственный апдейтер уже поставил новую версию на место, просило вас его «Restart»; то, что откладывает новую версию в сторону, пока вы его не закроете, просило «Relaunch». Разница была настоящей за кулисами и не значила для вас ровным счётом ничего: один и тот же клик в обоих случаях, и один и тот же результат, если вы вообще не нажимаете, — ведь обновление применяется при следующем закрытии приложения в любом случае. Теперь всюду используется слово «Перезапустить» — включая уведомления, подсказки и настройку, которая делает это за вас, — и это то же самое слово, которое перед вами ставят Chrome, Claude и большинство приложений, обновляющих себя сами. Только в английском для этого всегда было два разных слова; в немецком, японском, русском и китайском всегда использовалось одно, а испанский и французский переходят на ту формулировку, которую они уже использовали в других местах.

Обновление, которому требуется администратор, теперь так и просит, вместо того чтобы провалиться и обвинить разрешение. Нужен ли для замены пароль, решалось по папке, в которой лежит приложение, а не по самому приложению. Всё, что macOS установила от имени root — каждое приложение из App Store и любое приложение, положенное туда пакетом установщика, — проходило эту проверку, шло по пути, не требующему пароля, и просто не могло довести дело до конца: удаление старой версии требует права записи в её собственные каталоги. macOS сообщает об этом отказе тем же кодом, что и об отказе в разрешении на управление приложениями, поэтому сбой приходил в виде запроса выдать разрешение «Управление приложениями», которое всё равно ничем не могло помочь, ведь препятствием было владение файлами. На обычном Mac это касалось каждого приложения из App Store и ещё нескольких вдобавок, и страдали от этого именно администраторские учётные записи — со стандартными учётными записями всё и так уже шло правильным путём. Теперь такие обновления идут по пути, который действительно работает, а приложение сохраняет того владельца, который у него был, а не тихо становится вашим.

Приложения из App Store теперь тоже получают точку отката, как и всё остальное. Резервное копирование их пропускало, исходя из того, что магазин всегда может заново выдать предыдущую сборку. Не может — App Store предлагает только текущую версию приложения, — из-за чего магазин оставался единственным путём применения обновления без возможности его отменить. Теперь такие приложения перед обновлением тоже резервируются, как и любые другие, а поскольку копия делается клонированием, это почти не расходует место на диске, пока обновление на самом деле не заменит оригинал. Восстановление такой копии говорит именно то, что специфично для магазина: обновление тут же снова появляется в списке обновлений и само переустановится, если включены автоматические обновления приложений. А когда обновление из магазина всё равно не собиралось применяться — приложение для iPhone, запущенное на Mac, или наименование, не продающееся в вашем регионе, — точка отката больше не создаётся вовсе, поэтому строка больше не может предлагать откатиться к той версии, на которой приложение и так уже работает.

Longbridge Desktop теперь отслеживается, на обеих линиях выпуска. Stable и Preview получают каждая своё определение версии, установку официальной сборки для Apple silicon одним кликом и заметки о выпуске, отображаемые в собственном окне DuoUpdater, вместе с иллюстрациями.

Заметки о выпуске WhatsApp теперь появляются, пока его проверка через App Store ещё выполняется. Страница App Store, показываемая в этом окне, была заведена под именем, которое поиск никогда не мог сопоставить, поэтому панель заметок оставалась пустой вместо того, чтобы её показать.

Заголовок меню теперь вмещает больше в меньшем пространстве. Собственная версия DuoUpdater теперь стоит рядом с его именем, и щелчок по ней открывает его заметки о выпуске. «Обновить всё» переехало на отдельную строку, где переведённой подписи хватает места, чтобы полностью прочитаться, а действия внизу теперь представлены значками. Баннер, раньше объявлявший о самообновлении DuoUpdater, исчез — вместо него загорается искорка рядом с версией и остаётся гореть, пока вы не прочли, что изменилось. Строка статуса, слишком длинная для меню, теперь заканчивается многоточием, а не растягивает его.

Настройки больше не обрезают предлагаемые варианты обновления. Два меню, решающие, как применяется обновление, обрезали собственные подписи на нескольких языках. Теперь формулировки короче, а там, где словам всё же нужно больше места, они переходят на вторую строку.

«Что нового» теперь говорит, когда вышла каждая версия. Теперь у каждой версии в списке есть дата публикации.

Обновления под конкретную архитектуру теперь выбирают сборку, которую этот Mac реально способен запустить. Некоторые приложения публикуют одну и ту же версию дважды в одном Sparkle-фиде — отдельно для Apple silicon и отдельно для Intel, — и раньше DuoUpdater разрешал этот выбор просто по тому, какой адрес загрузки оказывался первым по алфавиту. Теперь он читает требование к оборудованию, указанное в фиде, а там, где поставщик оставил его пустым, — архитектуру из имени файла. Родная сборка теперь побеждает стабильно, а сборка, которую этот Mac не способен запустить, больше не предлагается. GitHub-релизы получают то же самое обращение — без того, чтобы объявлять совершенно здоровый рецепт сломанным только потому, что его самый новый артефакт нацелен на другую архитектуру.

Проверки обновлений ChatGPT теперь следуют треку выката, привязанному к учётной записи. OpenAI иногда держит бизнес- и корпоративные учётные записи на более старой десктопной сборке, пока новая уже дошла до потребительских учётных записей. DuoUpdater раньше не передавал в такой проверке тариф учётной записи, из-за чего для всех тихо выбирался осторожный трек: он мог заявлять, что установленная копия чем-то опережает всех, хотя сам ChatGPT уже загружал более новую сборку, или предлагать сборку, которую собственный апдейтер приложения тут же заменил бы снова. Теперь он отправляет метку тарифного плана из состояния входа ChatGPT/Codex вместе с тем же запросом обновления, который делает само приложение. Если эта метка недоступна, сохраняется прежнее осторожное поведение; сами учётные данные никогда не попадают ни в запрос, ни в диагностику.

Перезапуск, на который macOS так и не ответила, больше не способен заклинить все последующие обновления. Launch Services иногда принимает запрос на повторное открытие обновлённого приложения — и затем так никогда и не перезванивает. Строка навсегда оставалась в состоянии «Перезапуск…», её кнопка «Перезапустить» оставалась недоступной, а собственное обновление DuoUpdater ждало за ней в очереди. Теперь запуск, который не ответил в течение минуты, признаётся неудавшимся, поэтому строка восстанавливается, а остальная часть апдейтера продолжает работать.

Журнал релизов остаётся заполненным, даже если быстро дёрнуть его полосу прокрутки. Старый «ленивый» стек можно было обогнать длинным прыжком, ненадолго оставив пустое окно, пока строки создавались вокруг новой позиции. Теперь журнал использует переиспользуемый список, способный прыгать сразу к месту назначения. Элемент управления обновлением тоже сохраняет один и тот же размер при переключении между стрелкой и спиннером, поэтому нижняя строка больше не дёргается, когда начинается проверка.

Трафик загрузок теперь помечает обновления, использовавшие бинарный патч. Новые загрузки теперь записывают маршрут, которым обновление реально завершилось, — а не просто был ли патч предложен, — и несут в истории значок «Дельта». Заметно более лёгкие загрузки патчей из 0.3.62 тоже распознаются, хотя они были записаны ещё до того, как в журнале трафика появилось поле маршрута.

Обновления теперь загружают только то, что изменилось, — там, где разработчик публикует их именно так. Некоторые приложения выпускают вместе с каждым релизом небольшой патч — этого достаточно, чтобы превратить имеющуюся у вас версию в новую, не выкачивая всё заново. DuoUpdater раньше их игнорировал и каждый раз загружал полный пакет. Теперь он берёт патч, если он подходит именно к той сборке, на которой вы находитесь. Последнее обновление ChatGPT обошлось в 1,9 МБ вместо 605 МБ; Docker — в 87 МБ вместо 582 МБ. В обоих случаях результат — идентичное приложение: та же подпись, те же байты, сверенные с полной загрузкой ещё до того, как это было выпущено. Если ни один патч не подходит к тому, что у вас есть, или патч не применяется, происходит полная загрузка, как и раньше, поэтому из-за этого ничто не может не установиться.

DuoUpdater больше не загружает обновление, которое приложение уже загружает само. Многие приложения тоже обновляют себя сами, и когда мы оба одновременно тянулись за одним и тем же файлом в 600 МБ, вы платили за этот файл дважды. Теперь DuoUpdater замечает уже идущую загрузку и оставляет её в покое, сообщая об этом прямо в строке, а не молча бездействуя. Если такая загрузка окажется заброшенной, он перестаёт её учитывать через десять минут, чтобы ничто не оставалось заблокированным навсегда.

Обновление, которое приложение уже подготовило само, больше не перезаписывается. Приложения, обновляющие себя сами, часто загружаются в фоне, а затем ждут, пока вы их закроете, чтобы подставить новую версию. Установка поверх такого обновления выглядела успешной, а затем откатывалась в тот самый момент, когда вы закрывали приложение, — а там, где собственная ожидающая версия приложения оказывалась старше той, что только что установил DuoUpdater, вы оказывались даже дальше позади, чем в начале. Теперь такие обновления оставляют доводить дело до конца, какую бы версию они ни несли.

Собственные обновления DuoUpdater тоже стали меньше. Его релизы теперь поставляются в виде такого же патча, поэтому обновление с недавней версии подтягивает несколько сотен килобайт вместо одиннадцати мегабайт.

Объяснения, оставленные обновлением, теперь исчезают сами. Когда DuoUpdater передаёт приложение его собственному апдейтеру, строка сообщает об этом — «вывел его на передний план, чтобы его собственный апдейтер применил обновление». Раньше эта фраза оставалась навсегда: единственное, что вообще её убирало, — это запуск ещё одного обновления того же приложения, поэтому она всё ещё лежала под строкой спустя часы после того, как обновление уже состоялось, описывая нечто, давно завершившееся. Теперь она уходит, как только приложение становится актуальным. Предупреждение о том, что обновление было применено без точки отката, намеренно оставлено как есть, потому что оно описывает уже случившееся обновление и начинает иметь значение лишь после того, как всё закончилось.

Отклонённое обновление теперь объясняет причину на вашем языке. Когда уже устанавливается что-то ещё — DuoUpdater обрабатывает пакет или duo работает в терминале, — строка сообщает вам об этом. Раньше это сообщение было только на английском в остальном полностью переведённом окне, и заканчивалось номером процесса: полезным в терминале и совершенно бесполезным для действия в меню. Теперь оно переведено и говорит, что делать, а не кто держит блокировку. Инструмент командной строки по-прежнему выводит номер процесса — там, где с ним можно что-то сделать.

Строка с закономерностью выхода релизов, и вместе с ней часы, теперь следуют вашей локали. Раздел «Журнал релизов → Закономерности» подводил итог фразой вроде «Most often ships Friday, around 6 PM» («Чаще всего выходит по пятницам, около 18:00»). Языки, склоняющие названия дней, не могут сказать это, вставив день посередине предложения, и получали неверную форму слова — по-русски получалось «Чаще всего выходит пятница» там, где нужно «по пятницам». Теперь это надпись-ярлык: «Пик: пятница, около 18:00», которая верна везде. Время идёт вместе с этим — если ваш Mac пишет время на 24-часовом циферблате, так же поступает и это, в том числе на оси графика.

Поиск по настройкам теперь понимает слова, которые вы видите на экране. Поле поиска над боковой панелью настроек сверялось со списком дополнительных терминов, написанным по-английски и никогда не переводившимся, поэтому «rollback» находил раздел «Основные», а «Zurücksetzen» и «回滚» не находили ничего. Теперь эти термины существуют на каждом языке, на котором говорит DuoUpdater. Английские варианты по-прежнему работают на любом языке, ведь документация, из которой они взяты, написана по-английски.

Включение «Показать все» больше не заставляет меню задумываться. Полный список всех ваших приложений целиком измерялся заново при каждом появлении — на Mac со 127 приложениями это выливалось примерно в секунду работы, и почти всё это время уходило на раскладку строк, находящихся далеко за пределами видимой области. Плата взималась при каждом переключении, а не только при первом. Теперь строятся только те строки, что действительно есть на экране.

Объяснение, оставшееся от неудавшегося обновления, больше не переживает саму неудачу. Когда обновление не удавалось применить — например, потому что уже устанавливалось что-то другое, — строка красным объясняла почему. Ничто никогда это не убирало: даже когда обновление всё же проходило и строка возвращалась к галочке, старое объяснение по-прежнему висело под ней и оставалось при каждой следующей проверке вплоть до перезапуска DuoUpdater. Теперь оно уходит, как только приложение становится актуальным. Причины, относящиеся к обновлениям, которые всё ещё ожидают, остаются нетронутыми, поэтому ту, что вы ещё не прочли, не может стереть проверка, выполняющаяся в фоне.

Кнопка «Обновить всё» больше не меняет размер в зависимости от длины списка. Когда обновлений ожидало совсем немного, кнопку рисовали на размер меньше, чем следовало, с восемьюдесятью пунктами пустого места рядом с ней, и она подскакивала до правильного размера, стоило списку вырасти. Теперь она всегда остаётся тем размером, каким и должна быть.

Трафик загрузок теперь говорит, на какую сборку перешло обновление, а не только на какую версию. Немало приложений выпускают несколько сборок под одним именем версии — Surge выпустил под номером «6.9.0» четыре отдельных релиза, — поэтому такие строки читались как «6.9.0 → 6.9.0» и ничего вам не сообщали. Теперь они читаются как «6.9.0 (12028) → 6.9.0 (12030)», и только тогда, когда одного имени версии недостаточно; там, где версия и так уже изменилась, номер сборки был бы лишь шумом и опускается.

Записанной считается та сборка, что реально прижилась, — её считывают с самого приложения уже после установки обновления. А не то число, которое рекламировал собственный фид обновлений разработчика, — фиды и правда иногда врут, и заодно это работает для тех мест, что вообще не публикуют номер сборки: GitHub, Homebrew и App Store. Обновление, всё ещё ожидающее окно установщика macOS, никогда не угадывается заранее — для него ничего не записывается, пока оно не станет реальностью.

Загрузка, которая ничего не изменила, теперь так и помечается. Иногда обновление загружает и устанавливает ту же сборку, что уже стояла на вашем Mac, — несовпадение номера версии на стороне разработчика, зеркало, отдающее то, что у вас уже есть. Это реальный расход трафика без всякого результата, и именно окно трафика — то место, где вы хотели бы это увидеть. Теперь такие строки несут ярлык «без изменений». У загрузок, записанных до этого релиза, нет номеров сборок для сравнения, поэтому их оставляют как есть, а не гадают: «неизвестно» — не то же самое, что «без изменений».

DuoUpdater теперь показывает, во сколько трафика реально обошлось поддержание ваших приложений в актуальном состоянии. Он и раньше считал, до байта, каждое обновление, загруженное для вас, — но этому числу было негде появиться, и оно просто лежало в файле, который никто не мог прочитать. Теперь есть окно «Трафик загрузок», открываемое кнопкой-графиком внизу меню, а цифра за этот месяц напечатана прямо рядом с этой кнопкой, поэтому на самый частый вопрос отвечает уже сам факт, что вы ничего не открывали. Внутри: итог, последние три месяца бок о бок с изменением между ними, разбивка по источникам этих байтов и все приложения, отсортированные по тому, во сколько они обошлись, — щёлкните по любому, чтобы увидеть каждое его обновление: с какой версии на какую оно перешло и насколько большой была эта загрузка.

Итог честно говорит о том, чего он не видит. Homebrew, App Store и приложения, обновляющиеся через собственный встроенный апдейтер, тянут свои байты сами, и DuoUpdater их никогда не обрабатывает, — поэтому эта цифра является нижней границей, а не полным учётом. Так было всегда; изменилось то, что теперь окно говорит об этом постоянно, а не только на пустом экране, который вы видите до того, как хоть что-то было записано.

Приложения, которые вы с тех пор переименовали или удалили, сохраняют свою историю. Трафик записывается за тем местом на диске, где живёт приложение, а именно это и позволяет двум каналам одного и того же приложения — скажем, Android Studio Canary и Beta — оставаться раздельными, а не складываться в одно. Плата за это — переименование приложения оставляет его прошлое под именем, которого больше не существует. Когда OpenAI переименовала Codex в ChatGPT, это разделило 30 ГБ загрузок между двумя записями, которые выглядели как дубликаты. Теперь такие записи группируются и приглушаются внизу списка, под заголовком, который поясняет, что это такое. Ничего не выбрасывается, и итог по-прежнему включает их.

Приложению, установленному из App Store, больше не предлагается собственная загрузка с сайта разработчика. Немало приложений публикуются сразу в двух местах — в магазине и в виде прямой загрузки с сайта самого разработчика — под одной и той же идентичностью, но как по-настоящему разные сборки. Прямая загрузка обычно опережает магазин, потому что не ждёт проверки магазином. DuoUpdater сперва проверяет магазин для приложения, установленного из магазина, но когда эта проверка по любой причине не удавалась — оборвалось соединение, витрина не ответила, — он тихо переходил на сайт разработчика и предлагал всё, что там находил. WhatsApp показал это как «26.32.75 → 26.33.19»: настоящая версия, но не из того источника. Принять её означало бы заменить вашу магазинную копию такой, которую App Store уже никогда не смог бы обновить снова. Теперь приложения, установленные из магазина, проверяются только по магазину и нигде больше.

Переключение канала обновлений приложения прямо внутри него теперь регистрируется сразу. Некоторые приложения позволяют выбирать между обычными релизами и бета-версиями — Surge, Tailscale, Fork, OrbStack, IINA, Alfred и другие, — и DuoUpdater следует за тем, что выбрали именно вы, чтобы никогда не предложить сборку, о которой вы не просили. Раньше он замечал перемену только тогда, когда вы закрывали приложение или открывали одно из окон DuoUpdater. Ни то, ни другое не покрывает то, что люди на самом деле делают: выключить настройку, оставить приложение запущенным и просто взглянуть на строку меню. Хуже того, приложения записывают эту настройку на диск тогда, когда им удобно, а не в момент вашего клика — у Surge на это уходило пять минут, — так что даже закрытие приложения могло быть прочитано слишком рано. Теперь DuoUpdater сам следит за изменением этой настройки и перепроверяет именно это приложение в течение секунды-двух. Переключение Surge обратно на обычные релизы теперь сразу же убирает бета-версию из его строки, вместо того чтобы она провисела там ещё до часа.

Проверка, которая ни до чего не смогла достучаться, больше не выглядит как чистый лист здоровья. Когда отказывали все источники сразу — не было сети, или прокси тихо отклонял соединения, пока значок Wi-Fi по-прежнему уверял, что всё в порядке, — приложения, проверка которых провалилась, скрывались, а панель показывала «127 приложений · актуально». Это тот же самый экран, который вы видите, когда всё и вправду обновлено, из-за чего провалившуюся проверку было не отличить от успешной. Теперь панель говорит, до скольких приложений ей не удалось достучаться, показывает, что пошло не так, и предлагает попробовать снова именно их — только их, оставив в покое всё, что она всё-таки успела проверить.

A helper macOS wouldn't switch on no longer sends you to reset your whole Mac. App Store updates install through a small background item macOS asks you to approve once. When that approval was refused, DuoUpdater had exactly one explanation for it: the system's record of the item is damaged, and repairing it takes a Terminal command that clears the background-item approvals of every app on your Mac. That is one cause among several, and macOS never says which one applies — the ordinary one is that the switch is simply off. The message now leads with that instead: turn DuoUpdater on under "Allow in the Background" in Login Items & Extensions, and DuoUpdater opens the pane for you. The Terminal reset is still written down, as the fallback for when DuoUpdater isn't listed there or switching it on changes nothing. The message also stopped running off the edge of its card.

Two Settings options read on one line again. The two options under Install routing — how App Store updates install, and what happens to apps that ship their own updater — used to put their name to the left of the menu, the way options do everywhere else on macOS. Adding six languages moved both names above their menus instead, because a German or Russian option can be long enough to run off the end of the line, and the safe layout was applied to every language at once. Each row now decides for itself: the name stays beside the menu as long as the menu leaves room for it, and only moves above when the text genuinely needs the width. In English, Japanese and Chinese both rows are back on one line; in German and French they stay stacked, which is the only way they fit without being cut off.

DuoUpdater now speaks Russian, Simplified Chinese, Japanese, German, French and Spanish. It follows whatever language your Mac is set to, and switches with it — there is nothing to turn on. If you would rather read it in a language your Mac isn't set to, macOS can do that per app: System Settings ▸ General ▸ Language & Region ▸ Applications. Everything the app writes itself is translated: the menu-bar panel, every Settings page, the setup window, the notifications, the alerts, and the small print under each option. Counts are handled the way each language actually handles them rather than by bolting an "s" onto the end, which matters most in Russian, where "1 update", "2 updates" and "5 updates" take three different endings — and in Chinese and Japanese, where they take none.

Two things stay in English on purpose. Release notes are the vendor's own words, so they arrive in whatever language the vendor wrote them in — translating them would mean rewriting what a developer said about their own release. And the duo command-line tool stays English, the way command-line tools generally are.

An App Store app that was open when you updated it comes back again. Last release drew a line in the wrong place. It was fixing something real — an update that failed, or that you cancelled, could bring an app back to life minutes after you had closed it yourself — but it decided whether to reopen by asking whether someone had answered a quit prompt. Almost no App Store update shows one: the prompt only appears on a route DuoUpdater stopped using a while ago. So from 0.3.53, updating an App Store app that was running closed it and left it closed, with nothing on screen to say why. The question it asks now is whether the update actually landed, which is the thing that decides whether a quit is coming at all. This is verified against a real App Store update rather than reasoned about: the store terminates your app to replace its files and never brings it back — despite its own prompt promising that it will.

DuoUpdater now tells you when App Store is waiting on you. The store cannot replace an app while it is open, so it puts up a "cannot be open during installation" prompt and waits — with no time limit, holding the update and a download slot for as long as it takes. That prompt is a small panel inside App Store's own window, which may be sitting on some entirely unrelated page; App Store bounces its Dock icon a few times and gives up; and DuoUpdater lives in the menu bar with no Dock icon to bounce. An update could sit there indefinitely with nothing anywhere telling you a click was needed — one took four and a half minutes here, ending only because someone thought to look. The row now says what is being waited for, from the moment the update starts.

The dot that marks an app as open no longer lags behind. macOS does not reliably announce that an app has launched — some apps never trigger it at all, while quitting is always announced. DuoUpdater listened only for those announcements, so a row could insist an app was closed while its window sat in front of you, and only correct itself when some unrelated app happened to open or quit. It now re-derives which apps are running whenever it rescans, which includes the moment you open the menu.

Two things a review caught before you did. The warning that an update was applied without a rollback point was being erased before it could be read: restarting an app cleared the whole note, and restarting after an update is the default. It is now retracted only by whoever wrote it. And Update All could refuse to restart an app — telling you its own updater had a version staged and waiting — when nothing was staged at all: it compared what was on disk now against a build number recorded before the install, so an app whose version name had not changed looked like a conflict.

An app that already downloaded its own update is no longer asked to download it again. Plenty of apps fetch their next version quietly in the background and hold it until you next quit them — that's the "relaunch to update" state you see inside Claude, TablePlus and others. DuoUpdater has always recognised that state in Electron apps and offered you Relaunch instead of an Update, because the bytes are already on your disk. Apps built on Sparkle, which is most of the rest, were invisible to it: TablePlus sat there with a 133 MB download and an unpacked 382 MB copy of 26.9.11 in its cache, while its row offered to fetch 26.9.11 for you all over again. Those apps are now recognised too — the row offers Relaunch, and nothing is downloaded twice.

One thing it deliberately won't do is offer Relaunch for an older build. An app can be holding a version behind the one you have, which happens when a vendor releases to some people before others and DuoUpdater installed the newer one first. Relaunching there would quietly move you backwards, so the row doesn't offer it — and DuoUpdater won't restart the app for you either, because that restart is the exact signal the app's own installer is waiting for.

Three ways an update could go wrong that a review caught before you did. An App Store update that failed, or that you cancelled, could bring the app back to life minutes later — you would quit it yourself and it would reopen, because DuoUpdater had noted "this app may need reopening" before anything had actually closed it. It now only reopens an app when a quit was genuinely asked for. Separately, the check added last release to stop an app's own updater undoing ours compared only the version name: a vendor that ships several builds under one version number slipped straight past it, which is the same failure it was written to prevent. It now compares the build number too. And an app's own updater is no longer assumed to be waiting just because a downloaded copy is sitting in its cache — Sparkle leaves those behind for ten days after an interrupted install, which could have left a Restart button that did nothing but explain itself.

Same changes as 0.3.51, reissued so it can actually reach you. 0.3.51 went out carrying the same internal build number as 0.3.50. That number, not the one in the version name, is what an update check compares — so anyone already running 0.3.50 was told they were up to date and never offered it. This release carries the changes below under a build number that is properly newer. If you are reading this on 0.3.51, nothing about the app changed between the two.

An update that kept coming back. ChatGPT would offer a new version, install it, restart — and a minute later the same update was waiting again. The install was never the problem: the new version really did land on disk. What happened next is that ChatGPT's own updater put a different one back. There are two lists involved, and DuoUpdater was reading the wrong one. The first is everything the vendor has published; the second is what the vendor is actually handing out to your Mac today, which can be an earlier build while a release is still rolling out. DuoUpdater was reading the published list — the same address ChatGPT itself is configured with, which is what made it look right — and offering you a build the vendor was still holding back. ChatGPT had meanwhile downloaded the build it was being offered and parked it, waiting for the app to close. Restarting to apply our update is what closed it. DuoUpdater now asks the same question ChatGPT's own updater asks, so the two agree on what the current version is.

Restarting an app no longer applies somebody else's update. That collision isn't unique to ChatGPT. A lot of apps download their next version quietly and install it the instant you quit them — the "relaunch to update" state you've seen in Claude, TablePlus and others. They'll wait hours for that quit; one was observed holding on for nearly seven. When DuoUpdater restarts an app to put its own update into effect, that restart is exactly the signal they're waiting for, and theirs runs second. Before restarting, DuoUpdater now checks whether anything is waiting, and what version it holds. If it's the same version — which is the common case, and harmless — nothing changes. If it's a different one, the app isn't restarted: the row says what's waiting and leaves the choice to you, rather than quietly swapping in a build you didn't pick.

An App Store update no longer leaves your app closed. Updating an app you have open through the App Store means closing it — the store's own installer quits it to replace the bundle, and doesn't open it again afterwards. DuoUpdater knew to reopen it, but only if you'd answered its own "quit to finish updating" prompt. Answer the identical prompt in the App Store window instead, or take an update that raises no prompt at all, and nothing remembered that your app had been open. It updated correctly, said "Updated ✓", and your app was simply gone — with no restart offered, because by then there was no running app to restart. What decides now is whether the app was running when the update started, which is the thing that was actually true, rather than which window you happened to click in.

豆包输入法 now gets checked, and shows its release notes. It was in the list — DuoUpdater looks inside /Library/Input Methods — but nothing anywhere knew where to ask about it, so the row sat blank forever and read like "nothing to do". It now reads the same endpoint the vendor's own download button reads, and compares the same build number the vendor versions by — so even a re-release that keeps the version name unchanged shows up, rather than passing as the version you already have. The release notes come from the feed the input method's own updater polls, laid out as a proper list rather than a link to a page that doesn't exist. As with 微信输入法, DuoUpdater will tell you a new version is out but will not install it for you: an input method is registered with the system by its installer, not merely copied into place, and quietly swapping the bundle is how you lose your personal dictionary.

Zed's release notes come back instead of an error. DuoUpdater asks GitHub about a lot of apps, and GitHub lets an unidentified caller ask only sixty questions an hour from one network — a budget every GitHub-hosted app on your machine shares. Zed's notes were the ones losing that race, and the panel showed a failure rather than the notes. Those requests now carry the GitHub token you saved in Settings ▸ GitHub, or the one the gh command-line tool already holds if you use it, which lifts the limit far out of the way. Without a token nothing gets worse: Zed's notes now come from a single, smaller source that covers both its channels, where before each one fetched its own web page.

Notion's release notes are about the app you have. They were being read from Notion's product announcements — the page that introduces features as they launch. Those posts are titled by feature, not by version, so nothing on that page ever lined up with the version number on Notion's row, and the notes for the update you were being offered were never there to find. They now come from Notion's own "What's new" page for the Mac and Windows app, where the versions are the ones you can actually compare against.

Some release notes were quietly incomplete, and no longer are. A release's final line could go missing from ChatWise's notes. Two of Postman's releases were cut off mid-sentence — both at the exact point where the text contained a quotation mark. Six apps' notes are now read from the same data the vendor's own site is built from, rather than picked out of the finished page, which is both sturdier and how those two ended up whole. HBuilderX is the one trade-off: its notes now come from the official release document, which covers the HBuilderX editor itself and not the bundled uni-app and uniCloud module logs, so its entries are shorter than before — the same releases, in the vendor's own words, minus the parts about other products.

Release notes that arrive inside an app's update feed are laid out properly. A good number of apps ship their notes as a small piece of a web page tucked inside the feed their updater reads. DuoUpdater used to hand that straight to the system's HTML renderer, which produced a serif font nothing else in the app uses, bullets indented into the margin, and — the part that mattered — a long list could be cut in half, with everything after the cut silently absent. Those notes are now read into the same list layout the rest of the panel uses: right font, right indentation, and nothing dropped. Where the markup is too tangled to be sure of, DuoUpdater leaves it to the old renderer rather than risk showing you part of a list as if it were all of it. TablePro benefits most — its notes had stopped being found at all.

Four more apps show their release notes properly, instead of an embedded web page. Alcove, Docker, Kiro and Waku each publish their notes somewhere a program can read them — Alcove and Docker on their own sites, Kiro as a feed, Waku on GitHub — but DuoUpdater was showing you the web page instead, which meant the vendor's fonts, the vendor's navigation, and no way to move between versions. They now read as proper entries in the list, the same as everything else. Kiro's feed covers three separate products; only the notes for the app you have installed are shown.

A release whose notes are written as sentences no longer vanishes. Some releases don't have a bulleted list of changes — they have a line or two of prose, sometimes only "no public-facing changes in this release". DuoUpdater understood lists and nothing else, so those releases were skipped entirely: if you happened to be running exactly that version, the panel had no entry for it at all, as though your own build had never shipped. They're kept now. Where the notes are laid out in a way that still can't be read cleanly — a table, mostly — the page is shown as before rather than half-converted into something misleading.

Antigravity IDE gets checked. It's a separate app from Antigravity, with its own version, and it was in your list but nothing ever checked it — the row just sat there with no version to compare against and no way to find out. It's checked now. DuoUpdater won't install it for you; it will tell you when a new version is out and where to get it.

DuoUpdater tells you when it updated itself, and what changed. It installs its own updates quietly, on purpose — it waits until you're away from the machine and swaps itself without asking, because a tool that interrupts you to talk about itself is getting in the way of the work it's supposed to protect. The cost was that you'd end up on a new version you never agreed to and never saw the notes for: every other app in your list has a "what changed" panel, and the one app that changed under you in silence was this one. Now the menu says so once, and opens its release notes. It's shown until you read it rather than for a set time — the update this is for is the one that landed while you were asleep. A fresh install doesn't get told it was updated, because it wasn't, and going back to an older build on purpose doesn't either.

And you can read those notes any time. The ✨ button at the bottom of the menu opens every release DuoUpdater has ever shipped, with the one you're running marked in the list.

Switching an app's update channel in that app is noticed straight away. Some apps let you choose between their stable and pre-release builds in their own settings — Tailscale, Fork, Surge, OrbStack, TablePlus, CleanShot, IINA, Alfred, DuoPaste. That choice lives in the app's own preferences, where nothing tells DuoUpdater it has changed, so switching from a beta track back to stable left the row still comparing you against the beta — and still offering it — until the next scheduled check, up to an hour later. DuoUpdater now re-reads that choice when one of those apps opens or quits, and when you come back to its own window, and re-checks just the app that changed.

Tailscale's Release Candidate track is one of the choices DuoUpdater understands. Tailscale publishes three: stable, release candidate, and unstable. Only two were known here, so a Mac opted into release candidates was quietly checked against stable instead, and reported up to date whenever a candidate build was newer than the stable one. All three are now checked against the track you actually chose.

Confirming a quit late no longer leaves the app updated but closed. Some apps guard their own quit with a dialog — Claude, for one, asks about an active conversation — and that dialog could land in the middle of a Relaunch. DuoUpdater rightly refuses to sit there while you decide (and it still won't force the quit past your unsaved work), but once it stepped aside it also stopped listening. Answer the dialog a minute later and the quit went through, the app's own updater swapped in the new version — and then nothing happened: some updaters deliberately don't reopen the app after installing, DuoUpdater was no longer watching, and you were left staring at an app that had simply closed. It now leaves a note for itself when it steps aside: if you do confirm that quit within the next few minutes, it waits for the update to finish landing and then brings the app back, in front if that's where it was. The note expires after a few minutes, so a quit hours later is just you closing the app, and stays that way.

The same late answer now works for a plain Restart. A save prompt could block the Restart button (and the automatic restart that follows a one-click Update) in exactly the same way, with a worse ending: the new version was already on disk, so when you finally dismissed that prompt and the app closed, DuoUpdater's next look around decided there was nothing left to restart and quietly dropped the badge too — an app closed, an update half-applied, and no trace that anything had been asked for. Answering a save prompt within a few minutes now finishes the restart it belonged to, and the app comes back on the new version.

App Store updates tell you they're waiting, and don't leave the app closed if you answer late. When the App Store finishes downloading an update for an app you have open, it asks for that app to be closed before it can install — and DuoUpdater waits, indefinitely and on purpose, for you to say when. Until now that request lived only inside the menu: if you never opened it, an update sat downloaded-but-not-installed all night, and background checks waited with it. It now also arrives as a notification with a Relaunch button, so you can answer it without hunting for the row. And if your app puts up a save prompt of its own after you tap Relaunch, answering it minutes later no longer strands the app closed — the update lands and the app is reopened, the same as if it had quit right away.

The list holds still while you are clicking down it. Every finished update used to re-sort the list on the spot: the app that just landed left the pending group, or picked up a Restart badge and jumped to the top, and everything below it slid up a row — under the pointer of anyone working down a list of Update buttons. Click the top one, go for the next, and the next one had moved. Now the order is held from the first click until the whole round is done: an app that finishes shows its confirmation in place, nothing else moves, and the list settles once at the end, when the finished apps drop away as they always did.

One less version number on a row that needs a restart. An app with an update waiting and an earlier update still needing a restart tried to print all three versions on one line — installed, available, and the older one still running. On four-part versions like Chrome's it did not fit, and the line was cut off exactly where the digits started to differ, so the part left visible said nothing at all. The line now sticks to the comparison that matters — what you have and what is offered — and the running version moved to the row's tooltip, where it fits.

No more Dock icon. DuoUpdater is a menu-bar app — everything it does starts from the icon up there — but it also held a Dock slot, and the only thing that slot ever did was open the same window the menu bar opens. It now runs from the menu bar alone. If you would rather keep the Dock icon, Settings ▸ General ▸ "Hide the Dock icon" turns it back on, and with it the badge that shows the number of pending updates; hidden, that count lives on the menu-bar icon instead.

An app you ignored is no longer checked at all. Ignoring an app hid its row, but every check still asked its vendor after it — one network request per app per round, spent on an answer nothing would ever be said about. On an unauthenticated GitHub budget of sixty requests an hour, those were requests taken from the apps you do watch. Ignoring now means not asking, which is what "hide an app from update checks" always claimed. Naming an app on the command line still checks it, and so does asking for hidden rows, since both are you asking about that app specifically. Skipping a version is unchanged and still checked — whether the version on offer is still the one you skipped can only be known by asking. And un-ignoring re-checks that app on the spot, instead of leaving the row blank until the next round comes due.

An app you ignored stops notifying you. An app that updates itself leaves a "Relaunch to apply it" reminder in Notification Center and repeats it every few minutes until you act on it. That reminder never consulted the ignore list, so an app you had ignored went on sending it — hidden in DuoUpdater's own list, still arriving every five minutes, with nothing on screen to explain where it was coming from. Ignoring an app now silences those reminders and clears any already waiting in Notification Center. Skipping a version does the same for that version.

A download no longer squeezes the app's name or its version off the row. While an app was downloading, the progress bar and its percentage claimed enough of the row that a long name wrapped onto a second line, a long date-style version was clipped at both ends to something unreadable, and at 100% the percentage itself broke across two lines. The row now measures what the name and the version actually need and fits the progress readout into what's left: the bar gives way to a compact ring, and the percentage stays. Nothing is given up until there is genuinely no room for it.

An update no longer looks like it fired twice. With one update pending, installing it briefly emptied the list: the row dropped out the moment the new version reached the disk, the "Everything is up to date" placeholder took its place and jumped the window's height, and then the row reappeared saying "Relaunching...". Nothing was actually wrong underneath — the app still had to be restarted to run the new code — but it read as though something had happened twice. The row now stays where it is from the click through to the relaunch. The step that used to announce "Done" while the app was still being restarted says "Installed" instead; "finished" is left for the confirmation at the end, where it belongs.

The workbench sidebar follows the arrow keys again. Holding an arrow key walked the selection off the edge of the list and left it there, moving through apps that were never drawn and not catching up when the keys stopped. The selected app stays in view.

Moving through that sidebar is quicker. Every keypress was re-deriving, once per app per row, a fact about the whole list that had not changed — on a machine with 124 apps that came to about fifteen thousand redundant filesystem-path lookups per keystroke. It is derived once now. Fast key repeat can still outrun the list; there is more to do here.

An App Store update says "Update", not "Get". When the background helper has not been approved there is no way to install an App Store update in place, so the row hands off to the App Store app instead — but the button for that read "Get", which is what the store says about an app you do not own yet. Every row that reaches it is an app you already have, with an update waiting. It says "Update" now, and when the helper is what is missing the tooltip says so, since approving it in Settings is what turns those updates into one click.

The action column lines up. A checkmark or a small badge at the end of a row was centred in its slot while a wide button sat flush against the row's edge, so the right-hand column read as ragged — and visibly out of line with the Homebrew row pinned below it. Everything ends on the same edge now.

WeType (微信输入法) now reports the version you actually have. Its version was being read off the name of the vendor's installer file, which turns out to carry the installer's version rather than the app's — the installer is a small downloader that fetches the real app separately, and the two numbers drift apart. DuoUpdater now reads the same manifest the vendor's own installer reads, so the version matches your copy and new releases show up when they ship. WeType still has to be updated with the vendor's installer rather than in place: replacing the bundle skips the input-method registration step and was found to lose settings.

A beta build can never arrive on the stable channel. The fix in 0.3.44 looks further back through an app's releases when the newest one has no Mac build attached. That wider search could also see the developer's beta and release-candidate builds, which the normal check never shows you — so an app that happened to publish a release without its Mac download could have offered you a beta. Nothing had actually hit this, and now nothing can: the wider search only ever considers finished releases.

Notion's release notes are readable again. Notion restyled its releases page and DuoUpdater could no longer pick the posts out of it, so the notes fell back to showing the raw web page. They render as proper entries again.

PureMac's updates are visible again. The developer publishes a separate command-line tool from the same place as the app, and its release was being read as if it were the app — as version 1.0.0, which looks older than what you have installed, so the app reported itself up to date and every real update stayed hidden. It now reads only the app's own releases.

An update that only ever existed for phones no longer sits in your list. Some apps share one version number across Mac, Windows, Linux and mobile, and sometimes a release goes out to the phones alone — the version number moves, but no Mac build is ever made. DuoUpdater was reading that as a Mac update, which left an update you could never install and that never went away. It now looks for the Mac download itself rather than trusting the version number, so those releases are correctly ignored. LocalSend was the app affected; its row now reads as up to date, which it is.

LocalSend installed from its own website updates in one click. Now that the right release is identified, its Mac disk image can be installed in place like the rest.

An App Store copy is never replaced with a build from elsewhere. A few apps are published both on the Mac App Store and as a download from their developer, under the same identity — LocalSend is one. Those are genuinely different builds, and the App Store's copy has to keep updating through the App Store. DuoUpdater now leaves those copies to the store instead of ever offering the developer's build over them.

Updates that the wider ecosystem never picks up get flagged for us. Our nightly recipe sweep could only tell whether an app's version could still be read, not whether the answer made sense for a Mac — which is why the LocalSend problem had to be spotted by hand. It now also compares against Homebrew, and raises a flag when we are reporting a version that nobody else has packaged long after it was published. Nothing about this is visible on your Mac; it is how this class of mistake gets caught by machine next time.

Package updates are read more thoroughly before they are opened. The check added in 0.3.41 asks an installer package where it installs, and refuses one that will not say. It was reading only the summary the package publishes about itself; it now also reads the package's own file list, which is what the installer actually follows. That means a package that keeps quiet in its summary is still understood instead of turned away. Every app that updates this way was re-checked against its real installer, and none of them changed.

A download link that stays broken now gets noticed. When a vendor's server has a bad minute, DuoUpdater waits it out rather than crying wolf — but that was letting a download link that had been broken for good slip by unremarked, because it looked the same as a bad minute on any single check. It now tells the difference: brief trouble is still ignored, trouble that lasts is flagged and fixed. Nothing changes on your Mac; this is about broken apps getting repaired sooner instead of quietly staying broken.

Release notes can't be pulled down to an insecure page. A vendor's notes page is loaded over a secure connection, but nothing stopped that page from redirecting itself to an insecure one. Now it can't.

Updating OneNote no longer installs the whole of Microsoft Office. OneNote's update was being fetched from Microsoft's combined Office installer, which puts Word, Excel, PowerPoint, Outlook and OneDrive on your Mac along with it. If you keep OneNote on its own, that was five applications you never asked for. It now downloads Microsoft's standalone OneNote update, which installs OneNote and nothing else.

Package updates are checked more strictly before they are opened. An update that arrives as a macOS installer package now has to say where it installs, and has to name the app you are updating. A package that will not say is refused rather than let through. Every app that updates this way — Office, Edge, Teams, OneDrive, Tailscale, ToDesk, AweSun and the rest — was checked against its real installer first, so this should never fire on a normal update.

Telegram's one-click update stops vanishing when Telegram's servers hiccup. Working out where to download Telegram from needs one extra request to their servers, and those servers were intermittently refusing it — a few minutes at a time, then fine again. When that happened the update was still detected, but the Update button quietly disappeared for that check and you had to go to the website yourself. DuoUpdater now retries before giving up, so a brief hiccup no longer costs you the one-click install.

Package installers are checked against the app they claim to update. Some updates arrive as a macOS installer package, which runs with administrator rights the moment you confirm it. Until now the only check was that the package came from the same developer as the app being updated — which would have let any package from that developer through, not just the right one. DuoUpdater now also reads where the package says it will install and refuses it if that is not the app you are updating. Nothing changes for a normal update; this only ever fires on a package that does not belong.

Release notes only open over a secure connection. The notes pane loads a vendor's own page for some apps, and one of those pages was still being fetched over plain http. Those pages now have to be https, and a handful of other malformed addresses are refused outright rather than loaded.

Fewer apps can go silently missing after a vendor renumbers. Zotero's jump to 10.0 in 0.3.37 exposed a whole class of this: an app disappears from the update list, with no error, because the vendor changed how many numbers are in its version. Twenty-one apps — among them VS Code, Discord, Obsidian, Figma, WhatsApp and GIMP — no longer depend on that staying the same. The rest were checked and deliberately left alone, because for those a looser check would risk reading the wrong number off the page.

The download percentage no longer spills out of its row. While an update downloaded, the number next to the progress bar sat too far right — clipped by the edge of the list instead of lining up with everything else in the column — and there was more empty space between the bar and the number than there needed to be. Both are fixed; the percentage still holds a fixed width, so the row stays steady as it counts up to 100%.

Zotero 10 shows up as an update again. Zotero numbered its new major release 10.0 — two numbers where every previous release had three — and DuoUpdater's check for it quietly stopped recognising the version. Nothing looked wrong: no error, no failed check, Zotero simply never appeared in the list, so anyone still on 9.0.6 was never offered the upgrade. It is recognised again, and the one-click install is unchanged.

A package update that leaves the old copy running now offers to restart it. Some updates install as a package handed to macOS's own installer, and when that finished it left the previous copy still running the old version — with no prompt, so you had to notice and quit it yourself. DuoUpdater now spots that and offers a Restart, the same as it already does for other kinds of update. It only offers one when a copy that was open before the install is genuinely still running the old code — if the installer (or you) already relaunched the app, or it wasn't open, nothing is shown.

WeChat DevTools (微信开发者工具) is checked for updates now — Stable, RC and Nightly each on their own track. It used to sit there as "unknown": since version 2.02 the app reports Electron's stock identity on disk, calling itself version 36.6.0, and all three channels look identical from the outside. DuoUpdater now reads the real version and channel out of the app's own configuration, so whichever track you installed is the only one you are offered — a Nightly install is never handed a Stable build, or the other way round. Updates install in one click, and the release notes for the exact build show up in the window.

App Store updates stop breaking every time DuoUpdater updates itself. Replacing the app left the background helper from the previous copy running, and macOS then never started the new one — so the helper looked switched on while every App Store update failed talking to a copy that no longer existed. Only a restart cleared it. The helper now steps aside when it has been idle for a minute, which means a replaced app heals itself by the next update. For a Mac already in that state there is a Restart Helper button in Settings → Diagnostics and on the update that failed; it asks for an administrator password and takes effect immediately, no restart.

Diagnostics can tell you whether the helper actually works. "Enabled" only ever meant "switched on", and the difference between that and "answering" showed up as a failed update. A Check button now says which one you have, in those words.

Backups: choose what to delete. "Clean Up Now" only removed backups belonging to apps you had uninstalled, so on most Macs it deleted nothing and said nothing while the size stayed put. It now opens a list — every backup with its app icon, the update it would roll back, its size and date — with everything selected and anything you want to keep unselectable. The button says how much the selection frees. Backups whose records had gone missing were previously counted in the total but impossible to see or remove; they are listed too, marked unusable.

A silent self-update no longer leaves DuoUpdater sitting in front of you. When it applied its own update in the background, macOS brought back the windows that had been open — and bringing a window back also brings the app forward, so an update nobody asked for landed on top of whatever was being worked on and stayed there. DuoUpdater now notes which application was in front before it replaces itself, and gives the front back to it on the way in. Windows still return exactly as they were.

Docker updated to the version it said it would. Docker publishes its releases in an order that puts an older one first, and DuoUpdater read the newest version from that list while taking the download link from the top of it — so it fetched 574 MB, kept a backup, installed 4.86.0 over the 4.86.0 already there, and went on offering 4.87.0. Downloads are now matched to the version each entry declares for itself, whatever order a vendor lists them in.

An update that changed nothing is no longer reported as done. The check that runs immediately after installing already knew Docker hadn't moved; it was overruled by a success message and an "Updated ✓". When an update we applied ourselves leaves the app exactly as it was, that is now shown as the failure it is, naming what was installed and what is still on disk.

Silent self-updates no longer wait for an empty screen. With the switch turned on, DuoUpdater would hold its own update back while any of its windows were open — which, for a window people leave open, meant waiting until the app was quit. Open windows no longer delay it (macOS brings them back after the restart), while a DuoUpdater you are actually using still does: it waits for the keyboard and mouse to go quiet before restarting itself.

Installing DuoUpdater's own updates silently now actually is silent. The switch introduced in 0.3.30 downloaded the new version in the background and then still asked before applying it — the one thing it was meant to spare you. It now applies the update itself, at a moment when doing so interrupts nothing: no check or install running, nothing waiting to be relaunched, no DuoUpdater window open, and you working in another app. It restarts itself there, without a prompt. Until such a moment arrives it simply waits, and if none ever comes the update is still applied when you quit — so the wait can delay a version, never lose one. Leaving the switch off is unchanged: you are asked, as before.

An App Store update no longer blames you for a permission you already gave. When DuoUpdater is replaced while it is running — by its own update, or by a rebuild during development — the previous copy of its background helper keeps holding the slot the system reserves for it, while macOS still reports the helper as switched on. Every App Store update then failed with a red line telling you to go turn it on in Login Items, where you would find it already on, and the button offered beside that message quietly did nothing. That state is now recognised and named for what it is, along with the one thing that clears it. DuoUpdater no longer tries to repair it by re-registering the helper: that was measured to switch the background item off and leave it unable to be switched back on.

DuoUpdater can now update itself without asking. Settings → Updates has a new switch for installing DuoUpdater's own updates in the background, taking effect the next time it restarts. It stays off unless you turn it on, and the prompt-and-wait behaviour is unchanged for everyone who leaves it alone.

Its own updates are noticed within the hour. DuoUpdater checked for its own new versions once a day, so a release could sit unseen for most of a day. It now checks hourly.

Eight more AI desktop apps are tracked. OpenCode Desktop and OpenChamber follow their GitHub releases; Wispr Flow, Granola, Comet, Windsurf, AionUi and Msty are read from their vendors' own version endpoints.

Installer packages stay the same package from verification to macOS Installer. DuoUpdater now seals the selected installer before closing or replacing any existing Installer window, checks it again immediately before opening, and refuses the hand-off if another local process changed the file in between. This preserves Sparkle's signature guarantee all the way to the package you see in Installer without making the menu-bar UI pause while large packages are checked.

Multi-installer disk images handle more real-world package names without guessing. Versioned beta, release-candidate, Apple Silicon, and universal package names are recognized when they identify one unique product, while similarly named helpers and sibling products remain excluded. Older bundle-style macOS installer packages are supported by the same integrity checks.

Failed installer downloads are cleaned up immediately. A bad signature, unreadable disk image, cancelled download, or rejected package no longer leaves a full installer sitting in temporary storage until the next day's cleanup.

Signed Sparkle updates that arrive as installer packages now work. A few apps publish a perfectly valid, cryptographically signed .pkg instead of an app archive. DuoUpdater offered those updates, downloaded them, and then tried to unpack the package as though it were a zip — an update that could never finish. They now go to macOS's own Installer, after DuoUpdater verifies both the Sparkle signature on the download and the installer identity inside it.

A disk image containing several installers is no longer allowed to make a guess. Some vendors put a main installer, helpers, and sibling products in one image. Matching on a fragment of the filename could pick a helper simply because its name contained the app's name. DuoUpdater now opens a package only when it is the sole choice or can be identified uniquely; otherwise it stops and leaves the decision to you instead of presenting the wrong installer.

The App Store helper is more tightly scoped to your login session. The privileged helper now takes the account identity directly from macOS's authenticated XPC connection and refuses a request whose claimed user does not match. Normal App Store updates behave exactly as before; the change closes off a signed client from redirecting the helper into another user's session.

Release notes show their formatting instead of its punctuation. Notes that come from a project's GitHub release were rendered exactly as written — **bold** with the asterisks, links as [text](url). Bold is now bold and links are links. This affected every app whose updates come from GitHub, which is most of the open-source ones.

Arrow-keying down the app list no longer crawls. Holding an arrow key felt like moving one row at a time through mud, and long release notes made it worse. Three things were doing it: a permission check on every app in the list ran again for every row drawn; the notes for whichever app you passed through were re-parsed on each keypress; and a long set of notes — one project's runs to 54,000 characters — was laid out in a single pass, which froze the window for about two seconds. The check is now computed once per list, parsed notes are kept, and long notes are laid out only as far as you have scrolled. Worst measured stall went from ~2.1 s to under 0.6 s, and what remains is the deliberate pause before the detail pane catches up rather than a freeze.

Input methods are never updated by replacing the app, and 微信输入法 (WeType)'s one-click from 0.3.25 is withdrawn. Settings were lost on a Mac during the work that added it. What we can show is that the copy in the protected system folder was never actually replaced by DuoUpdater — but an older copy of the input method was installed and launched elsewhere on that machine while testing, inside the window where the settings were rewritten. Nothing here is proven, and an input method's dictionary is not something to test a theory on: WeType now reports its version and sends you to the vendor's installer, which registers the input source with the system — a step that replacing the app bundle skips, and the likely reason that Mac then appeared twice in WeType's own device list.

The refusal is not specific to WeType: DuoUpdater no longer offers a one-click for anything installed as an input method, whichever vendor it comes from. Those apps still report their versions and link out.

Three more apps now report their updates, and all three install with one click. Hidden Bar, XQuartz and EasyFind were sitting in the list as a grey "unknown".

Hidden Bar is the interesting one: it ships with an update feed configured, so from the outside it looked like it was already covered. The feed answers, and is well-formed, and contains no releases at all — which is indistinguishable from a healthy feed until you look inside it. Its version now comes from its release tags instead. EasyFind ships no updater at all, so a copy installed from the vendor's site had no way to learn about new versions.

XQuartz installs through the system installer rather than by replacing the app, because it is not just an app: it lays down a whole X11 stack, and swapping only the app bundle would leave the rest at the old version. macOS asks for the administrator password itself, as it does for any package.

Thirteen more apps now report their updates, twelve of them with one click. GIMP, MongoDB Compass, Meld, Emacs, Tor Browser, Zotero, GrandPerspective, TigerVNC, qBittorrent, Opera, LibreOffice, pgAdmin 4 and Telegram Desktop were all sitting in the list as a grey "unknown" — installed, with nothing to say about them. Each was worked out by downloading the vendor's actual build and reading its identity out of it, so a one-click only appears where the download is signed by the same developer as the copy you already have. The exception is qBittorrent: its own build isn't signed by an identified developer at all, so it reports its version and sends you to the project's page.

Opera, LibreOffice and pgAdmin 4 nearly joined that exception. All three publish nothing but a directory listing, and listings sort alphabetically — "100" comes before "99" — so the newest release is not the first one on the page. Reading the version was never the problem; building a download link was, because the obvious way to build one would have picked whichever release happened to be listed first. They now download the release that was actually compared. That is the one mistake a signature check cannot catch for you: an older build of the right app, signed perfectly.

1Password and Inkscape now install with one click too, and both were previously written off. 1Password's official download turns out to be a small installer program rather than the app — signed and notarised by 1Password, so every safety check passes it, and installing it would have replaced your password manager with its own installer. DuoUpdater now fetches the package that installer itself downloads. Inkscape's download page hands out its file through a one-time link that changes with every release; the same file also sits at a plain, predictable address, which is what gets used.

微信输入法 (WeType) now installs with one click. It lives in a folder only an administrator can write to, which is why it used to only report its version. It now goes through the same administrator prompt as any other app in a protected location.

Release notes for Opera, Inkscape and 1Password. Opera publishes one page per major version, Inkscape one wiki page per release, and 1Password a feed — all three now render as proper change lists in the app instead of a link out. 1Password's version and its notes both come from that feed now, which is a published interface, rather than from scraping the page beside it.

Discord's version check works again. Discord moved its downloads to a different server and the check was still looking at the old address, so DuoUpdater quietly reported "no version" for Discord Stable while everything else kept working. It now keys off the part of the address that names the release channel, which is the part that actually has to be right.

Fifteen more apps now report their updates, and all but one install with one click. Rancher Desktop, Cherry Studio, RedisInsight, Upscayl, WailBrew, Wave Terminal, Lens, Termius, Unity Hub, iStat Menus, Inkscape, Google Gemini, Antigravity, AnyDesk and Kiro were all showing as a grey "unknown" — installed, with nothing to say about them. Each one was worked out by reading the vendor's own build rather than trusting a download page: the version now comes from wherever that app's own updater looks, and a one-click only appears where the download is signed by the same developer as the copy you already have. Three of them (Google Gemini, Antigravity, Kiro) publish nothing a download page can be scraped for; their real update services answer the same questions their own updaters ask, so that is what DuoUpdater asks too.

AnyDesk in particular was written off and shouldn't have been. Its download and changelog pages both refuse anything that isn't a person with a browser, so an earlier sweep concluded the app was unreachable. The plain-text changelog on the same server answers fine — and it is what AnyDesk's own Homebrew entry has always read.

Updating an app in a location that needs an administrator password now asks, once. Most apps live in /Applications, which you can write to; a few — input methods, for one — live where only an administrator can. Those used to show an Update button that could never work. Now the button asks for the password, and if you dismiss that prompt DuoUpdater takes the hint: the row switches to Open and stops asking on every release. "Ask for administrator access again" in the row's right-click menu brings the button back. The choice is remembered for that copy of the app specifically, so declining for one install doesn't silence another.

An up-to-date Xcode beta no longer claims the vendor is behind it. Under "Show all", a row whose vendor has fallen behind what you have installed shows a muted note saying so — you're ahead, nothing to do. Xcode was getting that note while sitting on exactly the build Apple was offering: it publishes a build number plus a human label ("27.0 beta 5"), and comparing that label against the plain "27.0" the bundle reports made a release look newer than its own beta. The note now settles on the build whenever both sides have one, so the same release is recognised as the same release however it is labelled. A vendor that has genuinely fallen behind is still called out.

44 more apps now report their updates. Apps that publish on GitHub but ship no update feed of their own used to sit in the list as a grey "unknown" — DuoUpdater could see them installed and had nothing to say about them. Bruno, UTM, kitty, KeePassXC, Godot, Bitwarden, VSCodium, draw.io, Podman Desktop, Anki, Raspberry Pi Imager, LuLu, MarkEdit, Clash Verge, Freelens, Tabby, Espanso, Moonlight, SwiftBar, Sequel Ace, balenaEtcher, DB Browser for SQLite, OpenLens, Headlamp, OpenMTP, Goose, Caffeine, noTunes, KeepingYouAwake, MiddleClick and a dozen more now show a real version, and 36 of them install with one click like any other app. Which ones was decided by downloading each vendor's actual build and reading the identity out of it, so a one-click only appears where the download is signed by the same developer as the copy you already have. Seven — Alacritty, Flameshot, MarkText, darktable, OWASP ZAP, BlueBubbles and Wine — publish builds Apple hasn't notarised, so those report their version and send you to the vendor rather than installing anything. LocalSend is report-only for a different reason, corrected here after this version shipped: its builds are notarised, but its newest release attaches no macOS download at all, so there is nothing to install until the project starts publishing one again.

Apps that already carry a Sparkle feed needed nothing: they were checked as part of this sweep and were already working, which is why names like Rectangle, Maccy, iTerm2 and Telegram aren't in the list above.

An update that your Mac couldn't run is now refused rather than installed. Where a developer publishes one download per processor, DuoUpdater picks between them by the file's name — and names are not always honest: three of the apps above ship an Apple silicon build under a name that says nothing about it, or says the opposite. Before an app is replaced, its new version is now checked against the processor in your Mac, read out of the program itself instead of its name. If it can't run here, the update stops and your working copy is left exactly as it was. Nothing about a normal update changes; this is the case that used to end with an app that no longer opened.

An unanswered permission prompt no longer leaves the update check hanging. To tell a TestFlight build apart from an App Store one, DuoUpdater reads TestFlight's own database, and macOS keeps that behind the "access data from other apps" permission. Until that was answered the read didn't fail — it waited, indefinitely, for a prompt that might be sitting behind another window or might never be answered at all, and the scan behind it simply never finished. Nothing timed out and nothing said why. It now waits a few seconds and then carries on without TestFlight's side of the story; the only thing missing in the meantime is whether those particular apps came from TestFlight, and it sorts itself out on the next scan once the permission is granted.

Homebrew updates work behind a proxy. If your Mac reaches the internet through a proxy, upgrading brew packages failed with curl: (28) Failed to connect while every other update went through fine. Homebrew shells out to curl, which — unlike the rest of DuoUpdater's networking — doesn't read the proxy you configured in System Settings; it only reads proxy environment variables, and an app launched from the Dock or at login has none. DuoUpdater now passes your system proxy settings down to Homebrew itself. Nothing changes on a machine with no proxy configured, and a proxy you've already exported in your own shell still wins.

Claude's updates now show up while they're still rolling out. Anthropic releases Claude in stages: a build goes to a fraction of Macs at a time, and the public download page only catches up at the end. DuoUpdater was reading that public page, so for the whole of a rollout — most of a day, in the case of 1.30096.5 — it told you Claude was up to date while Claude itself had already quietly downloaded the new version and was waiting for a relaunch. It now also asks the same endpoint Claude's own updater asks, which answers for your Mac specifically, and offers whichever of the two is further ahead. Nothing about which build you're offered has changed: it is either the public release or the one your Mac was already allocated. Claude also gains real publication times, so its releases now appear in the Release Log with the moment Anthropic shipped them rather than an estimate.

A superseded package update no longer leaves its window sitting there. Updates that go through macOS's own installer — Microsoft Office, AweSun, ToDesk — open an Installer window and then wait for you. If you left one open and a newer release came along, installing that one opened a second window, and they stacked up. The older window is now closed once its replacement is ready, and its download cleaned up with it. A window that's mid-install, or asking for your password, is left strictly alone.

duo says which copy is which when two apps share a name. Naming an app that is installed twice — two Xcode betas, say — printed both candidates as a bare "Xcode" and told you to name one exactly, which matches both again. The listing now carries each copy's version, and when the matches genuinely share a name it asks for the path instead of repeating advice that cannot work.

"Open download page" no longer downloads a file. On apps whose page DuoUpdater knows — ToDesk and UU Remote among them — that button handed your browser the installer package instead of opening anything: the link it used was the same one the updater downloads from, so clicking it started a download you didn't ask for. The page and the package are now kept apart, and the button opens the vendor's actual download page. Where a source only ever publishes a package and no page at all — a bare Sparkle feed — there is now no button rather than one that downloads something.

The app list responds to the arrow keys again. Opening the workbench window left the keyboard focus nowhere in particular, so ↑ and ↓ did nothing until you clicked a row — and after clicking into the release notes on the right, or switching to another app and back, they stopped working again. The list now takes the keyboard when it opens and takes it back at the points it used to lose it. Typing in the search box is untouched: a search you've started keeps the caret.

The Brew section starts collapsed. Casks and command-line formulae are a side channel for most people, and having that tree open by default pushed your actual apps up the sidebar every time the window opened. It now starts closed and remembers however you leave it.

Xcode betas and release candidates are now detected, and two copies can be told apart. Xcode was a grey "v27.0" with no update information at all, and if you keep more than one build around — a current beta beside the previous one — they were indistinguishable: same name, same version, same icon. Each row now reads its real build, so an update shows as "27.0 beta 1 (27A5194q) → 27.0 beta 5 (27A5237l)". Which track a copy belongs to is worked out from Apple's published builds rather than guessed from what you named the folder, and you'll only ever be pointed at something at least as finished as what you have — a beta can be superseded by a beta, a release candidate or the finished release, never the other way round. Updating still means going to Apple: the downloads need you signed in with your Apple ID, so the row links to Apple's download page and its release notes.

Cursor's release notes are shown properly instead of an embedded web page. Cursor writes its changelog as dated posts rather than numbered releases, so the notes pane fell back to loading the website. Each post is now shown as its own entry — its date, its headline and its changes — the same as every other app with readable notes.

duo check now shows what changed when the version number doesn't. Updates that keep the same version and only move the build — Surge, the JetBrains previews — printed as "6.9.0 → 6.9.0" on the command line, which was accurate and told you nothing. It now shows the builds, matching what the menu bar has always shown.

Apps that ship their own updater are now updated directly by default. These are the ones like Chrome, VS Code, Cursor and the Electron apps — and because they are also the apps you tend to leave running all day, the old default of stepping aside while they were open meant they were almost never updated at all: the row offered to open the app and left the rest to you. DuoUpdater now downloads the vendor's own installer and applies it whether or not the app is running, then quits and relaunches it so the new version takes effect. Anything that installs background components alongside the app — Tailscale, Office — ships a package that macOS's own installer handles, so those pieces are still put in place properly. If you would rather nothing was touched while an app is open, Settings → General → Self-updating apps still has the old behaviour, and changing it back does not affect anything already installed.

An app whose developer changed its update signing key can be updated again. Apps that update through Sparkle sign each release with a key, and the copy you already have carries the matching public key to check it against. If a developer generates a new key and ships it without a hand-over release signed by the old one, that check fails for everybody — the app's own updater is just as stuck as DuoUpdater was, and the update sits there refusing to install with a signature error. DuoUpdater now recognises that specific situation: when the new download carries a different key of its own and the release was signed with it, it stops trusting the signature and falls back to the same checks it uses for apps that publish no signature at all — the download must be validly signed by Apple's developer certificates, and by the same developer as the app it is replacing, for the same app. A download that fails any of that is still refused, as is a bad signature that isn't explained by a key change. Mirage Beacon 1.3.0 was the first to hit this.

Update All no longer says a running app is finished before its restart. When an update had already replaced an app on disk but Update All was still busy with other installers, the row briefly showed a green checkmark and disappeared even though the old version was still running. The app now stays visible with its running and installed versions, explains that it is waiting for the batch restart, and offers Restart now. The completion checkmark appears only when the update is actually in effect.

Apps installed by a .pkg can now be rolled back. DuoUpdater keeps a copy of the previous version before it updates an app, so a bad update can be undone. Apps that install through macOS's own installer — Microsoft Office, AweSun, ToDesk and the like — never got that copy: the rollback was skipped for them entirely, so the one kind of update DuoUpdater can't watch land was also the one you couldn't back out of. They're now backed up like everything else.

Rollback no longer refuses apps that write inside their own bundle. Some apps keep working files in amongst their own program files — ToDesk stores its settings database and logs there, and doing so breaks the seal Apple puts on an app. DuoUpdater checked that seal before restoring a backup, so for those apps it declared a perfectly good backup damaged and refused to put it back. It now checks the copy against a fingerprint taken when the copy was made, which is the thing that actually matters: that what's being restored is exactly what was saved. Tampering with a stored backup is still caught, and still refused.

When a backup isn't possible, it says so instead of failing quietly. A few apps keep program files that your account simply can't read — EasyConnect is one — and no copy of those can be made. Rather than attempting it and reporting a failure part-way through an update, DuoUpdater now checks first, tells you which file is in the way, and updates anyway; you just don't get a rollback point for that one app.

The same app no longer appears several times over. Some apps leave a dated copy of themselves behind every time they update — DuoPaste, for one, parks a DuoPaste.backup-20260716-183428.app next to the real thing on each self-update. Those copies are complete, working app bundles as far as anything on disk can tell, so DuoUpdater listed each one as its own app: three identical DuoPaste rows, each offering the same update. Worse, taking one of those offers would have installed the new version into the backup, leaving the app you actually use untouched and creating another stray copy. Backup and duplicate bundles are now recognised for what they are and left out of the list, as are exact clones of an app found in two places. Genuinely separate installs that happen to share an identity — Firefox alongside Firefox Beta, two versions of Android Studio kept side by side — still each get their own row.

The list now reliably notices apps appearing and disappearing. DuoUpdater watches your Applications folders so that an app updating itself in the background, or one you drag to the Trash, is reflected within a few seconds. That watch could quietly stop working — nothing crashed, nothing was reported, it simply stopped hearing about changes, and the list then went stale until you reopened the window. It's now rebuilt periodically and after your Mac wakes from sleep, with a fresh scan each time, so a watch that dies recovers on its own instead of staying dead for the rest of the session.

An app that gets restarted after an update no longer jumps in front of what you're doing. When DuoUpdater updates an app that's currently running, it quits and reopens it so the new version actually takes effect. Reopening it also pulled it to the front — so an update to something sitting quietly in the background could drop a window on top of the thing you were typing into. The app's position now survives the restart: whatever was in front comes back in front, and whatever was in the background comes back in the background, still there and still updated, just not in your way. The same applies to apps DuoUpdater reopens after an App Store update. Apps that weren't running at all are, as before, updated on disk and left closed — updating an app never starts it up.

Fixes AweSun's update failing with "the server returned HTTP 404". DuoUpdater worked out where to download AweSun's installer by building the filename itself from the version number. Oray then renamed the file — the same 16.6.0 build, one letter's difference — and every attempt at the update hit a dead link. It now takes the filename straight from Oray's own download listing rather than guessing at it, so a future rename won't break it again.

An installer you've already downloaded no longer downloads again. Some apps update through an installer package that macOS opens for you to confirm. If you closed that window without finishing — or quit DuoUpdater and came back — the row went back to offering "Update", and taking it fetched the whole package a second time. ToDesk's is 375 MB. The download was on your disk the entire time; nothing was pointing at it. Those rows now offer "Install" instead, which just re-opens the file you already have. If the installer window is still open it comes forward rather than opening a second one, and the offer stands until either the download is gone or a newer version comes out — at which point the old package would be the wrong one, so the row goes back to a normal "Update".

Homebrew packages that aren't apps now show up. DuoUpdater tracked outdated Homebrew formulae, and left casks alone on the grounds that a cask installs an app, which already gets its own row. That holds right up until a cask installs no app — a command-line tool like codex, a font, a driver. Those had no row anywhere: nothing for the app list to find, and not a formula either. codex sat three versions behind without a word. They're now part of the Homebrew panel, which reads "packages" rather than "formulae" to match. Casks that do install an app are still managed per-app exactly as before, and apps that update themselves are still left to their own updater.

"Update All" now includes apps that install from a package. A handful of apps — ToDesk and AweSun among them — ship their update as an installer package rather than something DuoUpdater can swap into place on its own. Those were quietly left out of "Update All" and had to be updated one row at a time; if such an app was the only other update pending, the button disappeared altogether rather than acting on just one. They're now part of the batch, and they run at the very end: everything that updates unattended finishes first, so nothing opens a window or asks for your admin password until the rest is already done. One caveat worth knowing — DuoUpdater can't tell when macOS's installer has finished, so if two package updates come up in the same batch, both installer windows open one after the other rather than waiting in line.

Fixes updates going unnoticed for days at a time. DuoUpdater re-uses the answers it gets from each app's version feed so it isn't re-downloading the same file every few minutes. The problem was how long it trusted a stored answer: when a vendor's server doesn't say how long its reply stays valid, macOS guesses — and it guesses longer the longer that feed has gone unchanged. So the very feeds that had been quiet for a while were exactly the ones DuoUpdater stopped re-reading, and a new release could sit there for days with the app still reporting "up to date" and no error to show for it. Every version check now always asks the server whether anything changed, while still skipping the download when nothing has. OrbStack 2.2.2 is the release that surfaced this; the same blind spot applied to most apps checked directly against their vendor, including Chrome, Cursor, Claude, ChatGPT, Warp, Spotify, and Visual Studio Code.

Homebrew-managed apps no longer get stuck at the version they were on when DuoUpdater started. The catalog DuoUpdater reads to learn the latest version of a Homebrew app was loaded once per launch and never refreshed, which is invisible if you quit the app daily and wrong if you leave it running for weeks. It now refreshes periodically. As a bonus, machines with no Homebrew casks installed no longer download that 5 MB catalog at all.

Uses less memory and does less work in the background. This release is entirely under the hood — nothing about what DuoUpdater does has changed, only what it costs to leave running. Every update it downloaded used to leave a small amount of memory behind that was never reclaimed; harmless once, but it adds up over the weeks a menu-bar app tends to stay open. Separately, while the main window was open DuoUpdater re-read every installed app from disk every 15 seconds and started a system process each time to see what was running — that now happens every three minutes, since the filesystem watcher already notices a real change the moment it happens. Recording the release history after each check also used to save its file once per app rather than once per check, and release notes could be fetched more than once when the same page was already on its way in.

No more beachball while an app is relaunching. Clicking Update on another app while one was being quit and relaunched could freeze DuoUpdater for a moment — the spinning rainbow cursor, an unresponsive window, a click that seemingly did nothing. Relaunching an app now happens in the background instead of on the interface, so the rest of the list stays live and clickable throughout. The same freeze could show up when opening an app from a row's right-click menu, or when handing an update off to an app's own updater; both are fixed too.

Backups from uninstalled apps are now cleaned up automatically. DuoUpdater keeps one backup of an app's previous version so an update can be rolled back. Backups for apps you've since uninstalled or moved were never reclaimed and could quietly pile up gigabytes of disk space over time. They're now deleted automatically during the regular update check. Settings shows how much space backups are currently using, with a toggle to turn off the automatic cleanup and a "Clean Up Now" button to run it on demand.

JetBrains Toolbox apps no longer show a stuck or incorrect "update available." Version checks for Toolbox-managed apps (IntelliJ, Android Studio, Fleet, Air, and others) now always ask live rather than sometimes falling back to a local cache that could never actually report a new version — it fixes both a status that lingered after Toolbox had already installed the update, and one that never appeared in the first place.

Claude Desktop's release notes are now shown in DuoUpdater. Update entries for Claude Desktop now include Anthropic's own per-version changelog instead of a generic notice.

Update All now also relaunches apps that were only waiting on a restart. If an app had already downloaded its update and just needed a relaunch to finish — Claude, for instance — clicking Update All used to skip it, leaving a stray "Relaunch" button behind. It now relaunches those too, in the same pass, whenever automatic restart-after-update is on.

App Store updates recover from a receipt hiccup instead of just failing. Occasionally a Mac App Store update downloads in full but the very last install step trips over a "receipt" error — a transient App Store glitch that a second attempt usually clears. DuoUpdater now retries once automatically. If it still doesn't take, the row offers an "Open App Store" button to finish the update from the App Store's Updates page, instead of leaving a raw error on screen.

ToDesk update detection fixed. A change to ToDesk's download page stopped DuoUpdater from reading its latest Mac version, so ToDesk updates went unnoticed. Detection now reads the version reliably again.

App Store updates no longer show a scary error for an app that's already up to date. If the Mac App Store had quietly updated an app in the background — TestFlight, say — DuoUpdater's row could go stale and, on Update, try to reinstall the version that was already there. macOS's installer rejects that with an alarming red "The upgrade failed", even though nothing was actually wrong. DuoUpdater now confirms an App Store app really is behind before reinstalling, and treats a no-op reinstall as "already up to date" — settling the row quietly instead of showing an error.

App Store updates now ride out network hiccups. A brief connection drop mid-update — a flaky link, or a proxy resetting the connection — used to fail an App Store update outright with a "could not connect to the server" error. Those updates now retry automatically a few times before giving up, so a momentary blip no longer strands an update that a second attempt lands cleanly. Clicking Update again after a failure also clears the old error immediately, instead of leaving it on screen next to the spinner.

Apps that update themselves clear from the list faster. When an app like Chrome finishes updating itself in the background while an App Store update is running, its "update available" row now clears promptly — it no longer lingers until the rest of the queue finishes.

One-click updates for four more apps. HBuilderX, JetBrains Toolbox, and Microsoft Edge's Beta and Dev channels now update in place with a single click, instead of only telling you that an update exists. HBuilderX also now reads its version straight from DCloud's own release feed, so it picks up new builds sooner and more reliably.

Self-updating apps stay in their own lane. A running app that ships its own Sparkle updater is now handed off to that updater — the same courtesy DuoUpdater already gave other self-updating apps — instead of being replaced underneath it, unless you've chosen "Always replace" in Settings.

Fixes

  • The running-app dot and "Relaunch" badge no longer briefly lose track of an app right after an in-place update, when macOS keeps its process pinned to the temporary swap location for a moment.
  • When you restart an app yourself after it updated in the background, the "Relaunch" badge now clears the moment the app comes back up — instead of lingering until the next background check.

Fixes

  • When you restart an app yourself after it updated in the background, the "Relaunch" badge now clears the moment the app comes back up — instead of lingering until the next background check.

See when your apps actually ship. DuoUpdater now keeps a Release Log: a running timeline of every release the apps you track put out, each stamped with its publish time. Open it from the clock icon at the bottom of the popover.

Release-habit heatmap. A new Patterns view charts releases by weekday and hour, so you can see when an app tends to ship — pick any single app for its own pattern and version history, or view all of them together. History is backfilled from each app's update feed, so the heatmap is useful right away instead of starting empty.

Honest about what it can't time. Apps that publish an exact release date (Sparkle, GitHub, Alcove) are timed to the minute. Apps that only expose a version number get a clearly-marked "≈" estimated window — bounded by when DuoUpdater last saw the old version and first saw the new one — and never skew the heatmap.

Fixes

  • ToDesk update checks no longer report an older grayscale build; they now track the version actually offered for download.

Passwordless App Store updates. Updating Mac App Store apps no longer interrupts you for your password every time. DuoUpdater now installs a small, signed privileged helper (one-time approval) and bundles mas, so App Store updates apply directly in the background.

Cleaner "Restart to finish" lines. When an app updates itself on disk while it's still running, the pending-restart line now shows the real marketing version on both sides — e.g. 1.8.x (build) → 1.9.0 (build) instead of a bare build number on the left.

Fixes

  • Fixed a build issue on Xcode 26.5 (changelog extractor name collision).

Apps that update themselves now clear correctly. If an app updated through its own updater (for example, Chrome via "About Chrome") while DuoUpdater was busy installing other updates, it could keep showing a stale "update available" row long after it was already current. DuoUpdater now re-checks the moment the installs finish, so the row clears right away instead of lingering.

"Update All" shows the whole queue. Every app in an "Update All" run now shows a "Queued" state immediately, instead of leaving the ones further down the list looking idle with a clickable Update button. Clicking Update on an app that's already queued can no longer start a second install of it.