Skip to content

feat: implement cli uninstall command#1084

Merged
BYK merged 2 commits into
mainfrom
feat/uninstall
Jun 9, 2026
Merged

feat: implement cli uninstall command#1084
BYK merged 2 commits into
mainfrom
feat/uninstall

Conversation

@BYK

@BYK BYK commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

Part of #1055 — implements sentry cli uninstall, the reverse of sentry cli setup.

What it does

Removes all Sentry CLI artifacts that sentry cli setup creates:

Artifact Source Action
Shell completions (bash, zsh, fish) installCompletions() Delete completion files
Agent skills (~/.claude, ~/.agents) installAgentSkills() Delete sentry-cli/ skill directories
PATH/fpath entries in shell configs addToPath()/addToFpath() Remove # sentry blocks from .bashrc/.zshrc/etc.
Sentry binary (self-delete) installBinary() Delete the binary itself (curl/direct installs only)
Config directory (~/.sentry/) ensureConfigDir() Delete entire directory (DB, caches, patches)

Safety features

  • Package manager detection: Detects PM installs via stored install info OR runtime process.argv[1] sniffing (npm/pnpm/bun/yarn). Advises the user to use their PM's uninstall command.
  • Binary safety guard: Verifies the binary basename starts with sentry before self-deletion, preventing accidental deletion of node, tsx, or other interpreters when install info is missing.
  • Windows handling: Skips binary self-deletion on win32 (OS holds mandatory file lock) and reports a manual removal message.
  • --dry-run: Shows what would be removed without making changes.
  • --yes/--force: Skips confirmation prompt (required in non-interactive environments).
  • --keep-config: Preserves ~/.sentry/ directory (auth tokens, caches).
  • Type-out confirmation: Must type uninstall to confirm (unless --yes/--force).
  • Best-effort removal: Each step logs failures and continues to the next artifact.
  • Partial failure exit code: Sets process.exitCode = 1 when some removals fail.
  • Non-interactive guard: Refuses in non-TTY without --yes/--force (via buildDeleteCommand).

Shell config cleanup

Identifies sentry-managed lines by the # sentry marker comment that addToShellConfig() appends during setup. Removes exactly the marker and ONE command line that follows (matching what setup writes), plus any trailing blank line. Uses exact line matching (trim() === "# sentry") to avoid false positives on # sentry-wizard or similar.

Artifact ordering

Binary is deleted before config directory to prevent ENOENT failures when the binary lives inside ~/.sentry/bin/.

Files

File Purpose
src/commands/cli/uninstall.ts Command implementation (exported removeSentryLinesFromConfig for testing)
src/commands/cli/index.ts Route registration
test/commands/cli/uninstall.test.ts 13 tests

Testing

13 tests covering:

  • --dry-run mode
  • Package manager detection (npm, brew, pnpm via stored install info)
  • --yes removes config directory without prompting
  • --keep-config preserves config directory
  • --force as alternative to --yes
  • Nothing-to-uninstall case
  • --json structured output
  • Shell config cleanup: single block, multiple blocks, # sentry-wizard false-positive, no-entries case

@BYK BYK added the enhancement New feature or request label Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1084/

Built to branch gh-pages at 2026-06-09 13:58 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Comment thread src/commands/cli/uninstall.ts
Comment thread src/commands/cli/uninstall.ts Outdated
Comment thread src/commands/cli/uninstall.ts
Comment thread src/commands/cli/uninstall.ts
Comment thread src/commands/cli/uninstall.ts Outdated
Comment thread src/commands/cli/uninstall.ts Outdated
Comment thread src/commands/cli/uninstall.ts Outdated
@BYK BYK force-pushed the feat/uninstall branch from b37c81e to 0e65759 Compare June 9, 2026 13:23
Comment thread src/commands/cli/uninstall.ts
const results: string[] = [];

