# Hermes CLI reference

> `hermes okf` subcommands registered via `cli_extension.py` and `plugin.py`: `search`, `list --type`, `show --raw`, `snapshot --note`, `restore`, default `top_k`, and dispatch through `HermesOKFProvider`.

- Repository: EliaszDev/hermes-okf
- GitHub: https://github.com/EliaszDev/hermes-okf
- Human docs: https://grok-wiki.com/public/docs/eliaszdev-hermes-okf-b71befaafe02
- Complete Markdown: https://grok-wiki.com/public/docs/eliaszdev-hermes-okf-b71befaafe02/llms-full.txt

## Source Files

- `src/hermes_okf/cli_extension.py`
- `src/hermes_okf/plugin.py`
- `docs/HERMES_PLUGIN.md`
- `README.md`
- `src/hermes_okf/hermes_integration.py`

---

---
title: "Hermes CLI reference"
description: "`hermes okf` subcommands registered via `cli_extension.py` and `plugin.py`: `search`, `list --type`, `show --raw`, `snapshot --note`, `restore`, default `top_k`, and dispatch through `HermesOKFProvider`."
---

The `hermes okf` command group exposes five memory-inspection subcommands on the Hermes Agent CLI. Registration flows through `plugin.py` into `cli_extension.py`, which builds the argparse tree; each handler instantiates `HermesOKFProvider` and delegates to its search, bundle-read, snapshot, and restore methods. Bundle path and agent identity resolve from Hermes configuration — there is no `--path` flag on these commands.

<Note>
These commands require `hermes-okf` installed and registered via `hermes-okf-install`. They operate on the configured OKF bundle (default `~/.hermes/okf_memory`), not an arbitrary path on the command line.
</Note>

## Prerequisites

<Steps>
<Step title="Install and register the plugin">

```bash
pip install hermes-okf
hermes-okf-install
```

`hermes-okf-install` creates `~/.hermes/plugins/hermes-okf/` and updates `~/.hermes/config.yaml` with `plugins.enabled` and `memory.provider`.

</Step>
<Step title="Verify commands are available">

```bash
hermes okf list
```

If argparse recognizes the `okf` group, registration succeeded. Run `hermes memory setup` to customize `bundle_path` or `agent_id`.

</Step>
</Steps>

## Registration and dispatch

Pip-installed packages cannot rely on Hermes' convention-based `plugins/memory/<name>/cli.py` discovery. Instead, `hermes-okf` registers through the general plugin entry point and delegates CLI construction to `cli_extension.py`.

```mermaid
sequenceDiagram
    participant Hermes as Hermes CLI
    participant PM as PluginManager
    participant Plugin as plugin.py
    participant CLI as cli_extension.py
    participant Prov as HermesOKFProvider

    Hermes->>PM: Load hermes_agent.plugins entry point
    PM->>Plugin: register(ctx)
    Plugin->>CLI: ctx.register_cli_command("okf", setup_fn=register_cli)
    Hermes->>CLI: User runs hermes okf &lt;subcommand&gt;
    CLI->>Prov: HermesOKFProvider()
    Prov-->>CLI: search / bundle / snapshot / restore
    CLI-->>Hermes: stdout
```

| Component | Role |
|-----------|------|
| `pyproject.toml` → `hermes_agent.plugins` | Entry point `hermes-okf = "hermes_okf.plugin"` (module-only; no `:register` suffix) |
| `plugin.py` | Calls `ctx.register_cli_command(name="okf", setup_fn=register_cli, handler_fn=None)` |
| `cli_extension.py` | Builds subparsers; each subcommand sets `func=_cli_*` as its dispatch handler |
| `HermesOKFProvider` | Loads config, wraps `HermesAgent`, exposes `search`, `snapshot`, `restore`, and bundle access |

`handler_fn=None` because subparsers set their own `func` defaults — the parent `okf` parser has no handler of its own. Omitting a subcommand triggers argparse's standard usage error.

## Configuration resolution

Every `_cli_*` handler calls `HermesOKFProvider()` with no arguments. The provider reads `HermesOKFConfig` in this order:

1. `HERMES_OKF_*` environment variables
2. `~/.hermes/hermes-okf.yaml`
3. `~/.hermes/config.yaml` → `plugins.hermes_okf` keys
4. Defaults (`bundle_path=~/.hermes/okf_memory`, `agent_id=hermes`)

<Info>
The `memory.bundle_path` key written by `hermes-okf-install` is used by Hermes' memory provider at runtime. CLI handlers resolve bundle path through `HermesOKFConfig.from_hermes_config()`, which also checks `plugins.hermes_okf` in `config.yaml`.
</Info>

## Command summary

