Novidades

Todas as versões, da mais recente para a mais antiga — as mesmas notas que o app mostra quando se atualiza. Os downloads estão na página de versões. As versões mais antigas aparecem em inglês.

O novo ícone agora aparece corretamente no macOS 26. No estilo escuro, a seta e o anel não se fundem mais em manchas sólidas, e a cabeça e as orelhas do gato têm bordas limpas em vez de serrilhadas.

Fechar a bancada agora libera a memória usada pelas notas de versão. Antes, uma página de notas de versão que você tinha aberto continuava rodando em segundo plano até você sair do DuoUpdater.

Um novo ícone. Um gato siamês enrolado, com o rabo formando a seta de atualizar. No macOS 26 e posterior, ele segue o seu estilo de ícones claro, escuro ou colorido.

As verificações em segundo plano esperam enquanto você está no Modo Dados Reduzidos ou numa conexão limitada, como o Acesso Pessoal do iPhone. Elas rodam assim que você volta a uma rede normal. Verificar manualmente e instalar atualizações funcionam como antes.

Verificações que falham por uma instabilidade da rede são repetidas uma vez, dois minutos depois. Antes, as linhas com falha e o aviso ficavam até a próxima verificação agendada, seis horas depois por padrão.

Nos bastidores. As imagens das notas de versão ocupam bem menos espaço em disco, o painel Requisições não conta mais duas vezes uma requisição revalidada e a verificação do Muse não baixa mais a página de login dele.

Apps do Homebrew que se instalam com o próprio script de instalação, como o Quark Cloud Drive, agora são atualizados com um clique. Antes, toda tentativa terminava com um erro dizendo que não havia nenhum pacote de instalação.

Apps do Homebrew cujo instalador precisa ser executado por você agora mostram a atualização com um link, em vez de falhar. Antes, o DuoUpdater baixava o instalador inteiro e depois parava com um erro.

Mais apps do Homebrew são reconhecidos. Apps que o Homebrew instala com outro nome, como o Visual Paradigm Community Edition, agora são verificados, e um app de nome parecido não é mais confundido com eles.

Apps cujo cask do Homebrew foi retirado não recebem mais a oferta de uma atualização que o Homebrew se recusa a instalar. Em vez disso, eles são verificados pelo canal de atualizações do próprio app, quando existe um.

As notas de versão do VS Code voltam a aparecer.

Nos bastidores. Ajustes › Diagnóstico não fica mais avisando sobre o Antigravity e o OpenLens quando as atualizações deles são encontradas por outro caminho.

O Blender baixado do blender.org agora recebe atualizações, com um clique. Antes, só uma cópia instalada pelo Homebrew era verificada.

As versões alfa, beta e release candidate (RC) do Blender seguem seu próprio canal. O DuoUpdater identifica que tipo de versão você tem e avisa quando sai uma mais nova do mesmo tipo. Uma alfa nunca recebe a oferta de uma versão estável, nem o contrário.

As atualizações do Muse voltam a aparecer. Depois que o Muse passou a pedir login no link de download, a linha dele mostrava um erro em vez da nova versão.

Nos bastidores. O popover da barra de menus e a bancada abrem um pouco mais rápido na primeira vez depois de iniciar o app, e o duo check agora lista os apps cuja verificação falhou em vez de dizer que tudo está atualizado.

O DuoUpdater agora fala italiano, chinês tradicional, português (Brasil) e turco. São onze idiomas no total. Em alemão, espanhol e japonês, textos errados ou cortados foram corrigidos. Ajustes → Pastas agora mostra os nomes das pastas como o Finder mostra no seu idioma.

Apps que você instalou com o Homebrew agora são atualizados pelo Homebrew. Isso vale para apps instalados com o brew que também têm seu próprio atualizador. Antes, o DuoUpdater os atualizava diretamente sem que o Homebrew soubesse, e o brew upgrade seguinte baixava e reinstalava a versão que você já tinha.

As janelas abrem no Space em que você está. Antes, reabrir os Ajustes ou outra janela do DuoUpdater depois de fechá-la podia levar você de volta ao Space em que ela foi mostrada pela última vez.

Uma atualização, uma notificação. Alguns apps são verificados por duas fontes, e elas podiam anunciar a mesma versão nova várias e várias vezes.

O Registro de Versões não mostra mais versões com data no futuro. Se o feed de um desenvolvedor informa uma data posterior ao momento em que o DuoUpdater viu a versão pela primeira vez, o registro usa esse momento.

Com o disco de backup desconectado, a janela da bancada volta a caber na tela, e Copiar Agora diz por que não consegue copiar. Antes, a janela podia ficar mais alta que a tela, de modo que as listas não rolavam até o fim, e Copiar Agora não fazia nada sem avisar.

Os betas e release candidates do Xcode agora são atualizados com um clique. Inicie sessão uma vez na sua conta Apple Developer em Ajustes → Xcode, e o DuoUpdater baixa e instala os novos betas e RCs como qualquer outra atualização. Antes, ele só conseguia avisar que havia um novo.

Instale qualquer versão do Xcode ao lado das que você já tem. Ajustes → Xcode lista todas as versões do Xcode, agrupadas por versão, com o grupo do seu macOS já aberto. Instalar coloca a que você escolher na pasta Aplicativos como uma cópia separada (por exemplo, Xcode-26.6.app) e não substitui nada. Você também pode salvar apenas o arquivo (.xip). Com a sessão iniciada, a própria lista da Apple também é incluída, então as novas versões aparecem em poucos minutos.

Sua sessão do Apple Developer se renova sozinha. A Apple encerra uma sessão de desenvolvedor depois de cerca de oito horas. Agora o DuoUpdater obtém uma nova em segundo plano, sem janela e sem senha, enquanto a Apple ainda reconhecer este Mac. Você pode desativar isso em Ajustes → Xcode.

As novas versões do Xcode aparecem mais cedo. Nos dias úteis, durante o horário em que a Apple costuma publicar, o DuoUpdater procura um novo Xcode a cada cinco minutos.

Alguns apps voltaram a funcionar depois que seus desenvolvedores mudaram coisas. O CapCut beta e o Superconductor nightly voltam a ser encontrados e instalados, e o Superconductor mantém sua identidade de app atual. O VLC 3.0.24 e o JetBrains Air voltam a mostrar suas notas de versão.

O Qoder CN IDE agora é compatível. A edição do IDE da Qoder para a China continental ganha verificação de atualizações, instalação com um clique e suas notas de versão na janela. O Qoder CN, o app de desktop, agora também mostra suas notas de versão.

O Qoder IDE não muda mais de ideia sobre qual é a versão mais recente. A Qoder distribui as atualizações de forma gradual, e agora o DuoUpdater pergunta da mesma forma que a sua cópia do IDE, então recebe sempre a mesma resposta. Antes, a versão oferecida podia alternar entre duas versões, e uma instalação com um clique podia parar no meio porque a resposta mudou.

Apps com Sparkle que baixaram uma atualização que já ficou desatualizada podem ser atualizados de novo. Se um app que se atualiza sozinho pelo Sparkle baixou um build e depois saiu um mais novo, o DuoUpdater agora descarta o download antigo e instala o mais recente. Antes, Atualizar continuava dizendo que instalar agora seria desfeito, e a linha nunca mudava.

O duo install avisa quando o build mais recente já está esperando. Se o próprio atualizador de um app já baixou a versão mais recente, ele agora diz isso e sugere encerrar o app ou executar duo restart. Antes, dizia por engano que o app só podia ser verificado, e não instalado.

O 搜狗输入法 agora é atualizado com um clique. O DuoUpdater aplica a atualização do mesmo jeito que o próprio método de entrada se atualiza — mantendo o pacote instalado no lugar — e antes faz uma cópia do seu dicionário e dos seus ajustes, para que uma reversão também os traga de volta.

Os backups em outro disco agora preservam o dicionário e os ajustes de um método de entrada. Antes, só o app em si era movido para o disco de backup, então reverter um método de entrada a partir dali deixava para trás os dados da versão mais nova.

Chega de atualizações que nunca podem ser instaladas. O JetBrains Air agora mostra o build que o Toolbox realmente oferece. Um app da App Store que ficou para trás com o nome antigo depois que o desenvolvedor o renomeou agora informa qual cópia a App Store atualiza, em vez de oferecer uma atualização que só reinstala a outra cópia.

As notas de versão de mais apps aparecem formatadas. Os apps que publicam suas notas em Markdown agora recebem a mesma lista nativa que todos os outros. Antes, as notas apareciam como texto simples.

Reabrir não concorre mais com o instalador do próprio app. Quando um app baixou a própria atualização e o backup de reversão dele fica em um disco externo, essa cópia agora espera o instalador terminar. Antes, ela acontecia durante os poucos segundos que o macOS dá ao instalador para fazer o trabalho.

Os backups de reversão agora podem ficar em outro disco. Um backup é uma cópia inteira de um app, e no disco de inicialização eles se acumulam. Ajustes → Backups lista os discos conectados com o espaço livre de cada um, move os backups que você já tem e grava os novos lá em segundo plano — se você desconectar o disco, terá uma espera, não um ponto de reversão faltando. O duo backups ganhou disks, sync, verify e probe.

O 千问输入法 agora é compatível. O DuoUpdater avisa quando sai uma nova versão e atualiza o método de entrada do mesmo jeito que ele se atualiza sozinho.

As notas de versão não ficam mais presas na versão anterior. Quando um desenvolvedor publicava uma atualização alguns minutos antes de a página de histórico de alterações mencioná-la, as notas antigas eram arquivadas sob a versão nova e ficavam lá para sempre. O CleanShot X vinha mostrando as notas da 5.0 sob a 5.0.1 desde o dia do lançamento.

Apagar um backup agora libera o espaço que diz liberar. Os backups feitos por versões anteriores do DuoUpdater eram gravados de um jeito que o macOS se recusa a apagar, então Limpar deixava quase toda a cópia no disco e ainda assim a contava como espaço recuperado.

Limpar abre na hora. Antes, ele media do zero cada backup guardado toda vez que você clicava.

O WorkBuddy volta a mostrar sua versão mais recente. O serviço de atualização dele responde com o próximo passo de uma cadeia de atualizações, e não com o build mais novo, então as quatro edições do WorkBuddy ficavam duas versões atrás.

Nos bastidores. Um app que nunca declarou qual binário executa — o Muse, da Meta, entre eles — agora tem seus frameworks e seu SDK lidos mesmo assim.

As atualizações concluídas por Reabrir agora podem ser revertidas. Quando um app já baixou a própria atualização e você clica em Reabrir, o DuoUpdater agora salva a versão atual antes, então a atualização aparece em Reversão como qualquer outra. Antes, só as atualizações que o próprio DuoUpdater instalava podiam ser desfeitas.

Veja o que uma atualização mudou dentro de um app. Para qualquer app com uma versão anterior salva, a bancada agora tem uma visualização Diferenças do Pacote ao lado de Notas de Versão: assinatura e permissões, macOS mínimo, itens de segundo plano e de início de sessão, bibliotecas incluídas e os arquivos que foram adicionados, removidos ou mudaram de tamanho. O duo diff faz o mesmo pelo Terminal para quaisquer duas cópias de um app.

Reabrir avisa quando o próprio atualizador de um app não aplicou a atualização. Se o app fecha e a atualização nunca chega, a linha agora diz isso e continua oferecendo Reabrir. Antes, o indicador de progresso parava sem dizer nada.

O Cherry Studio volta a mostrar sua versão mais recente. Depois que o Cherry Studio renomeou seus downloads para Mac, o DuoUpdater passou a tratar uma versão mais antiga como a mais recente, então as cópias recentes apareciam como “atualizado” e às antigas era oferecido esse build mais antigo.

As atualizações da App Store não travam mais atrás de um auxiliar que não responde. Quando o auxiliar do DuoUpdater parava de responder, a atualização ficava em 0% e todas as atualizações da App Store na fila atrás dela esperavam até você encerrar o DuoUpdater.

Atualizar Tudo não reabre mais apps que você ignorou. Com “Reabrir apps atualizados automaticamente” ativado, o fim de um lote podia encerrar e reabrir um app ignorado, ou um cuja versão baixada você tinha pulado.

O Tinycast e o SuperCmd agora são compatíveis. O DuoUpdater avisa quando sai uma nova versão do Tinycast, ou do beta dele, e agora reconhece o SuperCmd original de código aberto ao lado do SuperCmd 2. As notas de versão do Kimi Code também passam a aparecer.

As notas de versão correspondem à versão oferecida. A página de notas de versão mais recente do VS Code aparecia vazia, e logo depois que surgia uma nova versão, o painel de notas podia mostrar a versão anterior.

O Registro de Versões não adiciona mais a mesma versão a cada abertura. Apps como Claude, Raycast e Cline ganhavam uma entrada duplicada toda vez que o DuoUpdater era aberto.

A barra lateral da bancada foi dividida nas abas Apps, Brew e Reversão. Clique em uma aba ou arraste por elas para alternar; a busca filtra as três ao mesmo tempo.

Nos bastidores. Reabrir e Reverter no mesmo app não se atropelam mais; um feed de atualização não consegue mais fazer o DuoUpdater apagar arquivos fora da pasta de downloads dele; as verificações em segundo plano não correm mais o risco de o macOS pedir acesso aos dados de outros apps; um número muito grande no filtro de Requisições não fecha mais o app; e a barra de menus agora respeita um pedido de administrador que você recusou no duo install.

As atualizações do iStat Menus são detectadas corretamente. Quando o iStat Menus relançava uma atualização, o DuoUpdater podia continuar oferecendo-a depois de instalada, e clicar em Atualizar de novo terminava em erro.

O Memoh Desktop agora é compatível. O DuoUpdater avisa quando sai uma nova versão e pode atualizá-lo com um clique.

Atualizar Tudo não pede mais para reabrir um app da App Store que já foi reaberto. Quando a App Store fecha um app e o reabre na versão nova, a linha dele agora aparece como atualizada na hora, em vez de mostrar “Reabrir agora” até o lote inteiro terminar.

Um app que já baixou a própria atualização não tem mais essa atualização baixada duas vezes. Alguns apps baixam uma atualização discretamente em segundo plano e depois esperam você reiniciá-los. Clique em Atualizar no DuoUpdater e ele agora instala a cópia que já está no seu disco: a atualização é aplicada em segundos e não custa nenhum download. Antes, o DuoUpdater baixava a mesma versão tudo de novo.

