feat(uninstall): --app/-RemoveApp removes the prebuilt binary install

The default curl|sh and irm|iex installs now put a real app on disk
(/Applications or ~/Applications, ~/.local/bin/VoiceStudio, MSI product).
Both uninstallers gain an opt-in flag that targets exactly those:
- uninstall.sh --app: adds the app bundle / AppImage to the dry-run plan
- uninstall.ps1 -RemoveApp: resolves the MSI product across HKLM/HKCU/
  WOW6432Node and uninstalls it silently under -Yes
This commit is contained in:
debpalash
2026-08-22 01:58:39 +05:30
parent 228019c9a8
commit 772e3e82b4
2 changed files with 55 additions and 8 deletions
+36 -7
View File
@@ -20,12 +20,26 @@
[CmdletBinding()]
param(
[switch]$Yes,
[switch]$Models
[switch]$Models,
[switch]$RemoveApp
)
$ErrorActionPreference = 'Stop'
$identifier = 'com.debpalash.omnivoice-studio'
# Prebuilt app from the default `irm ... | iex` install: an MSI product.
$msiProduct = $null
if ($RemoveApp) {
$uninstallKeys = @(
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$msiProduct = Get-ItemProperty $uninstallKeys -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -match 'VoiceStudio|OmniVoice' } |
Select-Object -First 1
}
# ── Resolve platform default paths (mirrors the app) ────────────────────────
$appData = [Environment]::GetEnvironmentVariable('APPDATA')
$localApp = [Environment]::GetEnvironmentVariable('LOCALAPPDATA')
@@ -71,6 +85,7 @@ $appTargets = @()
foreach ($p in @($dataDir, $configDefault, $logsDefault, $userEnvDir)) {
if (Test-Path -LiteralPath $p) { $appTargets += $p }
}
if ($RemoveApp -and $msiProduct) { $appTargets += "MSI product: $($msiProduct.DisplayName)" }
Write-Host 'VoiceStudio uninstaller (Windows)'
Write-Host '---------------------------------'
@@ -79,7 +94,10 @@ if ($appTargets.Count -eq 0) {
Write-Host 'env-configured locations. Nothing to remove.'
} else {
Write-Host 'App data, managed Python env, config, and logs:'
foreach ($t in $appTargets) { ' {0,-9} {1}' -f (Get-FolderSize $t), $t | Write-Host }
foreach ($t in $appTargets) {
if ($t -like 'MSI product:*') { Write-Host " {-} $t" }
else { ' {0,-9} {1}' -f (Get-FolderSize $t), $t | Write-Host }
}
}
$modelsPresent = Test-Path -LiteralPath $modelsDir
@@ -92,10 +110,13 @@ if ($modelsPresent) {
Write-Host ''
if (-not $Yes) {
Write-Host 'DRY RUN — nothing deleted. Re-run with -Yes to remove the app folders'
Write-Host 'DRY RUN — nothing deleted. Re-run with -Yes to remove the listed folders'
if ($modelsPresent) { Write-Host ' (add -Models to also remove the shared model cache).' }
Write-Host 'To remove the app itself: Settings > Apps > VoiceStudio > Uninstall'
Write-Host '(listed as "OmniVoice Studio" if you have not updated since the rename).'
if (-not $RemoveApp) {
Write-Host ' (add -RemoveApp to also uninstall the prebuilt app via msiexec).'
Write-Host ' Or manually: Settings > Apps > VoiceStudio > Uninstall'
Write-Host ' (listed as "OmniVoice Studio" if you have not updated since the rename).'
}
exit 0
}
@@ -135,6 +156,7 @@ try {
$deleted = 0
foreach ($t in $appTargets) {
if ($t -like 'MSI product:*') { continue }
Write-Host "Removing $t"
Remove-Item -LiteralPath $t -Recurse -Force -ErrorAction SilentlyContinue
$deleted++
@@ -146,8 +168,15 @@ if ($Models -and $modelsPresent) {
} elseif ($modelsPresent) {
Write-Host "Kept model cache ($modelsDir) — re-run with -Models to remove it."
}
if ($RemoveApp -and $msiProduct) {
Write-Host "Uninstalling $($msiProduct.DisplayName) via msiexec..."
Start-Process msiexec.exe -ArgumentList '/x', $msiProduct.PSChildName, '/norestart', '/qn' -Wait
if ($LASTEXITCODE -eq 0) { Write-Host 'MSI product uninstalled.' }
else { Write-Host "msiexec exited with $LASTEXITCODE — remove it via Settings > Apps if it is still listed." }
}
Write-Host ''
Write-Host "Done — removed $deleted folder(s)."
Write-Host 'To remove the app itself: Settings > Apps > VoiceStudio > Uninstall'
Write-Host '(listed as "OmniVoice Studio" if you have not updated since the rename).'
if (-not $RemoveApp) {
Write-Host 'To also uninstall the app: re-run with -RemoveApp, or use Settings > Apps.'
}
+19 -1
View File
@@ -22,10 +22,12 @@ set -euo pipefail
APPLY=0
INCLUDE_MODELS=0
REMOVE_APP=0
for arg in "$@"; do
case "$arg" in
--yes|-y) APPLY=1 ;;
--models) INCLUDE_MODELS=1 ;;
--app) REMOVE_APP=1 ;;
-h|--help)
grep '^#' "$0" | sed 's/^# \{0,1\}//' | sed '1d'
exit 0 ;;
@@ -73,6 +75,21 @@ USER_ENV_DIR="$HOME/.config/omnivoice"
# ── Collect existing targets ────────────────────────────────────────────────
app_targets=()
# ── Optional: the prebuilt app installed by `curl … | sh` (default mode) ────
if [ "$REMOVE_APP" -eq 1 ]; then
case "$OS" in
Darwin)
for app_dir in "/Applications/VoiceStudio.app" "$HOME/Applications/VoiceStudio.app"; do
[ -e "$app_dir" ] && app_targets+=("$app_dir")
done
;;
Linux)
[ -e "$HOME/.local/bin/VoiceStudio" ] && app_targets+=("$HOME/.local/bin/VoiceStudio")
;;
esac
fi
[ -e "$DATA_DIR" ] && app_targets+=("$DATA_DIR")
[ -e "$config_default" ] && app_targets+=("$config_default")
[ -e "$USER_ENV_DIR" ] && app_targets+=("$USER_ENV_DIR")
@@ -101,8 +118,9 @@ fi
echo
if [ "$APPLY" -ne 1 ]; then
echo "DRY RUN — nothing deleted. Re-run with --yes to remove the app folders"
echo "DRY RUN — nothing deleted. Re-run with --yes to remove the listed folders"
[ "$models_present" -eq 1 ] && echo " (add --models to also remove the shared model cache)."
[ "$REMOVE_APP" -ne 1 ] && echo " (add --app to also remove the prebuilt app binary)."
echo "See docs/install/uninstall.md to also remove the app binary itself."
exit 0
fi