Skip to content

Update Fleet-maintained apps - #49813

Merged
allenhouchins merged 3 commits into
mainfrom
fma-2607231228
Jul 23, 2026
Merged

Update Fleet-maintained apps#49813
allenhouchins merged 3 commits into
mainfrom
fma-2607231228

Conversation

@fleet-release

@fleet-release fleet-release commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Automated ingestion of latest Fleet-maintained app data.

Summary by CodeRabbit

  • New Features
    • Added/updated managed release definitions for many applications on both macOS and Windows.
    • Updated the Mozilla VPN installer script to better handle MSI installs in automation.
    • Marked Typora for frozen behavior in winget to prevent unintended updates.
  • Bug Fixes
    • Refreshed download links and integrity checksums across updated app versions.
    • Improved version detection for newly released builds.
  • Improvements
    • Enhanced uninstall behavior for select apps (additional cleanup/services and improved media handling for ONLYOFFICE macOS).

Generated automatically with cmd/maintained-apps.
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/advanced-installer/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/akiflow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/amie/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/anytype/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aptakube/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-sam-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/bettertouchtool/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/betterzip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/beyond-compare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/burp-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cleanmymac/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/clop/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/comet/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cursor/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dockside/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/drawio/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/enpass/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/filebeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@developer-edition/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-ads-editor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-gemini/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/groove-omnidialer/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hive-app/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hwmonitor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro-cli/darwin.json

=== Install Script (no changes) ===
=== Uninstall // 31b59062 -> ed98f0de ===

--- /tmp/old.36rILL	2026-07-23 12:36:02.250956493 +0000
+++ /tmp/new.3SSd3P	2026-07-23 12:36:02.250956493 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,14 @@
   fi
 }
 
+remove_launchctl_service 'com.amazon.codewhisperer.launcher'
 sudo rm -rf "$APPDIR/Kiro CLI.app"
 trash $LOGGED_IN_USER '~/.kiro'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'
 trash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'
+trash $LOGGED_IN_USER '~/Library/Caches/com.amazon.codewhisperer'
 trash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.amazon.codewhisperer.launcher.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'
+trash $LOGGED_IN_USER '~/Library/WebKit/com.amazon.codewhisperer'

ee/maintained-apps/outputs/kiro/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/lookaway/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/macwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/marsedit/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/megasync/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/melodics/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/darwin.json

=== Install // 54ba1114 -> 27c40399 ===

--- /tmp/old.DGfJJ2	2026-07-23 12:36:02.839962252 +0000
+++ /tmp/new.6rsAJb	2026-07-23 12:36:02.840962261 +0000
@@ -96,5 +96,5 @@
 
 # install pkg files
 quit_and_track_application 'com.naps2.desktop'
-sudo installer -pkg "$TMPDIR/naps2-8.3.1-mac-arm64.pkg" -target /
+sudo installer -pkg "$TMPDIR/naps2-8.3.2-mac-arm64.pkg" -target /
 relaunch_application 'com.naps2.desktop'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/notepadexe/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/obs/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/only-switch/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/onlyoffice/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/picview/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/popclip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powerphotos/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powershell/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0995d374 -> 06cf76b8 ===

--- /tmp/old.i4zF0G	2026-07-23 12:36:03.393967669 +0000
+++ /tmp/new.mA6ziZ	2026-07-23 12:36:03.393967669 +0000
@@ -1,4 +1,4 @@
-$product_code = '{7B031DCF-BDCE-47D6-89B9-4C558D76E773}'
+$product_code = '{92D9A5DC-8C64-40D5-B1BC-98DB9C7FDB7F}'
 $timeoutSeconds = 300  # 5 minute timeout
 
 # Fleet uninstalls app using product code that's extracted on upload

ee/maintained-apps/outputs/prisma-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rider/darwin.json

=== Install Script (no changes) ===
=== Uninstall // c52dae57 -> 22db20ac ===

--- /tmp/old.wgby1O	2026-07-23 12:36:03.573969429 +0000
+++ /tmp/new.PMjeOx	2026-07-23 12:36:03.573969429 +0000
@@ -54,9 +54,9 @@
 
 sudo rm -rf "$APPDIR/Rider.app"
 sudo rm -rf 'rider'
-trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'
-trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'

ee/maintained-apps/outputs/rive/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rustrover/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/setapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall // e23bd29d -> 9ef05eb6 ===

--- /tmp/old.CkIkGZ	2026-07-23 12:36:03.710970768 +0000
+++ /tmp/new.0tx7D5	2026-07-23 12:36:03.710970768 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,19 @@
   fi
 }
 
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAgent'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'
 sudo rm -rf "$APPDIR/Setapp.app"
 trash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'
+trash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'
 trash $LOGGED_IN_USER '~/Library/Logs/Setapp'
+trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'

ee/maintained-apps/outputs/sidenotes/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/snagit/darwin.json

=== Install Script (no changes) ===
=== Uninstall // b52ff2b2 -> 59bfdeae ===

--- /tmp/old.FRQxyP	2026-07-23 12:36:03.892972548 +0000
+++ /tmp/new.IfJAX2	2026-07-23 12:36:03.892972548 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,9 +92,14 @@
   fi
 }
 
+quit_application 'com.TechSmith.Snagit'
 sudo rm -rf "$APPDIR/Snagit.app"
+trash $LOGGED_IN_USER '~/Library/Application Scripts/7TQL462TU8.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.snagit.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/Snagit'
 trash $LOGGED_IN_USER '~/Library/Caches/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Group Containers/*.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.TechSmith.Snagit*.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.snagit.capturehelper*.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.TechSmith.Snagit*.savedState'

ee/maintained-apps/outputs/sourcetree/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/superwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/tabby/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/trezor-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/typora/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/visual-studio-code/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/vivaldi/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/wechat/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/whatsapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/winlogbeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/workflowy/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: abcde3e9-6951-4e41-ba02-b9342ff57e0f

📥 Commits

Reviewing files that changed from the base of the PR and between e090844 and 0e68453.

📒 Files selected for processing (3)
  • ee/maintained-apps/inputs/winget/mozilla-vpn.json
  • ee/maintained-apps/inputs/winget/scripts/mozilla-vpn_install.ps1
  • ee/maintained-apps/outputs/mozilla-vpn/windows.json

Walkthrough

Updated numerous Darwin and Windows maintained-app manifests to newer releases, synchronizing version checks, installer URLs, and SHA-256 checksums. Updated lifecycle scripts for selected applications, including uninstall cleanup, DMG/PKG installation handling, and bounded Mozilla VPN MSI installation. Changed ONLYOFFICE’s installer format to DMG, added its Winget install script configuration, and marked the Typora Winget input as frozen.

