Hermes — tiers, install, config & provider runbook
Hermes (NousResearch/hermes-agent) is a self-hosted, terminal-native AI agent with its own provider chain, profiles, memory, and pre-tool guards. himmel drives it in three tiers (config lives OUTSIDE this repo, so hermes is part of himmel even when a checkout doesn’t show it):
| Tier | What it does | Status |
|---|---|---|
| CR critic | Independent model-family reviewer over a branch diff, wired into /pr-check (scripts/cr/hermes-critic.sh + critic-first-pass.sh → scripts/hermes/invoke.sh). No free critic is registered (scripts/cr/critics.json); the panel defaults straight to the paid codex/gpt-6.1-sol anchor — set CR_PROFILE=none for claude-only. A second paid row, claude (claude-opus-5-5, effort medium), runs the official claude binary read-only, not hermes: provider claude-api (default, per-token key through scripts/api-lane/claude-api.sh) or claude-subscription (behind bank-preflight and the native-auth pin). A missing key, closed lane, exhausted credit or non-PROCEED usage is a clean skip (critic-first-pass.sh exit 5), never a red panel. It is same-family, so it never counts toward CR_REQUIRE_CROSS_MODEL. Tune with CR_CLAUDE_CRITIC_EFFORT / CR_CLAUDE_CRITIC_MAX_USD; turn it off with a drop:true row for slug claude in critics.local.json. Fail-closed verdict, fail-open transport. Routes + the proven invocation: CR critic: routes + proven invocation. | Working — the production hermes lane today. |
| Junior | Chore-shaped work (vault inbox capture, summaries, note-taking) on free inference, behind a read-only luna_vault_guard write fence. | Working. |
himmel_agent main tier | A full-control orchestrator (Codex / gpt-6.1-sol) carrying parity_guard instead of the junior fence. It does real engineering / research / vault work. | Alpha - guard parity now tests green; still treat as experimental until more live mileage. |
See the registry row in docs/tool-adoption/registry.md
(tool-adoption rubric) for the adoption rationale and trust posture. The rest of this
runbook is the install + configure + provider-wiring reference. Config lives
OUTSIDE this repo, so a machine rebuild reproduces it from here.
Quick start: install & configure (new user)
himmel ships no base-hermes installer and never writes your hermes identity
(SOUL.md, config.yaml, .env, profiles). You install and configure hermes
itself with hermes’s own tooling; himmel only adds the optional himmel_agent
profile on top. There are four steps: steps 1–3 give you the working CR-critic and junior
tiers, and step 4 is the alpha main tier.
1. Install hermes (upstream)
Use the official installer (quickstart):
# Linux / macOS:curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bashsource ~/.bashrc # or ~/.zshrc — reload PATHThis installs a hermes CLI and a config home (upstream default ~/.hermes/;
see Install layout below). Hermes requires a model with
≥64K context.
2. Configure hermes (provider + keys)
Hermes keeps secrets in <home>/.env, everything else in <home>/config.yaml
(config docs);
hermes config set KEY VAL auto-routes (API keys → .env, the rest →
config.yaml). Pick one path:
hermes setup --portal # fastest: one OAuth → Nous provider + Tool Gatewayhermes model # or: interactive provider/model picker# or wire a key + model by hand (secrets land in .env automatically):hermes config set OPENROUTER_API_KEY sk-or-...hermes config set model.default <provider/model>The model: block in config.yaml is {default, provider, base_url}, with an
ordered fallback_providers: list for resilience. himmel’s live chain and
fallback policy are in Provider routes
below. For himmel’s automated review paid-escalation lane (codex / gpt-6.1-sol), log in to
Codex once:
hermes auth # choose Codex (ChatGPT) — saved to <home>/auth.jsonVerify with hermes doctor (provider connectivity) and hermes config check
(missing settings after an upgrade).
3. Point himmel at your hermes
himmel’s hermes scripts do not all fall back to the same install root, so export both vars in the shell that launches Claude:
HERMES_HOME: install root; used by/himmel-update, the profile provisioner andinvoke.sh’s profile lookup. Fallback:~/.hermesfor/himmel-updateand the provisioner,~/.local/share/hermesforinvoke.shandparity_guard.HERMES_PY: the venv python; used by the CR lane (scripts/hermes/invoke.sh). Fallback: the interpreter the upstream launcher reports, else<home>/hermes-agent/venv/bin/python(scripts/lib/resolve-hermes-py.sh).HERMES_INVOKE_TIMEOUT: wall-clock watchdog budget in seconds forinvoke.sh(default 1800; ceiling 86400). A parity_guard DENY is not terminal to hermes, so this bounds a stuck deny-retry loop and kills the process tree on expiry (rc 124).PARITY_GUARD_DENY_ESCALATE_N(default 3) additionally aborts early (rc 125) after N identical denies in a row; seedocs/internals/harness-compat.md.
export HERMES_HOME="$HOME/.hermes"export HERMES_PY="$HERMES_HOME/hermes-agent/venv/bin/python"Smoke-test the automated review’s sanctioned script (spends your provider’s free credits, not paid budget):
bash scripts/hermes/invoke.sh "Reply with exactly: OK"A clean OK means /pr-check’s hermes critic is wired. That is the whole
working setup: the CR-critic and junior tiers need nothing further.
4. (Optional, alpha) add the himmel_agent main tier
The full-control orchestrator tier is experimental. Its parity_guard
tests green for the guard-parity set, but it still has less live mileage than
the Claude/himmel path. It is not required for the CR-critic or junior tiers. If you want it,
provision the additive profile per Profiles
below.
Install layout
- Install root:
~/.hermes/(orHERMES_HOME): config.yaml, SOUL.md,agent-hooks/luna_vault_guard.py(fail-closed vault write fence),.env(API keys), and thehermes-agent/checkout. - Hermes reads its OWN
.env(~/.hermes/.env); shell env and himmel’s repo-root.envare irrelevant to it.
Profiles: your default + himmel’s himmel_agent main tier
Alpha. The
himmel_agentmain tier is experimental. Itsparity_guardnow tests green for the guard-parity set indocs/internals/lane-parity.md, but it still has less live mileage than the Claude/himmel path. The working, production hermes lanes today are the CR critic and junior tiers (top of this doc). Usehimmel_agentknowingly.
Hermes supports named profiles (hermes profile create|list|use|show), each
an isolated workspace at <home>/profiles/<name>/ with its own SOUL.md,
config.yaml, .env, memories, and hooks. himmel uses this to add a capable
main tier without touching your existing setup:
default(and any profile you already have) is yours, never touched. himmel ships noSOUL.mdand has no hermes installer; it never creates, writes, or overwrites yourSOUL.md,config.yaml, profiles, or.env. A fresh hermes with noSOUL.mduses hermes’s own built-in identity.himmel_agentis an additive profile provisioned on demand byscripts/hermes/install-himmel-profile.sh. It is himmel’s main-tier orchestrator (Codex / gpt-6.1-sol): a generalist that does real engineering, research, vault, and writing work: the “main puller” when Claude capacity is scarce. It carriesagent-hooks/parity_guard.pyinstead of the juniorluna_vault_guard.py: the write/repo fence and routine git/gh/rm blocks are dropped, but the secret-read fence, self-protection (it can’t rewrite its own guard/config/SOUL), and catastrophic-shell blocks (rm -rf, force-push, scheduler/disk mutation,curl|sh) stay, for parity with what Claude/himmel themselves enforce.
# provision (or refresh) the himmel_agent profile AND wire parity_guard into# EVERY hermes profile by default (universal guard) — additive,# idempotent, non-clobbering (swaps a luna_vault_guard, or ADDS the guard where# a profile has none, preserving any other hooks it carries):bash scripts/hermes/install-himmel-profile.sh# narrow the universal pass to named profiles only:bash scripts/hermes/install-himmel-profile.sh --parity-guard=default,researchThe provisioner clones your default (for working keys), then overwrites only
the new profile’s SOUL.md (himmel owns that one) and wires its hook. After
running it, hermes gateway restart and approve the new hook once. Reach the
profile with hermes profile use himmel_agent (or the generated wrapper).
SOUL.md is identity only; project specifics (repo conventions, vault rules)
stay in each context’s AGENTS.md / CLAUDE.md / vault _CLAUDE.md.
hermes profile use is sticky, and hermes config set follows it. Once a
profile is active, hermes config set KEY VAL without -p writes to that
profile (for example himmel_agent), not to default. Pass -p default (or
the profile you mean) every time. To update hermes itself, run hermes update --yes --no-gateway-restart: it never starts a gateway you have stopped. A plain
git fetch inside the install checkout can crash, because the install is a
tree:0 partial clone and git’s pack-objects hits an internal BUG there.
Tier coupling — capability follows the model, not the other way round.
A weaker free-tier model holding the full parity_guard (write code, run git,
open PRs) is risky, and the pre-tool guard can’t tell at call time which model
will answer. So couple them structurally instead:
- The
himmel_agent(full control) runs on the trusted premium model only (Codex / gpt-6.1-sol) with no free fallback (fallback_providers: []). If the premium model is rate-limited, the main tier simply pauses; it does not degrade into a powerful agent backed by a free model. - The free tier lives on the read-only junior (your
default/luna_vault_guardprofile) on a free model (e.g. OpenRouternvidia/nemotron-3-ultra-550b-a55b:free, which draws no paid budget). It runs in parallel as always-available, low-stakes capacity, so when the premium model is down you still have a safe agent, just not a writing one.
In short: fall back to free only by also dropping to read-only; never pair a free model with write/git/PR control.
CR critic: routes + proven invocation
scripts/cr/hermes-critic.sh reviews a branch diff with a model family that did
not produce it. Two reviewer routes:
| Route | Reviewer | Cost |
|---|---|---|
hermes (default) | scripts/hermes/invoke.sh with no --model (the himmel_agent profile default) | free today (see below) |
claude (opt-in) | claude -p print-mode, --permission-mode plan --output-format json --max-turns 1 --strict-mcp-config in a scratch cwd | spends the Claude subscription usage budget — gated by scripts/lib/bank-preflight.sh: a SKIPPED-BANK verdict refuses the route (exit 3, fall back to another reviewer); BANK-STALE / BANK-UNKNOWN are fail-open |
Route selection: an explicit --route / CRITIC_ROUTE always wins; otherwise
it is derived from --implementer:
--implementer | Route | Why |
|---|---|---|
| (none) | hermes | default: free front-tier profile model, no subscription usage budget spend |
hermes | claude | hermes wrote it, so Claude reviews it |
codex | hermes | cross-family only while the hermes reviewer is not codex |
claude | hermes | cross-family, but a claude-family hermes reviewer leaves no cross-family route, so the script exits 2 instead of returning a verdict that looks cross-family and is not; pass --route to override deliberately |
other | hermes | cross-family |
The codex → hermes cell depends on the profile default. The
himmel_agent profile default is ox-alpha today: free, front-tier, and
temporary (operator ruling 2026-08-22; lane profiling is a planned follow-up).
ox-alpha is a different family from codex, so the cell holds. The script infers
the reviewer family from the resolved model id (gpt-*/o<N>*/codex* →
codex) and falls back to claude for a codex implementer when the hermes
reviewer is codex. Pin the answer with HERMES_CRITIC_FAMILY when the
profile default moves and that inference stops holding; pin the model itself
with HERMES_CRITIC_MODEL (--provider openai-codex is then applied only for
codex-family ids).
Invocation (the route was live-verified 2026-08-22 with a real JSON
verdict, exit 1, no rc=3):
HERMES_PY="$HOME/.hermes/hermes-agent/venv/bin/python" \ timeout 300 bash scripts/cr/hermes-critic.sh \ --repo . --base origin/main --goal "review this diff"HERMES_PY: the hermes venv interpreter; needed whenresolve-hermes-py.shcannot find it underHERMES_HOME.nodemust be onPATH(the verdict parser).- Exit
0pass /1findings /2usage /3transport (fail-open: fall back to another review route).rc=3also logs the first ~300 chars of the raw model response to stderr, which is what makes a dead-model default (the 2026-06-12 nemotron one) diagnosable in one run instead of an hour.
Tests: bash scripts/cr/test-hermes-critic.sh is fully stubbed (HERMES_PY for
the default route, a claude shim on PATH for --route claude), so it never
spends the subscription usage budget. It is in the run-shell-tests.sh SKIP_LIST; run it directly.
Free-tier SOUL tuning (559)
Himmel ships one tuned free-tier identity as an opt-in asset:
scripts/hermes/assets/free-tier.SOUL.md.
It is tuned for the open-model free anchor (read live from
scripts/cr/critics.json; the anchor model drifts as free quotas
exhaust, so do not hardcode it here). It adds rigid JSON / format-obedience
scaffolding, a declared Context budget: line, and fewer hedges. Open models
drift from the output contract and over-report, so the free SOUL compensates
where the premium GPT-anatomy prompt would instead rely on contradiction
resolution. It is identity-only: project specifics stay in each context’s
AGENTS.md / CLAUDE.md / vault _CLAUDE.md, never in the SOUL.
How you apply it (operator action, not himmel’s): copy the asset into the
SOUL.md of your existing read-only junior profile (the default /
luna_vault_guard profile from the tier-coupling section above):
# <home> = your hermes config home (upstream default: ~/.hermes)cp scripts/hermes/assets/free-tier.SOUL.md <home>/profiles/<your-junior-profile>/SOUL.mdhermes gateway restart # pick up the new identity, when no session is runningHimmel never overwrites your default profile SOUL for you, and this path
ships no install-himmel-profile.sh edit. The provisioner knows
wire_parity_guard set / ensure / swap, all of which wire the
write-allowed parity_guard; it has no supported way to wire a READ-ONLY
luna_vault_guard fence onto a fresh profile (and luna_vault_guard is a
hermes-side artifact himmel does not ship), so a himmel-created --free-tier
profile could not be safely fenced.
Applying the tuned SOUL to your existing read-only junior keeps the
tier-coupling invariant intact (the free model stays read-only) without himmel
wiring a fence it cannot ship.
The premium half of 559 is the himmel_agent SOUL
(scripts/hermes/assets/himmel-agent.SOUL.md),
which carries the GPT-anatomy markers: an explicit Precedence ladder +
<spec> tags. The free SOUL deliberately carries the JSON-obedience markers
instead (Context budget: + a fenced format-contract block); the two differ
on those named markers by design, asserted by
scripts/hermes/test-soul-markers.sh
(T11).
Keeping it updated
hermes-agent is an editable git checkout (pip install -e) of
NousResearch/hermes-agent living at <install-root>/hermes-agent, so a
himmel git pull never updates it. /himmel-update (and /himmel-update-all)
now pulls that checkout and re-runs the editable install as one of its steps;
/himmel-update --check reports whether a hermes update is available without
applying it. The step resolves the install root from HERMES_HOME (else
~/.hermes) and operates on its hermes-agent/ subdir; it skips
cleanly and never fails the himmel update when hermes isn’t installed. After an
update, restart the hermes gateway (hermes gateway restart, when no
session is running) to pick up changes. On Linux, /himmel-update now does
this for you: it restarts any running hermes-gateway.service (multiplexer)
or hermes-gateway-*.service (per-profile) user units once the checkout
actually moves, or prints the command to run by hand when systemctl isn’t
available.
Gateway topology: multiplexed vs per-profile
hermes runs its gateway one of two ways:
-
Multiplexed (opt-in; this station’s shape). ONE systemd user unit,
hermes-gateway.service, servesdefaultplus every named profile out of thedefaultprofile’s home; status, PID and process state all live there. Not hermes’ default: you opt in withhermes gateway migrate --multiplex, or viahermes update’s auto-migration when nothing blocks it.hermes statusshows aServes: …line naming the profiles it is multiplexing, andhermes -p <profile> gateway statusreports “running via the default-profile multiplexer” for any profile it is serving instead of duplicating the process/PID info. -
Per-profile (rollback shape). One unit per profile,
hermes-gateway-<profile>.service, each its own process. Restore it with:Terminal window hermes gateway migrate --standalone # rolls back to one unit per profile
Restart commands for both shapes:
systemctl --user restart hermes-gateway.service # multiplexersystemctl --user restart hermes-gateway-<profile>.service # per-profileA bot token belongs to exactly one profile. Two profiles polling the same
TELEGRAM_BOT_TOKEN fight over getUpdates, so hermes’ migration preflight
refuses to multiplex while a token is duplicated across profiles. On this
station default runs no bot, so its .env carries no TELEGRAM_* keys.
Multiplexer caveat: hactl role fallback (LUNA-208). ggs-local’s
hactl still honours GGS_ROLE from the environment first, but the
multiplexer sets terminal children’s HERMES_HOME to the served profile’s
home without forwarding that profile’s non-secret .env vars, so
GGS_ROLE simply isn’t there, and hactl then falls back to reading
$HERMES_HOME/ggs_role, failing closed to read-only if that file is
missing.
Upstream force-pushes main. So the checkout regularly stops
being a fast-forward of upstream through no fault of ours, and the update step
would otherwise fail permanently and abort the whole chain. It now resyncs
instead, printing upstream rewrote history — resynced <old> -> <new>, but
only when the working tree is clean and no commit in the checkout was
authored or committed by its own configured user.email. Anything else (local
edits, a commit of yours, an unreadable repo) still FAILs and stops the chain,
so your own work is never silently discarded. The pre-resync HEAD is kept at
the rolling tag himmel-pre-resync. To recover, check git status first and
commit or stash anything uncommitted, then git reset --hard himmel-pre-resync (it discards uncommitted work in the checkout, same as any
hard reset). himmel keeps nothing inside the checkout:
its tailoring is the himmel_agent profile at
<install-root>/profiles/, a sibling directory, which is what makes
discarding orphaned upstream commits safe.
Provider routes (wired 2026-06-12)
SUPERSEDED: since 2026-06-24 the live route is Codex via the
openai-codexprovider, todaygpt-6.1-sol(the impl/junior profiles; the CR critic pins its own model,gpt-6.1-sol, independently; see the tier table above), not the NVIDIA/OpenRouter chain documented below. The Nemotron block is kept for history; a full re-doc of the current routing is tracked. Verify the live model withhermes profile list(Model column) orhermes model.
Context-window budgeting for multi-model lanes (2026-07-07)
Do not assume a model slug’s marketing maximum applies on every backend.
Hermes budgets against the provider-enforced context window, and that value
can differ for the same slug across providers. Upstream issue
NousResearch/hermes-agent#27918
closed the Codex/GPT-5.5 “should be 1M” report as not a bug: live
openai-codex reports and enforces gpt-5.5 at 272000 tokens, while direct
OpenAI API gpt-5.5 can resolve around 1050000. Pinning Codex to 1M would
over-budget prompts that the Codex backend rejects.
Operational rule: every lane that can be triggered as its own model/provider must carry its own verified maximum context window, not inherit the parent lane’s expectation.
himmel_agentmain tier:openai-codex+gpt-5.5was a 272K Codex window when measured on 2026-07-07. This is expected even though the direct OpenAI API slug is larger.- GLM / Z.ai lanes (GLM lane dormant, HIMMEL-1967): request the explicit long-context model id
glm-5.2[1m]on Claude Code-compatible launchers. Bareglm-5.2can run capped below the advertised maximum, so it is not the desired full-control lane. - Hermes
/modeland delegation switches recalculate context for the new provider/model. A top-levelmodel.context_lengthoverride applies to that profile’s active model; it is not a generic guarantee for aliases or sibling external launchers. For custom endpoints that need explicit per-model windows, prefercustom_providers[].models.<model>.context_lengthin Hermes config.
Verification snippets (zero/near-zero inference):
hermes --profile himmel_agent profile show himmel_agent"<hermes-venv-python>" - <<'PY'from agent.model_metadata import get_model_context_lengthprint(get_model_context_length('gpt-6.1-sol', provider='openai-codex', base_url='https://chatgpt.com/backend-api/codex', api_key=''))print(get_model_context_length('glm-5.2[1m]', provider='custom', base_url='https://api.z.ai/api/anthropic', api_key=''))PYIf a context number changes, update this runbook and any lane launcher/config that budgets or summarizes context. Do not “fix” a lower provider-enforced window by hardcoding a larger one unless a live request proves the larger window is accepted on that exact backend.
Routing policy per the ticket: free routes first, fail-open down the chain with a visible note. API-key routes only.
The live config.yaml block:
model: default: nvidia/nemotron-3-ultra-550b-a55b provider: nvidia base_url: https://integrate.api.nvidia.com/v1providers: {}fallback_providers:- provider: openrouter model: nvidia/nemotron-3-ultra-550b-a55b:free| # | Route | Provider name | Model | Key (env name in hermes .env) | Why this position |
|---|---|---|---|---|---|
| 1 (primary) | NVIDIA NIM | nvidia (built-in; aliases nim, nemotron) | nvidia/nemotron-3-ultra-550b-a55b | NVIDIA_API_KEY | Free NIM credits; current Nemotron Ultra flagship. NIM model ids ARE vendor-prefixed; hermes doctor’s “vendor-prefixed slug” warning is a false-positive heuristic here. |
| 2 | OpenRouter | openrouter (built-in) | nvidia/nemotron-3-ultra-550b-a55b:free | OPENROUTER_API_KEY | Same model via a different aggregator, so the NIM quota/outage fallback keeps behavior comparable. |
Not wired, with reasons (recorded so a rebuild doesn’t “fix” them):
- DeepSeek: planned but no
DEEPSEEK_API_KEYon the machine yet. Add- provider: deepseek+ model when a key lands. - Ollama local: Ollama is not installed on this machine (PATH stub
only). If installed later: provider
customwithbase_url: http://localhost:11434/v1, no key.
providers: {} stays empty on purpose: both routes are built-in
provider names, so endpoint + key-env resolution comes from hermes’s
internal registry; a providers: entry is only needed for custom
endpoints or per-provider timeout overrides.
Fallback semantics (hermes docs fallback-providers.md): entries tried
in list order on 429-after-retries / 5xx-after-retries / immediate
401/403/404; fallback is per-turn, so the primary is retried on each new
user message.
Alibaba (Model Studio) free lane — activation + wiring (2026-07-06)
A free parallel implementation/critic lane on Alibaba Cloud Model Studio
(international, Singapore ap-southeast-1) running qwen models over the
OpenAI-compatible endpoint. Codex stays hermes’s main/default provider;
this lane never replaces it, it adds free capacity alongside. The free tier
is a PAYG 90-day trial with per-model free quotas (not every model gets
1M tokens), so enable stop-on-exhaust when you activate.
Activation (chief-side, one-time)
A 403 AccessDenied.Unpurchased from the API means the Model Studio
service has not been activated. It is not an identity, key, URL, or region
problem. Fix it in the Singapore-pinned Model Studio console
(https://modelstudio.console.alibabacloud.com/ap-southeast-1):
- Accept the service agreement; this auto-activates the service and grants the 90-day free quota (Singapore only).
- Batch-enable the models you alias below.
- Set stop-on-exhaust on each.
After that, the same key + URL that returned 403 returns HTTP 200.
Provider (hermes built-in)
hermes ships an alibaba-coding-plan provider, so no new provider code is needed.
Key env vars (read in order): ALIBABA_CODING_PLAN_API_KEY, then
DASHSCOPE_API_KEY; base override: ALIBABA_CODING_PLAN_BASE_URL (set in
~/.hermes/.env).
Workspace-endpoint caveat. The provider’s built-in default base
https://coding-intl.dashscope.aliyuncs.com/v1does not work with a workspace MaaS key (401). Only the workspace endpoint works, and it must include the/compatible-mode/v1path:https://ws-<your-workspace-id>.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1. The China-regiondashscope.aliyuncs.comendpoint 401s on an international key.
Routing (model_aliases is the lever)
hermes’s -z one-shot path auto-detects the provider from -m and
overrides the config default; a bare model name like qwen3-coder-plus
is not auto-detected and would fall through to the default (codex) and
fail. There is no provider-qualified -m syntax. model_aliases: in
~/.hermes/config.yaml is checked first, before auto-detect,
so wire aliases as a top-level block (do not touch
model.default / model.provider):
model_aliases: qwen3-coder-plus: model: qwen3-coder-plus provider: alibaba-coding-plan base_url: https://ws-<your-workspace-id>.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1Add one alias per tier you want reachable. Claude-tier parity map:
| Claude tier | qwen model |
|---|---|
| haiku | qwen-flash |
| sonnet | qwen-plus |
| opus | qwen3-max / qwen3.7-max |
| thinking / fable | qwq-plus / qwen3-235b-a22b-thinking |
| CR critic | anchor row in scripts/cr/critics.json (per-account quota state, e.g. exhausted models swapped out, lives in the gitignored scripts/cr/critics.local.json overlay) |
Validate THROUGH hermes
Don’t just probe the raw endpoint; run a one-shot through hermes so the alias + provider resolution is exercised end to end:
bash scripts/hermes/invoke.sh --model qwen3-coder-plus "say PONG"Expect PONG. If it errors on codex, the alias didn’t take: check the block
is top-level and the key is in .env. Do not use the -p profile route:
one-shot auto-detect on -m re-overrides a profile’s provider.
Consumers
The automated review panel’s free critic is anchored via this lane to the model in
the registry’s anchor row. The shipped
scripts/cr/critics.json carries UNIVERSAL defaults; when YOUR account’s
free quotas exhaust, record the swap in the gitignored
scripts/cr/critics.local.json overlay (auto-picked-up);
do not edit the shipped registry for account state (an earlier change did, and was reverted).
Free-quota exhaustion is why a quota guard is tracked
separately — it needs a dynamic API pull (dashboard screenshots are not
automatable).
Verify after a rebuild (zero inference cost)
hermes fallback list # chain resolves: nvidia primary + 1 fallbackhermes auth list # one credential per provider, sourced from envhermes doctor # API Connectivity: ✓ OpenRouter ✓ NVIDIA NIMThen one paid-nothing smoke: hermes --cli -z "Reply with exactly: OK"
(NIM free credits). The hermes gateway (Telegram bot) reads config at
start, so restart it (hermes gateway restart, when no session is
running) to pick up route changes.
Recover a broken venv pip (“No module named pip”)
uv-created venvs (the default hermes install uses uv venv) ship without
pip, so the editable refresh (and any manual pip install -e .) fails
with No module named pip. /himmel-update now bootstraps pip
automatically (ensurepip) before the refresh; to repair by hand (older
checkout, or the gateway is misbehaving after a pull):
# <venv-py> = …/hermes/hermes-agent/venv/bin/python"<venv-py>" -m ensurepip --upgrade # restore pip into the venvcd …/hermes/hermes-agent"<venv-py>" -m pip install -e . # editable reinstall (picks up pulled code)hermes gateway restart # restart the gateway to load the changesWiring verified 2026-06-12: all connectivity probes green (3 routes at the
time, now 2);
config backup at config.yaml.bak.20260612_overnight.