Commit Graph
12 Commits
Author SHA1 Message Date
5630c6f561 Count Hermes run as a module from an activated venv as Hermes too
With the venv active, a gateway started by hand is `python -m hermes_cli.main gateway run`: the interpreter is bare, the executable resolves outside the runtime, and no runtime path is on the command line, so the removal took it for a stranger and refused over the files it holds rather than closing it. Hermes's own package named with -m is the program.

Co-Authored-By: Codex XHigh <noreply@openai.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 21:41:08 -05:00
14eb9430c3 Close Hermes on removal instead of asking the user to close it
Remove > AI refused whenever anything had Hermes's files open and told the user to close it and try again, and the thing open was Hermes: the agent in the terminal that choosing it as the default agent leaves running, the desktop app, a gateway. Those are the removal's to close. It now stops the gateway unit that upstream's `hermes gateway install` wrote, since that unit starts the runtime about to be deleted and would start it again the moment it was killed, then ends every process whose program lives in that runtime or in the package, and only then refuses over whatever is left, which is somebody else's: an editor on a skill, a shell sitting in ~/.hermes, a writer on the state database. Both are judged by the program, never by a later argument or by the home served, so an editor opened on a runtime file is the user's and a unit running a Hermes kept elsewhere is left alone whatever home it serves; for an interpreter the program is the script it runs, so a gateway started by hand as `python .../hermes gateway run` is found too. The refusal comes before anything is touched, so a run that stops leaves Hermes running as it was. A unit that will not stop still aborts the removal, as dropping the package would strand a live gateway on deleted code.

Co-Authored-By: Codex XHigh <noreply@openai.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-24 21:35:46 -05:00
7eb818e37b Install Hermes for the default agent as the desktop app's self-updating runtime
Choosing Hermes as the default agent built it through mise: a pipx environment with no checkout, so `hermes update` had nothing to move, and the only Hermes that could update itself was the one Hermes Desktop set up. Both paths now run the same setup. omarchy-install-hermes-cli installs the hermes-desktop package and runs upstream's installer from it, pinned to the packaged release and started on main, exactly as Install > AI did; omarchy-install-ai-hermes is that plus opening the app. The terminal, the default agent and the app share one runtime, and it updates itself.

--check answers whether --now has anything left to do, not merely whether a hermes runs: choosing Hermes from the menu asks first and opens a terminal only on a no, so a yes has to mean no minutes-long step would run where nobody can see it. With the app installed that means the runtime's own command, its completion marker and the seeded packaged app; a finished runtime whose command is gone, somebody else's, or its own but unable to run gets it back from upstream's path stage without bootstrapping again. Either way the command has to be the one PATH finds, because omarchy-agent runs bare `hermes` and Omarchy puts mise's shims ahead of ~/.local/bin; a command in the way is named rather than installed over. The modes are named outright because the app's launcher used to call this command with no arguments to reconcile a mise copy; a default of --now would turn every launch into an install. --check still refuses to run the retired wrapper, since running it built Hermes through mise, and a machine whose migration is pending can still have it on PATH.

Provisioning no longer writes the wrapper, Remove Preinstalls no longer looks for it, and the wrapper, the environment it built and what proves them Omarchy's are known to the installer alone: --retire-mise is the migration's whole job, and --now runs the same removal once the runtime installer has saved the wrapper aside, so a user who chose Hermes before their migration ran is not left with mise's shim answering `hermes`. Only the wrapper proves the environment is Omarchy's, at its path or in that saved copy, so the environment goes first and the wrapper last, judged by mise neither having it installed nor still requesting it; a removal that leaves either behind, or a listing that cannot be read, mise missing included, stops with the commands to finish by hand and leaves the migration pending. The migration that once installed the wrapper is kept as a no-op for late updaters, and one whose default agent was Hermes is told to choose it again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
2026-09-21 19:26:02 -05:00
Spencer BullandGPT-6 Codex 1b4ac8380b Refuse Hermes removal while its files are in use
An open terminal can retain deleted SQLite WAL files across removal and reinstall, causing the updated desktop to refuse session writes. Check user processes before package/runtime removal and again after data confirmation, without killing sessions. Cover the failure with real SQLite writers in isolated fixtures.

Co-Authored-By: GPT-6 Codex (xhigh) <noreply@openai.com>
2026-09-07 03:56:51 -05:00
Spencer BullandCodex XHigh 8569d1cadc Harden the Hermes skin hand-over
Hermes' YAML reader breaks lines on carriage return, NEL and the Unicode line and paragraph separators, and stops at NUL, none of which grep treats as a line end, so a comment line carrying one could put a root-level key such as banner_logo past the validator and into Rich markup on Hermes' terminal surfaces. The lines grep accepted also did not add up to the YAML Hermes needs: a colour before colors:, a second colors:, or a key over YAML's simple-key limit all passed and loaded as no palette at all, which Hermes shows as its default. The validator now counts every byte outside printable ASCII first, then walks the file in order: the name, at most one plain description, colors:, and only #rrggbb colour lines after it.

omarchy-theme-set releases its lock before the hooks run, so the rendered skin can change under this one between the check and the copy. The check is made on a private copy and that copy is what gets published, both on the first pass and on the republish a minute after activation, which used to copy whatever the theme had become by then, unchecked.

A theme switch reads the config of the profile named in active_profile, which is the one Hermes reads, and a profile exists to Hermes once its directory does, with or without a config; it ends early only for a config plainly naming another skin, since only the default is ever replaced, and leaves anything Hermes might read as the default for Hermes to answer. Hermes is run by the path the readiness probe vets, ~/.local/bin/hermes, bounded the way the probe bounds it; an answer that did not come is not taken for the default, and a write Hermes refuses is reported rather than failed, being cosmetic.