O Cua Driver e o Petex agora são compatíveis. O DuoUpdater avisa quando qualquer um dos dois tem uma nova versão, e o Cua Driver também é atualizado com um clique e mostra suas notas de versão.

A mesma atualização não gera mais notificações repetidas. Quando o servidor de um desenvolvedor ficava alternando entre duas versões, cada verificação parecia uma nova atualização e publicava mais uma notificação.

Um pacote que acabou de ser instalado não oferece mais instalar de novo. A linha dele continuava dizendo que o pacote baixado seria reaberto.

O DuoUpdater agora requer o macOS 15 Sequoia ou posterior. Um Mac que ainda está no macOS 14 mantém a versão que tem e não recebe mais atualizações; todo Mac com Apple silicon pode ser atualizado para um macOS compatível.

Nos bastidores. As verificações de rotina não buscam mais os links de download antecipadamente, o que podia esconder por alguns instantes um botão Atualizar que funcionava sempre que o servidor de download de um desenvolvedor excedia o tempo limite.

O Aside agora é compatível. O DuoUpdater avisa quando sai um novo build do navegador Aside e mostra suas notas de versão.

As atualizações que o seu macOS não consegue executar não são mais oferecidas, e a linha agora explica o motivo. Quando um desenvolvedor informa quais versões do macOS uma versão aceita, o DuoUpdater segue essa informação: depois de uma atualização do macOS, o Little Snitch não oferece mais um build limitado a sistemas anteriores ao seu; o Xcode não oferece mais um build que exige um macOS mais novo que o seu; e um pacote de instalação cujo app exige um macOS mais novo é recusado, em vez de instalar um app que não vai abrir. As linhas que antes mostravam só um traço agora dizem “Ainda não para este macOS” ou “Requer um macOS mais recente”, com os detalhes a um clique.

Veja com qual SDK cada app foi compilado. Clique no selo ao lado do nome de um app e os detalhes agora dizem, por exemplo, “Criado com o SDK macOS 27.0.” — útil para saber quais apps já foram recompilados para o macOS mais recente.

Os apps do Homebrew distribuídos em dois pacotes — um para sistemas mais antigos e outro para o mais novo — agora são lidos a partir do pacote certo. O OnyX se divide assim para o macOS 27, e o DuoUpdater olhava apenas o pacote destinado aos sistemas mais antigos: ou não mostrava nada para o OnyX, ou o considerava atualizado em relação a uma versão que o Homebrew se recusa a instalar no 27. Agora o DuoUpdater acompanha aquele dos dois que você instalou.

Os betas do TestFlight não perdem mais a atualização quando o TestFlight é aberto. Um beta com um build novo esperando podia voltar para “atualizado” e ficar assim até você abrir o TestFlight de novo.

As atualizações com um clique do Dropbox e do ToDesk baixam o arquivo certo. No Apple silicon, o Dropbox baixava o build exclusivo para Intel, que a verificação de segurança depois recusava; ao ToDesk era oferecido o build de acesso antecipado que ele libera só para alguns usuários, em vez da versão geral.

Reabrir conclui a atualização do Spotify na hora. Quando o Spotify já tinha baixado a própria atualização, Reabrir ficava girando por minutos até a atualização ser aplicada.

Os builds beta passam para as versões finais correspondentes. Um beta do Xcode recebe a oferta do release candidate em vez de aparecer como atualizado, os betas do CotEditor passam a ver os release candidates dele, e um beta do Carbon Copy Cloner cujo ciclo de testes terminou recebe a oferta da versão em que ele se transformou, em vez de uma verificação com falha.

As notas de versão correspondem à versão que você tem. O Blender 5.2 mostrava as notas da 5.1, e o Raycast 1.x mostrava as notas da 2.x. O “Abrir página” do Gemini agora abre a página atual do app de desktop do Google, em vez de um erro.

Os Ajustes explicam cada opção logo ao lado dela. As notas longas embaixo de seções inteiras foram substituídas por uma linha curta embaixo de cada controle, e os seletores descrevem apenas a opção escolhida.

O app agora escreve o próprio nome como DuoUpdater, igual ao site.

Os pacotes do Homebrew vindos de taps em que você não confiou voltam a aparecer. Desde o Homebrew 6, o brew ignora silenciosamente os pacotes de taps não confiáveis ao listar o que está instalado, então eles sumiam do DuoUpdater sem explicação. Agora aparecem como “Não verificado · tap não confiável”, com o comando brew trust pronto para copiar — e, assim que você o executa (ou faz um upgrade) no Terminal, a janela se atualiza quando você volta para ela.

Os apps que precisam de senha de administrador para se atualizar não são mais atualizados duas vezes. Quando um app como o Tailscale já tinha baixado a própria atualização e esperava ser reaberto, o DuoUpdater não percebia e continuava oferecendo Atualizar, o que podia colidir com o instalador do próprio app. Agora a linha oferece Reabrir, e Atualizar Tudo deixa esse app de lado.

A seção do Homebrew agora pode atualizar o próprio Homebrew. Quando sai uma nova versão do Homebrew, uma linha no topo oferece executar brew update para você. Ela fica oculta se você definiu HOMEBREW_NO_AUTO_UPDATE.

Um upgrade do Homebrew que falha agora mostra o erro real do brew. A linha mostrava o conselho que o brew imprime depois do erro, ou nada, então uma mensagem como “your Command Line Tools are too outdated” nunca chegava até você. Fazer upgrade de vários pacotes de uma vez também não informa mais que terminou antes da hora.

O ícone da barra de menus conta além de 50. Com mais de 50 atualizações esperando, ele ficava parado em 50.

Notas de versão: as do Claude são agrupadas em Novo, Melhorado e Corrigido, como o próprio Claude as mostra; as do Mac Mouse Fix aparecem como texto em vez de uma página incorporada; e o app do próprio Homebrew agora tem notas.

O duo check não diz mais “Everything is up to date.” quando não conseguiu realmente verificar. Agora ele avisa quando não conseguiu ler o TestFlight ou quando a varredura de apps foi abandonada.

As notas de versão agora aparecem no seu idioma quando um app as publica em vários. Alguns apps distribuem as notas traduzidas junto com cada versão; o DuoUpdater pegava a tradução que o app listasse primeiro ou por último, então as notas de um app apareciam em alemão para todo mundo e as de outro mudavam de idioma de uma versão para a outra.

Os apps que ganharam uma versão para Mac não aparecem mais como “não compatível com este Mac”. Um app de iPhone ou iPad que você usa no Apple silicon era marcado por engano no momento em que o desenvolvedor lançava um build de verdade para Mac — justamente a mudança que torna a atualização mais disponível, e não menos.

Um app da App Store que você também testa em beta não é mais confundido com um build do TestFlight. Quando um desenvolvedor promovia um beta sem alterações, os dois tinham o mesmo número de build e a sua cópia comprada era entregue ao TestFlight — então a App Store nunca conseguia oferecer uma atualização para ela.

Uma atualização da App Store que exige um macOS mais novo que o seu agora avisa isso. Antes, a linha oferecia instalá-la mesmo assim e a App Store recusava no último passo, sem nada na tela explicando por quê.

A janela Requisições agora mostra até quando o registro realmente vai, e marca os intervalos de datas que não consegue cobrir por inteiro. Antes, escolher “Últimos 30 dias” em um registro que só cobria algumas horas parecia exatamente igual a escolher “Últimas 24 horas”, sem nada na tela explicando por quê.

Você escolhe o quanto o DuoUpdater faz com os betas do TestFlight, em Ajustes → Geral. Quando eu recarregar lê o que o TestFlight já sabe e pede a ele uma resposta atualizada quando você clica em Recarregar; Mantenha tudo em dia também deixa o DuoUpdater perguntar por conta própria, então um beta que o TestFlight instalou em segundo plano não fica mais como um ponto de interrogação até você recarregar, e um build esperando por você não passa mais despercebido atrás de um “atualizado”; Desativado não lê nada e diz isso nessas linhas, em vez de chutar. Os Macs que já tinham Acesso Total ao Disco começam em Quando eu recarregar; todos os outros, em Desativado.

Abrir o TestFlight por conta própria agora basta para o DuoUpdater perceber o que ele instalou. Um beta que você instalou pelo TestFlight ficava como um ponto de interrogação até a próxima recarga — e no macOS 27, onde o aviso “Ready to Test” do TestFlight não chega mais para apps que você já tem, isso podia levar horas.

O Cline agora recebe atualizações, tanto dos builds finais quanto dos beta, e mostra suas notas de versão. Até agora ele ficava com um ponto de interrogação em vez de uma versão — não tem nenhum feed de atualização do tipo que o DuoUpdater consegue ler, e não existe pacote do Homebrew para ele. O DuoUpdater agora consulta o mesmo endereço que o atualizador do próprio Cline consulta, então a atualização oferecida é a mesma que o Cline teria instalado sozinho, e o build beta continua na linha beta.

As notas de versão que agrupam as mudanças sob títulos como Adicionado e Corrigido agora mantêm esses títulos. Antes, todos os grupos eram mesclados em uma única lista, e não dava para saber quais mudanças eram recursos novos e quais eram correções de bugs.

O Mac Mouse Fix agora oferece as versões beta se você ativou “Get Beta Versions” nos ajustes gerais dele. Antes, o DuoUpdater só via as versões normais do Mac Mouse Fix, então um build beta passava despercebido até a próxima versão normal sair.

Os apps cujo número de build é um simples contador não escondem mais as próprias versões de correção. Para um app que informava uma versão como 12.10 com o build 282987, uma versão 12.10.1 aparecia como “já atualizado”.

Um novo build de um app que mantém o mesmo nome de versão volta a ser anunciado. Depois que um build era anunciado, todos os builds seguintes com esse nome chegavam em silêncio — a linha se acendia, o contador o incluía, mas nenhum aviso aparecia.

“Atualizar Tudo” agora conta apenas os apps que foram de fato atualizados. Um app que abre o Instalador da Apple para você terminar era contado como concluído enquanto a janela dele ainda estava aberta, então “2 apps foram atualizados” podia significar que nada tinha mudado ainda.

Uma atualização que foi aplicada mas deixou um resto para trás agora aparece como instalada, e não como “conceder Gerenciamento de Apps”. A nova versão já estava em execução enquanto a linha mandava você para os Ajustes do Sistema.

Interromper “Atualizar Tudo” agora interrompe o download em andamento. Antes, uma transferência de vários gigabytes continuava até o fim, com até cinco novas tentativas, e só então percebia que tinha sido cancelada.

As notas de versão não se misturam mais entre dois apps que compartilham uma página de histórico de alterações, e continuam atualizadas depois de uma atualização nos apps cujas notas ficam em páginas separadas por versão. O Antigravity e o Antigravity IDE podiam mostrar as notas um do outro por quinze minutos; o Thunderbird, o WeChat, o Opera e alguns outros continuavam mostrando as notas da versão anterior por um tempo depois de atualizar.

A busca na lista de apps ignora acentos, como a busca dos Ajustes já fazia. Digitar “cafe” agora encontra “Café”.

A página Diagnóstico lista uma linha de estado para cada canal de lançamento. Uma regra de beta ou de preview com problema ficava escondida atrás da regra estável irmã, que estava funcionando.

Uma resposta “forbidden” do GitHub não é mais informada como limite de requisições. Um repositório que virou privado ou um token sem um escopo levava você a adicionar um token que não teria ajudado.

Reabrir não é mais oferecido para um app que se atualiza sozinho quando o build que está esperando é mais antigo que o que está em execução.

Nos bastidores. Instalações, backups e verificações de pacotes não ocupam mais os threads em que o resto do app roda, então o menu continua respondendo enquanto uma delas está em andamento; o menu também continua fluido durante um download grande; o Registro de Versões conta todas as versões que um fornecedor lança sob um mesmo nome de versão; um backup de reversão é recusado, em vez de guardado, quando estiver faltando o executável do próprio app; a primeira abertura em um Mac novo não registra mais erros falsos de banco de dados; o duo verify e o duo reconcile agora informam um histórico de alterações cujo número de entradas despencou e um endereço de instalador que vem falhando há dias; um comando duo travado desiste da varredura depois de vinte segundos, em vez de ficar parado.

Alguns apps que se atualizam sozinhos não parecem mais atualizados quando já existe uma versão mais nova. Nos apps cujas informações de atualização ficam atrás de um servidor de download que demora a se atualizar, o DuoUpdater podia continuar vendo uma versão antiga por dias depois de um lançamento.

As notas de versão do Kimi agora aparecem no DuoUpdater.

As atualizações do CodeEdit agora aparecem. Uma versão mais nova do CodeEdit deixava a linha dele com um ponto de interrogação, em vez de oferecer a atualização.

Nos bastidores. A lista do Homebrew no menu é preenchida mais rápido, e os comandos duo iniciam mais rápido.

Verificar de Novo em um beta do TestFlight agora dá a resposta real. Antes, a linha virava um ponto de interrogação até a próxima recarga.

Os betas do TestFlight mantêm suas respostas enquanto o botão de recarregar consulta o TestFlight. Por alguns segundos, todos podiam virar pontos de interrogação.

O super.engineering agora é compatível: verificação de atualizações, notas de versão e instalação com um clique. Um novo nightly aparece com o que mudou nele, e Atualizar o instala para você.

O Microsoft Edge Beta podia oferecer um build estável do Edge. Enquanto o feed beta da Microsoft ficou vazio por um tempo, a linha indicava uma versão estável, e atualizar teria colocado essa versão por cima do seu beta.

Os betas do TestFlight agora mostram as atualizações que o TestFlight tem para eles, inclusive os betas de apps de iPhone e iPad. O botão de recarregar consulta o TestFlight em segundo plano, uma atualização não some mais minutos depois de você encontrá-la, e o botão TestFlight abre a página desse beta.

Quando o DuoUpdater não consegue saber se um beta do TestFlight está atualizado, ele diz isso. A linha mostra um ponto de interrogação em vez de considerá-lo atualizado — por exemplo, quando você saiu da sua conta no TestFlight ou não está mais testando esse beta.

O Acesso Total ao Disco agora é explicado, e nada fica insistindo se você não o conceder. Sem ele, o DuoUpdater não dispara mais os avisos do macOS sobre ler dados de outros apps; se um beta do TestFlight ou o CotEditor precisar dele, você é avisado uma vez sobre o motivo e onde concedê-lo.

