ADR-198: Uninstall is a lifecycle command that keeps what the operator owns¶
Summary¶
- Decided:
ways uninstallremoves agent-ways. It withdraws from every target and from~/.claude, stops the ways agent, removes the command links that point into the app, and deletes the app and every cache it has used. Without--yesit prints that plan and changes nothing. The operator's config and state stay unless--purgeis given. - Trades away: A single command that leaves nothing behind. Kept config and state outlive the app until the operator purges them.
- One-way? Running it with
--purgeis: it deletes the operator's ways and API keys. The default run is not; reinstalling restores everything it removed. - Probes: Confident (keep): you would rather a plain uninstall keep your own ways and keys, and delete them only when you ask. Not confident (state): events and probe data count as yours to keep, not as app data to delete.
- Inversion: Between removing only the links, as
make uninstalldid, and deleting everything the app ever wrote. The decision removes all the app owns and keeps what the operator owns.
Context¶
agent-ways had an install, an update, a repair (ways reconcile) and target withdrawal (ways config target remove, ADR-184), but no removal. make uninstall unlinked four commands. Taking agent-ways off a machine meant withdrawing the projection, then deleting the XDG directories, the links on PATH and caches from before the 1.0 rename by hand, and knowing which were the app's and which the operator's. A cache left from a pre-1.0 install changed the behaviour of the next clean install.
Decision¶
- One command.
ways uninstalltakes the machine back to before the install, apart from what the operator owns. - Withdraw first. It withdraws from every recorded target and from
~/.claudethe way a disabled target is withdrawn: our links, our hooks and permissions through the settings merge base (ADR-500), and our MCP entry. The installer projects into~/.claudewhatever the target list says, so~/.claudeis always included. Withdrawal leaves the config's target list unchanged, so a kept config activates the same targets on a later install. A failed withdrawal stops the command before anything is deleted; targets withdrawn before the failure stay withdrawn, and a reinstall projects them again. When the app is already gone nothing can be withdrawn, and the command goes on to remove the links and caches. - What is removed. The command links in
~/.local/binand$XDG_BIN_HOMEthat point into the app, every cache dir the app has used (agent-ways, and the pre-1.0claude-ways), and last the app ($XDG_DATA_HOME/agent-ways), so a failure part way leaveswaysin place to run again. The ways agent is asked to stop. - What is kept. The operator's config (
$XDG_CONFIG_HOME/agent-ways: their ways, API keys, settings) and state ($XDG_STATE_HOME/agent-ways: events, probe data).--purgedeletes both. - Plan first. Without
--yesthe command lists each path under withdraw, unlink, delete or keep, and exits having changed nothing. - Refused plans. Every deleted path is absolute and named
agent-waysorclaude-ways, and none is, holds or sits inside a kept directory,$HOMEor~/.claude. XDG directories set to the same place would otherwise put a kept directory on the delete list; the command refuses instead.
Consequences¶
Positive¶
- Removing agent-ways and reinstalling it are each one command, and a clean install can be demonstrated on a machine that had one.
- Nothing the operator wrote is lost by default.
Negative¶
- A machine where the app was deleted by hand and the projection left in place cannot be withdrawn by this command, because withdrawal identifies our links by the app they point into. The command still removes the links and caches and says so; reinstalling and then uninstalling clears the projection.
- Kept config and state are invisible clutter to an operator who expected everything gone; the plan lists them and names
--purge.
Neutral¶
make uninstallremains the Makefile's unlink step for a source checkout.
Alternatives Considered¶
- Delete everything by default. One command with no leftovers, but a plain uninstall would delete API keys and the operator's own ways. Rejected: deleting what the operator owns needs their explicit ask.
- Withdraw through
ways config target remove. It drops the target from the config, and removing the last one writes an empty list, so a kept config would install inactive. Rejected for the disable-style withdrawal, which leaves the list as it was. - A shell script beside
install.sh. It would duplicate the withdrawal logic the binary already owns, and drift from it.