Skip to main content

Hermes plugin that rewrites terminal commands through RTK for lower-context tool output

Project description

RTK Plugin for Hermes

GitHub release CI PyPI License: MIT

rtk-hermes is a small Hermes Agent plugin that rewrites terminal commands through RTK before execution.

Instead of letting Hermes run verbose shell commands directly, the plugin asks rtk rewrite for a lower-context equivalent:

Hermes wants to run:  git status
Plugin rewrites to:   : RTK && rtk git status
Hermes executes:      rtk git status

RTK then returns filtered output to the LLM, which usually means fewer tokens in the context window.

Status

  • Hermes plugin entry point: rtk-rewrite = "rtk_hermes"
  • Hermes hook used: pre_tool_call
  • Default mode: rewrite terminal commands in place
  • Failure mode: fail open; original command runs unchanged
  • Current GitHub release: v1.2.0
  • PyPI note: PyPI may lag behind GitHub releases. If PyPI still shows 1.0.0, install from the GitHub release URL below.

Installation

1. Install RTK

brew install rtk

Alternative installer:

curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh

Verify:

rtk --version
rtk rewrite "git status"

2. Install the plugin into Hermes' Python environment

Install into the same Python environment that runs hermes. Installing into system Python, conda, or a random virtualenv will not make the plugin visible to Hermes.

Recommended, pinned to the latest GitHub release:

"$(dirname "$(which hermes)")/python" -m pip install \
  "https://github.com/ogallotti/rtk-hermes/releases/download/v1.2.0/rtk_hermes-1.2.0-py3-none-any.whl"

When PyPI is updated to the same version, this is also valid:

"$(dirname "$(which hermes)")/python" -m pip install --upgrade rtk-hermes

If your Hermes install uses the default source layout, this explicit path also works:

$HOME/.hermes/hermes-agent/venv/bin/python -m pip install \
  "https://github.com/ogallotti/rtk-hermes/releases/download/v1.2.0/rtk_hermes-1.2.0-py3-none-any.whl"

3. Enable the plugin in Hermes

Hermes v0.11+ treats pip-distributed plugins as opt-in. Add rtk-rewrite to ~/.hermes/config.yaml:

plugins:
  enabled:
    - rtk-rewrite

Restart Hermes or start a new session after changing plugin config.

Current Hermes CLI caveat: hermes plugins enable rtk-rewrite may not recognize pip-only entry points even when the plugin is installed correctly. Editing plugins.enabled directly is the reliable path.

How it works

Agent calls terminal(command="cargo test --nocapture")
  -> rtk-hermes receives Hermes' pre_tool_call hook
  -> plugin calls: rtk rewrite "cargo test --nocapture"
  -> RTK returns: rtk cargo test --nocapture
  -> plugin mutates args["command"] in place
  -> Hermes executes the rewritten command
  -> RTK-filtered output reaches the model

The plugin does not implement command rules itself. All rewrite logic lives in RTK, so new RTK rules become available without a plugin release.

What gets rewritten

Anything supported by rtk rewrite, including common commands around:

  • Git status, logs and diffs
  • ls, find, grep and file inspection
  • test runners such as pytest and cargo test
  • package managers and build tools
  • Docker and Kubernetes commands

Check RTK's own docs for the current command list: https://github.com/rtk-ai/rtk#commands

Runtime configuration

rtk-hermes intentionally avoids adding extra Hermes tools or MCP servers. Runtime behavior is controlled through environment variables so the plugin stays lightweight.

Variable Default Values Behavior
RTK_HERMES_MODE rewrite rewrite, suggest, off rewrite mutates terminal commands; suggest logs suggestions without changing execution; off disables the plugin at register time.
RTK_HERMES_TIMEOUT_MS 2000 positive integer Max time spent in rtk rewrite per command.
RTK_HERMES_PREVIEW_MARKER true true, false Prefixes rewritten shell commands with : RTK && so Hermes previews clearly show RTK is active.

Example:

export RTK_HERMES_MODE=suggest
export RTK_HERMES_TIMEOUT_MS=500
export RTK_HERMES_PREVIEW_MARKER=false
hermes

Slash command

When the running Hermes version supports plugin slash commands, the plugin registers:

/rtk status
/rtk stats
/rtk reset-stats
/rtk config

The command returns JSON so it is easy to inspect or paste into an issue.

The metrics are process-local counters only. Commands are never stored in metrics to avoid leaking secrets or private shell input.

RTK rewrite exit codes

rtk rewrite uses exit codes to describe its decision:

Code Meaning Plugin behavior
0 Rewrite allowed Apply rewrite when stdout contains a different command.
1 No equivalent Pass through the original command.
2 Deny rule matched Pass through the original command.
3 Ask/confirm verdict; rewritten command exists on stdout Apply rewrite when stdout contains a different command.

Exit code 3 is common for valid rewrites such as git status -> rtk git status and cat file -> rtk read file, so the plugin treats both 0 and 3 as successful rewrites.

Graceful degradation

The plugin should never block command execution.