Reabrir desaparece assim que um app atualizado é encerrado. Um app que deixava um auxiliar em execução continuava pedindo para ser reaberto muito depois de a atualização ter entrado em vigor.

Um pedido de privacidade do macOS sem resposta não trava mais as verificações de atualização. A verificação continua sem o ajuste daquele app.

As notas de versão do Rockxy e do Ollama voltaram a ficar completas. As do Rockxy voltam a cobrir as versões recentes, não só a mais nova, e a versão mais nova do Ollama não fica mais de fora.

O duo, o complemento opcional de linha de comando, lida melhor com o TestFlight. O --refresh-testflight funciona com o TestFlight aberto ou não, sem tomar a sua tela, e o duo check não considera mais um beta atualizado quando o TestFlight já anunciou um build mais novo.

O Telegram Desktop volta a ter verificação de atualizações. O Telegram mudou o nome do arquivo que publica, e a linha não conseguia mais ler uma versão a partir dele — então mostrava uma falha de verificação em vez da atualização que estava esperando.

Um build do TestFlight de um app de iPhone ou iPad é reconhecido como tal. O DuoUpdater o lia como uma compra da App Store, então a linha indicava o responsável errado enquanto a loja era consultada sobre uma página que não existe — em todas as verificações, durante todo o tempo em que o app continuasse instalado.

Um beta do TestFlight é marcado com o próprio ícone do TestFlight. As linhas cuidadas pela App Store já traziam o ícone da loja; as cuidadas pelo TestFlight escreviam o nome por extenso, então o mesmo tipo de linha era marcado de duas formas diferentes.

O cabeçalho da janela Rede fica parado quando você troca de aba. As duas abas posicionavam os títulos em alturas ligeiramente diferentes, então alternar entre elas fazia a janela parecer tremer.

Rolar por toda a sua lista de apps voltou a ser fluido. Uma rolagem rápida pela lista completa perdia quadros; agora cada linha informa sua altura sem precisar ser construída antes.

As notas de versão de um app da App Store agora sempre vêm da App Store. Quando a consulta da própria loja para um app falhava ou não encontrava nada, a janela podia recorrer às notas da outra distribuição desse app — um build diferente, com números de versão próprios — descrevendo uma versão que nunca seria oferecida à sua cópia.

O Windscribe no canal Beta ou Guinea Pig recebe os builds desse canal. O DuoUpdater lê qual canal de atualização você escolheu nos ajustes do próprio Windscribe, então uma cópia que segue uma linha de pré-lançamento não é mais considerada atualizada enquanto existem builds mais novos nessa linha. A janela também mostra as notas desses builds de pré-lançamento, que antes só apareciam para os estáveis.

O Windscribe agora tem verificação de atualizações, com suas notas de versão. Uma cópia com um build mais antigo aparece com a versão para a qual pode ir e o que mudou nela; antes, o DuoUpdater não tinha como ver a versão do Windscribe. A atualização continua sendo feita pelo instalador do próprio Windscribe, que configura partes do app que ficam fora do app em si.

Uma atualização não é mais aplicada a um app que sumiu enquanto você clicava. Se o app for desinstalado, substituído ou deixar de poder ser lido entre o clique e o início da instalação, o DuoUpdater agora para e avisa, em vez de instalar por cima daquele local mesmo assim.

O duo, o complemento opcional de linha de comando, não considera mais concluída a instalação de um pacote antes da hora. Instalar um app distribuído como .pkg abre o instalador do macOS e deixa o resto com você, mas o resumo o contava como instalado — “1 installed” enquanto nada tinha sido substituído ainda. Agora esses casos são contados à parte. A saída --json também identifica em cada linha o que aconteceu com aquele app, então um script não precisa mais ler a explicação em inglês para distinguir uma falha de um pulo proposital.

Nos bastidores. A reverificação feita antes da instalação, que protege a atualização com um clique, agora protege também o duo install, e as verificações pelas quais um download precisa passar antes de substituir um app ficam em um único lugar para os dois caminhos que as usam.

Clicar em Atualizar não deixa mais de fazer efeito quando uma fonte de atualização se contradiz. Se a verificação feita no momento do clique volta com uma versão mais antiga que a oferecida pela linha, o DuoUpdater agora avisa e mantém a atualização disponível. Antes, informava que o app já estava atualizado e o tirava da lista, e a mesma atualização reaparecia na verificação seguinte.

As atualizações do Fork voltam a ser oferecidas quando ele está no canal Develop. O DuoUpdater lia o ajuste de canal do Fork ao contrário e seguia o feed Stable, que fica bem atrás — então uma cópia Develop aparecia como atualizada enquanto o próprio Fork oferecia uma versão mais nova.

O Mac Performance Monitor agora mostra suas notas de versão. O app as publica no repositório, e não no feed que lemos, então a janela não tinha nada para mostrar.

O CotEditor agora é compatível, tanto na linha final quanto na beta. A linha que uma cópia segue é definida pela versão em execução e pelo ajuste “Update to prereleases when available” do próprio CotEditor, então uma cópia beta recebe o próximo beta em vez de uma versão que a faria voltar atrás.

Um app instalado pela App Store nunca recebe a oferta de um download de outro lugar. Quando a consulta da própria loja falha ou volta vazia, a linha agora diz que a loja cuida dele, sem número de versão. Antes, a verificação podia cair na outra distribuição do app — um build diferente, com números de versão próprios — e oferecer instalá-lo por cima da sua cópia da loja.

Um app nunca recebe a oferta de uma atualização que o levaria para uma versão mais antiga. Alguns feeds listam uma versão estável acima de um pré-lançamento que na verdade está mais adiante, e aceitá-la teria feito o app voltar atrás.

Um erro longo em uma linha não empurra mais o resto da lista para baixo. Ele fica limitado a duas linhas, com o texto completo ao passar o cursor.

Mais quatro apps são compatíveis: WhatCable, Qoder IDE, Qoder e Yaak. Cada um ganha verificação de atualizações e instalação com um clique, e as notas de versão deles são lidas na janela como texto, e não como uma página incorporada.

Os dois apps da Qoder para Mac agora são diferenciados. O IDE e o app de desktop compartilham o nome e a página de download, mas seguem linhas de versão separadas, então cada um agora é acompanhado individualmente.

Os builds beta do WhatCable e do Yaak são acompanhados na própria linha. Uma cópia com um beta não tinha fonte nenhuma e ficava em “Falhou”; agora recebe o próximo beta, com notas de versão separadas das estáveis. No WhatCable, isso inclui também a versão estável em que um beta acaba se tornando — aceitá-la leva a cópia para a linha estável.

Verificar seus apps da App Store usa uma fração da rede que usava antes. Cada verificação baixava de novo a página de produto de cada app da App Store; agora as páginas ficam guardadas por uma hora e a loja é consultada sobre todos os seus apps em poucas requisições, em vez de uma por app. Com o intervalo de verificação de cinco minutos, isso dá cerca de um terço a menos de tráfego no total; com o intervalo padrão de seis horas, as páginas continuam expirando entre as verificações, então a economia é menor.

Verificar um app de novo não baixa mais todos os apps da App Store outra vez. Um único “Verificar de Novo” descartava todas as páginas de produto em cache, então a próxima verificação agendada pagava por todas elas; agora ele atualiza apenas o app que você pediu.

Verificar os apps distribuídos pelo GitHub custa uma fração da rede que custava antes. Cada verificação baixava de novo a descrição completa de cada versão, mesmo quando nada tinha sido publicado; agora pergunta ao GitHub se a versão mudou desde a última vez e não baixa nada quando não mudou. Uma vez por dia, relê cada versão por completo, então uma versão retirada é percebida em até um dia.

Os apps acompanhados em uma linha beta ou nightly do GitHub agora pedem uma versão, em vez de uma página inteira delas. A versão mais nova é a resposta quase sempre, e a página completa só é buscada nas rodadas em que não é.

A verificação de atualização do Vorssaint não depende mais de um redirecionamento. O repositório dele foi renomeado, e seguir o nome antigo fazia a requisição cair silenciosamente no limite anônimo de requisições do GitHub; agora a verificação vai direto ao nome novo.

Nos bastidores. O artefato de lançamento agora é compilado, assinado e notarizado em um Mac hospedado pelo GitHub, com uma procedência de build que qualquer pessoa pode verificar, e o registro de requisições diferencia uma resposta em cache de uma vinda da rede.

Os registros de requisições que você exporta não levam mais o nome da sua conta. Cada linha de um app instalado na sua pasta pessoal mostrava o caminho completo; agora mostra ~, qualquer que seja a forma como você exporta o registro.

A aba Requisições agora diz o que cobre e o que não cobre. Ela registra as buscas que o próprio DuoUpdater faz. Uma página de notas de versão carrega as próprias imagens e fontes, e as atualizações da App Store e do Homebrew são feitas por ferramentas separadas — nada disso aparece ali, e agora a janela diz isso em vez de deixar você supor.

Copiar URL agora codifica o endereço que entrega. Os caminhos com espaço — os downloads do Firefox, do Thunderbird e do Bartender entre eles — eram copiados sem tratamento, o que um navegador perdoa e uma linha de comando não.

A linha do beta do CapCut não informa mais uma verificação com falha. Entre um beta e outro — depois que um vira versão final e antes que o próximo comece — o fabricante não publica nada nessa linha, o que aparecia como uma linha vermelha e um botão Tentar de novo que nunca poderia funcionar. Agora a linha simplesmente fica sem resposta dessa fonte até o próximo beta aparecer.

O Audacity agora mostra o selo que diz com o que ele foi feito. Ele inicia por um pequeno lançador que passa o controle ao programa real ao lado dele, e o selo era lido do lançador, que não vincula nada.

As notas de versão da App Store agora chegam no seu idioma. Elas sempre eram buscadas no idioma padrão da loja, então um Mac em chinês ou japonês continuava lendo as notas em inglês.

As atualizações do próprio DuoUpdater agora aparecem com o nome dele na janela Rede. A verificação de versões, as notas de versão e o download dele eram todos registrados com a coluna de app em branco.

Nos bastidores. Uma credencial incluída no caminho de um endereço web agora é removida antes de a requisição ser registrada, como sempre foi feito com uma que estivesse na string de consulta.

A janela Tráfego de Downloads agora se chama Rede e tem uma segunda aba. Downloads é o registro que você já tinha — quanto cada atualização custou como arquivo. Requisições é nova: cada busca que o DuoUpdater faz em seu nome, para que serviu, a qual app pertencia e quanto custou, com um campo de filtro para fazer perguntas ao registro em vez de rolar por ele. Os números no topo respondem ao que você filtrou, e não ao total acumulado.

Verificar atualizações do Spotify agora quase não usa a rede. O Spotify não publica um arquivo de versão em lugar nenhum, então a verificação lê a versão de um instalador inicial de dois megabytes — e baixava o arquivo inteiro todas as vezes, dia e noite. Agora ela pergunta se esse arquivo mudou e pula o download quando não mudou.

O PDF Expert agora encontra suas atualizações e mostra o que mudou. Ele lia uma lista de versões que o fabricante parou de atualizar em 2022, então se dizia atualizado qualquer que fosse a sua versão. Agora segue a lista que o próprio atualizador do app usa, e passa a trazer também as notas de versão das versões anteriores, não só da mais nova.

Os builds de preview do UTM agora recebem as próprias atualizações, instalam com um clique e mostram as notas de versão correspondentes. Uma cópia preview era comparada com a linha final e considerada atualizada sem nenhum aviso; agora segue a própria linha e, quando aceita a versão final dessa linha, volta para a linha final.

Nos bastidores. As requisições registradas passaram para o mesmo armazenamento que o registro de downloads, então os dois relatos de um mesmo download não podem mais divergir. Seu registro atual é mantido intacto.

Mais quinze apps passam a ser acompanhados, e todos menos um instalam com um único clique. AgentsView, AnythingLLM, Chatbox, ChatGPT Classic, DSH Desktop, FluidVoice, GitHub Copilot, Kun, Meetily, Microsoft 365 Copilot, OpenLogi, OpenSuperWhisper, Paseo, T3 Code — nas linhas alpha e nightly — e Vorssaint. O ChatGPT Classic é a exceção: ele é verificado para você, mas vem com um instalador que atualiza o próprio app, então quem o executa continua sendo você.

Oito apps agora mostram as notas de versão dentro do DuoUpdater, em vez de mandar você para uma página web. Xcode, Antigravity, Antigravity IDE, AnyDesk, AnythingLLM, Chatbox, Headlamp e Helium. Três deles nem tinham para onde mandar você: a página do AnyDesk responde com um desafio contra bots, os criadores do Helium não publicam página de notas alguma, e o Antigravity IDE não tinha link de nenhum tipo.

Os betas do Xcode dizem o que mudou em cada beta. A linha oferecia um número de build e um link; agora lista as notas da Apple para o beta que você usa e para todos os betas anteriores dessa versão.

Word, Excel, PowerPoint, Outlook e OneNote agora percebem quando a atualização foi aplicada. Esses cinco continuavam oferecendo reabrir o instalador que você já tinha concluído, e nunca passavam a oferecer Reabrir — esperar ou verificar de novo não resolvia.

Uma linha esperando para reabrir volta a se explicar, nas duas janelas. Quando um app estava ao mesmo tempo à frente do que o fornecedor publica e esperando para reabrir, a linha acima do botão descrevia outra coisa totalmente diferente; a janela e o menu também discordavam sobre as linhas que esperavam Atualizar Tudo reabri-las.

As etiquetas das linhas não espremem mais o nome do app em russo. Algumas etiquetas também reaproveitavam textos de strings sem relação em todos os idiomas traduzidos.

As notas de versão agora aparecem nos apps cujo fornecedor informa a data de uma versão sem o horário. Essas versões não deixavam rastro em lugar nenhum.

Uma página de notas de versão que nos recusamos a abrir agora diz por quê. Antes, ela ficava em branco, o que parecia exatamente um app que não publica notas.

As notas de versão do WeChat DevTools nightly não estão mais vazias.

Nos bastidores. O tratamento de versões e de datas de lançamento foi unificado para que um número de build nunca seja lido como versão comercial, e a linha do tempo de lançamentos não inventa mais um horário que o fornecedor nunca informou.

As verificações com falha agora aparecem na janela. A janela não mostrava nada numa linha cuja verificação tinha falhado — nem numa que você ignorou, numa que você pulou ou numa gerenciada pela App Store, pelo Toolbox ou pelo TestFlight —, o que parecia exatamente “atualizado”. As duas janelas agora dizem a mesma coisa sobre o mesmo app, e o botão Tentar de novo está nas duas.

