Ask about the user's data whenever it exists, not only behind the bootstrap marker

This commit is contained in:
Spencer Bull committed 2026-09-05 18:30:49 -05:00
1 parent 8f15549380
commit a1095af075
2 files changed
+49 -41

No files matched your search

+31 -32
View File
@@ -22,7 +22,7 @@ omarchy-install-hermes-cli --remove || cli_removed=false
# and it is the only thing that tells that runtime apart from one the user
# installed themselves -- the paths are the same either way. Without it the app
# never got that far: a machine where it was installed but never launched still
# has whatever was there before, and none of it is ours to delete.
# has whatever was there before, and none of it is ours to delete unasked.
if [[ -f $HOME/.hermes/hermes-agent/.hermes-bootstrap-complete ]]; then
# The checkout and venv, its own uv, its own node. None of it is any use once
# the app is gone, so it goes without asking; what the user made with the app
@@ -55,39 +55,38 @@ if [[ -f $HOME/.hermes/hermes-agent/.hermes-bootstrap-complete ]]; then
fi
done
# What is left is the user's: the chats, memories and skills in ~/.hermes,
# the connections and their encrypted tokens in ~/.config/Hermes. Keeping
# them stays the default -- they are small, and finding them intact after a
# reinstall is the better surprise -- but a removal meant to be complete
# should not leave credentials behind either, so the choice is put in front
# of the user, default no. Only here, behind the bootstrap marker: without
# it ~/.hermes is an install the app never owned, and offering to delete it
# would put the user's own Hermes on the chopping block. Without a terminal
# to ask in, keeping it is the answer.
data_removed=false
if [[ -t 0 ]] && command -v gum >/dev/null; then
# du answers non-zero when either directory is missing (the app makes
# ~/.config/Hermes, but nothing says it is still there), and pipefail
# would turn that into an aborted removal; the size is worth no such thing.
size=$(du -shc "$HOME/.hermes" "$HOME/.config/Hermes" 2>/dev/null | tail -1 | cut -f1 || true)
if gum confirm --default=false "Also delete your Hermes data ($size: chats, memories, skills, connections and tokens)?"; then
rm -rf "$HOME/.hermes" "$HOME/.config/Hermes"
data_removed=true
fi
fi
fi
echo ""
echo "Hermes Desktop has been removed."
if [[ $data_removed == true ]]; then
echo "Its chats, memories, and settings in ~/.hermes and ~/.config/Hermes are gone too."
else
echo "Your chats, memories, and skills are still in ~/.hermes,"
echo "and your connections and settings in ~/.config/Hermes."
# What survives to here is the user's: the chats, memories and skills in
# ~/.hermes, the connections and their encrypted tokens in ~/.config/Hermes.
# Keeping them stays the default -- they are small, and finding them intact
# after a reinstall is the better surprise -- but a removal meant to be
# complete should not leave credentials behind either, so the choice is put in
# front of the user with the size, default no. Asked whenever the directories
# exist, marker or no marker: on a machine where the marker never appeared the
# data came from the terminal CLI or an install the app never finished, and it
# is still what removal is asked to clean up. Naming the paths keeps the
# question honest there too -- ~/.hermes may still carry a runtime the app
# never owned, a yes takes that with it, and saying so is the prompt's job.
# Without a terminal to ask in, keeping everything is the answer.
data_removed=false
if [[ -d $HOME/.hermes || -d $HOME/.config/Hermes ]] && [[ -t 0 ]] && command -v gum >/dev/null; then
# du answers non-zero when either directory is missing, and pipefail would
# turn that into an aborted removal; the size is worth no such thing.
size=$(du -shc "$HOME/.hermes" "$HOME/.config/Hermes" 2>/dev/null | tail -1 | cut -f1 || true)
if gum confirm --default=false "Also delete ~/.hermes and ~/.config/Hermes ($size: chats, memories, skills, connections and tokens)?"; then
rm -rf "$HOME/.hermes" "$HOME/.config/Hermes"
data_removed=true
fi
else
echo ""
echo "Hermes Desktop has been removed."
echo "It never finished installing its own Hermes, so nothing in ~/.hermes was touched."
fi
echo ""
echo "Hermes Desktop has been removed."
if [[ $data_removed == true ]]; then
echo "Its chats, memories, and settings in ~/.hermes and ~/.config/Hermes are gone too."
elif [[ -d $HOME/.hermes || -d $HOME/.config/Hermes ]]; then
echo "Your chats, memories, and skills are still in ~/.hermes,"
echo "and your connections and settings in ~/.config/Hermes."
fi
# The messages above still hold -- the app and its runtime are gone -- but a CLI
+18 -9
View File
@@ -184,18 +184,27 @@ OMARCHY_TEST_GUM_STATUS=0 remove_tty || fail "remove succeeds when the data goes
fail "a yes deletes ~/.hermes and ~/.config/Hermes"
pass "removal deletes the user's data only on an explicit yes"
# Without the bootstrap marker ~/.hermes is an install the app never owned, so
# it must not even be offered for deletion -- not to a terminal, not to a user
# who would say yes.
# Without the bootstrap marker the runtime is not the app's to take unasked,
# but the data question is still the user's to answer: declining keeps the
# whole tree -- runtime included -- untouched.
seed_install
rm -f "$test_home/.hermes/hermes-agent/.hermes-bootstrap-complete"
remove_tty || fail "remove succeeds when the app never installed Hermes"
tr '\0' '\n' <"$test_tmp/gum-log" | grep -qx 'confirm' ||
fail "removal still asks about the data without the bootstrap marker"
[[ -d $test_home/.hermes/hermes-agent && -d $test_home/.config/Hermes ]] ||
fail "declining keeps a Hermes the app never installed"
pass "removal asks without the marker and declining keeps everything"
# The prompt names ~/.hermes itself, so a yes takes the whole tree there too,
# unowned runtime and all -- that is what was asked and answered.
seed_install
rm -f "$test_home/.hermes/hermes-agent/.hermes-bootstrap-complete"
OMARCHY_TEST_GUM_STATUS=0 remove_tty ||
fail "remove succeeds when the app never installed Hermes"
[[ ! -s $test_tmp/gum-log ]] ||
fail "a Hermes the app never installed is not offered for deletion"
[[ -d $test_home/.hermes/hermes-agent && -d $test_home/.config/Hermes ]] ||
fail "a Hermes the app never installed survives a would-be yes"
pass "removal never offers a Hermes the app did not install"
fail "remove succeeds when the data goes too without the marker"
[[ ! -e $test_home/.hermes && ! -e $test_home/.config/Hermes ]] ||
fail "a yes takes ~/.hermes whole when the marker never appeared"
pass "removal honors a yes on the named paths without the marker"
# A CLI teardown that fails must not stop the runtime handling, and must not be
# papered over either: the data work still happens, and the failure reaches the