diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 1f23b2ac33..0ea3db27a1 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -5678,6 +5678,54 @@ def _finalize_update_output(state): pass +def _cmd_update_check(): + """Implement ``hermes update --check``: fetch and report without installing.""" + git_dir = PROJECT_ROOT / ".git" + if not git_dir.exists(): + print("✗ Not a git repository — cannot check for updates.") + sys.exit(1) + + git_cmd = ["git"] + if sys.platform == "win32": + git_cmd = ["git", "-c", "windows.appendAtomically=false"] + + print("→ Fetching from origin...") + fetch_result = subprocess.run( + git_cmd + ["fetch", "origin"], + cwd=PROJECT_ROOT, + capture_output=True, + text=True, + ) + if fetch_result.returncode != 0: + stderr = fetch_result.stderr.strip() + if "Could not resolve host" in stderr or "unable to access" in stderr: + print("✗ Network error — cannot reach the remote repository.") + elif "Authentication failed" in stderr or "could not read Username" in stderr: + print("✗ Authentication failed — check your git credentials or SSH key.") + else: + print("✗ Failed to fetch from origin.") + if stderr: + print(f" {stderr.splitlines()[0]}") + sys.exit(1) + + rev_result = subprocess.run( + git_cmd + ["rev-list", "HEAD..origin/main", "--count"], + cwd=PROJECT_ROOT, + capture_output=True, + text=True, + check=True, + ) + behind = int(rev_result.stdout.strip()) + + if behind == 0: + print("✓ Already up to date.") + else: + commits_word = "commit" if behind == 1 else "commits" + print(f"⚕ Update available: {behind} {commits_word} behind origin/main.") + from hermes_cli.config import recommended_update_command + print(f" Run '{recommended_update_command()}' to install.") + + def cmd_update(args): """Update Hermes Agent to the latest version. @@ -5691,6 +5739,10 @@ def cmd_update(args): managed_error("update Hermes Agent") return + if getattr(args, "check", False): + _cmd_update_check() + return + gateway_mode = getattr(args, "gateway", False) # Protect against mid-update terminal disconnects (SIGHUP) and tolerate @@ -8965,6 +9017,12 @@ Examples: default=False, help="Gateway mode: use file-based IPC for prompts instead of stdin (used internally by /update)", ) + update_parser.add_argument( + "--check", + action="store_true", + default=False, + help="Check whether an update is available without installing anything", + ) update_parser.set_defaults(func=cmd_update) # =========================================================================