Condition Behavior
RTK binary not found Plugin does not register the rewrite hook.
rtk rewrite times out Original command runs unchanged.
rtk rewrite crashes Original command runs unchanged.
No RTK equivalent Original command runs unchanged.
Unexpected RTK exit code Warning is logged; original command runs unchanged.

MCP and context mode

This plugin is not an MCP server and does not need to be one.

MCP exposes additional tools to Hermes. RTK rewriting needs to intercept Hermes' existing terminal tool before it executes. That belongs in the pre_tool_call plugin hook, not in MCP.

A pure pre_tool_call rewrite hook also avoids changing the tool schema sent to the model. That is safer for prompt caching than adding or removing tools mid-session.

Why output compaction is not enabled here

Hermes also has hooks such as transform_terminal_output and transform_tool_result. They can compact output after tools run, but they are riskier because they can hide debugging evidence or alter structured tool results.

rtk-hermes stays conservative by default:

  • rewrite before execution;
  • let RTK filter command output;
  • do not mutate read_file, search_files, process, or other non-terminal tool results.

If output compaction is added later, it should be opt-in and heavily tested.

Verification

Check the installed entry point:

"$(dirname "$(which hermes)")/python" - <<'PY'
import importlib.metadata as md
for ep in md.entry_points().select(group="hermes_agent.plugins"):
    if ep.name == "rtk-rewrite":
        module = ep.load()
        print(ep.name, ep.value, ep.dist.metadata["Version"], hasattr(module, "register"))
PY

Expected shape:

rtk-rewrite rtk_hermes 1.2.0 True

Check Hermes config:

python - <<'PY'
from pathlib import Path
import yaml
cfg = yaml.safe_load((Path.home() / ".hermes/config.yaml").read_text()) or {}
print(cfg.get("plugins", {}).get("enabled", []))
PY

Check RTK behavior:

python - <<'PY'
import subprocess
for cmd in ["ls -la", "git status", "cat /etc/hosts", "echo hello"]:
    cp = subprocess.run(["rtk", "rewrite", cmd], capture_output=True, text=True)
    print(cmd, "rc=", cp.returncode, "stdout=", cp.stdout.strip())
PY

Run tests from this repository:

python -m pip install -e '.[dev]'
python -m pytest
python -m build

Troubleshooting

Plugin installed but Hermes does not load it

Most likely cause: it was installed into the wrong Python environment.

Use this interpreter:

"$(dirname "$(which hermes)")/python" -m pip show rtk-hermes

If that command cannot find the package, reinstall using the same interpreter.

hermes plugins enable rtk-rewrite says the plugin is not installed

This is a current Hermes CLI limitation for pip-only entry points. Edit ~/.hermes/config.yaml directly:

plugins:
  enabled:
    - rtk-rewrite

Hermes shows no register() function

The installed package is old. Versions before 1.1.0 used the wrong entry point target.

Upgrade to the GitHub release:

"$(dirname "$(which hermes)")/python" -m pip install --force-reinstall \
  "https://github.com/ogallotti/rtk-hermes/releases/download/v1.2.0/rtk_hermes-1.2.0-py3-none-any.whl"

Rewritten commands do not appear

Check:

  1. rtk --version works in the same environment that starts Hermes.
  2. rtk rewrite "git status" returns a rewritten command.
  3. plugins.enabled contains rtk-rewrite.
  4. Hermes was restarted after the config change.
  5. RTK_HERMES_MODE is not set to off or suggest.

Development

git clone https://github.com/ogallotti/rtk-hermes.git
cd rtk-hermes
python -m pip install -e '.[dev]'
python -m pytest
python -m build

Before releasing:

rm -rf dist/ build/ src/*.egg-info
python -m pytest
python -m build
python -m twine check dist/*

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rtk_hermes-1.2.0.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rtk_hermes-1.2.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file rtk_hermes-1.2.0.tar.gz.

File metadata

  • Download URL: rtk_hermes-1.2.0.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rtk_hermes-1.2.0.tar.gz
Algorithm Hash digest
SHA256 9fedf1c3f9ff2dbe43f118b0c116140ef03c3c585c8c699a3ace67960264bd9d
MD5 c7534fc0e06e73d5942b1d2b5fc36e97
BLAKE2b-256 ab2d57e4abe4d88bf217a0238573e6939ae7c569fb03ac9fe967f6628bc2622c

See more details on using hashes here.

Provenance

The following attestation bundles were made for rtk_hermes-1.2.0.tar.gz:

Publisher: publish.yml on ogallotti/rtk-hermes

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rtk_hermes-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: rtk_hermes-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rtk_hermes-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d20e5c21bf5b3e1acd5a29f01c9ef37a894de114b18580bc933b2cc8a07d62cd
MD5 c33e698cc3c3cd8af4a54092470e2f64
BLAKE2b-256 fe82e794a75b3abb6c3e1fbbf08d25fb47e8a7fb47eb1ce14a6d8960f6287632

See more details on using hashes here.

Provenance

The following attestation bundles were made for rtk_hermes-1.2.0-py3-none-any.whl:

Publisher: publish.yml on ogallotti/rtk-hermes

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page