Possibly related PRs

  • fleetdm/fleet#49804: Overlaps on the same maintained-app version, query, URL, and checksum updates.
  • fleetdm/fleet#49743: Updates overlapping maintained-app release metadata, including Advanced Installer.
  • fleetdm/fleet#49759: Modifies several of the same maintained-app manifest entries and release fields.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is too vague and does not follow the required template sections or checklist items. Add the Related issue line plus the required checklist sections (changes, testing, migrations, GitOps) and fill or remove inapplicable items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: updating Fleet-maintained apps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fma-2607231228

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ee/maintained-apps/outputs/kiro-cli/darwin.json`:
- Line 20: Update remove_launchctl_service in both
ee/maintained-apps/outputs/kiro-cli/darwin.json and
ee/maintained-apps/outputs/setapp/darwin.json to resolve the logged-in console
user’s UID and remove /Library/LaunchAgents through that user’s launchctl domain
using launchctl asuser or bootout gui before deleting the plist; retain
system-domain handling for other entries.

In `@ee/maintained-apps/outputs/onlyoffice/darwin.json`:
- Around line 9-12: The OnlyOffice Darwin artifact format is inconsistent with
the referenced installation script. Update the configuration around
installer_url and install_script_ref so they use matching ZIP-based artifacts
and unzip logic, or switch to a DMG-compatible install script reference that
mounts and copies from the DMG; ensure sha256 matches the selected installer.

In `@ee/maintained-apps/outputs/rider/darwin.json`:
- Line 20: Update the Rider uninstall path handling to remove the documented
JetBrains directories under ~/Library: Application
Support/JetBrains/Rider2026.2, Caches/JetBrains/Rider2026.2, and
Logs/JetBrains/Rider2026.2. Replace the existing Rider2026.2 paths that omit the
JetBrains parent directory, and ensure all three data locations are deleted.
- Line 20: Update the Rider uninstall script in
ee/maintained-apps/outputs/rider/darwin.json at line 20 to invoke the bounded
quit_and_track_application() flow for com.jetbrains.rider before deleting or
moving Rider.app, preserving the existing relaunch tracking behavior as
applicable. Apply the same pre-cleanup quit pattern to the Setapp uninstall
script in ee/maintained-apps/outputs/setapp/darwin.json at line 20 if its
uninstall path removes a running application bundle.
- Line 20: The uninstall flow must terminate Rider before removing its
application bundle. Reuse the existing bounded quit logic from
quit_and_track_application, or invoke that shared helper, immediately before
sudo rm -rf "$APPDIR/Rider.app"; preserve the timeout behavior and ensure
removal proceeds only after the quit attempt.

In `@ee/maintained-apps/outputs/trezor-suite/darwin.json`:
- Around line 4-9: Update the installer_url for the Trezor Suite 26.7.2 manifest
to use the immutable versioned release directory instead of latest, preserving
the existing filename and checksum alignment; confirm the versioned URL path
exists before applying the change.

In `@ee/maintained-apps/outputs/zed/darwin.json`:
- Line 9: Update the installer_url in darwin.json to use a universal Zed macOS
artifact or the appropriate architecture-specific package selection, ensuring
both Apple Silicon and Intel clients receive compatible installers instead of
only Zed-aarch64.dmg.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ce645285-1de7-4e54-a640-eb6d73bc0ed5

📥 Commits

Reviewing files that changed from the base of the PR and between 62ed358 and c5deadd.

📒 Files selected for processing (87)
  • ee/maintained-apps/outputs/advanced-installer/windows.json
  • ee/maintained-apps/outputs/akiflow/darwin.json
  • ee/maintained-apps/outputs/amie/darwin.json
  • ee/maintained-apps/outputs/anytype/darwin.json
  • ee/maintained-apps/outputs/aptakube/windows.json
  • ee/maintained-apps/outputs/aws-cli/windows.json
  • ee/maintained-apps/outputs/aws-sam-cli/windows.json
  • ee/maintained-apps/outputs/bettertouchtool/darwin.json
  • ee/maintained-apps/outputs/betterzip/darwin.json
  • ee/maintained-apps/outputs/beyond-compare/darwin.json
  • ee/maintained-apps/outputs/brave-browser/darwin.json
  • ee/maintained-apps/outputs/brave-browser/windows.json
  • ee/maintained-apps/outputs/burp-suite/darwin.json
  • ee/maintained-apps/outputs/cleanmymac/darwin.json
  • ee/maintained-apps/outputs/clop/darwin.json
  • ee/maintained-apps/outputs/comet/windows.json
  • ee/maintained-apps/outputs/cursor/darwin.json
  • ee/maintained-apps/outputs/dataflare/darwin.json
  • ee/maintained-apps/outputs/dataflare/windows.json
  • ee/maintained-apps/outputs/datagrip/darwin.json
  • ee/maintained-apps/outputs/datagrip/windows.json
  • ee/maintained-apps/outputs/dockside/darwin.json
  • ee/maintained-apps/outputs/drawio/windows.json
  • ee/maintained-apps/outputs/enpass/windows.json
  • ee/maintained-apps/outputs/fellow/darwin.json
  • ee/maintained-apps/outputs/fellow/windows.json
  • ee/maintained-apps/outputs/filebeat/windows.json
  • ee/maintained-apps/outputs/firefox@developer-edition/darwin.json
  • ee/maintained-apps/outputs/firefox@nightly/darwin.json
  • ee/maintained-apps/outputs/firefox@nightly/windows.json
  • ee/maintained-apps/outputs/google-ads-editor/windows.json
  • ee/maintained-apps/outputs/google-gemini/darwin.json
  • ee/maintained-apps/outputs/granola/darwin.json
  • ee/maintained-apps/outputs/granola/windows.json
  • ee/maintained-apps/outputs/groove-omnidialer/darwin.json
  • ee/maintained-apps/outputs/hive-app/darwin.json
  • ee/maintained-apps/outputs/hwmonitor/windows.json
  • ee/maintained-apps/outputs/kiro-cli/darwin.json
  • ee/maintained-apps/outputs/kiro/darwin.json
  • ee/maintained-apps/outputs/kiro/windows.json
  • ee/maintained-apps/outputs/lookaway/darwin.json
  • ee/maintained-apps/outputs/loom/darwin.json
  • ee/maintained-apps/outputs/loom/windows.json
  • ee/maintained-apps/outputs/macwhisper/darwin.json
  • ee/maintained-apps/outputs/marsedit/darwin.json
  • ee/maintained-apps/outputs/megasync/windows.json
  • ee/maintained-apps/outputs/melodics/darwin.json
  • ee/maintained-apps/outputs/microsoft-teams/darwin.json
  • ee/maintained-apps/outputs/microsoft-teams/windows.json
  • ee/maintained-apps/outputs/mozilla-vpn/darwin.json
  • ee/maintained-apps/outputs/mozilla-vpn/windows.json
  • ee/maintained-apps/outputs/naps2/darwin.json
  • ee/maintained-apps/outputs/naps2/windows.json
  • ee/maintained-apps/outputs/nosql-workbench/darwin.json
  • ee/maintained-apps/outputs/nosql-workbench/windows.json
  • ee/maintained-apps/outputs/notepadexe/darwin.json
  • ee/maintained-apps/outputs/obs/darwin.json
  • ee/maintained-apps/outputs/only-switch/darwin.json
  • ee/maintained-apps/outputs/onlyoffice/darwin.json
  • ee/maintained-apps/outputs/picview/darwin.json
  • ee/maintained-apps/outputs/popclip/darwin.json
  • ee/maintained-apps/outputs/powerphotos/darwin.json
  • ee/maintained-apps/outputs/powershell/windows.json
  • ee/maintained-apps/outputs/prisma-browser/windows.json
  • ee/maintained-apps/outputs/pritunl/darwin.json
  • ee/maintained-apps/outputs/pritunl/windows.json
  • ee/maintained-apps/outputs/rider/darwin.json
  • ee/maintained-apps/outputs/rive/darwin.json
  • ee/maintained-apps/outputs/rustrover/windows.json
  • ee/maintained-apps/outputs/setapp/darwin.json
  • ee/maintained-apps/outputs/sidenotes/darwin.json
  • ee/maintained-apps/outputs/signal/darwin.json
  • ee/maintained-apps/outputs/signal/windows.json
  • ee/maintained-apps/outputs/snagit/darwin.json
  • ee/maintained-apps/outputs/sourcetree/darwin.json
  • ee/maintained-apps/outputs/superwhisper/darwin.json
  • ee/maintained-apps/outputs/tabby/darwin.json
  • ee/maintained-apps/outputs/trezor-suite/darwin.json
  • ee/maintained-apps/outputs/typora/windows.json
  • ee/maintained-apps/outputs/visual-studio-code/darwin.json
  • ee/maintained-apps/outputs/vivaldi/darwin.json
  • ee/maintained-apps/outputs/wechat/darwin.json
  • ee/maintained-apps/outputs/whatsapp/darwin.json
  • ee/maintained-apps/outputs/winlogbeat/windows.json
  • ee/maintained-apps/outputs/workflowy/darwin.json
  • ee/maintained-apps/outputs/zed/darwin.json
  • ee/maintained-apps/outputs/zed/windows.json

"31b59062": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Kiro CLI.app\"\ntrash $LOGGED_IN_USER '~/.kiro'\ntrash $LOGGED_IN_USER '~/.local/bin/kiro-cli'\ntrash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'\ntrash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'\ntrash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'\ntrash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'\n",
"7bf3d706": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'dev.kiro.cli'\nif [ -d \"$APPDIR/Kiro CLI.app\" ]; then\n\tsudo mv \"$APPDIR/Kiro CLI.app\" \"$TMPDIR/Kiro CLI.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Kiro CLI.app\" \"$APPDIR\"\nrelaunch_application 'dev.kiro.cli'\n"
"7bf3d706": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'dev.kiro.cli'\nif [ -d \"$APPDIR/Kiro CLI.app\" ]; then\n\tsudo mv \"$APPDIR/Kiro CLI.app\" \"$TMPDIR/Kiro CLI.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Kiro CLI.app\" \"$APPDIR\"\nrelaunch_application 'dev.kiro.cli'\n",
"ed98f0de": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n done\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.amazon.codewhisperer.launcher'\nsudo rm -rf \"$APPDIR/Kiro CLI.app\"\ntrash $LOGGED_IN_USER '~/.kiro'\ntrash $LOGGED_IN_USER '~/.local/bin/kiro-cli'\ntrash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'\ntrash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.amazon.codewhisperer'\ntrash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.amazon.codewhisperer.launcher.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.amazon.codewhisperer'\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repository files matching darwin.json in maintained-apps:\n'
fd -a 'darwin\.json$' ee/maintained-apps/outputs 2>/dev/null | sed 's#^\./##' | sort | head -200

printf '\nRelevant snippets for kiro-cli and setapp launchctl/trash paths:\n'
for f in \
  ee/maintained-apps/outputs/kiro-cli/darwin.json \
  ee/maintained-apps/outputs/setapp/darwin.json
do
  echo "===== ${f} ====="
  sed -n '1,160p' "${f}"
done

printf '\nSearch for launchctl asuser or launched in outputs:\n'
rg -n "launchctl|ConsoleUser|scutil|asuser|Library/LaunchAgents|LOGGED_IN_USER" ee/maintained-apps/outputs -g 'darwin.json' | head -200

Repository: fleetdm/fleet

Length of output: 50370


🌐 Web query:

Apple launchctl asuser run command as specific user launchd domain LaunchAgents

💡 Result:

The launchctl asuser command is a legacy tool used to execute a command in the execution context (specifically the Mach bootstrap namespace, exception server, and security audit session) of a target user's bootstrap [1][2]. Usage: sudo launchctl asuser [args] Key Details: 1. Privileges: You must run this command as root (e.g., via sudo) for it to successfully access another user's bootstrap context [3][4]. 2. Target Identifier: It requires the target user's UID [5][6]. 3. Scope: It does not modify process credentials like UID or GID, nor does it adopt user-specific environment variables; it strictly affects the Mach bootstrap context [1][6]. Modern Alternatives: While asuser remains functional, it is considered a legacy subcommand [7]. Modern macOS administration (since OS X Yosemite and later) often favors the "launchctl 2.0" syntax, which explicitly targets domains [6][7]. To load or manage LaunchAgents for a specific user, it is now recommended to use the bootstrap and bootout commands targeting the gui/ domain [6][7]. Example of the modern approach: loggedInUserID=$(id -u ) /bin/launchctl bootstrap gui/"${loggedInUserID}" /Library/LaunchAgents/com.example.agent.plist This approach is generally more reliable in recent versions of macOS, as subcommands like asuser have been deprecated in practice in favor of direct domain management [7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json, pathlib, re, zipfile, io

dirs = sorted(pathlib.Path("ee/maintained-apps/outputs").glob("*/darwin.json"))
print(f"darwin.json files inspected: {len(dirs)}")

for path in dirs[:200]:
    data = json.loads(path.read_text())
    if isinstance(data, list):
        scripts = [entry.get("uninstaller_version_script") or entry.get("script") or "" for entry in data if isinstance(entry, dict)]
    elif isinstance(data, dict):
        scripts = [data.get("uninstaller_version_script") or data.get("script") or ""]
    else:
        continue

    for idx, script in enumerate(scripts):
        # Narrow to scripts containing these service targets and launchctl commands in remove_launchctl_service body/call paths.
        has_label = "com.amazon.codewhisperer.launcher" in script or "com.setapp.DesktopClient.SetappAgent" in script or "com.setapp.DesktopClient.SetappAssistant" in script or "com.setapp.DesktopClient.SetappLauncher" in script or "com.setapp.DesktopClient.SetappUpdater" in script
        if not has_label:
            continue

        needs_launchctl = any(pat in script for pat in ["launchctl list", "launchctl remove", "launchctl uninstall"])
        uses_launchctl_asuser = "launchctl asuser" in script
        uses_user_bootstrap = re.search(r"launchctl\s+(bootstrap|bootout)\s+gui/", script) is not None

        # Capture representative launchctl lines around label mentions/inside helper
        lines = script.splitlines()
        hits = []
        for n,l in enumerate(lines, 1):
            if any(x in l for x in ["launchctl list", "launchctl remove", "launchctl uninstall", "# functions", "remove_launchctl_service"]):
                hits.append((n,l))

        print(f"===== {path} =====")
        print(f"idx={idx}")
        print(f"needs_launchctl={needs_launchctl}, launchctl_asuser={uses_launchctl_asuser}, user_bootstrap={uses_user_bootstrap}")
        for n,l in hits[:50]:
            print(f"{n}: {l}")
PY

Repository: fleetdm/fleet

Length of output: 184


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'kiro-cli darwin entries matching kiro/codewhisperer:\n'
python3 - <<'PY'
import json, pathlib
for path in pathlib.Path("ee/maintained-apps/outputs/kiro-cli").glob("*.json"):
    data=json.loads(path.read_text())
    for i,entry in enumerate(data if isinstance(data,list) else [data]):
        txt=entry.get("uninstaller_version_script") or entry.get("script") or ""
        if any(x in txt for x in ["codewhisperer","kiro-cli","launchctl","LaunchAgents"]):
            print(f"----- {path}:idx={i} -----")
            for n,l in enumerate(txt.splitlines(),1):
                if any(x in l for x in ["codewhisperer","kiro-cli","launchctl","LaunchAgents","LOGGED_IN_USER"]):
                    print(f"{n:4}: {l}")
PY

printf '\nsetapp darwin entries matching SetappAgent/SetappAssistant/SetappLauncher/SetappUpdater:\n'
python3 - <<'PY'
import json, pathlib
for path in pathlib.Path("ee/maintained-apps/outputs/setapp").glob("*.json"):
    data=json.loads(path.read_text())
    for i,entry in enumerate(data if isinstance(data,list) else [data]):
        txt=entry.get("uninstaller_version_script") or entry.get("script") or ""
        if any(x in txt for x in ["SetappAgent","SetappAssistant","SetappLauncher","SetappUpdater","launchctl","LaunchAgents"]):
            print(f"----- {path}:idx={i} -----")
            for n,l in enumerate(txt.splitlines(),1):
                if any(x in l for x in ["SetappAgent","SetappAssistant","SetappLauncher","SetappUpdater","launchctl","LaunchAgents","LOGGED_IN_USER"]):
                    print(f"{n:4}: {l}")
PY

Repository: fleetdm/fleet

Length of output: 294


Target the console user’s LaunchAgents domain during uninstall cleanup.

The root/system launchctl context used here does not operate on the logged-in user’s user LaunchAgents, so user-started helpers can remain registered after uninstall. Resolve the console UID and manage the /Library/LaunchAgents entries via the console user domain (launchctl asuser "$uid" or launchctl bootout gui/"$uid") before/while deleting each LaunchAgent plist.

Apply this to both kiro-cli and Setapp uninstall scripts.

📍 Affects 2 files
  • ee/maintained-apps/outputs/kiro-cli/darwin.json#L20-L20 (this comment)
  • ee/maintained-apps/outputs/setapp/darwin.json#L20-L20
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/kiro-cli/darwin.json` at line 20, Update
remove_launchctl_service in both ee/maintained-apps/outputs/kiro-cli/darwin.json
and ee/maintained-apps/outputs/setapp/darwin.json to resolve the logged-in
console user’s UID and remove /Library/LaunchAgents through that user’s
launchctl domain using launchctl asuser or bootout gui before deleting the
plist; retain system-domain handling for other entries.