| Subcommand | Positional args | Flags | Provider method |
|------------|-----------------|-------|-----------------|
| `search` | `query` | `--top-k` (default `5`) | `provider.search(query, top_k=...)` |
| `list` | — | `--type` | `provider.agent.memory.bundle.list_concepts()` + filter |
| `show` | `path` | `--raw` | `provider.agent.memory.bundle.read_concept(path)` |
| `snapshot` | — | `--note` (default `""`) | `provider.snapshot(note=...)` |
| `restore` | — | — | `provider.restore()` |

---

## `hermes okf search`

Full-text search over all concepts in the configured bundle. Uses `SearchIndex` with token-frequency scoring; the index rebuilds on each invocation because the handler calls `invalidate()` before searching.

<ParamField body="query" type="string" required>
Search string. Tokenized into lowercase alphanumeric terms.
</ParamField>

<ParamField body="--top-k" type="integer">
Maximum results to return. Default: `5`. The provider's Python API defaults to `10`, but the CLI overrides this at the argparse layer.
</ParamField>

<RequestExample>

```bash
hermes okf search "dark mode"
hermes okf search "deployment strategy" --top-k 10
```

</RequestExample>

<ResponseExample>

```text
  [0.50] hermes/decisions/model_strategy
  [0.33] hermes/observations/user_profile_2026-06-15
```

When no concepts match:

```text
No results found.
```

</ResponseExample>

---

## `hermes okf list`

Lists every concept in the bundle by scanning all `.md` files except reserved `index.md` and `log.md`. Output shows concept type and ID.

<ParamField body="--type" type="string">
Filter results to concepts whose frontmatter `type` field matches exactly (e.g. `Decision`, `Plan`, `Session`, `AgentConfig`, `Snapshot`).
</ParamField>

<RequestExample>

```bash
hermes okf list
hermes okf list --type Decision
hermes okf list --type Session
```

</RequestExample>

<ResponseExample>

```text
  [Decision] hermes/decisions/model_strategy
  [Plan] hermes/plans/research_ai_trends
  [AgentConfig] config/agent
```

When the bundle is empty or all concepts are filtered out:

```text
No concepts found.
```

</ResponseExample>

---

## `hermes okf show`

Displays a single concept by its bundle-relative path (without `.md` extension).

<ParamField body="path" type="string" required>
Concept path relative to bundle root. Examples: `config/agent`, `hermes/sessions/2026-06-14T22-14-58Z`, `hermes/decisions/model_strategy`.
</ParamField>

<ParamField body="--raw" type="boolean">
When set, prints only `concept.body` (markdown content). Omits type header, metadata block, and separator.
</ParamField>

<RequestExample>

```bash
hermes okf show config/agent
hermes okf show hermes/sessions/2026-06-14T22-14-58Z
hermes okf show hermes/decisions/model_strategy --raw
```

</RequestExample>

<ResponseExample>

Default output (metadata + body):

```text

[AgentConfig] config/agent
Metadata:
  type: AgentConfig
  title: hermes Configuration
  model: openai/gpt-4o
  system_prompt: You are a helpful, autonomous Hermes agent.
  timestamp: 2026-06-14T22:14:58Z
---
# Agent Configuration

System prompt and behaviour settings.
```

With `--raw`:

```text
# Agent Configuration

System prompt and behaviour settings.
```

When the path does not exist:

```text
Concept not found: config/agent
```

</ResponseExample>

---

## `hermes okf snapshot`

Saves a full agent state snapshot. The provider flushes the hot memory buffer first, then writes a `Snapshot` concept to `snapshots/<timestamp>.md` containing `agent_id`, `model`, `current_session`, `current_plan`, `system_prompt`, and the note.

<ParamField body="--note" type="string">
Optional annotation stored in snapshot metadata. Default: empty string.
</ParamField>

<RequestExample>

```bash
hermes okf snapshot
hermes okf snapshot --note "Before deployment"
```

</RequestExample>

<ResponseExample>

```text
✓ Snapshot saved.
```

</ResponseExample>

<Warning>
`snapshot` flushes pending hot-buffer writes before saving. Observations, decisions, and tool calls buffered in `HotMemoryBuffer` are written to the cold OKF archive as part of this operation.
</Warning>

---

## `hermes okf restore`

Restores agent state from the most recent snapshot in the `snapshots/` subdirectory. Sorts snapshot concept IDs lexicographically and reads the last entry. Updates in-memory `model`, `current_session_id`, `current_plan_id`, and `system_prompt` on the underlying `HermesAgent`.

<RequestExample>

```bash
hermes okf restore
```

</RequestExample>

<ResponseExample>

On success:

