feat: PyPI wheel packaging — pip install hermes-agent && hermes#26350
feat: PyPI wheel packaging — pip install hermes-agent && hermes#26350alt-glitch wants to merge 19 commits into
Conversation
For pip-installed hermes-agent (no .git directory), fall back to querying PyPI's JSON API to compare __version__ against the latest published release, using stdlib only (urllib + json, no packaging dep).
…bootstrap Adds --ensure DEPS for pip-runtime dep installation and --postinstall for pip users who want the full post-install experience without cloning.
When cli-config.yaml.example is not present (e.g. pip wheel install), fall back to writing DEFAULT_CONFIG via save_config() instead of warning and requiring a manual fix.
…hermes/node_modules Extract PATH building into _build_service_path_dirs() that skips directories which don't exist on disk (e.g. node_modules/.bin for pip installs) and also includes ~/.hermes/node/bin and ~/.hermes/node_modules/.bin for agent-browser.
…m build Add _find_bundled_tui() that checks for hermes_cli/tui_dist/entry.js (present in wheel installs) and wire it into _make_tui_argv() between the HERMES_TUI_DIR prebuilt path and the npm install fallback.
…command Adds detect_install_method() to identify nixos/homebrew/git/pip installs, and recommended_update_command_for_method() to return the right upgrade command for each method. Updates recommended_update_command() to use these for pip-installed instances (no .git dir, not managed).
When .git is absent and detect_install_method returns "pip", fork hermes update to run `uv pip install --upgrade hermes-agent` (or `python -m pip install --upgrade hermes-agent` as fallback) instead of hard-exiting with "Not a git repository".
…ffold Match the full set of subdirs created by install.sh: pairing, hooks, image_cache, audio_cache, and skills are now pre-created alongside the existing cron, sessions, logs, logs/curator, and memories dirs. This makes hermes doctor checks cleaner without changing any runtime behaviour.
Includes paired change: browser tool now searches ~/.hermes/node_modules/.bin/ for agent-browser installed via install.sh --ensure browser.
…ate update command - banner.py: remove redundant `import json as _json` (json already at module level) - main.py: _cmd_update_pip now delegates to recommended_update_command_for_method instead of duplicating the uv-vs-pip detection logic - main.py: remove redundant `import subprocess as _sp` (subprocess already at module level)
_cmd_update_check() had its own `.git` gate separate from _cmd_update_impl. For pip installs, fork to _check_via_pypi() and display the result with the correct recommended_update_command().
🔎 Lint report:
|
fb4f5f4 to
9913545
Compare
Before: missing node → hard exit; missing browser → FileNotFoundError. After: both try ensure_dependency() first, which prompts interactively and delegates installation to install.sh --ensure. ripgrep and ffmpeg already degrade gracefully (grep fallback, skip conversion) so they don't need wiring. Also documents the design rationale in dep_ensure.py: detection and prompting live in Python (portable, instant, UX-integrated); only the actual installation delegates to install.sh (1900 lines of battle-tested OS/package-manager logic).
One-shot bootstrap that installs non-Python deps (node, browser, ripgrep, ffmpeg) via ensure_dependency(), then runs setup if no provider is configured. Closes the gap between `pip install` and the full user-facing experience. Also fixes 3 pre-existing test regressions caused by earlier commits: - test_recommended_update_command: mock detect_install_method for git env - test_check_for_updates_no_git_dir: now falls back to PyPI, not None - test_plist_path_includes_node_modules_bin: skip when dir absent
… CLI reference Document pip install hermes-agent as a first-class install option. Clarify that PyPI releases track tagged versions (major/minor), not every commit on main — git installer is for bleeding-edge.
- dep_ensure.py: use get_hermes_home() instead of hand-rolled env var - dep_ensure.py: add "chrome" to browser name list (was inconsistent with browser_tool.py) - main.py _cmd_update_check: use detect_install_method() directly instead of redundant .git check - main.py _cmd_update_pip: build command list directly instead of fragile split() on display string - banner.py: rename _check_via_pypi → check_via_pypi (cross-module public API)
… --check description - installation.md: add tip about `hermes postinstall` for upfront dep install - quickstart.md: show `hermes postinstall` in pip install flow - updating.md: fix --check description to mention PyPI path for pip installs
86c3468 to
349f054
Compare
| return None | ||
|
|
||
|
|
||
| def detect_install_method(project_root: Optional[Path] = None) -> str: |
There was a problem hiding this comment.
should we toss a docker detection in here too? or maybe we can simply write an INSTALL_METHOD file to ~/.hermes or something?
There was a problem hiding this comment.
Done — added both. detect_install_method() now checks ~/.hermes/.install_method first (stamped by installers), then falls back to heuristics (managed → docker → .git → pip). Docker detection checks /.dockerenv and /proc/1/cgroup. install.sh stamps 'git', Dockerfile stamps 'docker', hermes postinstall stamps 'pip'.
| @@ -0,0 +1,106 @@ | |||
| """Lazy dependency bootstrapper for non-Python runtime deps. | |||
There was a problem hiding this comment.
don't love the idea that we're duplicating the list of required packages (ffmpeg etc) in even more places (nix , dockerfile, install.sh..), but you gotta do what you gotta do..
There was a problem hiding this comment.
Yeah it's inherent to multi-ecosystem projects — Nix uses nixpkgs attrs (nodejs_22, ripgrep), Dockerfile uses apt names (nodejs, ripgrep), install.sh has its own install functions. The Python side is centralized in dep_ensure.py (single _DEP_CHECKS dict), and main.py just iterates its keys. Cross-language sharing isn't worth the complexity — they're fundamentally different toolchains.
| **Option A — pip (simplest):** | ||
|
|
||
| ```bash | ||
| pip install hermes-agent |
There was a problem hiding this comment.
should we recommend uv pip here? :3
There was a problem hiding this comment.
Done — switched all docs to uv pip install as the default. Added a tip for folks without uv pointing them to the install script.
|
|
||
| ### pip installs | ||
|
|
||
| PyPI releases track **tagged versions** (major and minor releases), not every commit on `main`. Check for updates and upgrade with: |
There was a problem hiding this comment.
another path that only tracks tagged versions is pushing our need for release management hard. I think me & you & @teknium1 & one or two other folks should have a chat and make sure we're ready for this internally before we merge docs with this
There was a problem hiding this comment.
Agreed — the docs shouldn't go live until we've aligned on release cadence. For now this PR just adds the plumbing (detect pip, update --check queries PyPI, etc). The doc changes are descriptive of what the code does if/when we ship to PyPI, not a public promise. Happy to gate the doc pages behind a flag or move them to a draft section until we finalize the release workflow with the team.
| models-dev-upstream/ | ||
| hermes_cli/tui_dist/* | ||
| hermes_cli/scripts/ | ||
| docs/superpowers/* No newline at end of file |
There was a problem hiding this comment.
Removed — was there for wheel build artifacts (install.sh gets copied to hermes_cli/scripts/ during CI build). Not needed in the gitignore since that only happens in the CI workflow.
|
Merged via #26593 with all 19 commits cherry-picked and your authorship preserved end-to-end. Thanks for the thorough work — Tests: 315 passed (your 17 new + the surrounding ACP + hermes_cli suites). Wheel build confirmed to include One small follow-up I'll handle in a separate PR: the recently-merged #26234 added |
Summary
Makes
pip install hermes-agent && hermesa seamless experience:uv buildhermes updatedetects pip installs and runspip install --upgradeinstead of git pullhermes update --checkqueries PyPI for pip users instead ofgit rev-listhermes postinstall— one-shot bootstrap for non-Python deps (node, browser, ripgrep, ffmpeg) + runs setupensure_dependency()wired into TUI and browser tool — prompts to install missing deps on first useinstall.sh --ensureand--postinstallmodes for targeted dep bootstraphermes doctor --fixgenerates config from defaults when template files are missingWhat works from pip install
hermes setuphermes dashboardhermes --tuihermes updatehermes doctorTest plan
hermes update --checkpip-aware (was the one failure, now fixed)/simplifycode review: DRY cleanup, no TOCTOU issues, browser name list aligned