“Verificar de Novo” em qualquer linha consulta só aquele app. Ele também relê quais apps estão em execução, então é a forma rápida de corrigir uma bolinha verde que parece errada.

Pular e ignorar agora funcionam pelo menu de clique secundário da janela. As duas linhas mandavam você clicar com o botão direito para desfazer, numa janela cujo menu não tinha essa opção.

A verificação em segundo plano não tira mais as notas de versão que você está lendo. A verificação de hora em hora descartava todas as notas já carregadas, então um painel de Notas de Versão aberto voltava a mostrar o indicador de carregamento. Agora só uma recarga que você pediu as recomeça.

Os downloads interrompidos são verificados antes de serem considerados completos. Um servidor que reenviava o arquivo inteiro, ou parava antes do fim, era aceito sem conferência, e o problema só aparecia um passo depois, como uma instalação que falhava por causa de um arquivo compactado corrompido. Os downloads por trás de um proxy que antes falhavam sempre agora funcionam.

Atualizar um app não faz mais uma nova varredura de todos os apps do seu disco. Cada clique fazia duas varreduras completas de todos os seus aplicativos para examinar o que você tinha pedido.

As notas de versão do Chrome não podem mais travar. Uma simples mudança de visual no blog do Google bastava para travá-las por minutos; agora elas carregam prontamente, seja qual for a aparência da página.

Um instalador baixado não é mais descartado e baixado de novo. Quando um fornecedor escrevia a mesma versão de duas formas (v1.2.3 e 1.2.3), o pacote em espera não era reconhecido e Reabrir podia continuar esperando uma troca que já tinha acontecido.

Uma instalação como administrador que falhou não é mais confundida com você clicando em Cancelar. Nenhum erro era mostrado, e aquele app deixava de oferecer atualizações com um clique, sem aviso, até você pedir acesso de administrador de novo no menu da linha dele.

A bolinha verde de “em execução” agora percebe todos os apps. O macOS nunca anuncia a abertura ou o encerramento de alguns apps, e a bolinha deles ficava errada até algo sem relação atualizá-la.

“Atualizar Tudo” não fica mais aparecendo e sumindo durante uma recarga, e um app que você atualiza no meio de uma recarga não volta a oferecer a atualização que já instalou.

Uma verificação que falha no momento em que você clica em Atualizar agora avisa, em vez de ser tratada como “nada a fazer”.

Nos bastidores. As datas de lançamento escritas em formatos incomuns são lidas corretamente, a verificação de endereço nas páginas de notas de versão cobre todas as grafias equivalentes, e a manutenção de rotina não acessa mais o disco toda vez que algum app do seu Mac abre ou é encerrado.

O selo do Docker agora descreve a interface do Docker, e não o daemon dele. A linha dizia “nativo”; o Docker Desktop é um app Electron. O selo é lido do pacote do app, e o pacote do Docker é um invólucro: o programa que ele indica é um serviço em segundo plano escrito em Go, não traz framework próprio, e o app que realmente desenha as janelas fica um nível dentro dele. Tudo estava sendo lido corretamente, só que do arquivo errado. O DuoUpdater agora olha o app aninhado quando — e somente quando — o externo não traz nada por conta própria e contém exatamente um app desse tipo que comprova com o que foi feito, para que um processo auxiliar distribuído junto de uma interface real continue sem poder emprestar sua identidade ao app que o contém. O Docker aparece como Electron 42.5.0 e, dos cento e quarenta e seis apps da lista no computador em que isto foi escrito, é a única linha que muda.

As notas de versão do CleanShot X voltaram a ser legíveis — inclusive as da 5.0. O CleanShot lançou sua maior versão em anos e reconstruiu a página de histórico de alterações junto com ela: a data passou para cima do número da versão, surgiram duas novas camadas em volta dela, e uma versão com recursos novos agora coloca uma introdução e dois links de vídeo entre a versão e a lista de mudanças. O leitor que o DuoUpdater usava deixou de reconhecer tudo isso. O que tornava isso pior que um painel vazio é que ele não parecia vazio: as notas que já tinham sido salvas para a versão anterior continuavam na tela sob o título da versão nova, então o painel dizia “5.0” em cima das mudanças da 4.8.10, e nada em lugar nenhum dizia o contrário.

As notas salvas antes de uma versão ser publicada agora são relidas, em vez de serem aceitas para sempre. Essa é a outra metade da mesma história. O DuoUpdater soube da existência da 5.0 seis minutos antes de o CleanShot publicar o que havia nela, salvou a página como estava e a arquivou sob a 5.0 — e, a partir daí, cada verificação encontrava algo já salvo e nunca mais olhava. Agora as notas salvas são confirmadas com o fornecedor uma vez por sessão antes de serem tratadas como definitivas, então uma versão cujas notas chegam atrasadas se completa na visita seguinte, em vez de continuar errada.

Tudo o que você abre pela barra de menus agora abre no primeiro clique. Escolher Histórico de alterações em uma linha — ou os Ajustes, ou o Registro de Versões — não fazia absolutamente nada na primeira vez, e funcionava do segundo clique em diante. Reabrir o menu fazia cada tentativa voltar a ser a primeira, então, para quem abre o menu, clica uma vez e espera uma janela, nunca funcionava. O primeiro clique dentro do menu era gasto trazendo o DuoUpdater para a frente, em vez de fazer o que se pretendia. A janela aberta agora também fica na frente: ela era trazida para cima e empurrada de volta para baixo no mesmo instante, que é a outra forma pela qual isso parecia um clique que não fazia nada.

Um app que deixa o próprio nome em branco agora ganha um mesmo assim. O Eudic (欧路词典) aparecia na lista com um ícone, uma versão e absolutamente nada no lugar do nome. O pacote dele declara, sim, um nome de exibição — e o deixa vazio, porque os nomes reais ficam nas traduções do app —, e o DuoUpdater tomava essa resposta vazia como definitiva, em vez de fazer a próxima pergunta. Agora ele recorre ao outro nome do app e, depois, ao nome do arquivo do app, então nenhuma linha fica sem nome. Aqui, um app em cento e cinquenta foi afetado; o ponto é que a informação já estava lá e estava sendo ignorada.

Reabrir agora avisa quando o app se recusou a encerrar, em vez de parecer um clique que não fez nada. Se um app tem uma janela esperando por você — um pedido para salvar, uma tela de login, algum diálogo —, o macOS não deixa que ele encerre, e não há nada que o DuoUpdater possa fazer: a janela é do app. O DuoUpdater ficava girando por trinta segundos e depois mostrava o mesmo botão de novo sem explicação, o que parece exatamente um botão quebrado, então as pessoas clicavam de novo. Agora a linha diz o que aconteceu e indica o app para você resolver essa janela. Nada foi alterado e a nova versão já está instalada, então só falta mesmo reabrir — e, se você simplesmente encerrar o app por conta própria nos próximos dez minutos, o DuoUpdater percebe e o reabre na versão nova sem que você precise clicar em nada.

As notas de versão do 欧路词典 voltaram a ser de uma versão, e não de dezesseis anos delas. O app publica todo o seu histórico — todas as versões desde a 2.5.0 — dentro das notas da versão mais nova, então o painel de detalhes mostrava tudo isso sob o título “26.9.0” e era preciso rolar por uma década para achar o que tinha acabado de mudar. Agora cada versão tem a própria entrada na lista, como acontece com todos os outros apps.

O selo que diz com o que um app foi feito agora exige prova para o Tauri, e não só semelhança. O Tauri não deixa nada para encontrar num pacote — nenhum framework, nenhuma pasta própria —, então esse selo era deduzido da forma como o app foi empacotado mais o fato de ele vincular a visualização web da Apple. O Longbridge atende a tudo isso e não é Tauri: ele desenha as próprias janelas com o mesmo renderizador que o Zed usa e incorpora uma visualização web em um canto da interface. O DuoUpdater agora lê a impressão digital do próprio Tauri no binário antes de afirmar isso, então um app só é chamado de Tauri quando é um — e o Longbridge aparece como o app nativo para Mac que ele é.

O CapCut não fica mais vermelho porque os servidores da ByteDance tiveram um meio segundo ruim. O endpoint que o DuoUpdater consulta para saber a versão do CapCut responde com um código de sucesso e então, cerca de uma vez em cinquenta, com um objeto de erro no lugar da resposta — um tempo limite interno na própria infraestrutura da ByteDance, uns 390 bytes onde se esperavam 436 kilobytes. Nada do lado de cá conseguia distinguir isso de o CapCut ter mudado o formato da resposta, então a linha dizia que a verificação tinha falhado, o que soa como “isto está quebrado e alguém precisa consertar” para algo que se resolve sozinho na tentativa seguinte. Esse formato específico agora é reconhecido pelo que é: a requisição é repetida na hora, e só é informada como um problema real se continuar acontecendo por cinco dias.

Todos os apps da lista agora dizem com o que foram feitos. A linha de um app da App Store sempre trouxe o selo da loja, e todas as outras linhas eram iguais — um app Sparkle, um app Electron e um nativo não se distinguiam. Agora cada nome traz o símbolo da própria tecnologia — clique nele para ver uma palavra e uma frase, ou passe o cursor para ver a dica: Electron, Tauri, Flutter, Qt, Java, Chromium, Mac Catalyst, um app de iPhone no Apple silicon ou um app nativo para Mac —, com a versão do runtime quando ela pode ser lida como um fato (Electron 42.4.1, Qt 6.2, o Chromium que um app incorpora, o Tauri com que foi compilado). Isso é lido do próprio pacote — o framework que um empacotador teve de incluir, o runtime de que um lançador precisa, as bibliotecas que o binário vincula —, então é um fato sobre o que está instalado, e não um palpite a partir do nome do app. Quando um nome comprido não deixa espaço, o símbolo sai de cena em vez de empurrar o nome para uma segunda linha: o nome é a linha. Desative tudo isso em Ajustes → Geral.

O LibreOffice não alega mais um rebaixamento para a versão que você já tem. O índice de downloads dele lista versões com três partes (26.8.0), enquanto a cópia instalada informa quatro (26.8.0.3), e completar a parte que faltava com um zero fazia a cópia instalada parecer mais nova — então a linha mostrava um aviso discreto de que “o fornecedor está atrás de você” sobre um app que estava exatamente em dia. Uma fonte que publica menos partes do que o app informa agora é lida como descrevendo a mesma versão, e não uma mais antiga; uma reversão de verdade continua sendo indicada.

Um ajuste adicionado por uma atualização agora é destacado uma vez. Uma preferência nova que surge no meio da janela de Ajustes é uma preferência que ninguém encontra. A engrenagem da barra de menus ganha um ponto azul depois de uma atualização que adicionou um ajuste, a página onde ele fica ganha um na barra lateral, e o próprio controle mantém o seu até você olhar para ele. Só para quem de fato atualizou para essa versão — uma instalação nova não é recebida com pontos em recursos que simplesmente fazem parte do app que acabou de conhecer.

Os apps com manifesto Electron adicionados na versão anterior agora podem de fato ser atualizados. A 0.3.75 ensinou o DuoUpdater a ler o arquivo que esses apps trazem dentro de si, e ele o lia — descobria a nova versão, o download certo para o seu Mac e o checksum para conferi-lo — e depois não tinha para onde mandar nada disso. O botão de instalar nunca aparecia, e o duo install explicava a recusa com um motivo que não era o verdadeiro. O caminho de instalação foi conectado nesta versão. Na prática, talvez você não veja diferença nenhuma: esse leitor fica atrás de todas as regras escritas à mão, então só atua em um app que nada mais cobre — o que hoje, no computador em que isto foi compilado, não é o caso de nenhum. Ele importa para o app que você instalar amanhã e para o qual ninguém escreveu uma regra.

Um download que tiraria você de um build nativo agora é recusado. O Apple silicon ainda consegue executar apps Intel por tradução, o que fazia um download só para Intel passar na verificação “isto vai rodar no seu Mac?” e ser instalado sem problemas — deixando você com uma cópia traduzida de um app que rodava de forma nativa, sem aviso, e com cada atualização futura fazendo a mesma coisa de novo. Agora toda instalação no lugar compara o que você tem com o que chegou e recusa essa troca. O caminho inverso, ou de um build universal para um só para Apple silicon, é normal e continua permitido.

Quando não consegue provar qual é a arquitetura de um download, ele agora recusa em vez de chutar. Alguns fornecedores publicam um build para Apple silicon ao lado do build padrão, e a única forma de saber que o padrão é o build Intel é perceber que o outro existe. Se essa segunda verificação não voltar sem problemas — o servidor do fornecedor a recusa, a conexão cai ou os dois discordam sobre qual versão são —, o DuoUpdater não trata mais esse silêncio como uma resposta. Ele informa a versão e não oferece instalação, que é o resultado honesto.

Uma regra quebrada não pode mais sumir do Diagnóstico. Nos apps cobertos tanto por uma regra escrita à mão quanto pelo novo leitor de manifesto — a maioria deles, de propósito —, uma falha da regra era anulada pelo sucesso do leitor logo em seguida, então um app cuja regra tinha de fato quebrado continuava aparecendo como saudável. Agora os dois são registrados separadamente. O leitor de manifesto também informa as próprias falhas pela primeira vez; três apps na máquina de desenvolvimento estavam apontando para endereços que vinham retornando “não encontrado” havia algum tempo, algo que antes nada teria dito em voz alta.

As linhas que conseguem ver uma atualização mas não conseguem instalá-la agora oferecem a mesma coisa nos dois lugares. A barra de menus mostrava um botão chamado “Abrir” que abria o Finder, e a janela não mostrava nada para a mesma linha.

Os apps feitos com Electron agora são reconhecidos sem que ninguém precise cadastrá-los antes. Muitos apps para Mac trazem dentro de si um pequeno arquivo que diz onde ficam suas atualizações. Até agora o DuoUpdater só conhecia aqueles para os quais alguém tinha escrito uma regra à mão — todos os outros ficavam na sua lista sem versão ao lado e sem nenhum jeito de avisar que tinha saído um build novo. Agora ele lê esse arquivo diretamente, do mesmo jeito que sempre leu o do Sparkle, então um app assim fica coberto no dia em que você o instala, e não no dia em que alguém tiver tempo de cuidar dele.

Os apps que já tinham uma regra escrita à mão continuam intactos. O novo leitor fica atrás delas, então só pode preencher uma lacuna — nunca assumir algo que já estava funcionando.

