Skip to content

One command to uninstall atomic-agent, and a Danger zone to reach it from - #233

Merged
plombeer31 merged 2 commits into
mainfrom
feat/uninstall
Aug 25, 2026
Merged

One command to uninstall atomic-agent, and a Danger zone to reach it from#233
plombeer31 merged 2 commits into
mainfrom
feat/uninstall

Conversation

@plombeer31

Copy link
Copy Markdown
Collaborator

Why

There was no way to remove atomic-agent short of reconstructing an rm -rf from the README, and the paths are easy to get wrong in both directions: too narrow leaves 3 GB of GGUF and a stale PATH line behind, too wide takes ~/.local/bin/node_modules — with somebody else's tools in it — along with ours. The thing an operator most often wants is not even a full removal: it is a clean first run, and there was no way to ask for that either.

What

atomic-agent uninstall removes the state directory (config, memory, sessions, tasks, traces, downloaded models), the binary and its atag alias, the asset directories the installer puts beside them, and the PATH stanza install.sh appends to the shell rc file.

atomic-agent uninstall --dry-run      # print the plan, remove nothing
atomic-agent uninstall                # plan, then type the word
atomic-agent uninstall --keep-data    # program only — reinstall keeps your memory
atomic-agent uninstall --keep-binary  # data only — same binary, fresh onboarding
atomic-agent uninstall --yes          # scripts

src/uninstall/ builds the plan once and both frontends read it, so the list the confirm screen shows is byte-for-byte the list that gets removed. Real output on my machine:

  /Users/valerii/.atomic-agent                    3.2 GB
  /Users/valerii/.local/bin/atomic-agent        134.6 MB
  /Users/valerii/.local/bin/atag                    12 B
  /Users/valerii/.local/bin/grammars              3.5 KB
  /Users/valerii/.local/bin/starter-skills       88.7 KB
  /Users/valerii/.local/bin/vendor                4.2 MB
  /Users/valerii/.local/bin/node_modules         10.1 MB
  total: 3.4 GB

The menu entry

A new danger group, always last and always alone — a separator you have to scroll past is the cheapest warning in the ladder and the only one that costs nothing to read.

│ HELP                                                         │
│   Commands                                                   │
│   List built-in tools                                        │
│   Write debug bundle                                ctrl+g d │
│   Quit                                              ctrl+g q │
│ DANGER ZONE                                                  │
│ ▶ Uninstall atomic-agent…                                    │

No chord: every other verb is one leader-plus-key away, and that is exactly the property this one must not have.

The warnings, stacked

╭──────────────────────────────────────────────────────────────╮
│ UNINSTALL ATOMIC-AGENT — THIS DELETES DATA                   │
│                                                              │
│ /Users/valerii/.atomic-agent                          3.2 GB │
│ /Users/valerii/.local/bin/atomic-agent              134.6 MB │
│ …                                                            │
│ total: 3.4 GB                                                │
│                                                              │
│ This cannot be undone. There is no backup.                   │
│ Memory, sessions and models go with it.                      │
│                                                              │
│ ▸ Cancel    [ Continue ]                                     │
╰──────────────────────────────────────────────────────────────╯

╭──────────────────────────────────────────────────────────────╮
│ UNINSTALL ATOMIC-AGENT — LAST CHANCE                         │
│                                                              │
│ Deleting 3.4 GB permanently.                                 │
│                                                              │
│ Type uninstall to enable the last key:                       │
│ ❯ uninstall                                                  │
│                                                              │
│ enter uninstall   esc cancel                                 │
╰──────────────────────────────────────────────────────────────╯

Cursor starts on Cancel. Cancel is the raised chip and Continue is the outline — the reverse of every other dialog, because here the safe answer is the one the thumb should reach for. y means nothing on any screen. Enter on the last screen is inert until the word is complete, and the reducer re-checks that itself so no other caller can start the removal from a screen where it was never typed.

Nothing is deleted while the app is up

The last key sets a flag and quits. The removal runs after Ink unmounts and orchestrator.shutdown() has closed the three SQLite handles and stopped llama-server — the same post-exit slot the self-update restart uses. Deleting a live state directory leaves handles writing into unlinked inodes on POSIX, fails outright on Windows, and either way the operator watches the directory they just removed blink back into existence.

Safety

  • Every program target is gated on <installDir>/atomic-agent existing: node_modules next to our binary is ours, the same name next to someone else's is not.
  • isSafeToRemove refuses /, the home directory itself, and one-segment paths outside home — a backstop for execPath or ATOMIC_AGENT_STATE_DIR being empty or /.
  • A failure never aborts the run. A half-uninstall that stops at the first EPERM is the worst outcome available; every target is attempted and failures are reported together.
  • The rc edit takes only the installer's own marked stanza and leaves every other byte alone.
  • A dev checkout is detected and says so instead of guessing at an install dir.

Tests

66 new tests: plan construction (incl. Windows paths and a relocated state dir), the safety denylist, rc stripping (incl. an assertion that the marker still matches scripts/install.sh), real-fs removal, the CLI's flags and exit codes, the reducer's step machine, the key layer, and the modal's wording — the warnings are the safety mechanism, so they are asserted rather than eyeballed.

tsc --noEmit clean. src/tui src/cli src/uninstall is 2477 passed / 8 failed, and those 8 are a pre-existing better-sqlite3 NODE_MODULE_VERSION mismatch on my Node 22 — identical on unmodified main.

🤖 Generated with Claude Code

Valerii and others added 2 commits August 24, 2026 16:34
…ch it from

There was no way to remove atomic-agent short of reconstructing an
`rm -rf` from the README, and the paths are easy to get wrong in both
directions: too narrow leaves 3 GB of GGUF and a stale PATH line behind,
too wide takes `~/.local/bin/node_modules` with somebody else's tools in
it. Worse, the thing an operator most often wants is not a full removal
at all — it is a clean first run, and there was no way to ask for that
either.

`atomic-agent uninstall` removes the state directory, the binary and its
`atag` alias, the asset directories the installer put beside them, and
the PATH stanza install.sh appended to the shell rc file. `--dry-run`
prints the plan and stops; `--keep-data` reinstalls-friendly; `--yes` is
for scripts. `src/uninstall/` builds the plan once and both frontends
read it, so the list the confirm screen shows is the list that gets
removed.

The TUI reaches the same flow through a new `danger` menu group that is
always last and always alone, and the warnings are stacked on purpose:
the group heading, then a screen naming every path with its real size
and the sentence saying there is no backup, with the cursor parked on
Cancel, then a screen that will not arm until the word `uninstall` has
been typed out. `y` means nothing on any of them.

Nothing is deleted while the app is up. The last key sets a flag and
quits; the removal runs after Ink unmounts and the runtime has closed
its three SQLite handles and stopped llama-server, in the same post-exit
slot the self-update restart uses. Deleting a live state directory
leaves handles writing into unlinked inodes on POSIX, fails outright on
Windows, and either way the operator watches the directory they just
removed come back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@plombeer31
plombeer31 merged commit dbc6fe5 into main Aug 25, 2026
@plombeer31
plombeer31 deleted the feat/uninstall branch August 25, 2026 17:58
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