One command to uninstall atomic-agent, and a Danger zone to reach it from - #233
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
There was no way to remove atomic-agent short of reconstructing an
rm -rffrom 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 uninstallremoves the state directory (config, memory, sessions, tasks, traces, downloaded models), the binary and itsatagalias, the asset directories the installer puts beside them, and the PATH stanzainstall.shappends to the shell rc file.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:The menu entry
A new
dangergroup, 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.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
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.
ymeans 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
programtarget is gated on<installDir>/atomic-agentexisting:node_modulesnext to our binary is ours, the same name next to someone else's is not.isSafeToRemoverefuses/, the home directory itself, and one-segment paths outside home — a backstop forexecPathorATOMIC_AGENT_STATE_DIRbeing empty or/.EPERMis the worst outcome available; every target is attempted and failures are reported together.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 --noEmitclean.src/tui src/cli src/uninstallis 2477 passed / 8 failed, and those 8 are a pre-existingbetter-sqlite3NODE_MODULE_VERSION mismatch on my Node 22 — identical on unmodifiedmain.🤖 Generated with Claude Code