Dois detalhes decidem se o download oferecido é o certo, e ambos foram resolvidos conferindo apps reais, sem suposições. Alguns fornecedores marcam um build Intel como o download “principal” mesmo publicando um para Apple silicon ao lado; outros dão ao build para Apple silicon um nome de arquivo que não se diferencia em nada do Intel, então o nome não revela nada. O DuoUpdater escolhe pela arquitetura e, quando não tem certeza de que um download vai rodar no seu Mac, informa a versão e deixa de oferecer a instalação — em vez de entregar algo que instala sem problemas e depois não abre.

Se você usa o build beta, release candidate ou nightly de um app, o DuoUpdater estava acompanhando a linha errada sem avisar. Ele descobre em qual linha você está encontrando o seu build na própria lista de versões do fornecedor — mas, quando um pré-lançamento mantém o mesmo número de versão público da versão estável da qual saiu, que é o normal para um pré-lançamento, ele acabava associando a entrada estável. O efeito era silencioso: nada de errado aparecia na tela, você simplesmente nunca ficava sabendo do próximo build da sua própria linha, e as notas de versão mostradas eram as da linha estável. Descobrimos isso instalando os builds de pré-lançamento reais do Supacode e do TypeWhisper e observando o que acontecia; os dois agora seguem a linha em que realmente estão.

O beta do CapCut mostrava uma versão que você não tem. A linha dizia “9.3.4545 → 9.4.0-beta6”, enquanto o próprio CapCut, o Finder e todos os outros atualizadores chamavam a sua cópia de 9.4.0-beta5. Alguns apps guardam a versão real em um campo diferente do da maioria, e o DuoUpdater lia o de aparência mais arrumada do seu lado da seta, enquanto lia o real do lado do fornecedor. A atualização oferecida sempre foi a certa — só o rótulo estava errado. Agora as duas metades da linha vêm do mesmo lugar, para o CapCut e para os outros sete apps feitos desse jeito.

MacWhisper, GitHub Copilot for Xcode, TypeWhisper e OpenUsage agora mostram suas notas de versão. Os quatro tinham o painel de notas vazio: os feeds de atualização deles não trazem nota nenhuma, o que só foi percebido quando cada um foi comparado com o que o fornecedor de fato publica. O DuoUpdater agora lê a página de notas de versão do próprio MacWhisper, o arquivo de histórico de alterações do Copilot e o site de histórico de alterações do TypeWhisper, e aponta o OpenUsage para a lista de versões dele.

O Helium agora se atualiza pelo próprio serviço de atualização, o que traz o canal beta dele e downloads bem menores. Ele era acompanhado pela lista pública de versões, que só mostra builds estáveis — então quem estava no beta do Helium recebia o estável. O serviço próprio dele também publica patches, então uma atualização de rotina fica em torno de 40 MB, em vez de um novo download de 124 MB. Verificado com um build estável e com um beta, e o download é conferido com a chave de assinatura da sua cópia instalada antes de qualquer coisa ser substituída.

As versões beta, developer e nightly do Firefox e do Thunderbird agora são acompanhadas corretamente — até hoje, nenhuma dessas cinco linhas tinha informado uma única atualização. Elas eram lidas do arquivo público de versões da Mozilla, que só publica a versão exibida para você, e instalar um beta tira o “b5” dela: um beta do Firefox se chama 155.0 durante todo o ciclo, então a única pergunta feita era “155.0b5 é mais nova que 155.0?”, e a resposta é não. O nightly era pior — a Mozilla lança um por dia e todos se chamam 157.0a1, então um ciclo de quatro semanas não produzia absolutamente nada. O DuoUpdater agora consulta o próprio serviço de atualização da Mozilla, o mesmo endereço que o atualizador integrado do Firefox usa e que o app traz escrito dentro de si, e compara o identificador de build que os dois lados têm. Conferido com os downloads reais das cinco linhas antes do lançamento: o identificador que esse serviço informa é idêntico, byte a byte, ao que está dentro do app que você tem; um beta um build atrás agora mostra sua atualização, e um nightly compilado mais cedo no mesmo dia também. As versões estável e ESR nunca foram afetadas e continuam intactas. Um limite que vale deixar claro: esse serviço não publica data de lançamento, então, para essas cinco linhas, o Registro de Versões ainda anota quando o DuoUpdater viu um build pela primeira vez, e não quando a Mozilla o lançou.

Wispr Flow, AionUi e Devin agora se atualizam com um clique, em vez de só avisar que existe uma versão nova. Os três já enxergavam suas atualizações, mas nenhum conseguia aplicá-las, com a justificativa de que o fornecedor publica builds separados para Intel e Apple silicon e o DuoUpdater não tinha como escolher. Quando se mediu em vez de presumir, esse motivo não se sustentava: os endpoints de onde esses três são lidos já são os de Apple silicon, e o DuoUpdater só roda em Apple silicon — nunca houve escolha a fazer. Cada download foi baixado e conferido antes de ser integrado: o app certo lá dentro, assinado pelo mesmo desenvolvedor da cópia que você tem, notarizado pela Apple e, no caso do AionUi, conferido com o checksum que o próprio manifesto publica. Depois, cada um foi instalado de verdade por cima de uma cópia mais antiga e voltou na versão nova.

O Grok Bot agora é acompanhado — versões novas e atualizações com um clique. O app de desktop da xAI é compilado e assinado pela Anysphere, a empresa por trás do Cursor, e se atualiza pelo próprio serviço de lançamentos do Cursor — e é por isso que nenhum dos caminhos habituais respondia por ele: nada de feed do Sparkle, nada de página na App Store, nenhum repositório público de lançamentos e um cask do Homebrew que devolve a atualização ao próprio app. Em vez disso, o DuoUpdater lê o endpoint de versão do próprio fornecedor. Havia outros dois endpoints disponíveis, e os dois foram deixados de lado por motivos concretos: o que fica por trás do botão de download em x.ai não publica número de versão nenhum, e o que o atualizador do próprio app usa responde com um corpo vazio quando você já está em dia — um silêncio que não daria para distinguir de um endpoint quebrado. A instalação foi conferida antes de ser integrada: a imagem de disco traz o app de verdade, assinado pelo mesmo desenvolvedor da cópia que você tem e notarizado pela Apple. Uma coisa ele deliberadamente não oferece: notas de versão. A xAI não publica nenhuma para este app, e o único histórico de alterações que ela publica pertence a outro produto.

Comet e Msty Studio também se atualizam com um clique, e uma nova verificação fica de olho em apps que poderiam fazer isso e não fazem. Eram os dois últimos do grupo que enxergavam atualizações mas não conseguiam aplicá-las, e nenhum dos dois precisou de nada novo — só de um olhar mais atento ao que o fornecedor realmente envia. O link de download do Comet é assinado e expira em uma hora, então o botão de atualizar aponta para o gateway da própria Perplexity, e o link é gerado no momento em que você clica, e não horas antes, quando a verificação rodou. A Msty publica quatro downloads num único arquivo, com o de Intel listado primeiro, e a impressão digital usada para verificar o download vinha justamente dessa primeira entrada; agora ela está amarrada ao build de Apple silicon que de fato é baixado, o que em geral também detecta uma versão publicada entre a verificação e o clique, em vez de instalá-la em silêncio. Os dois foram baixados e passaram pelas barreiras reais de instalação antes do lançamento. A lição mais ampla não tinha nada a ver com nenhum dos dois: nada no DuoUpdater conseguia perceber um app deixado apenas com detecção por um motivo que já não era verdade, então a varredura noturna de receitas agora avisa quando um app que ela só observa já está nos entregando um instalador.

O QQ音乐 agora é acompanhado — versões novas, atualizações com um clique e suas notas de versão na janela. Nenhum dos caminhos habituais respondia por ele. Ele não publica feed do Sparkle e nem traz o framework do Sparkle; seu cask do Homebrew devolve a atualização ao próprio app; e o endpoint de atualização citado no próprio binário responde com 200 e um corpo vazio a tudo o que conseguimos perguntar — um silêncio que não dá para distinguir de um endpoint quebrado, por isso ele foi deixado de lado. O que o DuoUpdater lê em vez disso é o arquivo de dados a partir do qual a própria página de download do fornecedor é montada: essa página chega como uma casca vazia e se preenche a partir desse arquivo, que é também o único lugar onde as notas de versão existem — não há blog, nem appcast, nem página por versão. Por isso as notas são lidas direto dali e exibidas na própria janela do DuoUpdater, e a atualização instala a imagem de disco notarizada indicada nessa mesma resposta. Uma armadilha que vale registrar: esse arquivo ainda carrega um segundo registro para Mac, de seis anos atrás, ao lado do atual, então as duas regras se baseiam no nome de arquivo com versão do download para Mac, e não na palavra “Mac”. E um limite que vale deixar claro: o arquivo publica a versão que você vê, mas nunca o número de build por trás dela, então uma nova compilação de uma versão que mantém o mesmo nome fica invisível aqui. Ele não tem como inventar uma atualização que não existe — só não consegue enxergar esse tipo específico.

O TimeMachineEditor agora é acompanhado — versões novas e atualizações com um clique. Nenhum dos caminhos habituais respondia por ele: nada de feed do Sparkle (o app não traz nem um endereço de feed nem o framework que o usaria), nada de página na App Store, nenhum repositório público de lançamentos e um cask do Homebrew que devolve a atualização ao próprio app. O que ele tem é um pequeno site do fornecedor cujo único link de download informa a versão no próprio texto — a mesma página, lida da mesma forma, em que a verificação de versão do próprio Homebrew se apoia; ou seja, é a interface que o fornecedor pretende oferecer, e não um palpite. A atualização é instalada pelo pacote instalador do próprio fornecedor, e não como uma simples troca do app, e isso é proposital: o download também instala um agendador em segundo plano, uma ferramenta de linha de comando e um launch daemon fora do app, então trocar só o app deixaria uma cópia nova ao lado de um agendador desatualizado, sem nada que percebesse a diferença.

O Little Snitch agora é acompanhado, tanto nas versões estáveis quanto nas nightly. A Object Development publica um arquivo de versão ao qual o próprio atualizador do app recorre — o mesmo que o Homebrew lê — e o DuoUpdater o lê diretamente, porque o Little Snitch não publica feed do Sparkle e seu cask devolve a atualização ao app. As duas versões compartilham a mesma identidade, o que normalmente torna impossível distingui-las; esta se entrega na string de versão, onde um build nightly escreve a palavra por extenso (“6.5 nightly (7301)”), enquanto o build estável aparece como um simples “6.4.1”. Vale dizer o que isso deliberadamente não faz: não instala a atualização para você. O Little Snitch roda uma extensão do sistema e um serviço privilegiado em segundo plano junto com o app, e ainda não foi verificado numa máquina real se trocar só o app mantém essas partes intactas — então o DuoUpdater avisa que a versão nova saiu e leva você ao download do próprio fornecedor, em vez de arriscar com um filtro de rede.

O Carbon Copy Cloner agora é acompanhado, e não vai tentar levar você de uma versão principal para outra. A Bombich mantém três gerações ativas ao mesmo tempo — CCC 5, 6 e 7 —, todas se apresentando ao sistema com a mesma identidade, o que torna “existe algo mais novo?” uma pergunta mais difícil do que parece: 7.1.6 de fato vem depois de 6.1.13 na ordenação, mas passar de uma para a outra é uma compra à parte, e o CCC 7 exige um macOS mais novo do que uma máquina com CCC 5 talvez esteja rodando. Responder só pelo número de versão teria dito a todo dono de CCC 5 e 6 que havia uma atualização gratuita esperando, para sempre — e estaria errado todas as vezes. Por isso o DuoUpdater lê cada geração no seu próprio endereço e só oferece a próxima versão dentro da geração que você realmente tem. As versões beta também são detectadas, para quem as ativou dentro do CCC. Por enquanto é só detecção — o CCC instala um auxiliar privilegiado ao lado do app, o que é uma promessa maior do que as atualizações com um clique que já existem aqui — e vale registrar por que nada conseguia enxergar essas atualizações antes: o próprio feed de atualização do app responde a toda requisição com sucesso, com uma página totalmente vazia.

Uma atualização que o seu Mac não consegue rodar não é mais baixada nem instalada. Todo pacote de app informa o macOS mais antigo em que vai abrir, e alguns fornecedores também informam o mais novo — “este build não é para um sistema tão recente”, que é como um app que ainda não se adaptou ao macOS 27 avisa isso. O DuoUpdater não lia nenhum dos dois. Nos apps acompanhados por um feed do Sparkle o limite mínimo já era respeitado, mas eles são minoria: entre os apps de um Mac típico, os que são lidos no endpoint do próprio fornecedor ou em versões do GitHub são a maior parte, e uma versão do GitHub não publica requisito de macOS em lugar nenhum. Assim, um app que já tinha passado a exigir um macOS mais novo que o seu podia ser oferecido, baixado por inteiro, trocado — e depois não abrir. Agora o DuoUpdater lê o requisito no próprio app baixado, logo ao lado da verificação que já existia de que ele foi compilado para o seu processador, e recusa a troca em vez de substituir uma cópia que funciona por uma que não vai abrir. O limite máximo informado pelo fornecedor também é respeitado, quando um feed o publica, então um build que o desenvolvedor marcou como não compatível com o seu macOS nem chega a ser oferecido. Três limites que vale deixar claros. Ler o requisito no download significa que o download já aconteceu — isso evita uma instalação quebrada, não o tráfego, porque para a maioria dos apps não há onde perguntar antes. Um app cuja versão mais nova o seu Mac não consegue rodar vai continuar mostrando essa atualização e continuar se recusando a instalá-la; a recusa agora informa qual versão do macOS ela exige, mas o DuoUpdater ainda não guarda essa resposta para parar de oferecê-la. E a verificação cobre os caminhos em que o próprio DuoUpdater troca o pacote do app — um pacote instalador entrega o arquivo ao macOS, que aplica os requisitos do próprio pacote, e o Homebrew e a App Store escolhem seus próprios builds; os apps que vieram da seção de iPhone e iPad da App Store são pulados de propósito, já que a versão que informam é uma versão do iOS, e compará-la com o macOS seria pior do que não verificar nada. Uma coisa que ele ainda não diz em voz alta: quando um desenvolvedor marca um build como não compatível com o seu macOS, essa atualização simplesmente não é oferecida, e o app aparece como em dia em vez de explicar o motivo. Num Mac mais antigo isso se resolve sozinho no dia em que você atualizar o macOS. Num Mac novo demais, não se resolve — e ali se deve uma resposta melhor do que o silêncio.