Comment thread ee/maintained-apps/outputs/onlyoffice/darwin.json
"b5794400": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.jetbrains.rider'\nif [ -d \"$APPDIR/Rider.app\" ]; then\n\tsudo mv \"$APPDIR/Rider.app\" \"$TMPDIR/Rider.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Rider.app\" \"$APPDIR\"\nrelaunch_application 'com.jetbrains.rider'\n",
"c52dae57": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Rider.app\"\nsudo rm -rf 'rider'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'\ntrash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'\ntrash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'\ntrash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'\n"
"22db20ac": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Rider.app\"\nsudo rm -rf 'rider'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'\n",
"b5794400": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.jetbrains.rider'\nif [ -d \"$APPDIR/Rider.app\" ]; then\n\tsudo mv \"$APPDIR/Rider.app\" \"$TMPDIR/Rider.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Rider.app\" \"$APPDIR\"\nrelaunch_application 'com.jetbrains.rider'\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | rg 'ee/maintained-apps/outputs/rider/darwin.json|jetbrains|Uninstall|rider' || true

echo "== context in target file =="
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  wc -l ee/maintained-apps/outputs/rider/darwin.json
  cat -n ee/maintained-apps/outputs/rider/darpin.json 2>/dev/null || sed -n '1,160p' ee/maintained-apps/outputs/rider/darwin.json | cat -n
else
  echo "target file missing"
fi

echo "== all JetBrains paths in repo =="
rg -n "Library/(Application Support|Caches|JetBrains|Rider|Application Support/Rider|Caches/Rider)" ee maintained-apps maintained 2>/dev/null || true

Repository: fleetdm/fleet

Length of output: 50370


🌐 Web query:

JetBrains Rider macOS uninstall Application Support Caches JetBrains/Rider version

💡 Result:

To completely uninstall JetBrains Rider on macOS and remove its associated user directories, follow these steps according to official JetBrains documentation [1][2]. 1. Delete the Application: Move the JetBrains Rider application file from your Applications folder to the Trash [1][2]. 2. Remove User Directories: Delete the following folders in your user library (where {RiderVersion} corresponds to the specific version installed, such as Rider2026.1) [1][2]: - ~/Library/Application Support/JetBrains/Rider{RiderVersion} - ~/Library/Caches/JetBrains/Rider{RiderVersion} - ~/Library/Logs/JetBrains/Rider{RiderVersion} - ~/Library/Preferences/JetBrains/Rider{RiderVersion} Note that deleting the Caches directory will trigger a full solution analysis the next time you open a project, as this directory contains caches and local history files [3][4]. If you simply wish to clear space rather than perform a full uninstall, you can also use the built-in cleanup tool within Rider by navigating to Help | Delete Leftover IDE Directories to remove data associated with older versions [3]. Always ensure that all instances of Rider are closed before manually deleting these directories to avoid potential file locking issues [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== rider darwin.json =="
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  wc -l ee/maintained-apps/outputs/rider/darwin.json
  sed -n '1,80p' ee/maintained-apps/outputs/rider/darwin.json | cat -n
fi

echo "== exact Rider trash paths in output files =="
rg -n "JetBrains/Rider2026|Application Support/Rider2026|Caches/Rider2026|Preferences/JetBrains/Rider2026|Logs/JetBrains/Rider2026" ee/maintained-apps/outputs ee -g 'rider/**' 2>/dev/null || true

echo "== all rider-related user dirs in maintained apps =="
rg -n "Rider2026|Rider[0-9].*JetBrains|JetBrains/Rider" ee/maintained-apps/outputs ee/maintained-apps -g 'rider/**' 2>/dev/null || true

echo "== deterministic path check from installed script text =="
python3 - <<'PY'
from pathlib import Path
import json
p = Path("ee/maintained-apps/outputs/rider/darwin.json")
if p.exists():
    data=json.loads(p.read_text())
    first_val=list(data.values())[0]
    for label in ["~/Library/Application Support/Rider2026.2", "~/Library/Caches/Rider2026.2"]:
        print(f"{label}: {label in first_val}")
    print("contains JetBrains/Rider2026.2:", "JetBrains/Rider2026.2" in first_val)
PY

Repository: fleetdm/fleet

Length of output: 7285


Use Rider’s documented macOS user data paths.

Rider’s uninstall documentation removes data under ~/Library/Application Support/JetBrains/Rider2026.2, ~/Library/Caches/JetBrains/Rider2026.2, and ~/Library/Logs/JetBrains/Rider2026.2; the uninstall script now deletes ~/Library/Application Support/Rider2026.2 and ~/Library/Caches/Rider2026.2, so configuration, cache, and log data can be left behind.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/rider/darwin.json` at line 20, Update the Rider
uninstall path handling to remove the documented JetBrains directories under
~/Library: Application Support/JetBrains/Rider2026.2,
Caches/JetBrains/Rider2026.2, and Logs/JetBrains/Rider2026.2. Replace the
existing Rider2026.2 paths that omit the JetBrains parent directory, and ensure
all three data locations are deleted.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files 'ee/maintained-apps/outputs/**/darwin.json' | sed -n '1,120p'

echo
echo "Rider target excerpt:"
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  python3 - <<'PY'
import json
from pathlib import Path
p = Path('ee/maintained-apps/outputs/rider/darwin.json')
data = json.loads(p.read_text())
for key, value in data.items():
    print(f'KEY {key}')
    print(value)
PY
fi

echo
echo "Setapp target excerpt / relevant lines:"
if [ -f ee/maintained-apps/outputs/setapp/darwin.json ]; then
  python3 - <<'PY'
import json
from pathlib import Path
p = Path('ee/maintained-apps/outputs/setapp/darwin.json')
data = json.loads(p.read_text())
for key, value in data.items():
    print(f'KEY {key}')
    lines = value.split('\n')
    for i,line in enumerate(lines):
        if any(s in line for s in ['Setapp', 'rm', 'bash', 'sudo rm', 'Application Scripts']):
            print(f'{i+1}: {line}')
PY
fi

echo
echo "Search for similar quit logic in nearby output files:"
rg -n "quit_and_track_application|relaunch_application|killall|pkill|launchctl Kill|rm -rf|mv |open -b" ee/maintained-apps/outputs -g 'darwin.json' | sed -n '1,240p'

Repository: fleetdm/fleet

Length of output: 12881


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Setapp uninstall ref excerpt:"
python3 - <<'PY'
import json
from pathlib import Path
p = Path('ee/maintained-apps/outputs/setapp/darwin.json')
data = json.loads(p.read_text())
for key, value in data.items():
    if key == 'refs':
        continue
    print(key, type(value).__name__, value)
print('--- refs ---')
for ref in ['5b4e5e38', '9ef05eb6']:
    # use first matching ref containing relevant commands if present
    pass
# locate the uninstall ref by references in version metadata
for k,v in data.items():
    if isinstance(v, list):
        for item in v:
            if isinstance(item, dict) and (item.get('version') == '1') and (item.get('uninstall_script_ref') or item.get('install_script_ref')):
                print(k, item)
PY

echo
echo "Find Setapp refs:"
python3 - <<'PY'
import json
p = Path('ee/maintained-apps/outputs/setapp/darwin.json')
data = json.loads(p.read_text())
values = []
for k, v in data.items():
    if k == 'refs':
        values.append((k, v))
    elif isinstance(v, list):
        for x in v:
            if isinstance(x, dict) and 'uninstall_script_ref' in str(x) or 'install_script_ref' in str(x):
                values.append((k, v))
for k, v in values:
    if isinstance(v, dict):
        for ref_id, script in v.items():
            print(f"REF {ref_id}")
            lines = script.splitlines()
            for i in range(min(len(lines), 220)):
                if any(s in lines[i].lower() for s in ['setapp', 'rm -rf', 'trash', 'applications']):
                    print(f"{i+1}: {lines[i]}")
PY

echo
echo "Current uninstall scripts containing Rider.app or Setapp.app removal:"
rg -n "Rider\\.app|Setapp\\.app|rm -rf|trash|quit_and_track_application|relaunch_application" ee/maintained-apps/outputs -g 'darwin.json' -g '*darwin.json' | sed -n '1,260p'

echo
echo "Validate installed/uninstalled script ordering behavior via static ordering around removal lines:"
python3 - <<'PY'
import json, re
from pathlib import Path
for rel in ['rider', 'setapp']:
    p = Path(f'ee/maintained-apps/outputs/{rel}/darwin.json')
    data = json.loads(p.read_text())
    ref_map=data.get('refs',{})
    for k,v in data.items():
        if not isinstance(v, list): continue
        for item in v:
            if not isinstance(item, dict): continue
            u=item.get('uninstall_script_ref')
            if not u: continue
            script=ref_map.get(u,'')
            print(f"--- {rel} uninstall {u} ---")
            lines=script.splitlines()
            terms=[]
            for i,l in enumerate(lines):
                if any(s in l.lower() for s in ['rm -rf', 'trash', 'quit_and_track_application', 'relaunch_application', 'killall', 'pkill', 'launchctl kill']):
                    terms.append((i+1,l))
            for i,l in terms:
                print(f"{i}: {l}")
            rem=[(i,l) for i,l in terms if 'rm -rf' in l or l.startswith('trash ') or 'trash' in l.lower()]
            print("removal_count", len(rem))
PY

Repository: fleetdm/fleet

Length of output: 942


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path

def show_app(name):
    p = Path(f'ee/maintained-apps/outputs/{name}/darwin.json')
    data = json.loads(p.read_text())
    print(f"--- {name} refs count ---")
    print(len(data.get('refs', {})))
    for key, script in data.get('refs', {}).items():
        if 'Rider.app' in script or 'Setapp.app' in script or 'Kill' in script or 'quit_and_track' in script:
            lines = script.splitlines()
            print(f"REF {key} relevant line count", sum('Rider' in l or 'Setapp' in l or 'rm -rf' in l or 'trash' in l.lower() or 'kill' in l.lower() for l in lines))
            for i,l in enumerate(lines):
                if any(term in l for term in ['Rider.app', 'Setapp.app', 'rm -rf', 'killall', 'pkill', 'launchctl kill', 'kill', 'kill -15', 'quit_and_track_application', 'relaunch_application', "trash $LOGGED_IN_USER"]):
                    print(f"{i+1}: {l}")
    for k,v in data.items():
        if not isinstance(v, list): continue
        for item in v:
            if isinstance(item, dict) and 'uninstall_script_ref' in item:
                print("version", item.get('version'), "uninstall_script_ref", item['uninstall_script_ref'])
for name in ['rider', 'setapp']:
    show_app(name)
PY

echo
echo "All uninstall refs mentioning bundle removal without quit helper:"
python3 - <<'PY'
import json
from pathlib import Path

def has_unquit_bundle_removal(script):
    removals = [l for l in script.splitlines() if 'rm -rf' in l and ('Rider.app' in l or 'Setapp.app' in l)]
    quit_helpers = any(h in script for h in ['quit_and_track_application', 'relaunch_application', 'killall', 'pkill', 'launchctl kill'])
    return bool(removals) and not quit_helpers

for name in ['rider', '1password', 'slack']:
    p = Path(f'ee/maintained-apps/outputs/{name}/darwin.json')
    if not p.exists(): continue
    data=json.loads(p.read_text())
    for i,v in enumerate(data.get('refs',{}).items(),1):
        print(i, v[0], has_unquit_bundle_removal(v[1]))
PY

Repository: fleetdm/fleet

Length of output: 2700


Quit Rider before removing its bundle.

ee/maintained-apps/outputs/rider/darwin.json version 2026.2 uses uninstall ref 22db20ac, which deletes $APPDIR/Rider.app/'rider' without the bounded quit_and_track_application() flow already present in the install script. A running Rider process can survive with its application bundle removed.

Use a bounded quit path before the bundle cleanup, and apply the same pattern to the Setapp uninstall path (ee/maintained-apps/outputs/setapp/darwin.json uninstall ref 9ef05eb6) if the same concern is intended there.

📍 Affects 2 files
  • ee/maintained-apps/outputs/rider/darwin.json#L20-L20 (this comment)
  • ee/maintained-apps/outputs/setapp/darwin.json#L20-L20
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/rider/darwin.json` at line 20, Update the Rider
uninstall script in ee/maintained-apps/outputs/rider/darwin.json at line 20 to
invoke the bounded quit_and_track_application() flow for com.jetbrains.rider
before deleting or moving Rider.app, preserving the existing relaunch tracking
behavior as applicable. Apply the same pre-cleanup quit pattern to the Setapp
uninstall script in ee/maintained-apps/outputs/setapp/darwin.json at line 20 if
its uninstall path removes a running application bundle.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^|/)rider/.+\.json$|^\Qee/maintained-apps/outputs/rider/darwin.json\E|uninstall|rider' | head -200