```text
✓ Restored from: 2026-06-14T22:14:58Z
```

When no snapshots exist:

```text
No snapshots found.
```

</ResponseExample>

The timestamp printed comes from `state.get('timestamp', 'unknown')` on the restored snapshot metadata.

---

## Provider dispatch details

Each CLI handler follows the same pattern:

1. `from hermes_okf import HermesOKFProvider`
2. `provider = HermesOKFProvider()` — fresh instance per invocation
3. Delegate to the appropriate provider or bundle method
4. Print human-readable stdout (no JSON mode on Hermes CLI)

| Handler | Provider call chain |
|---------|---------------------|
| `_cli_search` | `provider.search(args.query, top_k=args.top_k)` → `SearchIndex.search()` |
| `_cli_list` | `provider.agent.memory.bundle.list_concepts(subdir=None)` → `read_concept()` per path |
| `_cli_show` | `provider.agent.memory.bundle.read_concept(args.path)` |
| `_cli_snapshot` | `provider.snapshot(note=args.note)` → `_flush_hot()` → `agent.snapshot()` |
| `_cli_restore` | `provider.restore()` → `_flush_hot()` → `agent.restore()` |

`HermesOKFProvider` also implements session hooks (`on_session_start`, `on_memory_write`, `on_tool_call`) used by `HermesOKFMemoryProvider` during live agent sessions. The CLI commands bypass those hooks and operate directly on the cold OKF archive.

## Hermes CLI vs standalone CLI

| Capability | `hermes okf` | `hermes-okf` (standalone) |
|------------|--------------|---------------------------|
| Bundle path | From Hermes config | `--path` flag on every command |
| Subcommands | `search`, `list`, `show`, `snapshot`, `restore` | Full set: `init`, `validate`, `log`, `graph-*`, `context`, `sessions`, `plans`, `tools`, etc. |
| JSON output | Not available | `--json` on some commands |
| Requires Hermes running | No (CLI only needs plugin registration) | No |

Use `hermes okf` when inspecting memory from within the Hermes ecosystem with config-driven bundle resolution. Use `hermes-okf` for bundle administration, graph inspection, and operations on arbitrary paths.

## Exit codes and errors

Handlers do not call `sys.exit()` explicitly. Successful commands exit `0`. Argparse errors (missing subcommand, missing positional argument) exit with argparse's default non-zero code. Uncaught exceptions (missing `pyyaml`, unreadable config, filesystem errors) propagate as Python tracebacks.

| Condition | Stdout message | Exit code |
|-----------|----------------|-----------|
| Search returns no hits | `No results found.` | `0` |
| List returns no concepts | `No concepts found.` | `0` |
| Show path missing | `Concept not found: <path>` | `0` |
| Restore with no snapshots | `No snapshots found.` | `0` |
| Missing subcommand | argparse usage error on stderr | non-zero |

<AccordionGroup>
<Accordion title="Plugin not visible in hermes CLI">

Confirm `~/.hermes/plugins/hermes-okf/` contains `plugin.yaml` and `__init__.py`. Verify `plugins.enabled` in `~/.hermes/config.yaml` is a YAML list containing `hermes-okf`, not a JSON-encoded string. Restart Hermes after install.

</Accordion>
<Accordion title="Commands target wrong bundle">

Check resolution order: `HERMES_OKF_BUNDLE_PATH` env var → `~/.hermes/hermes-okf.yaml` → `plugins.hermes_okf` in `config.yaml`. The install script sets `memory.bundle_path` but CLI handlers read through `HermesOKFConfig.from_hermes_config()`.

</Accordion>
<Accordion title="show prints empty or wrong content">

Concept body is stored in `concept.body`, not `concept.content`. Use `--raw` to verify markdown content without metadata formatting.

</Accordion>
</AccordionGroup>

## Related pages

<CardGroup>
<Card title="Install Hermes plugin" href="/install-hermes-plugin">
Register `hermes-okf` via `hermes-okf-install`, configure `~/.hermes/config.yaml`, and run `hermes memory setup`.
</Card>
<Card title="Hermes provider integration" href="/hermes-provider-integration">
Session hooks, memory callbacks, `prefetch`/`sync_turn`, and exposed tool schemas on `HermesOKFMemoryProvider`.
</Card>
<Card title="Standalone CLI reference" href="/standalone-cli-reference">
Full `hermes-okf` command set with `--path`, `--json`, graph inspection, and validation.
</Card>
<Card title="Configuration reference" href="/configuration-reference">
`HermesOKFConfig` fields, `HERMES_OKF_*` environment variables, and config file resolution order.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
Recovery for missing install scripts, plugin discovery failures, and stale model config.
</Card>
</CardGroup>