A profile that cannot take the skin no longer costs the others or the activation; a directory at the skin's path is an error rather than a place mv puts the temp file; a temp file the copy could not fill is removed. Remove stops the unit the installer left waiting, so a removal within the waiter's half hour does not hand the theme to a Hermes installed some other way or recreate the skin under a home the user asked to delete. The migration no longer swallows the hook's exit: what is not ready or refused is reported and done with inside the hook, so only Omarchy's own failures return, and those keep the migration pending as the guide requires.

Comments are cut to what the code cannot say; the reasoning is here.

Co-Authored-By: Codex XHigh <noreply@openai.com>
2026-09-05 23:28:46 -05:00
Spencer Bull a1095af075 Ask about the user's data whenever it exists, not only behind the bootstrap marker 2026-09-05 18:30:49 -05:00
Spencer Bull 8f15549380 Ask, default no, before Remove Hermes deletes the user's data 2026-09-04 21:50:41 -05:00
46cfc4ada5 Judge the CLI teardown by what is left, and match flags as definitions
Two review follow-ups. The probe counted any mention of --tui/--query in
the help as support -- Hermes already writes "With --tui:" into --dev's
description, so a release that dropped the option while keeping the
prose would still read as ready. A flag now counts only when followed by
a shape argparse prints after a definition: the usage bracket, the gap
before same-line help text, an uppercase metavar, or the line end. Not
probed by parsing a real invocation on purpose -- a release that ignores
unknown arguments would turn the probe into a live session.

And the teardown trusted its commands: a stub rm that failed aborted
Remove Hermes under set -e before any ~/.hermes handling, while mise
failures vanished into || true. --remove now attempts every step, then
judges by what is left -- the marked stub still present, or mise still
resolving the tool -- and Remove Hermes tolerates the failure until the
runtime is handled, then carries it in its exit code.

Findings from the same codex review at xhigh, verified and proven by
mutation before landing.

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-02 01:01:13 -05:00
c462aad9ee Prove ownership before --remove touches mise
The teardown removed the Omarchy tool spec from mise unconditionally,
so removing Hermes Desktop could destroy a mise environment the user
had built against the same spec while sparing their wrapper -- the very
command the removal claims to preserve, broken behind its back. The
whole teardown now turns on the marked stub, as replacement already
does; the desktop takeover keeps its own bargain, where a second Hermes
goes whoever built it and the app still provides the command after.

Also close the probe over underscores -- _ continues a flag name just
as - does, so --tui_mode no longer answers for --tui -- and pin the
gaps review found in the tests: each flag must match on its own (either
grep could be deleted before without a failure), a foreign wrapper's
mise environment must survive --remove, and Remove Hermes must tear
down the CLI in the interrupted-install case, not only after the app's
runtime landed.

Findings from an independent codex review at xhigh, each verified
against the source and proven by mutation before landing.

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-01 23:32:35 -05:00
Spencer BullandClaude 36d52254a7 Tear down the mise Hermes CLI on Remove Hermes
Remove Hermes dropped the desktop package and its ~/.hermes runtime but
never touched the mise CLI, on the assumption the install-time handoff
had already removed it. A CLI the app never superseded -- an interrupted
install, or the terminal CLI from before the app existed -- was left
stranded on PATH after uninstall.

Add a --remove mode to omarchy-install-hermes-cli that performs the same
teardown the desktop takeover already does (mise rm -g + mise uninstall,
and the marked stub), and call it from omarchy-remove-ai-hermes. The tool
spec and ownership marker stay defined in one place, so the takeover and
teardown paths cannot drift. Scoped to what Omarchy owns: a Hermes the
user installed themselves is left alone.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-01 22:51:03 -05:00
ba78e7df09 Leave a Hermes the app never installed alone
Remove > AI > Hermes deleted ~/.hermes/hermes-agent, bootstrap-cache, bin and
node unconditionally, plus any wrapper on PATH pointing into ~/.hermes. The
official Hermes installer uses those same paths, so a user who installed the
CLI themselves, then installed the app and never launched it, lost their
checkout, venv and any local changes -- while being told their chats, memories
and skills were safe.

The app provisions its runtime on first launch and writes
.hermes-bootstrap-complete when it lands. Without that marker the app never got
that far and everything under ~/.hermes predates it, so dropping the package is
the whole job.

Two smaller things in the same path. The wrapper test matched ~/.hermes as a
pattern, and the dot made it claim a wrapper pointing at a sibling like
~/xhermes; it is a plain string now, and a symlink there is the user's
arrangement rather than something to delete. And -u, so an unset HOME is an
error instead of a set of rm -rf paths rooted at /.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex XHigh <noreply@openai.com>
2026-08-27 11:44:39 +02:00
a12a21c02f Add Hermes as a desktop app and a coding agent
Hermes joins Install > AI as a desktop app, sits beside it under Remove > AI,
and becomes a choice in the default-agent list. The CLI installs through
omarchy-install-hermes-cli rather than a bare `mise use`, so its interpreter
is pinned before mise builds it.

Rebased onto quattro. Ori claimed U+E909 in #7709 while this branch was open,
so the Hermes mark moves to U+E90A in the icon font, the menu entries, the
font README, and the charset the menu test pins. The glyph outline itself is
unchanged; it is spliced in beside Ori rather than over it.

Co-Authored-By: witcheer <witcheer.eth@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SySdB3RtCA8BNv6Am246BP
2026-08-26 18:04:41 +02:00