Skip to content

feat(shell): in-app uninstall button replacing copy-to-terminal#150

Merged
stuffbucket merged 1 commit into
mainfrom
feat/in-app-uninstall-ported
Jun 22, 2026
Merged

feat(shell): in-app uninstall button replacing copy-to-terminal#150
stuffbucket merged 1 commit into
mainfrom
feat/in-app-uninstall-ported

Conversation

@stuffbucket

Copy link
Copy Markdown
Owner

What

Replaces the Diagnostics "copy an uninstall command to Terminal" card with a real in-app "Uninstall Maximal…" button that runs the cleanup itself.

  • CLI (src/uninstall.ts): new --keep-app flag — removes the ~/.local/bin/maximal symlink + other PATH binaries but leaves /Applications/maximal.app (the in-app uninstall can't delete the bundle it's running from; the user trashes it afterward).
  • Rust (lib.rs): a uninstall_maximal(revert_claude, purge) Tauri command that shells out to maximal uninstall --unattended --keep-app (+ per-checkbox flags) and returns success/failure to the webview. Registered in invoke_handler!; granted to the loopback webview via allow-uninstall-maximal (mirrors restart_sidecar).
  • Webview: a tightened card with two in-card checkboxes (Revert Claude Desktop keys ✓, Delete stored secrets & config), a window.confirm summary → busy → invoke → calm completion or a non-blocking inline error, plus a quiet terminal fallback.

Provenance

This ports the long-stranded local branch feat/in-app-uninstall (commit bbace2a, authored 2026-06-17 by @stuffbucket) — it predated the shell rewrite (#135/#146) and had never been pushed. Investigation showed the "rewrite" was additive (parallel React islands); the Settings/Diagnostics page is the same vanilla HTML+TS, so the commit cherry-picks cleanly onto current main. The only adaptation: the handler used a bare invoke(...), but current main.ts imports only safeInvoke (which can't drive the inline error UI), so one import was added: import { invoke } from "@tauri-apps/api/core".

Verification

  • bun test tests/uninstall.test.ts — 9/9 (the --keep-app install-target selection).
  • shell tsc + build clean; cargo check clean (the uninstall_maximal command compiles).
  • check:fast 0 errors; design-token check clean.
  • Visual smoke of the rendered card (destructive --accent-destructive button, teal checkboxes, single card / no nesting, all tokenized — design-rule compliant).

Replace the Diagnostics 'copy a command to Terminal' Uninstall card with
a real in-app 'Uninstall Maximal…' button that runs the cleanup itself.

- CLI: add a --keep-app flag to `maximal uninstall` that skips deleting
  the .app bundle while still removing the ~/.local/bin/maximal symlink
  and the other PATH binaries. The in-app uninstall can't delete the
  bundle it's running from, so the user trashes it afterwards.
- Rust: add #[tauri::command] uninstall_maximal(revert_claude, purge),
  which spawns `maximal uninstall --unattended --keep-app` (plus the
  per-checkbox flags), awaits .output(), and returns Result so the
  webview learns success/failure. Registered in invoke_handler! and
  granted to the loopback webview via the allow-uninstall-maximal
  permission (mirrors restart_sidecar — without it the command silently
  no-ops in production).
- Webview: tightened card with two in-card option checkboxes (Revert
  Claude Desktop keys, checked; Delete stored secrets & config,
  unchecked), a destructive 'Uninstall Maximal…' button, and a quiet
  terminal fallback. Click → window.confirm summarizing the choices →
  setBusy → invoke → calm completion state, or a non-blocking inline
  error on failure. Old copy-uninstall-cmd wiring removed.
@stuffbucket
stuffbucket merged commit 57837e9 into main Jun 22, 2026
4 checks passed
@stuffbucket
stuffbucket deleted the feat/in-app-uninstall-ported branch July 13, 2026 05:29
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.

1 participant