Skip to main content

HermeAd

PyPI version License Python CI

HermeAd is a Hermes Agent plugin that automatically runs linters, type checkers, formatters, and security scanners on project files after every write_file or patch tool call.

No manual commands. No context switching. Files get checked the moment you write them.

How It Works

HermeAd registers a single post_tool_call hook. After each file modification:

  1. Detects the file type from extension or filename
  2. Walks up the tree to find the project root (.git, .hg, or .hermes directory)
  3. Loads config: built-in defaults → global ~/.hermes/hermead.yaml → per-project .hermes/hermead.yaml
  4. Auto-detects tooling from pyproject.toml, package.json, go.mod, Cargo.toml, .shellcheckrc
  5. Routes to the right runner for each check category (lint, type check, format, security)

Results appear inline in the session. Issues surface at the moment of introduction, not after a CI run.

Quick Install

pip install hermead

From source:

git clone https://github.com/asimons81/hermead.git
cd hermead
pip install -e ".[dev]"

Verify it loaded:

hermes plugin list
# → hermead should appear

Features

  • Zero-config for common projects. Works out of the box with ruff + mypy for Python, eslint + prettier + tsc for JS/TS, golangci-lint + go vet + gofmt for Go, clippy + rustfmt for Rust, shellcheck for shell scripts, and rubocop + standardrb + brakeman for Ruby.
  • Auto-detection. Reads pyproject.toml, package.json, go.mod, Cargo.toml, .shellcheckrc, and .rubocop.yml/Gemfile to pick the right tools. Auto-detected tools take priority over config.
  • Per-project config. .hermes/hermead.yaml overrides global ~/.hermes/hermead.yaml, which overrides built-in defaults.
  • Threshold system. Set findings to block, warn, or ignore per severity level (lint warnings, type errors, security findings).
  • 7 language runners. Python, JavaScript/TypeScript, Go, Rust, Shell, Ruby, and a Generic runner for config/script files (semgrep).
  • Graceful degredation. Missing tools produce empty results. No crashes, no spurious errors. Use which <tool> to check availability.
  • Ignore patterns. Skip node_modules/, venv/, build output dirs, and anything else you add.
  • Extra CLI args. Pass custom flags per tool (e.g. ruff: ["--line-length", "100"]).

Configuration

Quick Start

Create .hermes/hermead.yaml at your project root:

python:
  lint: ruff
  type_check: mypy
  formatter: ruff
  security: semgrep

thresholds:
  lint_warnings: warn
  type_errors: block
  security_high: block

ignore_paths:
  - node_modules/**
  - venv/**
  - __pycache__/**

Full Reference

# Per-language tool assignments (null = skip that check category)
python:
  lint: ruff
  type_check: mypy
  formatter: ruff
  security: semgrep

javascript:
  lint: eslint
  type_check: tsc
  formatter: prettier
  security: semgrep

go:
  lint: golangci-lint
  type_check: go vet
  formatter: gofmt
  security: gosec

rust:
  lint: clippy
  type_check: cargo check
  formatter: rustfmt
  security: cargo audit

shell:
  lint: shellcheck
  formatter: shfmt

generic:
  lint: semgrep
  security: semgrep

thresholds:
  lint_warnings: warn       # warn | block | ignore
  type_errors: block
  security_high: block
  security_medium: warn
  security_low: info

ignore_paths:
  - node_modules/**
  - venv/**
  - .venv/**
  - __pycache__/**
  - .git/**
  - dist/**
  - build/**
  - target/**
  - .hermes/**

extra_args:
  ruff: ["--line-length", "100"]
  mypy: ["--strict"]
  golangci-lint: ["--timeout", "5m"]

Supported Languages

Language Extensions Lint Type Check Format Security
Python .py ruff mypy ruff / black bandit / semgrep
JavaScript / TypeScript .js, .ts, .jsx, .tsx, .mjs, .cjs eslint tsc prettier semgrep
Go .go golangci-lint go vet gofmt gosec
Rust .rs clippy cargo check rustfmt cargo audit
Shell .sh, .bash, .zsh, .fish shellcheck — shfmt —
Ruby .rb, Gemfile, Rakefile rubocop — standardrb brakeman
Generic Dockerfile, Makefile, .gitignore, etc. semgrep — — semgrep

Inline Reports

When HermeAd runs, findings appear in your session as structured results:

🔍 ruff: 1 error

  🔍(line 42:5) F841 — local variable 'x' is assigned to but never used (F841)

Each result shows the tool, severity, source location, message, and rule code. Empty output means the file passed or the tool wasn't available.

Contributing

PRs welcome. HermeAd is a young project — the runner interface, result format, and hooks API are still finding their shape.

  • Runners live in hermead/runners/. Each module self-registers via register_runner(language, action, func).
  • The hook dispatcher lives in hermead/hooks.py.
  • Config loading lives in hermead/config.py.
  • The registry lives in hermead/runners/__init__.py.

Before opening a PR, run the test suite:

pip install -e ".[dev]"
pytest -v

Plugin Architecture

HermeAd is a Hermes Agent plugin — no MCP server, no web server, no external API. It registers a single hook entry point in pyproject.toml:

[project.entry-points."hermes_agent.plugins"]
hermead = "hermead:register"

For more on building Hermes plugins, see the Hermes Agent Plugin Docs.

License

MIT — see LICENSE.

Metadata

Release files for hermead 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hermead 0.2.0
File Size Uploaded Provenance
hermead-0.2.0.tar.gz 38.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hermead 0.2.0
File Interpreter ABI Platform
hermead-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 76.6 kB

Release files / hermead-0.2.0.tar.gz

Download URL hermead-0.2.0.tar.gz
Size 38.5 kB
Tags Source
SHA-256 checksum
How to use checksums
3ddaa4b12c86a1fa324a876796d1dfe852560a80468183cad1b847567d15a75f
BLAKE2b-256 checksum
How to use checksums
47266fec4e68d5f09b853aeb678b7af8e64fa87d5330c74607776bce22565063
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Release files / hermead-0.2.0-py3-none-any.whl

Download URL hermead-0.2.0-py3-none-any.whl
Size 38.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fcc25a60213f44ab395423a963be37a31016786443a23083efe0532b32a52833
BLAKE2b-256 checksum
How to use checksums
d3eae9dc13fd224057cd522da3531e8f5e2599054a1936a6bce142f437f0a25c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.15

Security for hermead 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page