for (const shellType of shellTypes) {
const candidates = getConfigCandidates(shellType, home);

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.

Missing XDG config home lookup

Medium Severity

findSentryConfigFiles calls getConfigCandidates without XDG_CONFIG_HOME, while sentry cli setup passes that env var into detectShell. Shell configs under a custom XDG location can keep # sentry PATH/fpath blocks after uninstall.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7082ba7. Configure here.

Comment thread src/commands/cli/uninstall.ts Outdated
try {
const remaining = readdirSync(parentDir);
if (remaining.length === 0) {
await rm(parentDir, { recursive: true, force: true });

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.

Broad sentry bin path match

Medium Severity

After deleting the binary, parent cleanup treats any path ending in sentry/bin as safe to remove when empty. That suffix also matches unrelated directories (e.g. my-sentry/bin), so an empty non-Sentry folder could be deleted.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7082ba7. Configure here.

Comment thread src/commands/cli/uninstall.ts
@BYK BYK force-pushed the feat/uninstall branch from 7082ba7 to 5402c4a Compare June 9, 2026 13:44
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

❌ Patch coverage is 73.17%. Project has 4925 uncovered lines.
❌ Project coverage is 81.4%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/commands/cli/uninstall.ts 73.17% ⚠️ 44 Missing and 13 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
- Coverage    81.47%    81.40%    -0.07%
==========================================
  Files          376       377        +1
  Lines        26315     26480      +165
  Branches     17158     17251       +93
==========================================
+ Hits         21438     21555      +117
- Misses        4877      4925       +48
- Partials      1776      1791       +15

Generated by Codecov Action

Comment thread src/commands/cli/uninstall.ts
Comment thread src/commands/cli/uninstall.ts
Comment thread src/commands/cli/uninstall.ts
Reverse of `sentry cli setup`: removes all CLI artifacts including shell
completions, agent skill files, PATH/fpath entries from shell configs,
the config directory, and the binary itself.

Key behaviors:
- Package manager installs (npm/brew/pnpm/bun/yarn) are detected and
  the user is advised to use their PM's own uninstall command
- `--dry-run` shows what would be removed without making changes
- `--yes`/`--force` skips the confirmation prompt
- `--keep-config` preserves ~/.sentry/ (auth tokens, caches)
- Shell config cleanup identifies blocks by the `# sentry` marker
  added by `addToShellConfig()` during setup
- Binary self-deletion only for curl/direct installs (SEA binaries)
- Each removal step is best-effort (logs failures, continues)

Uses `buildDeleteCommand` for automatic `--yes`/`--force`/`--dry-run`
injection and non-interactive safety guard.
@BYK BYK force-pushed the feat/uninstall branch from b5b8592 to 4ff29bd Compare June 9, 2026 13:56
@BYK BYK enabled auto-merge (squash) June 9, 2026 13:57

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 39377f2. Configure here.

yield new CommandOutput(result);
return {
hint: `This CLI was installed via ${pmMethod}. Run \`${hint}\` to uninstall.`,
};

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.

PM block omits failure exit

Low Severity

When a package manager install is detected, the command yields an UninstallResult with a non-empty failed array and human output under “Failed”, but it returns without setting process.exitCode = 1. That diverges from the partial-removal path, which sets exit code 1 whenever failed is non-empty.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 39377f2. Configure here.

const home = homedir();

// Check if installed via a package manager
const installInfo = getInstallInfo();

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.

Bug: The uninstall command creates the config directory via getInstallInfo() before checking for artifacts, causing it to always find and offer to remove a directory it may have just created.
Severity: LOW

Suggested Fix

Delay the initialization logic that creates the config directory. The call to getInstallInfo() should be moved to after the gatherArtifacts function and the subsequent check for existing artifacts. This prevents the side effect of directory creation before the uninstallable items are inventoried.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/commands/cli/uninstall.ts#L457

Potential issue: The `uninstall` command, when executed, calls `getInstallInfo()` which
in turn calls `getDatabase()` and `ensureConfigDir()`. This unconditionally creates the
`~/.sentry/` configuration directory if it doesn't already exist. Subsequently, the
`gatherArtifacts` function identifies this newly created directory as an existing
artifact to be uninstalled. This behavior bypasses the guard condition intended to
report 'nothing to uninstall' when no artifacts are present, leading to a confusing user
experience where the command offers to remove a directory it just created.

@BYK BYK merged commit 0ec1383 into main Jun 9, 2026
38 checks passed
@BYK BYK deleted the feat/uninstall branch June 9, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant