Skip to content

install

attest install: idempotent setup + --check doctor mode.

Step functions each return a StepResult; run_install() executes them in spec order and prints one aligned line per step. All subprocess calls go through the single _run() seam so tests can monkeypatch it.

This module implements the detection steps + pure-local fixes (uv, Ollama reachability, models, .env, first data, warmup) and the agent-wiring steps (mcp/skill/reasoning/cron), all gated on _find_agent_binary() finding hermes-agent's own CLI (never our venv's console script).

Status

Bases: StrEnum

The closed set of step outcomes.

A StrEnum member IS a str -- every existing result.status == "OK" comparison, f-string, and json.dumps call keeps working untouched -- but ty now rejects a typo'd literal at check time instead of _STATUS_LABEL[result.status] raising KeyError after all ten install steps have already run.

StepResult dataclass

One step's outcome: its Status plus a one-line human detail, printed verbatim as run_install's aligned report line.

run_install(check=False, yes=False, now=False)

Run every step in spec order, print one aligned line each, and exit nonzero iff any step is BROKEN -- the CLI entry point for attest install and its --check doctor mode.

step_env_file(check=False)

Does .env exist; create it from .env.sample if not (skipped entirely outside a checkout, where there is no sample to copy).

step_first_data(check=False, yes=False, now=False)

Does the database hold any items yet; ingest (and with now, tag) with consent if not.

An absent database is reported rather than opened: get_db runs CREATE TABLE as a side effect, so --check opening one would write a ~90KB file for a step whose whole point is to change nothing.

step_mcp_wiring(agent, check=False)

Register the attestation MCP server with hermes-agent (and its per-surface tool restrictions) if not already wired, and verify the registration rather than trust it.

Confirms mcp add actually took (see the comment above the returncode check) because this is the one step every other tool depends on: a silent failure here means the agent has no attestation tools while the installer reports success.

step_models(check=False, yes=False)

Are the configured chat + embed models installed; pull them with consent if not.

Every failure mode here is reported rather than left to abort the whole run (see the comment above the shutil.which guard): a missing ollama binary, an unreachable daemon, or a pull that fails partway all become a StepResult instead of an uncaught exception that would blank the report for every step after this one.

step_ollama_reachable()

Can the configured Ollama root be reached at all -- skipped, not broken, for a non-Ollama LLM_BASE_URL, which has nothing for this to check.

step_reasoning_override(agent, check=False)

Set agent.reasoning_overrides.<model>: none for a hermes3 chat model.

Scoped to hermes3 by fnmatch (see CLAUDE.md's llm.py note): the override exists for a model-specific quirk and every other chat model is skipped as not needing it, rather than the override being applied broadly on the theory that it is harmless elsewhere.

step_schedule(agent, check=False)

Write the refresh script and register hermes-agent's own cron job for it, detecting a hand-added crontab duplicate rather than reporting OK for a schedule that is silently racing itself.

Verifies agent cron create actually registered the job (see the comment above the returncode check): one build parsed "cron" as a chat prompt and exited 0 having registered nothing, so this checks cron list afterwards rather than trusting the exit code.

step_skill_copy(check=False)

Sync every bundled skill into every skills tree Hermes reads, byte-for-byte, skipping unchanged files -- and disable the superseded research-provenance monolith wherever it is still enabled.

Skipped -- not broken -- when the skills are not bundled with this install (see the comment below): this is a fallback lane, and an odd packaging mode losing it should not fail the rest of the run.

step_uv()

Is uv on PATH -- the one dependency this installer cannot fix itself.

step_warmup(check=False)

Pin chat + embed models in VRAM, skipped under --check (see below) and for a non-Ollama backend, which has nothing to pin.