echo
echo "Inspect target:"
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  wc -l ee/maintained-apps/outputs/rider/darwin.json
  sed -n '1,220p' ee/maintained-apps/outputs/rider/darwin.json | sed -n '1,220p'
else
  echo "missing ee/maintained-apps/outputs/rider/darwin.json"
fi

echo
echo "Search uninstall scripts / removal patterns:"
rg -n "Rider\.app|rider|uninstall|quit_and_track_application|relaunch_application|happens?|rm|remove|mv" . --glob '*.json' --glob '*.sh' --glob '*.ts' --glob '*.js' -S | head -300

Repository: fleetdm/fleet

Length of output: 344


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^|/)rider/.+\.json$|^ee/maintained-apps/outputs/rider/darwin.json$|uninstall|rider' | head -300

echo
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  echo "Inspect target file length:"
  wc -l ee/maintained-apps/outputs/rider/darwin.json
  echo
  echo "Parsed script contents:"
  python3 - <<'PY' >/tmp/rider_darwin.json.txt
import json
from pathlib import Path
p = Path('ee/maintained-apps/outputs/rider/darwin.json')
data = json.loads(p.read_text())
print(json.dumps(data.get('script'), indent=2))
PY
  sed -n '1,240p' /tmp/rider_darwin.json.txt
else
  echo "missing ee/maintained-apps/outputs/rider/darwin.json"
fi

echo
echo "Search uninstall/scripts for Rider removal patterns:"
rg -n "Rider\.app|quit_and_track_application|relaunch_application|open -b|com\.jetbrains\.rider|uninstall|happens?|rm|remove|mv|sudo mv|sudo rm" . --glob '*.json' --glob '*.sh' --glob '*.ts' --glob '*.js' --glob '*.ps1' --glob '*.py' -S | head -400

Repository: fleetdm/fleet

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | rg '(^|/)rider/.+\.json$|^ee/maintained-apps/outputs/rider/darwin.json$|uninstall|rider' | head -300

echo
if [ -f ee/maintained-apps/outputs/rider/darwin.json ]; then
  echo "Inspect target file length:"
  wc -l ee/maintained-apps/outputs/rider/darwin.json
  echo
  echo "Parsed script contents:"
  python3 - <<'PY' >/tmp/rider_darwin.json.txt
import json
from pathlib import Path
p = Path('ee/maintained-apps/outputs/rider/darwin.json')
data = json.loads(p.read_text())
print(json.dumps(data.get('script'), indent=2))
PY
  sed -n '1,240p' /tmp/rider_darwin.json.txt
else
  echo "missing ee/maintained-apps/outputs/rider/darwin.json"
fi

echo
echo "Search uninstall/scripts for Rider removal patterns:"
rg -n "Rider\.app|quit_and_track_application|relaunch_application|open -b|com\.jetbrains\.rider|uninstall|happens?|rm|remove|mv|sudo mv|sudo rm" . --glob '*.json' --glob '*.sh' --glob '*.ts' --glob '*.js' --glob '*.ps1' --glob '*.py' -S | head -400
echo
echo "Check uninstall context around matching files:"
matching=$(git ls-files | rg '(^|/)rider/.+\.json$|^ee/maintained-apps/outputs/rider/darwin.json$|uninstall|rider' | grep -E '(uninstall|darwin\.json|.*rider.*\.json$)' || true)
for f in $matching; do
  echo "===== $f ====="
  rg -n "Rider\.app|Rider.app|quit_and_track_application|relaunch_application|open -b|com\.jetbrains\.rider|happens?|rm|remove|mv|sudo mv|sudo rm" "$f" -S || true
done

Repository: fleetdm/fleet

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Raw target JSON:"
cat -n ee/maintained-apps/outputs/rider/darwin.json

echo
echo "Input/output files and sizes:"
for f in \
  ee/maintained-apps/inputs/homebrew/rider.json \
  ee/maintained-apps/inputs/winget/rider.json \
  ee/maintained-apps/outputs/rider/darwin.json \
  ee/maintained-apps/outputs/rider/windows.json
do
  echo "===== $f ====="
  cat -n "$f"
done

echo
echo "Focused relevant matches only:"
rg -n "Rider\.app|quit_and_track_application|relaunch_application|open -b|com\.jetbrains\.rider|rm -rf /Applications/Rider\.app|mv /Applications/Rider\.app|uninstall_script|rider" ee/maintained-apps ee/mdm server/pkg server/cmd server/web --glob '*.json' --glob '*.ts' --glob '*.go' -S | head -400

Repository: fleetdm/fleet

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "raw target JSON bytes/size:"
wc -c ee/maintained-apps/outputs/rider/darwin.json
cat ee/maintained-apps/outputs/rider/darwin.json

echo
echo "rider files:"
for f in ee/maintained-apps/inputs/homebrew/rider.json ee/maintained-apps/inputs/winget/rider.json ee/maintained-apps/outputs/rider/darwin.json ee/maintained-apps/outputs/rider/windows.json; do
  echo "===== $f ====="
  cat -n "$f"
done

echo
echo "focused app/removal lines only:"
rg -n "quit_and_track|rider|Rider\.app|rm -rf|uninstall_script_path|uninstall_script_ref" \
  ee/maintained-apps/inputs ee/maintained-apps/outputs ee/mdm \
  --glob '*.json' --glob '*.ts' --glob '*.sh' --glob '*.ps1' --glob '*.go' -S | head -400