O 百度网盘 agora é acompanhado — versões novas, atualizações com um clique e suas notas de versão na janela. Nenhum dos caminhos habituais estava aberto. Ele não publica feed do Sparkle; o cask do Homebrew não responde por uma cópia instalada manualmente; e o manifesto de atualização citado no próprio pacote do app está morto — esse arquivo, o gêmeo arm64 dele e o diretório que contém tudo isso respondem 404. Por isso o DuoUpdater lê o endpoint a partir do qual a própria página de download do fornecedor é montada e instala a imagem de disco arm64 notarizada indicada nessa mesma resposta. As notas de versão chegam do mesmo jeito: a página “版本更新” tem uma aba Mac版, mas a página em si chega vazia e se preenche a partir de uma API, então o DuoUpdater lê essa API diretamente e exibe os últimos quarenta lançamentos na própria janela. Um limite que vale deixar claro: esse feed publica a versão que você vê, mas nunca o número de build por trás dela, então uma nova compilação de uma versão que mantém o mesmo nome fica invisível aqui. Ele não tem como inventar uma atualização que não existe — só não consegue enxergar esse tipo específico.

Uma verificação que falhou agora diz que falhou, em vez de mostrar um espaço em branco. Um app cuja versão só o endpoint do próprio fornecedor sabe informar tinha um único jeito de dizer “sem resposta”: um traço vazio, que é também a aparência de um app que nada cobre. Assim, o endpoint de um fornecedor que expirava ou mudava de lugar parecia exatamente “o DuoUpdater não acompanha este app” — um veredito com cara de definitivo, sem botão Tentar de novo e sem entrar na contagem de “apps que não puderam ser verificados”. Agora esses casos são uma verificação que falhou, que é o que eles são: um botão Tentar de novo, um lugar na contagem e o motivo informado. Mas não tudo, de propósito: uma condição a respeito da qual o seu Mac simplesmente não pode fazer nada — nenhuma receita para a linha de lançamentos em que você está, um endpoint que exige uma identidade que esta máquina não tem — continua sendo o traço discreto de sempre, e uma verificação que falhou três rodadas seguidas continua saindo do aviso em vez de ficar presa nele para sempre. Um app instalado pelo JetBrains Toolbox também mantém seu botão “abrir o Toolbox” quando a leitura de versão por trás dele falha, já que abrir o Toolbox era a resposta de qualquer jeito.

O lembrete “reabra para aplicar” agora some depois que você reabre o app. Quando o próprio atualizador de um app baixava um build em segundo plano, o DuoUpdater avisava e oferecia um botão Reabrir na notificação. Usá-lo funcionava — o app voltava no build novo e dizia “Agora em 1.0.” —, mas o lembrete que ele substituía continuava na Central de Notificações, por baixo, ainda pedindo para você reabrir algo que você tinha acabado de reabrir. O DuoUpdater esperava o lembrete deixar de ser relevante, e o momento em que ele verificava era justamente o único momento que já tinha sido levado em conta. Agora ele remove o lembrete sempre que não há nenhuma reabertura pendente, o que também limpa um lembrete deixado para trás por um app que aplicou a própria atualização enquanto o DuoUpdater não estava rodando.

Apps que lançam vários builds com o mesmo número de versão agora são tratados direito — em todo lugar. Um app de Mac carrega duas strings de versão: a que ele mostra para você (“1.0”) e um número de build que de fato vai aumentando. A maioria dos apps muda as duas. Alguns mudam só o build: o Amp lançou dez builds num único dia, todos chamados 1.0; o Surge já lançou quatro versões diferentes como 6.9.0; os builds de prévia da JetBrains fazem o mesmo. O DuoUpdater decidia “isso mudou?” comparando a versão mostrada em cerca de uma dúzia de lugares, e para esses apps essa comparação só podia responder “não” — ou, onde a pergunta era “são iguais?”, “sim” —, não importava o que tivesse acontecido de fato. O que vem a seguir é o que isso quebrou. É um erro só, descoberto porque o Amp o deixou visível.

Reabrir não parece mais travar por três minutos para depois relatar uma falha que não aconteceu. Clicar em Reabrir num app cujo próprio atualizador tinha um build esperando deixava o indicador girando por três minutos e depois dizia que tinha falhado — quando, na verdade, a atualização tinha sido aplicada em um ou dois segundos e o app já tinha reaberto no build novo. O DuoUpdater ficava observando a versão mostrada à espera de uma mudança que nunca ia acontecer. Medido no Amp: 189 segundos de indicador girando para uma troca que levou menos de um. Agora isso se resolve em bem menos de um segundo, e uma falha real continua sendo relatada como falha.

Reabrir não oferece mais um build que já está desatualizado. Quando o atualizador de um app tinha baixado um build e o desenvolvedor já tinha publicado outro depois, o DuoUpdater ainda oferecia Reabrir — então você reabria e ficava imediatamente um build atrás, exatamente o que essa verificação foi escrita para evitar. Essas linhas agora oferecem Atualizar, que baixa o build atual.

Pular uma versão não silencia mais um app para sempre. Esta é a que vale a pena conhecer. “Pular esta versão” serve para recusar um lançamento e deixar o próximo passar. Ela registrava só a versão mostrada, então, num app que mantém o mesmo nome de versão entre builds, pular uma vez recusava todos os lançamentos futuros — de forma permanente, sobrevivendo a reinicializações, sem nada na tela indicando que o app tinha ficado em silêncio. Agora pular registra o build que foi recusado. Uma consequência da correção: uma versão pulada por um DuoUpdater anterior será oferecida mais uma vez, porque o registro antigo não tem como dizer a qual build se referia. Pulá-la de novo a registra corretamente.

A reversão volta a aparecer em atualizações que pareciam não ter mudado nada. A bancada esconde uma reversão que não faria nada — e, para esses apps, toda reversão parecia não fazer nada, então a linha sumia depois de uma atualização real, enquanto um backup completo ficava no disco sem nenhum jeito de chegar até ele.

O lembrete para reabrir volta a ser anunciado uma vez por build, e sobrevive ao desenvolvedor lançar outro. A 0.3.69 substituiu um lembrete que se repetia a cada cinco minutos por um que fala uma vez por build preparado — mas identificava o build pelo nome, então, para esses apps, anunciava o primeiro e depois ficava em silêncio para todos os seguintes. Isso foi corrigido. Além disso: se um app se recusa a fechar porque tem trabalho não salvo, o DuoUpdater guarda um lembrete para reabri-lo depois que você responder. Esse lembrete era descartado se o desenvolvedor publicasse outro build enquanto você decidia, deixando o app fechado depois da troca sem nada para reabri-lo. Agora ele acompanha o build novo.

Uma atualização da App Store que falhou não é mais registrada silenciosamente como sucesso, e um pacote instalador baixado não é mais tratado como o que está sendo oferecido no momento quando é um build mais antigo. Os dois problemas vinham da mesma comparação. O histórico de lançamentos também contava dez builds de um app como um só lançamento; a partir de agora conta separadamente, embora o histórico já registrado não possa ser recuperado.

A própria linha diz qual build a reabertura vai aplicar. Ela mostrava “1.0 → 1.0” — uma linha que não apontava diferença nenhuma. Agora mostra “1.0 (129) → 1.0 (130)”, e só quando o build é o que mudou; quando os nomes de versão já são diferentes, a linha continua igual. A mesma correção chega às dicas do Reabrir, à notificação, à nota que explica por que uma instalação foi adiada e à recusa do duo install.

O 微信输入法 e o 豆包输入法 voltam a ser atualizados com um clique — e do mesmo jeito que eles se atualizam sozinhos. A atualização com um clique para métodos de entrada foi retirada na 0.3.25, no mesmo dia do lançamento, depois que os ajustes de método de entrada de alguém sumiram. O problema estava no formato da instalação: ela substituía o app inteiro, como faz um instalador na primeira instalação. Um método de entrada é registrado no macOS pela localização do seu app, e esses dois apps se atualizam sem mexer nessa localização — eles mantêm o app e trocam o que está dentro dele. Agora o DuoUpdater faz a mesma coisa, então o app registrado atravessa a atualização como o mesmo app, e uma falha em qualquer ponto deixa a cópia que você estava usando exatamente onde estava. E nenhum dos dois pede mais a sua senha.

Antes que qualquer um deles seja atualizado, tudo o que aprenderam é copiado primeiro. Seu dicionário, seus ajustes e o estado da sua conta não ficam dentro do app, então a cópia de reversão que o DuoUpdater já guardava não tinha como responder por eles. Agora é tirado um snapshot deles antes de toda atualização de método de entrada, e eles são restaurados junto com a reversão, e a cópia sai quase de graça — 578 MB de um deles levam um décimo de segundo e quase nada de disco. Isto é uma rede de segurança, não um conserto: o que um app decide fazer com os seus dados na próxima vez que abre é código do próprio app rodando, e nada pode se colocar na frente disso. Agora existe algo para onde voltar.

Uma atualização não tira mais, silenciosamente, a capacidade de um app de se atualizar sozinho. Quando o DuoUpdater precisava de um administrador para substituir um app, ele restaurava o dono do app, mas não as permissões com que o app tinha sido instalado — e um download normalmente é descompactado com permissões mais restritas do que as que um instalador define. Nos dois métodos de entrada, essa é a diferença entre o próprio atualizador conseguir concluir a próxima atualização e não conseguir limpar a própria bagunça. As permissões com que um app foi instalado agora são levadas para a cópia que o substitui.

O DuoUpdater para de pedir que você reabra o mesmo app a cada cinco minutos. Um app que se atualiza sozinho deixa a versão nova guardada no disco e espera você fechá-lo. O DuoUpdater percebia isso a cada verificação e postava um lembrete toda vez, então um build que você tinha decidido não reabrir ainda continuava insistindo pelo tempo que você o deixasse ali. Agora cada build é anunciado uma vez: reabra, pule ou ignore o app e ele fica quieto, e o build seguinte se anuncia normalmente.

Um app esperando para ser reaberto conta como atualização, e um ignorado não conta mais. Uma versão nova que já está no disco é uma atualização — só foi baixada antes — então agora ela entra no contador do ícone e na linha “N atualizações disponíveis”, em vez de numa contagem separada ao lado. Os apps ignorados foram no sentido oposto: um app que você tinha ignorado podia acender o contador enquanto a linha dele mostrava uma etiqueta discreta “Ignorado” e nenhum botão para clicar, então o número apontava para algo com que você não podia fazer nada. Ignorar e pular agora significam a mesma coisa nas três superfícies — o lembrete, o contador e a lista.

O 搜狗输入法 agora é acompanhado — perguntando ao próprio atualizador dele, em vez de ler o site. A página de histórico de alterações da Sogou publica números de versão com três segmentos, enquanto a cópia instalada tem quatro, então comparar com ela exigiria cortar antes a versão real. A própria verificação de atualização do app, por outro lado, responde na numeração do próprio pacote. O DuoUpdater consulta esse endpoint do mesmo jeito que o app e lê o lançamento a partir dele, com os quatro segmentos, então uma nova compilação que muda só o último fica visível. Este é só de detecção: o atualizador da Sogou faz muito mais do que trocar o app — ele registra de novo um gerador da Visualização Rápida, move seus dados para um novo local e força o encerramento do método de entrada —, então a atualização em si fica por conta dele. Uma coisa que vale saber, e que é obra da Sogou, não nossa: o endpoint responde de acordo com a versão do macOS que faz a pergunta, e um Mac com macOS 28 perguntando por si mesmo recebe um build de 2023. O DuoUpdater não pergunta por si mesmo, então a versão que você vê é a atual em qualquer Mac.

Notas de versão que uma correção posterior teria acertado são lidas de novo, em vez de ficarem erradas para sempre. As notas ficam em cache por versão, partindo do raciocínio de que as notas de uma versão lançada nunca mudam. Isso vale para as notas, mas não para o que o DuoUpdater consegue extrair delas, então um app cujas notas saíram embaralhadas ficava assim naquela versão, não importava quantas correções de análise saíssem depois. Agora cada entrada do cache registra qual geração da lógica de extração a gravou, e uma gravada por uma geração mais antiga é buscada de novo. Os dois caches fazem isso — históricos de alterações de apps e notas de fórmulas do Homebrew.

Uma verificação que falha na CDN de alguém é tentada mais uma vez antes de ser considerada quebrada. 502, 503 e 504 significam, todos, que um intermediário não conseguiu alcançar o servidor por trás dele: a requisição nunca chegou, então a mesma requisição um instante depois costuma funcionar. A verificação do Headlamp morreu exatamente assim — o GitHub respondeu 504 sem nenhum cabeçalho de limite de requisições. Esses três agora ganham uma nova tentativa, depois de oito décimos de segundo. Só esses três, de propósito: um 500 é o próprio servidor falhando, e repetir o pedido quase sempre só reproduz a falha; e tentar de novo após atingir o limite de requisições gasta justamente a cota de que ele está reclamando.

As notas de versão de uma fórmula do Homebrew acompanham a versão a que pertencem. As notas eram guardadas por fórmula, nunca por versão, então, depois que as notas de uma fórmula eram carregadas, toda consulta seguinte recebia as notas daquela primeira versão pelo resto da sessão — inclusive depois que aparecia uma versão mais nova. Lê-las também ocupava a fila da qual o resto da lista de fórmulas dependia, então um brew info lento podia travar a lista em volta.

Clique com o botão direito num app na barra lateral da bancada para abri-lo. É a mesma opção Abrir que as linhas da barra de menus sempre ofereceram, agora na janela em que é mais provável que você queira usá-la.

Descartar um instalador baixado leva junto o erro que ele deixou para trás. Jogar fora um pacote preparado já fazia a linha voltar para Atualizar, mas uma falha em vermelho da tentativa que você tinha acabado de cancelar continuava ali — e nada jamais a apagaria, já que um erro só é retirado quando a linha fica em dia, o que nunca acontece com uma linha que ainda oferece uma atualização. Agora ele vai embora junto com o download.

