feat: integrate Hermes Agent as 5th coding CLI#136
Merged
Conversation
Adds Hermes Agent (github.com/NousResearch/hermes-agent) alongside Claude Code, Codex, OpenCode, and Gemini CLI. Hermes is a Python-based multi- provider AI CLI with tool-calling, persistent memory, and a rich skill system — installed via its official installer into ~/.local/bin/hermes. Integration points: - setup_hermes.py: installs Hermes, writes ~/.hermes/config.yaml pointing at Databricks AI Gateway (/mlflow/v1) or /serving-endpoints fallback. Configures custom provider, fallback_providers chain (opus-4-7 -> opus-4-6 on 429/529/503), external skills dir shared with Claude Code, and MCP servers (deepwiki + exa + optional team-memory). - app.py: adds hermes to setup_state steps, parallel_steps, and the _configure_all_cli_auth re-run loop. - cli_auth.py: _update_hermes() rewrites api_key lines in ~/.hermes/config.yaml on PAT rotation (every 10m). - app.yaml.template: HERMES_MODEL env var (default opus-4-7). - CLAUDE.md / README.md / docs/deployment.md: documentation. Usage after deploy: hermes chat # interactive chat hermes --tui chat # rich TUI hermes model # select default model hermes mcp list # list configured MCP servers
The original setup_hermes.py cloned the full NousResearch/hermes-agent repo (135MB) with a 180s timeout, which silently failed on Databricks Apps. Switched to `uv tool install` from git URL — handles venv and binary setup automatically. Also dropped the `matrix` extra (requires native libolm).
When PAT rotation happens while a setup script is still installing (e.g., Hermes takes minutes to install from git), the rotation's update_cli_tokens() silently skips missing config files. The setup script then writes config with the initial (now-revoked) token. Fix: after all parallel setup completes, re-apply the current token to all CLI configs. This ensures every config has the latest token regardless of installation timing vs rotation timing. Closes the race window that caused HTTP 403 on first Hermes launch.
Two bugs preventing Gemini CLI from authenticating: 1. setup_gemini.py wrote GEMINI_API_KEY_AUTH_MECHANISM="bearer" (with literal quotes). Node.js dotenv parses this as '"bearer"' — Gemini CLI expects 'bearer' without quotes, fails auth check, falls back to interactive prompt asking for credentials. 2. Terminal sessions inherited GEMINI_API_KEY from the parent process env, which goes stale after PAT rotation. Now stripped from shell env (like DATABRICKS_TOKEN) so Gemini CLI reads from ~/.gemini/.env which is kept current by cli_auth.py.
Updated in setup_gemini.py, setup_opencode.py, setup_hermes.py, app.yaml, app.yaml.template, README.md, and deployment docs.
Gemini CLI has a workspace trust system that silently skips loading .env files in untrusted directories (gemini-cli#20005). Terminal sessions on Databricks Apps start in ~/projects/ which was never trusted, so GEMINI_API_KEY from ~/.gemini/.env was never loaded. Fix: write ~/.gemini/trustedFolders.json during setup to pre-trust both ~/projects/ and ~/ so .env loading works from any directory.
Gemini CLI expects string enum values (TRUST_FOLDER, TRUST_PARENT, DO_NOT_TRUST), not booleans. Using true caused: Invalid trust level "true" for path "..."
Hermes is installed via uv tool install into an isolated venv. The mcp Python package (HTTP transport) wasn't included, so MCP servers (DeepWiki, Exa) failed with "mcp.client.streamable_http not available." Fix: add --with 'mcp>=1.2.0' to the uv tool install command.
Owner
Author
Testing SummaryAll changes validated on Databricks Apps deployment: Hermes Agent - Working end-to-end:
Gemini CLI - Fixed three-layer auth bug:
Token rotation - All 5 CLIs confirmed receiving rotated tokens via cli_auth.py Ready to merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrate Hermes Agent as the 5th coding CLI in CoDA, plus auth fixes for Hermes and Gemini.
Commits
uv tool installfrom git URL_update_hermes()silently skipped missing config)"bearer"in.env(Node.js dotenv included quotes in value); stripped staleGEMINI_API_KEYfrom terminal session envdatabricks-gemini-3-1-pro→databricks-gemini-2-5-proTest plan
Hermes Agent
/api/setup-statusshows hermes step completing (not stuck/pending)which hermesreturns~/.local/bin/hermesin a terminal sessioncat ~/.hermes/config.yamlshowsprovider: custom+ correct AI Gateway endpointhermes chatconnects and can send/receive messagescat ~/.hermes/config.yamlshows updatedapi_key:valuehermes chatafter rotation works without 403Gemini CLI
geminiCLI starts without prompting for GEMINI_API_KEY / Vertex / GCAcat ~/.gemini/.envshowsGEMINI_API_KEY_AUTH_MECHANISM=bearer(no quotes)env | grep GEMINI_API_KEYin terminal session returns empty (stripped from env)databricks-gemini-2-5-promodel by defaultToken rotation (all CLIs)
~/.claude/settings.json→ANTHROPIC_AUTH_TOKEN~/.codex/.env→OPENAI_API_KEY~/.gemini/.env→GEMINI_API_KEY~/.hermes/config.yaml→api_key:(both primary and fallback)~/.local/share/opencode/auth.json→api_keyPost-setup token sync