Repository: fleetdm/fleet

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(mktemp -d)"
for f in ee/maintained-apps/inputs/homebrew/rider.json \
         ee/maintained-apps/inputs/winget/rider.json \
         ee/maintained-apps/outputs/rider/darwin.json \
         ee/maintained-apps/outputs/rider/windows.json; do
  echo "===== $f ====="
  python3 - <<'PY' "$f"
import json, pathlib, sys
p=pathlib.Path(sys.argv[1])
text=p.read_text()
if p.suffix==".json":
    data=json.loads(text)
    if "script" in data:
        print(data["script"])
    else:
        print(json.dumps(data, indent=2))
else:
    print(text)
PY
  echo
done

echo "Focused removal/script entries only:"
python3 - <<'PY'
import json, pathlib, re
for p in pathlib.Path("ee/maintained-apps/inputs").rglob("*.json"):
    try:
        data=json.loads(p.read_text())
    except Exception:
        continue
    txt = json.dumps(data)
    if re.search(r'(?i)\brider\b|com\.jetbrains\.rider', txt):
        print(f"\n{p}")
        for k in ["label","script_path","uninstall_script_path","bundle_id","app_id","uninstall_script_ref"]:
            if k in data or any(k in json.dumps(v) for v in (data.values() if isinstance(data, dict) else [])):
                print(k, ":", data.get(k) or (data.get("uninstall_script_refs") or data.get("install_script_refs")))
for p in pathlib.Path("ee/maintained-apps/outputs").rglob("*.json"):
    try:
        data=json.loads(p.read_text())
    except Exception:
        continue
    txt = json.dumps(data)
    if re.search(r'(?i)\brider\b|com\.jetbrains\.rider|Rider\.app', txt):
        print(f"\n{p}")
        for k,v in data.items():
            if isinstance(v,str) and re.search(r'(?i)\brider\b|com\.jetbrains\.rider|Rider\.app', v):
                print(k, ":", v[:2000])
PY

Repository: fleetdm/fleet

Length of output: 12458


Quit Rider before deleting its bundle.

The macOS uninstall script directly runs sudo rm -rf "$APPDIR/Rider.app" without first prompting or terminating a running Rider process, so an open instance can remain alive after the bundle is gone. Reuse the bounded quit flow from the install script before removal.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/rider/darwin.json` at line 20, The uninstall flow
must terminate Rider before removing its application bundle. Reuse the existing
bounded quit logic from quit_and_track_application, or invoke that shared
helper, immediately before sudo rm -rf "$APPDIR/Rider.app"; preserve the timeout
behavior and ensure removal proceeds only after the quit attempt.

Comment on lines +4 to +9
"version": "26.7.2",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'io.trezor.TrezorSuite';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'io.trezor.TrezorSuite' AND version_compare(bundle_short_version, '26.6.1') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'io.trezor.TrezorSuite' AND version_compare(bundle_short_version, '26.7.2') < 0);"
},
"installer_url": "https://data.trezor.io/suite/releases/desktop/latest/Trezor-Suite-26.6.1-mac-arm64.dmg",
"installer_url": "https://data.trezor.io/suite/releases/desktop/latest/Trezor-Suite-26.7.2-mac-arm64.dmg",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Tracked trezor suite manifests:"
git ls-files | grep -F 'ee/maintained-apps/outputs/trezor-suite/darwin.json' || true

echo
echo "Relevant manifest section:"
if [ -f ee/maintained-apps/outputs/trezor-suite/darwin.json ]; then
  sed -n '1,80p' ee/maintained-apps/outputs/trezor-suite/darwin.json | cat -n
fi

echo
echo "Search for Trezor release URL patterns in repo:"
rg -n "trezor-suite|Trezor-Suite|data\.trezor\.io/suite/releases|latest/" . || true

Repository: fleetdm/fleet

Length of output: 50370


🌐 Web query:

data.trezor.io/suite/releases/desktop/latest directory indexing Trezor Suite releases

💡 Result:

The URL https://data.trezor.io/suite/releases/desktop/latest/ is an official directory index maintained by Trezor that provides access to the latest desktop releases of the Trezor Suite application [1][2]. This directory is primarily used for the following purposes: 1. Auto-update Mechanism: The Trezor Suite desktop application uses an auto-updater that references these files to check for, download, and verify the latest software updates [3]. The directory contains YAML metadata files (e.g., latest.yml, latest-mac.yml, latest-linux.yml) that specify the version and update information required by the application [1][3][4]. 2. Third-Party Integrations: Open-source package managers and distribution maintainers (such as NixOS and Homebrew) use this directory to automate the tracking and packaging of the latest Trezor Suite releases [5][6]. By referencing these metadata files, they can programmatically determine the current version and verify updates [5][6]. While this directory is an official source of distribution for binary files and metadata, users are generally advised to download and verify Trezor Suite through the official website (https://trezor.io/trezor-suite) or the official GitHub repository (https://github.com/trezor/trezor-suite/releases) to ensure security and authenticity [7]. The directory index provides a raw, machine-readable view of these releases [1][2].

Citations:


🌐 Web query:

data.trezor.io/suite/releases/desktop/v26.7.2 Trezor Suite 26.7.2

💡 Result:

Trezor Suite version 26.7.2 is the official desktop update released in July 2026 [1][2]. This update includes several new features and improvements, such as [1]: - Tron (TRX) staking support. - Ability to cancel pending EVM transactions. - Options to view and edit the nonce in the EVM send form. - A new preview step in the Buy flow. - SLIP24 support for Ripple transactions. - A WalletConnect button in the account menu. Additionally, the update addresses various bug fixes, including resolutions for issues with EVM transaction management (such as preventing cancellations or speed-ups when a nonce gap exists) and improvements to token search results and Bitcoin Cash address prefixes [1]. Users are encouraged to update their desktop application by following the on-screen instructions within Trezor Suite [1]. For those who are not yet using the application, the latest version can be downloaded from the official Trezor website at https://trezor.io/trezor-suite [1][3]. Updates are rolled out in stages, so some users may not be prompted immediately [1].

Citations:


🌐 Web query:

data.trezor.io/suite/releases/desktop/latest/index.yml Trezor Suite latest.yml

💡 Result:

The file path data.trezor.io/suite/releases/desktop/latest/index.yml is not a direct file, but rather part of a directory index on Trezor's update server [1]. In the context of Trezor Suite desktop releases, latest.yml (and its variations like latest-mac.yml and latest-linux.yml) serves as a metadata manifest file used by the application's auto-updater [2]. These YAML files contain critical information such as the current version number and SHA512 hashes required for verifying the integrity of update binaries [3]. Key details regarding these files: - Purpose: They provide the information necessary for the Trezor Suite desktop client to check for, download, and verify new software updates [2][3]. - Structure: The latest.yml file is generally used for Windows updates, while platform-specific variants (e.g., latest-mac.yml, latest-linux.yml) handle updates for other operating systems [1][2]. - Accessibility: These files are hosted publicly at https://data.trezor.io/suite/releases/desktop/latest/ [1]. - Technical Integration: Developers and automated systems, such as package maintainers (e.g., NixOS), use these files to programmatically track the latest release versions and verify file checksums [3]. For official technical documentation on how these updates and manifest files are handled, you can refer to the Trezor Suite developer documentation regarding desktop updates [2][4].

Citations:


🌐 Web query:

trezor data.trezor.io/suite/releases/desktop/ directory structure versioned releases latest.yml

💡 Result:

The Trezor Suite desktop release repository at https://data.trezor.io/suite/releases/desktop/ follows a structured organization to manage versioned releases and auto-updates [1]. Directory Structure The root directory contains: - A latest/ directory, which holds the metadata and binaries for the most recent version of Trezor Suite [1][2]. - Individual versioned directories (e.g., v26.3.3/, v25.6.3/), which contain the binaries, blockmaps, and detached signature files (.asc) for specific past releases [1][3][4]. - A canary/ directory for experimental or pre-release builds [1]. Within each versioned directory (and the latest/ folder), you will typically find the following files: - Application binaries for various platforms (e.g., .AppImage for Linux, .dmg/.zip for macOS, .exe for Windows) [3][4]. - Corresponding signature files (e.g., ...AppImage.asc) used for verification [3][4]. - Blockmap files (e.g., ...blockmap) used to support efficient updates [3][4]. - YAML metadata files (e.g., latest.yml, latest-mac.yml, latest-linux.yml) which are critical for the auto-update mechanism [2][3]. latest.yml and Auto-Updates The latest.yml files (and their platform-specific variants like latest-linux.yml or latest-mac.yml) serve as the feed for the Trezor Suite auto-updater [2][5]. When the Trezor Suite desktop application checks for updates, it queries these YAML files to determine if a newer version is available [5]. The latest.yml file typically contains information such as: - The version number of the latest release. - The file path or URL to the update binary. - Cryptographic hashes (often SHA-512) required to verify the integrity of the downloaded update package. This structure allows the desktop application to automatically identify, download, and verify new versions without user intervention beyond confirming the update [5]. Developers can also mock this update process in a development environment by hosting their own local versions of these directories and YAML files and pointing the Suite configuration to them [5].

Citations:


Pin the Trezor installer URL to the immutable release directory.

This manifest pins 26.7.2 plus the SHA-256, but installer_url points at Trezor’s mutable latest directory. If Trezor updates latest, the pinned checksum can stop matching the downloaded bytes. Use the versioned directory URL, e.g. https://data.trezor.io/suite/releases/desktop/26.7.2/Trezor-Suite-26.7.2-mac-arm64.dmg, after confirming the path exists.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/trezor-suite/darwin.json` around lines 4 - 9,
Update the installer_url for the Trezor Suite 26.7.2 manifest to use the
immutable versioned release directory instead of latest, preserving the existing
filename and checksum alignment; confirm the versioned URL path exists before
applying the change.

"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed' AND version_compare(bundle_short_version, '1.12.0') < 0);"
},
"installer_url": "https://zed.dev/api/releases/stable/1.11.3/Zed-aarch64.dmg",
"installer_url": "https://zed.dev/api/releases/stable/1.12.0/Zed-aarch64.dmg",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'aarch64|x86_64|"architecture"|"arch"' \
  ee/maintained-apps/outputs/zed ee/maintained-apps

Repository: fleetdm/fleet

Length of output: 29692


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Zed output files:"
ls -l ee/maintained-apps/outputs/zed/ || true

echo
cat -n ee/maintained-apps/outputs/zed/darwin.json

echo
cat -n ee/maintained-apps/outputs/zed/windows.json

echo
echo "Search for zed app name and architecture restriction:"
rg -n '\\bzed\\b|architecture|arch|target|darwin|aarch64|x86_64' ee/maintained-apps -g '!**/.git/**' | head -n 200

Repository: fleetdm/fleet

Length of output: 50369


🌐 Web query:

zed dev macos x86_64 aarch64 release downloads