O duo, o complemento opcional de linha de comando, para de se descrever de forma imprecisa. O --timeout foi removido — ele era aceito, documentado e não era lido por nada. O --budget é documentado pela primeira vez, e a única mensagem que o menciona agora informa um número real de minutos, em vez de sempre “15”. O --max-calls alegava um padrão de 20 quando o padrão é 6. Uma opção numérica que recebe algo que não é número agora é um erro: duo verify --max-concurrency 1x era ignorado e a varredura rodava com o padrão de quatro, o que é o contrário do que quer alguém que está deliberadamente deixando uma varredura mais lenta. E o duo verify conta as requisições que realmente fez: um feed que responde 502 e dá certo na nova tentativa não informa mais um ok limpo depois de ter perguntado duas vezes sem avisar. O -h funciona em todo lugar onde o --help funciona.

Mais quatro apps acompanhados, mais dois canais de lançamento, e todos se atualizam no lugar. CapCut, Canva e WorkBuddy nos dois sites em que é distribuído — o internacional e o chinês têm ciclos de lançamento independentes, então uma instalação só recebe a versão e as notas do seu próprio site. Termius e VSCodium ganham os canais Beta e Insiders ao lado dos builds estáveis que já eram cobertos. O segundo canal do CapCut é o mais complicado: ele é escolhido por um botão dentro do próprio CapCut e não aparece em lugar nenhum do número de versão, então o canal em que você está é lido da cópia no disco, e não deduzido do build que por acaso está rodando. Vale saber se você marcar essa opção: o DuoUpdater vai oferecer o beta mais novo assim que ele existir, o que pode ser antes do momento em que a liberação gradual do próprio CapCut chegaria até você.

Os canais de prévia do Android Studio não oferecem mais um build mais antigo que o seu. O Google lista os lançamentos na ordem em que foram publicados, não por versão, e o DuoUpdater procurava nessa lista três vezes separadas — uma para a versão, uma para a data, uma para o download —, então um release candidate publicado depois de um canary mais novo podia fornecer a versão de uma entrada e o arquivo de outra. Em 26 de agosto, o canal Canary respondeu com 2026.1.4 RC 2 quando o 2026.2.1 Canary 2 já tinha saído. Agora essas respostas precisam vir todas da mesma entrada.

Uma versão recompilada não instala mais a cópia que ela deveria substituir. Quando um projeto recompila uma versão sem mudar o número, os dois arquivos ficam sob a mesma tag — o KeePassXC publica KeePassXC-2.7.11-1-arm64.dmg ao lado do original KeePassXC-2.7.11-arm64.dmg — e o DuoUpdater pegava o que estivesse listado primeiro. Essa ordem é alfabética, o que desta vez por acaso colocou a recompilação em primeiro, e da próxima a teria colocado em último. Nada disso era visível: a versão na linha estava certa, só o arquivo por trás dela estava errado. Agora o arquivo certo é escolhido pelo que o próprio nome do arquivo diz.

Builds nightly e snapshot são reconhecidos como os builds de pré-lançamento que são. O nightly do VLC, o snapshot do KeePassXC e o nightly do Freelens são instalados com o mesmo nome e o mesmo identificador de pacote do app estável, então a string de versão é a única coisa que os denuncia — e ela não estava sendo lida. Eles contavam como instalações estáveis, e é assim que um nightly acaba recebendo uma versão comum para se sobrescrever. O nightly do DB Browser for SQLite é lido pelo próprio nome de arquivo do app pelo mesmo motivo, e ali o problema era real, só que escondido: a versão congelada dele fica acima da estável atual só até a estável alcançá-la, e a partir desse momento toda instalação nightly receberia, sem aviso, um build estável.

Reabrir um app informa o que realmente aconteceu. Alguns apps trazem um segundo app dentro do próprio pacote — o Surge guarda o Dashboard ali — e, quando só esse app interno precisava ser reiniciado, o DuoUpdater dizia que o app externo tinha sido reaberto, quando nada tinha acontecido. Agora ele informa o resultado do próprio app interno e não mostra mais uma notificação de reabertura para uma reabertura que nunca aconteceu.

Uma atualização que já foi baixada avisa isso, e pode ser desfeita. Uma linha com um pacote instalador já baixado mostrava um botão azul Instalar e mais nada — nada dizia que o download já estava concluído, nem que o botão reabre o instalador em vez de recomeçar a atualização, e não havia como mudar de ideia. Agora isso aparece na própria linha, em vez de ficar escondido numa dica, e Descartar Instalador Baixado no menu de clique com o botão direito da linha joga o download fora e faz a linha voltar para Atualizar. Descartar um pacote enquanto uma instalação do mesmo app já estava em andamento também podia jogar fora um pacote que tinha acabado de ser baixado; isso não acontece mais.

Botões de notas de versão que apontavam para páginas desativadas voltam a abrir páginas ativas. A Microsoft renomeou as páginas de notas de versão do Edge para empresas e o Termius mudou seu histórico de alterações de lugar, então três canais do Edge e o Termius estavam levando você a uma página que não existia mais. Nada nunca tinha verificado se essas páginas continuavam no ar, e é por isso que elas podiam se deteriorar indefinidamente enquanto todo o resto parecia saudável — agora elas são verificadas periodicamente. O canal Dev do Edge fica sem botão nenhum: a Microsoft parou de publicar notas para ele, e todas as páginas que ainda existem pertencem a outra linha de lançamentos.

O Raycast é acompanhado até a versão 2, e só nos Macs que conseguem rodá-la. O Raycast 2 exige o macOS Tahoe e Apple silicon. Um Mac que não atende a isso continua na linha da versão 1 e não é mais avisado de um lançamento que nunca poderia ter instalado. As duas linhas também passam a ter as próprias notas de versão, então uma instalação da versão 1 mostra o histórico da versão 1, e não o da versão 2.

As notas de versão são exibidas na própria janela do DuoUpdater para mais apps. BetterDisplay nos três canais, Shotbase e WorkBuddy nos dois sites. As notas do BetterDisplay não terminam mais com o código bruto do botão de download e não repetem mais a lista de colaboradores em cada lançamento.

O duo, o complemento opcional de linha de comando, recusa uma linha de comando que não entende. Uma opção digitada errado era ignorada, e uma opção ignorada é lida como se você nunca a tivesse passado — então duo verify --githubb verificava, sem avisar, todas as receitas em vez da que você pediu. Opções desconhecidas, uma opção sem o seu valor e argumentos soltos agora são erros que dizem o que o comando realmente aceita, e o --help funciona depois de qualquer comando.

Os builds de pré-lançamento e internos do BetterDisplay agora são oferecidos a quem pediu por eles. O BetterDisplay traz suas três linhas de lançamento num único feed de atualização e escolhe entre elas com dois botões nos próprios ajustes. O DuoUpdater só conseguia deduzir a sua linha pelo build que você por acaso estava rodando, o que não diz nada sobre um botão que você ativou mas ainda não usou — então alguém com os dois botões ativados, num build estável, ouvia que estava em dia enquanto o próprio atualizador do BetterDisplay oferecia uma versão quatro lançamentos à frente. Agora a sua escolha real é lida no BetterDisplay, incluindo o caso em que ativar os builds internos também mantém os pré-lançamentos comuns chegando. Os builds de prévia exclusivos para Apple silicon ficam de fora de propósito, para que um Mac Intel nunca receba um que não consegue rodar.

Trocar o canal de lançamento de um app duas vezes seguidas não deixa mais a linha presa na resposta antiga. Mudar o botão de canal faz o DuoUpdater verificar aquele app de novo, e uma segunda mudança enquanto a primeira verificação ainda rodava era descartada — a linha continuava oferecendo um beta a alguém que tinha acabado de desativar os betas, até que algo sem relação por acaso disparasse outra verificação. Agora a mudança mais recente assume o lugar da anterior, e uma verificação interrompida no meio deixa os apps que não chegou a alcançar marcados para a próxima rodada, em vez de registrá-los como resolvidos. As linhas também entram mais cedo no estado de verificação depois de uma mudança, então sobra menos tempo em que a resposta na tela é uma que o seu botão já invalidou.

Um app que fica dentro de outro app agora é fechado e reaberto junto com ele. Alguns apps trazem um segundo app completo dentro do próprio pacote — o Surge guarda o Dashboard ali. O macOS trata esse app como um app separado, então nada o fechava quando uma atualização era aplicada ao app em volta dele: ele continuava rodando a versão que tinha acabado de ser substituída, a partir de uma cópia que já não estava onde ele achava que estava, e dali não conseguia mais se comunicar com o app a que pertence. Agora esses apps são fechados junto com o app em que ficam e reabertos depois dele, e a janela em que você realmente estava trabalhando é a que volta para a frente. Só apps que você mesmo poderia ter aberto são tratados assim; os processos auxiliares invisíveis que um app roda para si mesmo são deixados em paz.

Pontos de reversão que tinham deixado de ser criados sem aviso voltam a ser criados. Um app pode bloquear um dos próprios arquivos para que nada consiga apagá-lo, e a cópia guardada para reversão herdava esse bloqueio — então ela nunca podia ser substituída pela seguinte, e uma única tentativa interrompida podia deixar para trás uma cópia que nada conseguia remover. A partir daí, toda atualização daquele app seguia sem caminho de volta, e dizia isso numa linha que não dava motivo nenhum. Um app no próprio Mac do desenvolvedor tinha ficado nesse estado por dois dias. As cópias guardadas para reversão não carregam mais o bloqueio, o app instalado fica exatamente como o desenvolvedor o configurou, e uma cópia que ficou presa não consegue mais impedir a que deveria substituí-la.

Uma atualização que funcionou não informa mais que falhou. O macOS pode colocar uma versão nova no lugar e depois falhar ao remover a que foi deslocada. Isso era levado ao pé da letra: o DuoUpdater dizia que um app não tinha sido atualizado quando tinha, ou que não havia ponto de reversão enquanto um completo estava guardado nos backups — e, no primeiro caso, mandava você conceder uma permissão que você já tinha concedido e que não teria ajudado de qualquer forma. Agora o que realmente aconteceu no disco é verificado antes de qualquer coisa ser informada.

