# Hermes Remote

> Manage a remote Hermes Agent deployment from the CLI — list/create/pause/trigger cron jobs, check status, inspect env vars, swap models, and send one-shot chat calls to the OpenAI-compatible /v1/chat/completions endpoint. Use this skill whenever you need to control a Hermes instance that lives on another machine (VPS, Coolify app, etc.), since the upstream `hermes` CLI only talks to a local gatew…

- **Type:** Skill
- **Install:** `agentstack add skill-osouthgate-agent-plus-skills-hermes-remote`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [osouthgate](https://agentstack.voostack.com/s/osouthgate)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [osouthgate](https://github.com/osouthgate)
- **Source:** https://github.com/osouthgate/agent-plus-skills/tree/main/hermes-remote/skills/hermes-remote

## Install

```sh
agentstack add skill-osouthgate-agent-plus-skills-hermes-remote
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# hermes-remote

Remote CLI for talking to a [Hermes Agent](https://github.com/NousResearch/hermes-agent) deployment over its REST API. Stdlib-only Python 3. No pip installs.

The binary lives at `${CLAUDE_SKILL_DIR}/../../bin/hermes-remote` inside this plugin, and `bin/` is auto-added to PATH when the plugin is enabled — so call it as `hermes-remote`.

## When to reach for this

- The user asks about the state of a remote Hermes instance (status, model, crons, env).
- The user wants to pause, resume, trigger, or delete a Hermes cron job.
- The user wants to create a new cron — **always use the skillify pattern below**, not a prompt-only job.
- The user wants to inspect which env vars Hermes can see vs has missing.

For one-shot chat calls (`/v1/chat/completions`), use `hermes-remote chat ""` — needs `HERMES_CHAT_API_KEY` set (distinct from the admin password).

```bash
hermes-remote chat "status?"                               # quick one-shot
hermes-remote chat --model anthropic/claude-haiku-4-5 ...  # override per-call
hermes-remote chat --max-tokens 200 "..."                  # cap output
hermes-remote chat --system "Be terse." "what is k8s?"     # add system prompt
hermes-remote chat --json "..."                            # full response body
```

For multi-turn conversations or streaming, use an OpenAI-compatible SDK pointed at `$HERMES_URL/v1` — this wrapper is for one-shot calls and cron-friendly scripting.

## When NOT to use this — fall back to the Hermes REST API directly

**This wrapper covers a deliberately narrow slice:** status, model, env list (read-only), config get/set, cron CRUD, and one-shot chat. It does NOT wrap a local CLI — there is no `hermes` remote-control CLI to fall back to. "Fall back" here means **hit the Hermes REST API directly with `curl`** (or `http.client` / `requests`) using the same cookie + bearer token flow `hermes-remote` uses internally. There is no other route.

Specific cases where you should talk to the Hermes endpoint directly, not through `hermes-remote`:

- **Streaming chat responses.** `hermes-remote chat` buffers the full response then prints. For live token streaming, POST to `$HERMES_URL/v1/chat/completions` with `"stream": true` and an SSE-capable client.
- **Multi-turn conversations / conversation history.** The `chat` subcommand is one-shot (system + user only). Maintain a `messages[]` array yourself and POST to `/v1/chat/completions` directly, or use an OpenAI-compatible SDK pointed at `$HERMES_URL/v1`.
- **File uploads, attachments, or anything multipart.** Not wrapped. Hit the relevant Hermes endpoint with `curl -F` or a multipart-capable HTTP client.
- **Mutating env vars, editing existing cron jobs, managing deliveries/platforms/skills, or triggering a gateway restart.** `hermes-remote env list` is read-only; `cron create` exists but there is no `cron edit`; gateway/platform/skill/delivery management isn't wrapped at all. Use `curl` against `/api/env`, `/api/cron/jobs/` (PUT/PATCH), `/api/gateway/*`, `/api/platforms/*`, `/api/skills/*` with the session cookie + bearer token.
- **Authentication/login flows or session management.** `hermes-remote` logs in silently on every call using `HERMES_PASSWORD`. If you need to inspect the raw `/login` response, manage cookies manually, or debug auth, hit `/login` directly.
- **Any Hermes endpoint the wrapper simply doesn't expose yet** — job run history, raw logs, delivery channels, webhooks. Grab the cookie + token the same way (`POST /login`, scrape `__HERMES_SESSION_TOKEN__` from `/`) and call the endpoint directly.

**Don't get stuck in a loop.** If the user needs something the wrapper clearly doesn't cover, switch to `curl` against the Hermes REST API immediately rather than contorting `hermes-remote` flags. The wrapper's job is to make the common read/cron paths ergonomic — not to be the only way in.

## Configure

Config is layered. Highest precedence first:

1. `--env-file ` passed on the CLI
2. `.env.local` / `.env` found by walking up from the current working directory
3. Shell environment (including vars exported via Claude Code settings)

**Project `.env` files override the shell** — opposite of the usual rule. This
lets you drop a `.env` in whichever repo you're working in and have it win
over any globals, without having to unset anything.

Only `HERMES_*` and `COOLIFY_*` keys are picked up from .env files.

If no URL or password is configured, the CLI prints a suggestion showing
exactly where to put them (project `.env` preferred, or `~/.claude/settings.json`
for a global default).

Set one URL mode and one password source.

**URL — one of:**

```bash
export HERMES_URL="https://hermes.example.com"
# OR for reverse-proxy-by-Host setups with flaky DNS:
export HERMES_VPS_IP="1.2.3.4"
export HERMES_HOST="hermes.example.com"
```

The second form hits the IP on port 80 directly and passes the Host header, letting Traefik/Caddy/Nginx route. Skips DNS.

**Password — one of:**

```bash
export HERMES_PASSWORD="..."                      # plain value
export HERMES_PASSWORD_CMD="pass show hermes"     # shell command, stdout is the password
```

If the Hermes instance is managed by Coolify, the script can fetch the password automatically:

```bash
export COOLIFY_URL="http://your-vps:8000"
export COOLIFY_API_KEY="..."
export HERMES_APP_UUID="..."
```

**Admin user** (optional, default `admin@example.com`):

```bash
export HERMES_ADMIN_USER="you@example.com"
```

## Commands

```bash
hermes-remote status                    # gateway state + connected platforms
hermes-remote model                     # current LLM + context window
hermes-remote env list [--all]          # env vars Hermes knows about
hermes-remote config get [key]          # read full config, or a dotted-path key
hermes-remote config set    # mutate config.yaml via /api/config
hermes-remote cron list                 # all cron jobs, one line each
hermes-remote cron show     # full JSON for one job
hermes-remote cron pause 
hermes-remote cron resume 
hermes-remote cron trigger          # fire on next scheduler tick
hermes-remote cron remove  -y
hermes-remote cron create \
    --name  --schedule "every 15m" \
    --script /path/to/work.sh \
    --prompt "If script output contains ERROR, report it. Otherwise [SILENT]." \
    --deliver origin --model anthropic/claude-haiku-4-5
```

Most subcommands take `--json` for machine-parseable output. **Recommended: pipe through `jq`** for field extraction and filtering — e.g. `hermes-remote cron list --json | jq '.[] | select(.state=="paused") | .id'`, `hermes-remote config get --json | jq -r .model`, `hermes-remote status --json | jq .gateway_state`. Every JSON payload is prefixed with a `tool: {name, version}` field so you can self-diagnose version drift (`hermes-remote --version` also works).

## Changing the LLM model (READ THIS)

**Hermes's `config.yaml` overrides env vars for keys it knows about.** The `LLM_MODEL` env var only sets the default at first boot. Once config.yaml has a model, `LLM_MODEL` is ignored — so setting it in Coolify / Docker env and redeploying won't change anything.

To actually change the model, write it via the config API:

```bash
hermes-remote config set model anthropic/claude-haiku-4-5
```

No redeploy needed — it's live. Verify:

```bash
hermes-remote model   # reads /api/model/info; should match immediately
```

Same applies to any other config.yaml key (agent.max_turns, compression.threshold, telegram.channel_prompts, etc.) — `config set` is the mutation path.

## Skillify cron pattern (READ BEFORE CREATING A CRON)

A Hermes cron job has two input fields: `prompt` and `script`.

- `prompt` runs **inside a full agent LLM session** on every tick. Default model, full context, tool loop. Expensive.
- `script` runs **before** the agent starts — pure shell/python, zero LLM tokens. Its stdout becomes context for the agent.

If your cron does deterministic work (sync, embed, poll, sanity check), the work belongs in `--script`. The agent should only be invoked to decide "report or stay quiet" based on the script's output.

**Template for any recurring deterministic cron:**

```bash
hermes-remote cron create \
    --name  \
    --schedule "every 15m" \
    --script /path/on/hermes/host/to/worker.sh \
    --prompt "If the script output contains ERROR, report the relevant lines. Otherwise respond with only [SILENT]." \
    --model anthropic/claude-haiku-4-5 \
    --deliver origin
```

When the agent's response starts with `[SILENT]`, Hermes suppresses delivery — so successful quiet runs cost essentially nothing.

**Why this matters (real incident):** A gbrain sync cron on our Hermes deployment was created with `--prompt` only, using the default Sonnet 4.6 model, running every 15 minutes. Each run invoked the full reasoning loop to execute two shell commands masquerading as reasoning work — burning OpenRouter credit fast. Fixing it to `--script` + minimal Haiku prompt was a roughly three-orders-of-magnitude cost reduction.

**Rules of thumb for cron models:**
- Cheap recurring jobs → `anthropic/claude-haiku-4-5` (fast, cheap, fine for "is this output an error?")
- Genuinely latent work (entity extraction, summarisation, non-trivial judgment) → stay on Sonnet but cap `max_tokens` in Hermes config.

## Quirks

- `is_build_time` is not a valid field on Hermes env POSTs (will 422). Stick to `{"key":..., "value":..., "is_preview": false, "is_literal": true}`.
- urllib.request overrides Host based on URL netloc; this script uses `http.client` with `skip_host=True` to honour explicit Host headers.
- Hermes's `/api/env` only lists vars that match its config schema. A var can be in the container's shell env but not in this list — they're different surfaces.

## Troubleshooting

- **`HTTP 401` from /login**: password wrong, or you're hitting the `:3000` port directly and it has a separate basic-auth gate in front. Route through the main reverse-proxy URL.
- **`Couldn't extract __HERMES_SESSION_TOKEN__`**: login worked but the SPA HTML didn't include the token. Probably a version mismatch; upstream Hermes < 0.10 may not expose it in the same place.
- **`Unauthorized` on specific `/api/*` endpoints with cookie + token set**: that endpoint isn't wired up in your Hermes version, or you're on a preview that renamed it. Try listing with `--json` on a known-good endpoint first to confirm auth is working.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [osouthgate](https://github.com/osouthgate)
- **Source:** [osouthgate/agent-plus-skills](https://github.com/osouthgate/agent-plus-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-osouthgate-agent-plus-skills-hermes-remote
- Seller: https://agentstack.voostack.com/s/osouthgate
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