💡 Result:

Zed is available for macOS on both Apple Silicon (aarch64) and Intel (x86_64) architectures [1][2][3]. Both architectures are supported natively, meaning no Rosetta translation is required [3]. You can download the Zed editor for macOS through the following official channels: 1. Official Website: You can download the latest stable version directly from the official download page at https://zed.dev/download [4][1]. The download is provided as a.dmg file, which you can open to install the application to your /Applications folder [2][3]. 2. Homebrew: For macOS users who prefer package managers, Zed can be installed via Homebrew [2][5]. - To install the stable version: brew install --cask zed [2][5] - To install the preview version: brew install --cask zed@preview [2][5] The editor supports macOS 10.15 (Catalina) and newer versions [1][2][3]. After the initial manual installation, Zed includes a built-in mechanism to check for and apply updates [1][5]. For advanced users and developers, specific release binaries for different architectures can also be found on the project's official GitHub releases page [6].

Citations:


Use an architecture-specific Zed macOS installer or a universal artifact.

zed/darwin.json currently points only to Zed-aarch64.dmg, while Zed supports both Apple Silicon and Intel macOS and provides separate Zed-x86_64 downloads. Add an x86_64 path or use a universal installer so Intel clients do not receive an incompatible package.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/zed/darwin.json` at line 9, Update the
installer_url in darwin.json to use a universal Zed macOS artifact or the
appropriate architecture-specific package selection, ensuring both Apple Silicon
and Intel clients receive compatible installers instead of only Zed-aarch64.dmg.

…, revert Pritunl (mac)

- typora/windows: revert 1.14.7 -> 1.14.1 and freeze winget input (installer
  registers as 1.14.1 in the registry, so 1.14.7 is never found by osquery)
- onlyoffice/darwin: installer is a DMG, not a ZIP; set installer_format=dmg
  and regenerate so the install script uses hdiutil instead of unzip
- pritunl/darwin: revert 1.3.4696.56 -> 1.3.4686.95 (the release installs a
  bundle still reporting 1.3.4686.95)
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/advanced-installer/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/akiflow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/amie/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/anytype/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aptakube/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-sam-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/bettertouchtool/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/betterzip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/beyond-compare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/burp-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cleanmymac/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/clop/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/comet/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cursor/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dockside/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/drawio/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/enpass/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/filebeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@developer-edition/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-ads-editor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-gemini/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/groove-omnidialer/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hive-app/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hwmonitor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro-cli/darwin.json

=== Install Script (no changes) ===
=== Uninstall // 31b59062 -> ed98f0de ===

--- /tmp/old.HfbRDX	2026-07-23 15:45:39.863962505 +0000
+++ /tmp/new.T573rE	2026-07-23 15:45:39.863962505 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,14 @@
   fi
 }
 
+remove_launchctl_service 'com.amazon.codewhisperer.launcher'
 sudo rm -rf "$APPDIR/Kiro CLI.app"
 trash $LOGGED_IN_USER '~/.kiro'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'
 trash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'
+trash $LOGGED_IN_USER '~/Library/Caches/com.amazon.codewhisperer'
 trash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.amazon.codewhisperer.launcher.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'
+trash $LOGGED_IN_USER '~/Library/WebKit/com.amazon.codewhisperer'

ee/maintained-apps/outputs/kiro/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/lookaway/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/macwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/marsedit/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/megasync/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/melodics/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/darwin.json

=== Install // 54ba1114 -> 27c40399 ===

--- /tmp/old.E293CW	2026-07-23 15:45:40.391957493 +0000
+++ /tmp/new.mYEpiB	2026-07-23 15:45:40.391957493 +0000
@@ -96,5 +96,5 @@
 
 # install pkg files
 quit_and_track_application 'com.naps2.desktop'
-sudo installer -pkg "$TMPDIR/naps2-8.3.1-mac-arm64.pkg" -target /
+sudo installer -pkg "$TMPDIR/naps2-8.3.2-mac-arm64.pkg" -target /
 relaunch_application 'com.naps2.desktop'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/notepadexe/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/obs/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/only-switch/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/onlyoffice/darwin.json

=== Install // 5beeff19 -> e2c9162f ===

--- /tmp/old.OesSlj	2026-07-23 15:45:40.705954513 +0000
+++ /tmp/new.DtbIQY	2026-07-23 15:45:40.705954513 +0000
@@ -95,7 +95,10 @@
 
 
 # extract contents
-unzip "$INSTALLER_PATH" -d "$TMPDIR"
+MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+hdiutil detach "$MOUNT_POINT" || true
 # copy to the applications folder
 quit_and_track_application 'asc.onlyoffice.editors-helper-renderer'
 if [ -d "$APPDIR/ONLYOFFICE.app" ]; then

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/picview/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/popclip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powerphotos/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powershell/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0995d374 -> 06cf76b8 ===

--- /tmp/old.2q5qtq	2026-07-23 15:45:40.896952700 +0000
+++ /tmp/new.UhGpHS	2026-07-23 15:45:40.896952700 +0000
@@ -1,4 +1,4 @@
-$product_code = '{7B031DCF-BDCE-47D6-89B9-4C558D76E773}'
+$product_code = '{92D9A5DC-8C64-40D5-B1BC-98DB9C7FDB7F}'
 $timeoutSeconds = 300  # 5 minute timeout
 
 # Fleet uninstalls app using product code that's extracted on upload

ee/maintained-apps/outputs/prisma-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rider/darwin.json

=== Install Script (no changes) ===
=== Uninstall // c52dae57 -> 22db20ac ===

--- /tmp/old.sU528R	2026-07-23 15:45:41.021951514 +0000
+++ /tmp/new.G0f3w7	2026-07-23 15:45:41.021951514 +0000
@@ -54,9 +54,9 @@
 
 sudo rm -rf "$APPDIR/Rider.app"
 sudo rm -rf 'rider'
-trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'
-trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'

ee/maintained-apps/outputs/rive/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rustrover/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/setapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall // e23bd29d -> 9ef05eb6 ===

--- /tmp/old.jJX3to	2026-07-23 15:45:41.145950337 +0000
+++ /tmp/new.PSi2Ex	2026-07-23 15:45:41.145950337 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,19 @@
   fi
 }
 
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAgent'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'
 sudo rm -rf "$APPDIR/Setapp.app"
 trash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'
+trash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'
 trash $LOGGED_IN_USER '~/Library/Logs/Setapp'
+trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'

ee/maintained-apps/outputs/sidenotes/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/snagit/darwin.json

=== Install Script (no changes) ===
=== Uninstall // b52ff2b2 -> 59bfdeae ===

--- /tmp/old.PYfEPQ	2026-07-23 15:45:41.314948733 +0000
+++ /tmp/new.mjcMPW	2026-07-23 15:45:41.314948733 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,9 +92,14 @@
   fi
 }
 
+quit_application 'com.TechSmith.Snagit'
 sudo rm -rf "$APPDIR/Snagit.app"
+trash $LOGGED_IN_USER '~/Library/Application Scripts/7TQL462TU8.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.snagit.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/Snagit'
 trash $LOGGED_IN_USER '~/Library/Caches/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Group Containers/*.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.TechSmith.Snagit*.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.snagit.capturehelper*.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.TechSmith.Snagit*.savedState'

ee/maintained-apps/outputs/sourcetree/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/superwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/tabby/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/trezor-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/visual-studio-code/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/vivaldi/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/wechat/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/whatsapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/winlogbeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/workflowy/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ee/maintained-apps/outputs/onlyoffice/darwin.json`:
- Line 20: Update the embedded installer script to enable strict error handling
with set -euo pipefail, and add an EXIT trap after MOUNT_POINT is initialized to
detach the mount and remove the temporary directory. Make extraction commands,
especially cp and hdiutil attach, propagate failures instead of continuing;
remove the ignored detach error and ensure cleanup occurs before any backup or
installation steps run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a8f2bcd-fb0e-42bd-89ec-4dccc2ff53fa

📥 Commits

Reviewing files that changed from the base of the PR and between c5deadd and e090844.

📒 Files selected for processing (3)
  • ee/maintained-apps/inputs/homebrew/onlyoffice.json
  • ee/maintained-apps/inputs/winget/typora.json
  • ee/maintained-apps/outputs/onlyoffice/darwin.json