As linhas de versão não repetem mais dígitos que o número de versão já contém. Quando um app está esperando para ser reaberto, a linha mostra a versão que você está rodando e aquela em que a reabertura vai deixar você. Os dois lados traziam um número de build, que é o que torna a diferença legível quando um desenvolvedor lança vários builds com o mesmo nome de versão — e puro ruído quando as versões já são diferentes. A linha do Chrome gastava a largura inteira imprimindo “151.0.7922.174 (7922.17…” e acabava antes dos dígitos que realmente mudaram. Agora os números de build só aparecem quando são eles que mudaram.

Agora uma só palavra para reabrir um app e concluir a atualização. Um app cujo próprio atualizador já tinha colocado a versão nova no lugar pedia que você o “reiniciasse”; um que guarda a versão nova à parte até você fechá-lo pedia que você o “reabrisse”. Essa diferença era real nos bastidores e não fazia diferença nenhuma para você: o mesmo clique nos dois casos, e o mesmo resultado se você nunca clicasse, já que a atualização entra na próxima vez que você fechar o app de qualquer jeito. Agora aparece Reabrir em todo lugar — inclusive nas notificações, nas dicas e no ajuste que faz isso por você —, que é também a palavra que o Chrome, o Claude e a maioria dos apps que se atualizam sozinhos colocam na sua frente. Só o inglês chegou a ter duas palavras para isso; alemão, japonês, russo e chinês sempre usaram uma só, e espanhol e francês passam a usar a palavra que já empregavam em outros lugares.

Uma atualização que precisa de um administrador agora pede um, em vez de falhar e pôr a culpa numa permissão. Se uma troca precisava de senha era decidido olhando a pasta em que o app fica, e não o próprio app. Tudo o que o macOS instalou como root — todo app da App Store e qualquer app instalado por um pacote instalador — passava nesse teste, seguia pelo caminho que não pede senha e não tinha como terminar: remover a versão antiga exige permissão de escrita nos diretórios dentro dela. O macOS informa essa recusa com o mesmo código que usa para uma permissão de Gerenciamento de Apps negada, então a falha chegava como um pedido para conceder o Gerenciamento de Apps, o que nunca ajudaria, porque o obstáculo era o dono dos arquivos. Num Mac comum, isso afetava todos os apps da App Store e mais alguns outros, e atingia contas de administrador — contas padrão já eram encaminhadas corretamente. Essas atualizações agora seguem pelo caminho que funciona, e o app mantém o dono que tinha, em vez de passar silenciosamente a ser seu.

Os apps da App Store agora ganham um ponto de reversão como todos os outros. Os backups os pulavam, partindo do raciocínio de que a loja sempre pode baixar de novo um build anterior. Ela não pode — a App Store só oferece a versão atual de um app —, o que fazia da loja o único caminho que aplicava uma atualização sem ter como desfazê-la. Agora esses apps ganham backup antes de uma atualização como qualquer outro, e, como a cópia é feita por clonagem, ela quase não ocupa espaço em disco até a atualização de fato substituir o original. Restaurar um deles avisa o que é específico da loja: a atualização reaparece na lista de Atualizações na hora, e é reaplicada sozinha se as atualizações automáticas de apps estiverem ativadas. E quando uma atualização da loja nunca ia ser aplicada — um app de iPhone rodando num Mac, um título não vendido na sua região —, nenhum ponto de reversão é mais criado, então uma linha não pode mais oferecer reverter para a versão que já está rodando.

O Longbridge Desktop agora é acompanhado, nas suas duas linhas de lançamento. Stable e Preview ganham, cada uma, detecção de versão, instalação com um clique do build oficial para Apple silicon e notas de versão exibidas na própria janela do DuoUpdater, com ilustrações.

As notas de versão do WhatsApp agora aparecem enquanto a verificação na App Store ainda está em andamento. A página da App Store mostrada nessa janela tinha sido registrada sob um nome que a busca nunca conseguiria encontrar, então o painel de notas ficava vazio em vez de mostrá-la.

O cabeçalho do menu mostra mais coisas em menos espaço. A versão do próprio DuoUpdater agora fica ao lado do nome, e clicar nela abre as notas de versão. “Atualizar Tudo” foi para uma linha própria, onde um rótulo traduzido tem espaço para ser lido por inteiro, e as ações na parte de baixo viraram ícones. O aviso que anunciava a autoatualização do DuoUpdater foi removido — em vez disso, o brilho ao lado da versão se acende e continua aceso até você ler o que mudou. Uma linha de status comprida demais para o menu agora termina em reticências, em vez de esticá-lo.

Os Ajustes não cortam mais as opções de atualização que oferecem. Os dois menus que decidem como uma atualização é aplicada cortavam os próprios rótulos em vários idiomas. O texto ficou mais curto, e eles passam para uma segunda linha quando as palavras ainda precisam disso.

A janela Novidades diz quando cada versão foi lançada. Toda versão na barra lateral agora traz a data de publicação.

Atualizações específicas de arquitetura agora escolhem o build que este Mac realmente consegue rodar. Alguns apps publicam a mesma versão duas vezes num único feed do Sparkle — uma para Apple silicon e outra para Intel — e o DuoUpdater desempatava pelo endereço de download que por acaso vinha primeiro na ordenação. Agora ele lê o requisito de hardware do feed e, quando o fornecedor o deixa em branco, a arquitetura no nome do arquivo. O build nativo sempre vence, e um build que este Mac não consegue abrir não é oferecido. As versões do GitHub recebem o mesmo tratamento, sem declarar quebrada uma receita perfeitamente saudável só porque o artefato mais novo dela é para outra arquitetura.

As verificações de atualização do ChatGPT agora seguem a linha de liberação associada à conta. A OpenAI às vezes mantém contas empresariais num build de desktop anterior enquanto um novo chega primeiro às contas pessoais. O DuoUpdater omitia o plano da conta nessa verificação, o que silenciosamente selecionava a linha mais cautelosa para todo mundo: ele podia dizer que a cópia instalada estava de alguma forma à frente enquanto o próprio ChatGPT já baixava um build mais novo, ou oferecer um build que o próprio atualizador do app substituiria de novo. Agora ele envia o rótulo do plano, lido do estado de login do ChatGPT/Codex, na mesma requisição de atualização que o app faz. Se esse rótulo não estiver disponível, ele mantém o comportamento cauteloso; as credenciais em si nunca entram na requisição nem nos diagnósticos.

Uma reabertura que o macOS nunca responde não consegue mais travar todas as atualizações seguintes. O Launch Services de vez em quando aceita um pedido para reabrir um app atualizado e nunca dá retorno. A linha ficava em “Reabrindo…” para sempre, o botão Reiniciar continuava desativado e a atualização do próprio DuoUpdater ficava esperando atrás dela. Uma abertura que não respondeu depois de um minuto agora é liberada como falha, então a linha se recupera e o resto do atualizador continua funcionando.

O Registro de Versões continua preenchido quando a barra de rolagem é arrastada depressa. A pilha preguiçosa antiga podia ficar para trás num salto longo, deixando por um instante a janela em branco enquanto as linhas eram criadas em volta da nova posição. Agora o registro usa uma lista com reciclagem que consegue saltar direto para o destino. O controle de atualizar também mantém o mesmo tamanho ao alternar entre a seta e o indicador de progresso, então a linha de baixo não dá mais um tranco quando uma verificação começa.

O Tráfego de Downloads agora marca as atualizações que usaram um patch binário. Os downloads novos registram o caminho que de fato foi concluído — e não só se um patch foi oferecido — e ganham um selo Delta no histórico. Os downloads de patch da 0.3.62, claramente menores, também são reconhecidos, mesmo tendo sido registrados antes de o registro de tráfego ter um campo de caminho.

As atualizações agora baixam só o que mudou, quando o desenvolvedor as publica desse jeito. Alguns apps lançam um pequeno patch junto com cada versão — o suficiente para transformar a versão que você tem na nova, sem baixar tudo de novo. O DuoUpdater ignorava esses patches e baixava o pacote completo toda vez. Agora ele usa o patch quando há um que corresponde exatamente ao build que você tem. A última atualização do ChatGPT ficou em 1,9 MB em vez de 605 MB; a do Docker, em 87 MB em vez de 582 MB. O resultado é o mesmo aplicativo de qualquer forma — mesma assinatura, mesmos bytes, conferido com o download completo antes deste lançamento. Quando nenhum patch serve para o que você tem, ou um deles falha ao ser aplicado, o download completo acontece como antes, então nada pode deixar de ser instalado por causa disso.

O DuoUpdater não baixa mais uma atualização que o próprio app já está baixando. Muitos apps também se atualizam sozinhos, e nós dois indo buscar o mesmo arquivo de 600 MB ao mesmo tempo custava a você esse arquivo duas vezes. Agora o DuoUpdater percebe um download em andamento e o deixa em paz, avisando isso na linha em vez de simplesmente não fazer nada em silêncio. Se esse download acabar abandonado, ele deixa de contar depois de dez minutos, para que nada fique bloqueado.

Uma atualização que um app já preparou não é mais sobrescrita. Apps que se atualizam sozinhos costumam baixar em segundo plano e depois esperar você fechá-los para colocar a versão nova no lugar. Instalar por cima de uma dessas parecia funcionar e se desfazia no momento em que você fechava o app — e, quando a versão pendente do próprio app era mais antiga do que a que o DuoUpdater tinha acabado de instalar, você terminava mais atrasado do que quando começou. Agora essas atualizações são deixadas para terminar, seja qual for a versão que trazem.

As atualizações do próprio DuoUpdater também ficaram menores. Os lançamentos dele agora trazem o mesmo tipo de patch, então atualizar a partir de uma versão recente baixa algumas centenas de kilobytes em vez de onze megabytes.

As explicações deixadas por uma atualização agora se apagam sozinhas. Quando o DuoUpdater entrega um app ao próprio atualizador dele, a linha avisa — “foi trazido para a frente para que o atualizador dele aplique a atualização”. Essa frase ficava ali para sempre: a única coisa que a removia era começar outra atualização do mesmo app, então ela continuava embaixo da linha muito tempo depois de a atualização ter entrado, descrevendo algo que tinha terminado horas antes. Agora ela some assim que o app fica em dia. Um aviso de que uma atualização foi aplicada sem ponto de reversão é deixado de propósito, porque ele descreve a atualização que já aconteceu e só passa a importar depois que ela termina.

Uma atualização recusada agora se explica no seu idioma. Quando outra coisa já está instalando — o DuoUpdater trabalhando num lote, ou o duo num terminal —, a linha avisa. Essa mensagem só existia em inglês, numa janela de resto traduzida, e terminava com um número de processo: útil num terminal, e nada com que você possa fazer algo num menu. Agora ela é traduzida e diz o que fazer, em vez de quem está com o bloqueio. A ferramenta de linha de comando continua mostrando o número do processo, onde dá para fazer algo com ele.

A linha do padrão de lançamentos, e o horário dela, agora seguem a sua região. Registro de Versões → Padrões resumia tudo como “Most often ships Friday, around 6 PM”. Idiomas que flexionam os nomes dos dias não conseguem dizer isso com o dia encaixado no meio da frase, e acabavam com a forma errada da palavra — o russo mostrava “Чаще всего выходит пятница” quando precisa de “по пятницам”. Agora é um rótulo: “Pico: sexta-feira, por volta de 18:00”, que fica correto em qualquer idioma. O horário vai junto — se o seu Mac escreve as horas no formato de 24 horas, isto também escreve, inclusive no eixo do gráfico.

A busca dos Ajustes agora entende as palavras que estão na sua tela. O campo de busca acima da barra lateral dos Ajustes comparava com uma lista de termos extras escrita em inglês e nunca traduzida, então “rollback” levava a Geral, enquanto “Zurücksetzen” e “回滚” não levavam a lugar nenhum. Agora esses termos existem em todos os idiomas que o DuoUpdater fala. Os termos em inglês continuam funcionando em todos os idiomas também, já que a documentação de onde vêm está em inglês.

Ativar “Mostrar tudo” não faz mais o menu hesitar. A lista completa de todos os seus apps era medida por inteiro a cada vez que aparecia — num Mac com 127 apps, isso dava cerca de um segundo de trabalho, quase todo gasto organizando linhas bem abaixo das que você consegue ver. E o custo se repetia a cada vez que a opção era ativada, não só na primeira. Agora só as linhas que estão de fato na tela são montadas.

Uma explicação que sobrou de uma atualização que falhou não dura mais do que a falha. Quando uma atualização não podia ser aplicada — porque outra coisa já estava instalando, por exemplo —, a linha dizia o motivo, em vermelho. Nada jamais removia essa linha: quando a atualização finalmente entrava e a linha voltava a mostrar o sinal de visto, a explicação antiga continuava embaixo, e ficava ali a cada nova verificação até o DuoUpdater ser reiniciado. Agora ela some assim que o app fica em dia. Os motivos que pertencem a atualizações ainda pendentes são deixados em paz, para que um que você ainda não leu não seja apagado por uma verificação rodando em segundo plano.

O botão “Atualizar Tudo” não muda mais de tamanho conforme o comprimento da lista. Com poucas atualizações pendentes, ele era desenhado um tamanho menor do que deveria, com oitenta pontos de espaço vazio ao lado, e voltava ao tamanho certo sempre que a lista crescia. Agora ele fica sempre do tamanho que deve ter.

O Tráfego de Downloads agora diz para qual build uma atualização foi, e não só para qual versão. Muitos apps lançam vários builds com o mesmo nome de versão — o Surge lançou quatro versões diferentes como “6.9.0” —, então essas linhas mostravam “6.9.0 → 6.9.0” e não diziam nada. Agora elas mostram “6.9.0 (12028) → 6.9.0 (12030)”, e só quando o nome da versão sozinho não basta; quando a versão já mudou, o número de build seria só ruído e fica de fora.

O build registrado é o que de fato entrou, lido no próprio app depois que a atualização está no lugar. Não o número anunciado pelo feed de atualização do desenvolvedor — feeds às vezes informam errado, e assim funciona também para as fontes que não publicam número de build nenhum: GitHub, Homebrew e a App Store. Uma atualização que ainda está esperando na janela do instalador do macOS nunca é adivinhada; nada é registrado para ela até que seja real.

Um download que não mudou nada agora é marcado como tal. De vez em quando, uma atualização baixa e instala o build que já estava no seu Mac — um número de versão desencontrado do lado do desenvolvedor, um espelho servindo o que você já tem. Isso é banda de verdade gasta sem resultado nenhum, e a janela de tráfego é onde você iria querer ver isso. Essas linhas agora têm uma etiqueta “sem mudança”. Os downloads registrados antes desta versão não têm números de build para comparar, então são deixados como estão em vez de adivinhados: desconhecido não é o mesmo que inalterado.

O DuoUpdater agora mostra quanto manter seus apps em dia realmente custou em downloads. Ele vinha contando, byte a byte, cada atualização que baixou para você — mas a contagem não tinha onde aparecer, então o número ficava num arquivo que ninguém conseguia ler. Agora existe uma janela Tráfego de Downloads, aberta pelo botão de gráfico na parte de baixo do menu, com o total deste mês impresso ao lado desse botão, para que a pergunta mais comum seja respondida sem abrir nada. Lá dentro: o total, os últimos três meses lado a lado com a variação entre eles, um detalhamento de onde vieram os bytes e todos os apps classificados pelo quanto custaram — clique num deles para ver cada atualização que ele recebeu, de qual versão para qual versão foi e o tamanho do download.

O total é honesto sobre o que não consegue ver. O Homebrew, a App Store e os apps que se atualizam pelo próprio atualizador interno baixam os próprios bytes, e o DuoUpdater nunca passa por eles — então o número é um piso, não uma contabilidade completa. Isso sempre foi verdade; o que mudou é que a janela agora diz isso de forma permanente, e não só na tela vazia que você vê antes de qualquer coisa ser registrada.

Apps que você renomeou ou apagou mantêm o histórico. O tráfego é registrado pelo local em que o app fica no disco, e é isso que permite que dois canais do mesmo app — Android Studio Canary e Beta, por exemplo — fiquem separados em vez de somados. O preço é que renomear um app deixa o passado dele sob um nome que não existe mais. Quando a OpenAI renomeou o Codex para ChatGPT, isso dividiu 30 GB de downloads entre duas entradas que pareciam duplicadas. Agora essas entradas ficam agrupadas e esmaecidas no fim da lista, sob um título que diz o que elas são. Nada é descartado, e o total continua incluindo essas entradas.

Um app que você instalou pela App Store não recebe mais a oferta do download do próprio desenvolvedor. Muitos apps são publicados em dois lugares ao mesmo tempo — na loja e como download direto no site do desenvolvedor — com a mesma identidade, mas como builds realmente diferentes. O download direto costuma sair na frente, porque não espera a revisão da loja. O DuoUpdater verifica primeiro a loja para um app instalado por ela, mas, quando essa verificação falhava por qualquer motivo — uma conexão que caiu, uma loja regional que não respondeu —, ele passava silenciosamente para o site do desenvolvedor e oferecia o que estivesse lá. O WhatsApp mostrou isso como “26.32.75 → 26.33.19”: uma versão real, do lugar errado. Aceitá-la teria substituído a sua cópia da loja por uma que a App Store nunca mais conseguiria atualizar. Os apps instalados pela loja agora são verificados só na loja, e em nenhum outro lugar.

Trocar o canal de atualização de um app dentro do próprio app agora é percebido na hora. Alguns apps deixam você escolher entre as versões normais e as beta — Surge, Tailscale, Fork, OrbStack, IINA, Alfred e outros — e o DuoUpdater segue o que você escolheu, para nunca oferecer um build que você não pediu. Antes, ele só percebia a mudança quando você fechava o app ou abria uma das janelas do DuoUpdater. Nenhuma das duas coisas cobre o que as pessoas realmente fazem: desativar a opção, deixar o app aberto e dar uma olhada na barra de menus. Pior: os apps gravam essa opção no disco quando lhes convém, não no momento em que você clica — o Surge levou cinco minutos aqui —, então até fechar o app podia ser lido cedo demais. Agora o DuoUpdater observa a própria opção mudar e verifica aquele app de novo em um ou dois segundos. Voltar o Surge para as versões normais agora limpa a versão beta da linha dele na hora, em vez de deixá-la ali por até uma hora.

Uma verificação que não conseguiu alcançar nada não parece mais um atestado de que está tudo bem. Quando todas as fontes falhavam — sem rede, ou um proxy recusando conexões em silêncio enquanto o ícone do Wi-Fi continua dizendo que está tudo certo —, os apps que falharam eram escondidos e o painel dizia “127 apps · atualizados”. É a mesma tela que você vê quando tudo realmente está em dia, o que tornava uma verificação que falhou impossível de distinguir de uma bem-sucedida. Agora o painel diz quantos apps ele não conseguiu alcançar, mostra o que deu errado e oferece tentar esses de novo — só esses, deixando em paz tudo o que ele conseguiu verificar.

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.