Skip to content

fix: improve uninstall wizard cleanup#147

Open
udhaya10 wants to merge 2 commits intoparcadei:mainfrom
udhaya10:fix/uninstall-cleanup
Open

fix: improve uninstall wizard cleanup#147
udhaya10 wants to merge 2 commits intoparcadei:mainfrom
udhaya10:fix/uninstall-cleanup

Conversation

@udhaya10
Copy link
Copy Markdown

@udhaya10 udhaya10 commented Feb 15, 2026

Summary

The uninstall wizard archives ~/.claude and restores backup, but leaves several artifacts behind. This PR fixes that.

Changes

claude_integration.py

  • Add settings.local.json to PRESERVE_FILES — users store custom permissions here; was being lost on uninstall
  • Log preserve warnings — instead of except Exception: pass, now records which files failed to preserve and includes them in the summary message

wizard.py

  • Remove CLAUDE_OPC_DIR from shell config — the install wizard adds export CLAUDE_OPC_DIR=... to ~/.zshrc/~/.bashrc but uninstall never cleaned it up
  • Offer to remove TLDR CLIuv tool uninstall llm-tldr (default: No, since user might want to keep it)

Not included (intentionally)

  • Docker container cleanup — removed from scope; users may share containers with other projects

Test plan

  • Run --uninstall with CLAUDE_OPC_DIR in ~/.zshrc → verify it's removed
  • Run --uninstall with settings.local.json present → verify it's preserved
  • Simulate preserve failure → verify warning appears in output instead of silent pass
  • Run --uninstall with TLDR installed → verify removal prompt appears
  • Decline TLDR removal → verify it stays installed

Closes #142

Summary by CodeRabbit

  • New Features

    • Configuration files are now preserved during uninstall
    • Shell configuration exports are automatically removed during uninstall
    • Optional cleanup for related tools offered during uninstall
  • Bug Fixes

    • Enhanced error reporting during configuration preservation with warning messages

- Add settings.local.json to PRESERVE_FILES (user permissions)
- Log warnings instead of silently ignoring preserve failures
- Remove CLAUDE_OPC_DIR from shell config (~/.zshrc, ~/.bashrc)
- Offer to remove TLDR CLI tool (uv tool uninstall llm-tldr)

Closes parcadei#142
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Walkthrough

This pull request enhances the uninstall process by preserving settings.local.json during uninstallation, improving error visibility during file preservation operations, and adding post-uninstall cleanup for shell environment variables and optional CLI tool removal.

Changes

Cohort / File(s) Summary
Config File Preservation
opc/scripts/setup/claude_integration.py
Added settings.local.json to PRESERVE_FILES list. Enhanced error handling during file preservation to record warnings instead of silencing exceptions. Updated uninstall message assembly to include any preserve_warnings with [WARN] prefix.
Post-Uninstall Cleanup
opc/scripts/setup/wizard.py
Added cleanup steps in run_uninstall_wizard() to remove CLAUDE_OPC_DIR export lines and related comments from ~/.zshrc and ~/.bashrc. Presents optional user prompt to uninstall TLDR CLI via uv tool uninstall llm-tldr.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses 4 of 5 requirements from issue #142: shell config cleanup, TLDR removal prompt, settings.local.json preservation, and warning logging. However, Docker container cleanup is intentionally out of scope. Clarify whether Docker container cleanup (issue #142 requirement 2) will be addressed in a follow-up PR, or document why it remains out of scope in the issue discussion.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: improve uninstall wizard cleanup' accurately summarizes the main objective of reducing leftover artifacts after uninstall operations.
Out of Scope Changes check ✅ Passed All changes directly address uninstall wizard cleanup objectives: file preservation warnings, shell config cleanup, and CLI tool removal prompts are all in scope per issue #142.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 15, 2026