"refs": {
"1f5bdb95": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/ONLYOFFICE.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/asc.onlyoffice.ONLYOFFICE'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/asc.onlyoffice.onlyoffice.sfl*'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/asc.onlyoffice.ONLYOFFICE'\ntrash $LOGGED_IN_USER '~/Library/Preferences/asc.onlyoffice.editors-helper-renderer.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/asc.onlyoffice.ONLYOFFICE.plist'\n",
"5beeff19": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n# copy to the applications folder\nquit_and_track_application 'asc.onlyoffice.editors-helper-renderer'\nif [ -d \"$APPDIR/ONLYOFFICE.app\" ]; then\n\tsudo mv \"$APPDIR/ONLYOFFICE.app\" \"$TMPDIR/ONLYOFFICE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/ONLYOFFICE.app\" \"$APPDIR\"\nrelaunch_application 'asc.onlyoffice.editors-helper-renderer'\n"
"e2c9162f": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'asc.onlyoffice.editors-helper-renderer'\nif [ -d \"$APPDIR/ONLYOFFICE.app\" ]; then\n\tsudo mv \"$APPDIR/ONLYOFFICE.app\" \"$TMPDIR/ONLYOFFICE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/ONLYOFFICE.app\" \"$APPDIR\"\nrelaunch_application 'asc.onlyoffice.editors-helper-renderer'\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'set -e|pipefail|trap|cp -R|hdiutil detach' ee/maintained-apps/outputs/onlyoffice/darwin.json

Repository: fleetdm/fleet

Length of output: 3941


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File context =="
wc -l ee/maintained-apps/outputs/onlyoffice/darwin.json
sed -n '1,80p' ee/maintained-apps/outputs/onlyoffice/darwin.json | cat -n

echo "== Installer JSON schema context (around this file) =="
fd -a 'darwin\.json$' ee/maintained-apps/outputs 2>/dev/null | head -30
python3 - <<'PY'
import json, pathlib
p=pathlib.Path('ee/maintained-apps/outputs/onlyoffice/darwin.json')
data=json.loads(p.read_text())
print(type(data).__name__)
if isinstance(data, dict):
    for k in sorted(data):
        v=data[k]
        if isinstance(v, dict):
            print(k, {kk:v.get(kk) for kk in v if kk != 'install_script'})
        else:
            print(k, v[:240] if isinstance(v, str) else v)
PY

echo "== Shell behavior probe: pipeline status after yes + command that fails =="
# Demonstrate that `yes | hdiutil ... || exit 1` reports the final pipeline status
# in POSIX shell and that subsequent commands would still run only if that command succeeds.
sh -c 'yes | sh -c "exit 42" || echo "pipeline_failed"; echo "pipeline_status=$?"; next'
sh -c 'set -e; yes | sh -c "exit 42"; echo "continues_unless_pipefail"; set +e'

echo "== Simulate current script failure points without repository execution =="
python3 - <<'PY'
# Read-only behavioral model of the relevant shell command structure.
# Current pipeline: yes | hdiutil attach ... || exit 1
# The `||` only checks the pipeline exit status; if this succeeded, later commands run.
# Current cleanup: hdiutil detach || true means detach failures are ignored.
cases = [
    ("cp_after_attach_fails", {"attach_ok": True, "cp": 1, "detach_ok": True}),
    ("detach_fails", {"attach_ok": True, "cp": 0, "detach_ok": False}),
]
for name, k in cases:
    attach_ok = k["attach_ok"]
    detach_ok = k["detach_ok"]
    first_failed = not attach_ok
    # The script only proceeds if the first command exits 0.
    proceeds_to_install = attach_ok
    detach_ignored = True  # current `|| true`
    print(f"{name}: attach_ok={attach_ok}, cp_ok={k['cp']==0}, detach_ok={detach_ok}")
    print(f"  proceeds_to_install={proceeds_to_install}, detach_ignored={detach_ignored}")
PY

Repository: fleetdm/fleet

Length of output: 16172


Propagate extraction failures and clean up the mount point.

sudo cp -R "$MOUNT_POINT"/* \"$TMPDIR\" can fail and is followed by relaunch/install steps, and hdiutil detach ignores errors with || true. Add set -euo pipefail, an EXIT trap to unmount/remove MOUNT_POINT, and explicit failures before backing up the installed app.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/onlyoffice/darwin.json` at line 20, Update the
embedded installer script to enable strict error handling with set -euo
pipefail, and add an EXIT trap after MOUNT_POINT is initialized to detach the
mount and remove the temporary directory. Make extraction commands, especially
cp and hdiutil attach, propagate failures instead of continuing; remove the
ignored detach error and ensure cleanup occurs before any backup or installation
steps run.

@github-actions

Copy link
Copy Markdown
Contributor

Closing in favor of #49835.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/advanced-installer/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/akiflow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/amie/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/anytype/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aptakube/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-sam-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/bettertouchtool/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/betterzip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/beyond-compare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/burp-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cleanmymac/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/clop/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/comet/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cursor/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dockside/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/drawio/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/enpass/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/filebeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@developer-edition/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-ads-editor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-gemini/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/groove-omnidialer/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hive-app/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hwmonitor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro-cli/darwin.json

=== Install Script (no changes) ===
=== Uninstall // 31b59062 -> ed98f0de ===

--- /tmp/old.CDMgF9	2026-07-23 17:34:51.797608917 +0000
+++ /tmp/new.2OtkjA	2026-07-23 17:34:51.797608917 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,14 @@
   fi
 }
 
+remove_launchctl_service 'com.amazon.codewhisperer.launcher'
 sudo rm -rf "$APPDIR/Kiro CLI.app"
 trash $LOGGED_IN_USER '~/.kiro'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'
 trash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'
+trash $LOGGED_IN_USER '~/Library/Caches/com.amazon.codewhisperer'
 trash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.amazon.codewhisperer.launcher.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'
+trash $LOGGED_IN_USER '~/Library/WebKit/com.amazon.codewhisperer'

ee/maintained-apps/outputs/kiro/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/lookaway/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/macwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/marsedit/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/megasync/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/melodics/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/darwin.json

=== Install // 54ba1114 -> 27c40399 ===

--- /tmp/old.1w9mIU	2026-07-23 17:34:52.368611310 +0000
+++ /tmp/new.aiMaem	2026-07-23 17:34:52.368611310 +0000
@@ -96,5 +96,5 @@
 
 # install pkg files
 quit_and_track_application 'com.naps2.desktop'
-sudo installer -pkg "$TMPDIR/naps2-8.3.1-mac-arm64.pkg" -target /
+sudo installer -pkg "$TMPDIR/naps2-8.3.2-mac-arm64.pkg" -target /
 relaunch_application 'com.naps2.desktop'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/notepadexe/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/obs/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/only-switch/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/onlyoffice/darwin.json

=== Install // 5beeff19 -> e2c9162f ===

--- /tmp/old.JK4d1I	2026-07-23 17:34:52.678612610 +0000
+++ /tmp/new.332JjH	2026-07-23 17:34:52.678612610 +0000
@@ -95,7 +95,10 @@
 
 
 # extract contents
-unzip "$INSTALLER_PATH" -d "$TMPDIR"
+MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+hdiutil detach "$MOUNT_POINT" || true
 # copy to the applications folder
 quit_and_track_application 'asc.onlyoffice.editors-helper-renderer'
 if [ -d "$APPDIR/ONLYOFFICE.app" ]; then

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/picview/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/popclip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powerphotos/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powershell/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0995d374 -> 06cf76b8 ===

--- /tmp/old.M7MRTL	2026-07-23 17:34:52.867613402 +0000
+++ /tmp/new.5vx44d	2026-07-23 17:34:52.867613402 +0000
@@ -1,4 +1,4 @@
-$product_code = '{7B031DCF-BDCE-47D6-89B9-4C558D76E773}'
+$product_code = '{92D9A5DC-8C64-40D5-B1BC-98DB9C7FDB7F}'
 $timeoutSeconds = 300  # 5 minute timeout
 
 # Fleet uninstalls app using product code that's extracted on upload

ee/maintained-apps/outputs/prisma-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rider/darwin.json

=== Install Script (no changes) ===
=== Uninstall // c52dae57 -> 22db20ac ===

--- /tmp/old.DXI21k	2026-07-23 17:34:52.995613939 +0000
+++ /tmp/new.DSNdUx	2026-07-23 17:34:52.995613939 +0000
@@ -54,9 +54,9 @@
 
 sudo rm -rf "$APPDIR/Rider.app"
 sudo rm -rf 'rider'
-trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'
-trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'

ee/maintained-apps/outputs/rive/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rustrover/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/setapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall // e23bd29d -> 9ef05eb6 ===

--- /tmp/old.3iJ2D2	2026-07-23 17:34:53.125614484 +0000
+++ /tmp/new.3EuB4Y	2026-07-23 17:34:53.126614488 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,19 @@
   fi
 }
 
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAgent'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'
 sudo rm -rf "$APPDIR/Setapp.app"
 trash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'
+trash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'
 trash $LOGGED_IN_USER '~/Library/Logs/Setapp'
+trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'

ee/maintained-apps/outputs/sidenotes/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/snagit/darwin.json

=== Install Script (no changes) ===
=== Uninstall // b52ff2b2 -> 59bfdeae ===

--- /tmp/old.xb4k64	2026-07-23 17:34:53.303615230 +0000
+++ /tmp/new.M487Jc	2026-07-23 17:34:53.303615230 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,9 +92,14 @@
   fi
 }
 
+quit_application 'com.TechSmith.Snagit'
 sudo rm -rf "$APPDIR/Snagit.app"
+trash $LOGGED_IN_USER '~/Library/Application Scripts/7TQL462TU8.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.snagit.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/Snagit'
 trash $LOGGED_IN_USER '~/Library/Caches/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Group Containers/*.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.TechSmith.Snagit*.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.snagit.capturehelper*.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.TechSmith.Snagit*.savedState'

ee/maintained-apps/outputs/sourcetree/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/superwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/tabby/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/trezor-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/visual-studio-code/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/vivaldi/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/wechat/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/whatsapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/winlogbeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/workflowy/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

The MSI starts the MozillaVPNBroker/MozillaVPNProxy services (Wait=1) and
auto-launches the Mozilla VPN GUI as an async custom action on a fresh
install. The default 'Start-Process msiexec -Wait' waits on the whole process
tree, so the validate step never returned and the shard died after ~1h.

Add a custom install_script_path that launches msiexec without -Wait, polls
the msiexec process itself (not descendants) with a 300s timeout, then stops
the lingering GUI so it can't affect later apps in the run. Uninstall is
unchanged (default bounded MSI uninstall).
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/advanced-installer/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/akiflow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/amie/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/anytype/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aptakube/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/aws-sam-cli/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/bettertouchtool/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/betterzip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/beyond-compare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/brave-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/burp-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cleanmymac/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/clop/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/comet/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/cursor/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dataflare/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/datagrip/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dockside/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/drawio/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/enpass/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/fellow/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/filebeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@developer-edition/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/firefox@nightly/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-ads-editor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/google-gemini/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/granola/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/groove-omnidialer/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hive-app/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/hwmonitor/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro-cli/darwin.json

=== Install Script (no changes) ===
=== Uninstall // 31b59062 -> ed98f0de ===

--- /tmp/old.mkJwBQ	2026-07-23 18:27:28.331845308 +0000
+++ /tmp/new.5kcZdC	2026-07-23 18:27:28.332845310 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,14 @@
   fi
 }
 
+remove_launchctl_service 'com.amazon.codewhisperer.launcher'
 sudo rm -rf "$APPDIR/Kiro CLI.app"
 trash $LOGGED_IN_USER '~/.kiro'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli'
 trash $LOGGED_IN_USER '~/.local/bin/kiro-cli-chat'
 trash $LOGGED_IN_USER '~/Library/Application Support/kiro-cli'
+trash $LOGGED_IN_USER '~/Library/Caches/com.amazon.codewhisperer'
 trash $LOGGED_IN_USER '~/Library/Caches/dev.kiro.cli'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.amazon.codewhisperer.launcher.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/dev.kiro.cli.plist'
+trash $LOGGED_IN_USER '~/Library/WebKit/com.amazon.codewhisperer'

ee/maintained-apps/outputs/kiro/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/kiro/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/lookaway/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/loom/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/macwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/marsedit/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/megasync/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/melodics/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/microsoft-teams/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/mozilla-vpn/windows.json

=== Install // 8959087b -> c02fc638 ===

--- /tmp/old.oY91h7	2026-07-23 18:27:28.819846402 +0000
+++ /tmp/new.ztyhDn	2026-07-23 18:27:28.819846402 +0000
@@ -1,16 +1,77 @@
+# Learn more about .msi install scripts:
+# http://fleetdm.com/learn-more-about/msi-install-scripts
+#
+# Mozilla VPN's MSI starts the MozillaVPNBroker / MozillaVPNProxy services
+# (ServiceControl with Wait=1) and, on a fresh install, auto-launches the
+# "Mozilla VPN" GUI via an async custom action. On a headless CI host those
+# processes linger, and the default "Start-Process msiexec -Wait" waits on the
+# whole process tree -- so the step never returns even though the product
+# installs correctly, and the runner is eventually killed (~1h). Instead we
+# wait on the msiexec process ITSELF (not its descendants) with a bounded
+# timeout, then stop any lingering Mozilla VPN GUI process so it can't
+# interfere with the rest of the validation run.
+
 $logFile = "${env:TEMP}/fleet-install-software.log"
+$msiFilePath = "${env:INSTALLER_PATH}"
+
+$timeoutSeconds = 300
+$pollIntervalSeconds = 5
+
+# Recursively stop a process and its children (used only if msiexec wedges).
+function Stop-ProcessTree {
+    param([int]$ParentId)
+    Get-CimInstance Win32_Process -Filter "ParentProcessId = $ParentId" -ErrorAction SilentlyContinue |
+        ForEach-Object { Stop-ProcessTree -ParentId $_.ProcessId }
+    Stop-Process -Id $ParentId -Force -ErrorAction SilentlyContinue
+}
 
 try {
+    if (-not (Test-Path $msiFilePath)) {
+        Write-Host "Error: Installer file not found at: $msiFilePath"
+        Exit 1
+    }
+
+    $processOptions = @{
+        FilePath     = "msiexec.exe"
+        ArgumentList = "/i `"$msiFilePath`" /quiet /norestart /lv `"$logFile`""
+        PassThru     = $true
+    }
+
+    # NOTE: intentionally launched WITHOUT -Wait; -Wait would block on the
+    # auto-launched app / services that outlive the install.
+    $process = Start-Process @processOptions
+    Write-Host "Launched Mozilla VPN MSI (PID: $($process.Id))"
+
+    $elapsed = 0
+    while (-not $process.HasExited -and $elapsed -lt $timeoutSeconds) {
+        Start-Sleep -Seconds $pollIntervalSeconds
+        $elapsed += $pollIntervalSeconds
+    }
+
+    if (-not $process.HasExited) {
+        Write-Host "msiexec did not complete within ${timeoutSeconds}s; stopping it."
+        Stop-ProcessTree -ParentId $process.Id
+        Get-Content $logFile -Tail 500 -ErrorAction SilentlyContinue
+        Exit 1
+    }
+
+    $exitCode = $process.ExitCode
+    Write-Host "Install exit code: $exitCode"
+
+    # Stop the auto-launched GUI so it doesn't linger into later apps in the run.
+    # (This only ends the running process; it does not uninstall anything.)
+    Stop-Process -Name "Mozilla VPN", "MozillaVPN" -Force -ErrorAction SilentlyContinue
 
-$installProcess = Start-Process msiexec.exe `
-  -ArgumentList "/quiet /norestart /lv ${logFile} /i `"${env:INSTALLER_PATH}`"" `
-  -PassThru -Verb RunAs -Wait
+    # MSI reboot-required success codes.
+    if ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }
 
-Get-Content $logFile -Tail 500
+    if ($exitCode -ne 0) {
+        Get-Content $logFile -Tail 500
+    }
 
-Exit $installProcess.ExitCode
+    Exit $exitCode
 
 } catch {
-  Write-Host "Error: $_"
-  Exit 1
+    Write-Host "Error: $_"
+    Exit 1
 }

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/darwin.json

=== Install // 54ba1114 -> 27c40399 ===

--- /tmp/old.tRPTxF	2026-07-23 18:27:28.867846509 +0000
+++ /tmp/new.FQijeU	2026-07-23 18:27:28.867846509 +0000
@@ -96,5 +96,5 @@
 
 # install pkg files
 quit_and_track_application 'com.naps2.desktop'
-sudo installer -pkg "$TMPDIR/naps2-8.3.1-mac-arm64.pkg" -target /
+sudo installer -pkg "$TMPDIR/naps2-8.3.2-mac-arm64.pkg" -target /
 relaunch_application 'com.naps2.desktop'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/naps2/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/nosql-workbench/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/notepadexe/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/obs/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/only-switch/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/onlyoffice/darwin.json

=== Install // 5beeff19 -> e2c9162f ===

--- /tmp/old.3lfbAF	2026-07-23 18:27:29.160847166 +0000
+++ /tmp/new.gDsPY5	2026-07-23 18:27:29.160847166 +0000
@@ -95,7 +95,10 @@
 
 
 # extract contents
-unzip "$INSTALLER_PATH" -d "$TMPDIR"
+MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
+hdiutil detach "$MOUNT_POINT" || true
 # copy to the applications folder
 quit_and_track_application 'asc.onlyoffice.editors-helper-renderer'
 if [ -d "$APPDIR/ONLYOFFICE.app" ]; then

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/picview/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/popclip/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powerphotos/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/powershell/windows.json

=== Install Script (no changes) ===
=== Uninstall // 0995d374 -> 06cf76b8 ===

--- /tmp/old.0PlRlb	2026-07-23 18:27:29.342847574 +0000
+++ /tmp/new.9ju3VX	2026-07-23 18:27:29.342847574 +0000
@@ -1,4 +1,4 @@
-$product_code = '{7B031DCF-BDCE-47D6-89B9-4C558D76E773}'
+$product_code = '{92D9A5DC-8C64-40D5-B1BC-98DB9C7FDB7F}'
 $timeoutSeconds = 300  # 5 minute timeout
 
 # Fleet uninstalls app using product code that's extracted on upload

ee/maintained-apps/outputs/prisma-browser/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/pritunl/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rider/darwin.json

=== Install Script (no changes) ===
=== Uninstall // c52dae57 -> 22db20ac ===

--- /tmp/old.INhLaV	2026-07-23 18:27:29.464847848 +0000
+++ /tmp/new.7pQLwq	2026-07-23 18:27:29.465847850 +0000
@@ -54,9 +54,9 @@
 
 sudo rm -rf "$APPDIR/Rider.app"
 sudo rm -rf 'rider'
-trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'
-trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'

ee/maintained-apps/outputs/rive/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/rustrover/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/setapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall // e23bd29d -> 9ef05eb6 ===

--- /tmp/old.YWlzm7	2026-07-23 18:27:29.586848121 +0000
+++ /tmp/new.iniPso	2026-07-23 18:27:29.587848124 +0000
@@ -5,6 +5,76 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+remove_launchctl_service() {
+  local service="$1"
+  local booleans=("true" "false")
+  local plist_status
+  local paths
+  local should_sudo
+
+  echo "Removing launchctl service ${service}"
+
+  # A wildcard label can't be used with launchctl or as a plist name, so expand
+  # it to the labels of currently loaded services that match the pattern.
+  local services=("$service")
+  if [[ "$service" == *"*"* ]]; then
+    local regex
+    # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+    # it matches a full label rather than a substring.
+    regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+    regex="^${regex}$"
+    services=()
+    local id
+    # Match every loaded job by label regardless of PID; launchctl list reports
+    # loaded-but-not-running jobs with a "-" in the PID column.
+    while read -r _ _ id; do
+      [[ "$id" =~ $regex ]] && services+=("$id")
+    done < <(launchctl list 2>/dev/null | tail -n +2)
+    if [[ ${#services[@]} -eq 0 ]]; then
+      echo "No loaded launchctl service matches ${service}"
+      return
+    fi
+  fi
+
+  local service_label
+  for service_label in "${services[@]}"; do
+    for should_sudo in "${booleans[@]}"; do
+      plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+      if [[ $plist_status == \{* ]]; then
+        if [[ $should_sudo == "true" ]]; then
+          sudo launchctl remove "${service_label}"
+        else
+          launchctl remove "${service_label}"
+        fi
+        sleep 1
+      fi
+
+      paths=(
+        "/Library/LaunchAgents/${service_label}.plist"
+        "/Library/LaunchDaemons/${service_label}.plist"
+      )
+
+      # if not using sudo, prepend the home directory to the paths
+      if [[ $should_sudo == "false" ]]; then
+        for i in "${!paths[@]}"; do
+          paths[i]="${HOME}${paths[i]}"
+        done
+      fi
+
+      for path in "${paths[@]}"; do
+        if [[ -e "$path" ]]; then
+          if [[ $should_sudo == "true" ]]; then
+            sudo rm -f -- "$path"
+          else
+            rm -f -- "$path"
+          fi
+        fi
+      done
+    done
+  done
+}
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,10 +122,19 @@
   fi
 }
 
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAgent'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'
 sudo rm -rf "$APPDIR/Setapp.app"
 trash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'
 trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'
+trash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'
 trash $LOGGED_IN_USER '~/Library/Logs/Setapp'
+trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'

ee/maintained-apps/outputs/sidenotes/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/signal/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/snagit/darwin.json

=== Install Script (no changes) ===
=== Uninstall // b52ff2b2 -> 59bfdeae ===

--- /tmp/old.cRCzCH	2026-07-23 18:27:29.750848489 +0000
+++ /tmp/new.XtySid	2026-07-23 18:27:29.751848491 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -52,9 +92,14 @@
   fi
 }
 
+quit_application 'com.TechSmith.Snagit'
 sudo rm -rf "$APPDIR/Snagit.app"
+trash $LOGGED_IN_USER '~/Library/Application Scripts/7TQL462TU8.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.snagit.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/Snagit'
 trash $LOGGED_IN_USER '~/Library/Caches/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Group Containers/*.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.TechSmith.Snagit*'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.TechSmith.Snagit*.plist'
 trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.snagit.capturehelper*.plist'
 trash $LOGGED_IN_USER '~/Library/Saved Application State/com.TechSmith.Snagit*.savedState'

ee/maintained-apps/outputs/sourcetree/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/superwhisper/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/tabby/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/trezor-suite/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/visual-studio-code/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/vivaldi/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/wechat/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/whatsapp/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/winlogbeat/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/workflowy/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/darwin.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/zed/windows.json

=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===

@allenhouchins
allenhouchins merged commit 7071996 into main Jul 23, 2026
21 of 24 checks passed
@allenhouchins
allenhouchins deleted the fma-2607231228 branch July 23, 2026 19:28
allenhouchins added a commit that referenced this pull request Jul 23, 2026
- pritunl/windows: revert 1.3.4696.56 -> 1.3.4686.95 (the installer registers
  as 1.3.4686.95, so 1.3.4696.56 is never found by osquery)
- pritunl/darwin: revert the re-bump to 1.3.4696.56 (same issue as the earlier
  revert in #49813: the bundle still reports 1.3.4686.95)
- freeze winget + homebrew inputs so the bot stops re-bumping until upstream
  ships a release that reports its own version
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants