# `augment uninstall` — design

Date: 2026-08-03
Status: approved (approach A)

## Goal

`npx @fingerskier/augment@latest uninstall all` removes the agent wiring that
`augment install` wrote, for Codex, Claude, and Grok Build. It breaks the
integration; it never destroys memory data.

## Approach

Mirror-installer module. `src/uninstall.ts` exposes `uninstallIntegration()`,
reversing each target with the same path helpers the installer uses. The path
helpers and shared constants move out of the 961-line `src/install.ts` into
`src/install-paths.ts`, imported by both sides, so install and uninstall can
never drift on where an artifact lives.

Rejected: an install-time manifest (does nothing for already-installed
machines, adds install-side state) and a name-based sweep (unsafe).

## CLI

```
augment uninstall <codex|claude|grok|all> [options]

  --scope user|repo   Which install to reverse. Default: user.
  --dry-run           Print what would change without writing.
  --no-plugin         Skip the best-effort `claude plugin` deregistration.
  --keep-daemon       Do not stop the running daemon.
```

`parseUninstallArgs` is exported (mirrors `parseInstallArgs`), the help text
gains an `UNINSTALL` section and a `uninstall <target>` command line, and
unknown flags/targets throw with a usage string.

Return shape:

```ts
interface UninstallPlan {
  summary: string[];   // human-readable lines
  removed: string[];   // paths deleted
  modified: string[];  // paths rewritten in place
}
```

The CLI prints `summary`, then `- <path>` lines for removed and modified, the
same way `install` prints its plan.

## Per-target removal (scope-mirrored)

### Claude

- Delete the `<root>/plugins/augment` tree — this covers `plugin.json`,
  `.mcp.json`, `hooks/hooks.json`, and every `skills/<name>/SKILL.md`.
- Drop the `augment` entry from `<root>/.claude-plugin/marketplace.json`.
- Delete `mcpServers.augment` from the direct config: `~/.claude.json` (user
  scope) or `<cwd>/.mcp.json` (repo scope).
- Strip the `<!-- augment:start -->…<!-- augment:end -->` block from CLAUDE.md
  (`~/.claude/CLAUDE.md` user, `<cwd>/CLAUDE.md` repo).
- Best effort, unless `--no-plugin`: `claude plugin uninstall augment@<marketplace>`
  and, when the marketplace file emptied, `claude plugin marketplace remove
  <marketplace>` through the injected `ClaudeCommandRunner`. Unavailable CLI or
  a non-zero exit degrades to a manual instruction line, never a failure.

### Codex

- Delete the `<root>/plugins/augment` tree.
- Drop the `augment` entry from `<root>/.agents/plugins/marketplace.json`.

### Grok Build

- Strip `[mcp_servers.augment]` and its nested tables from `config.toml`, reusing
  the installer's existing `removeTomlTables` + `isGrokAugmentMcpTable` via a
  thin exported `removeGrokMcpToml(existing)`.
- Delete `.grok/hooks/augment.json`.
- Delete only the bundled skill directories under `.grok/skills/` — the names
  enumerated from the package's `integrations/claude/skills/`, never the whole
  skills root.
- Strip the marked block from AGENTS.md.

`all` runs codex + claude + grok.

## Safety invariants

1. Never touch `memoryRoot`, and never touch `~/.augment` — `config.json`,
   `npm-exec`, the state dir, and the database all survive. Uninstall removes
   wiring, not data.
2. Only delete paths the installer authored. Merge-writes preserve every
   unrelated key, marketplace plugin, TOML section, and line of prose.
3. Idempotent. Missing artifacts are skipped, not errors; a second run exits
   clean with a "nothing to remove" summary.
4. `~/.claude.json` is only key-pruned, never deleted — it holds unrelated user
   state. When `mcpServers` becomes empty the key itself is dropped.
5. Files the installer creates outright — repo `.mcp.json`, both
   `marketplace.json` files — are deleted when they become empty (`{}` or a
   zero-length `plugins` array) rather than left as husks.
6. A TOML `config.toml` that ends up empty is deleted; otherwise rewritten.

## Daemon

Best-effort `stopRecordedDaemon` through an injectable `stopDaemon` seam on
`UninstallOptions` (tests never touch a real process). Failure is reported in
`summary` and does not fail the command. `--keep-daemon` skips it entirely.

## Error handling

- Unknown target or flag: throw with usage text (matches install).
- Filesystem `ENOENT`: treated as already-removed.
- Any other filesystem error propagates — a partially-removed install must be
  loud, not silent.
- Malformed JSON in a config being pruned: report it in `summary` and leave the
  file untouched rather than clobbering user state.

## Testing (red/green TDD)

`test/uninstall.test.ts`, over temporary `home`/`cwd` roots:

- Install → uninstall round-trip for each target and both scopes leaves no
  augment artifact behind.
- Foreign state survives: an unrelated `mcpServers.other`, a second marketplace
  plugin, an unrelated `[mcp_servers.foo]` table, and surrounding CLAUDE.md /
  AGENTS.md prose are all intact afterward.
- Second run is a clean no-op.
- `--dry-run` writes nothing but reports the same paths.
- `~/.augment` (config.json, npm-exec) and the memory root are untouched.
- `all` reverses all three targets.
- Daemon seam invoked once; `--keep-daemon` suppresses it; a throwing seam
  still yields a successful command.

`test/cli.test.ts`: `parseUninstallArgs` round-trip, bad target/flag errors,
help text contains the uninstall lines.

Existing `test/install.test.ts` must keep passing after the `install-paths.ts`
extraction (pure move, no behavior change).

## Docs

README uninstall section and FEATURES entry, mirroring the install docs, with
the explicit note that memories are never removed and how to delete them
manually if that is what the user wants.