PR author is not in the allowed authors list.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@opc/scripts/setup/wizard.py`:
- Around line 1352-1366: The uninstall call using subprocess.run inside the TLDR
removal block should be wrapped in a try/except to handle
subprocess.TimeoutExpired and OSError/FileNotFoundError so the wizard doesn't
crash; locate the block that checks shutil.which("tldr") and Confirm.ask, then
around the subprocess.run call (which sets timeout=30) catch
subprocess.TimeoutExpired and OSError/FileNotFoundError (or the base OSError)
and log a warning via console.print including guidance to run "uv tool uninstall
llm-tldr" manually, and also handle non-zero return codes as currently done
using remove_result.returncode.
🧹 Nitpick comments (1)
opc/scripts/setup/wizard.py (1)

1352-1353: shutil.which("tldr") doesn't distinguish llm-tldr from tldr-pages.

The install wizard (Line 960) validates this by checking for "tree", "structure", "daemon" in --help output. Here, offering to uv tool uninstall llm-tldr when the detected tldr is actually tldr-pages is harmless (uv will report it's not installed), but could confuse the user. Consider either skipping the check or adding a similar heuristic.

Comment on lines +1352 to +1366
if shutil.which("tldr"):
if Confirm.ask("\n Remove TLDR CLI tool?", default=False):
import subprocess

remove_result = subprocess.run(
["uv", "tool", "uninstall", "llm-tldr"],
capture_output=True,
text=True,
timeout=30,
)
if remove_result.returncode == 0:
console.print(" [green]OK[/green] TLDR removed")
else:
console.print(" [yellow]WARN[/yellow] Could not remove TLDR")
console.print(" Remove manually: uv tool uninstall llm-tldr")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing error handling for subprocess.runTimeoutExpired and OSError can propagate uncaught.

If uv is not on PATH or the process times out (Line 1360 sets timeout=30), the resulting FileNotFoundError / subprocess.TimeoutExpired will bubble up unhandled and crash the wizard after an otherwise successful uninstall.

🛡️ Proposed fix: wrap in try/except
     if shutil.which("tldr"):
         if Confirm.ask("\n  Remove TLDR CLI tool?", default=False):
             import subprocess
 
-            remove_result = subprocess.run(
-                ["uv", "tool", "uninstall", "llm-tldr"],
-                capture_output=True,
-                text=True,
-                timeout=30,
-            )
-            if remove_result.returncode == 0:
-                console.print("  [green]OK[/green] TLDR removed")
-            else:
-                console.print("  [yellow]WARN[/yellow] Could not remove TLDR")
+            try:
+                remove_result = subprocess.run(
+                    ["uv", "tool", "uninstall", "llm-tldr"],
+                    capture_output=True,
+                    text=True,
+                    timeout=30,
+                )
+                if remove_result.returncode == 0:
+                    console.print("  [green]OK[/green] TLDR removed")
+                else:
+                    console.print("  [yellow]WARN[/yellow] Could not remove TLDR")
+                    console.print("  Remove manually: uv tool uninstall llm-tldr")
+            except (subprocess.TimeoutExpired, OSError) as e:
+                console.print(f"  [yellow]WARN[/yellow] Could not remove TLDR: {e}")
                 console.print("  Remove manually: uv tool uninstall llm-tldr")
🤖 Prompt for AI Agents
In `@opc/scripts/setup/wizard.py` around lines 1352 - 1366, The uninstall call
using subprocess.run inside the TLDR removal block should be wrapped in a
try/except to handle subprocess.TimeoutExpired and OSError/FileNotFoundError so
the wizard doesn't crash; locate the block that checks shutil.which("tldr") and
Confirm.ask, then around the subprocess.run call (which sets timeout=30) catch
subprocess.TimeoutExpired and OSError/FileNotFoundError (or the base OSError)
and log a warning via console.print including guidance to run "uv tool uninstall
llm-tldr" manually, and also handle non-zero return codes as currently done
using remove_result.returncode.

Comment on lines +1358 to +1361
capture_output=True,
text=True,
timeout=30,
)

This comment was marked as outdated.

Wrap subprocess.run() in try/except to catch TimeoutExpired and OSError,
preventing the uninstall wizard from crashing if uv is missing or times out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Bug: Uninstall wizard doesn't clean up shell env vars, Docker containers, or CLI tools

1 participant