Skip to main content

Hermes Agent plugin for project-level linting, type-checking, formatting, and security scanning

Project description

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.

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

hermead-0.2.0.tar.gz (38.5 kB view details)

Uploaded Source

Built Distribution

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

hermead-0.2.0-py3-none-any.whl (38.2 kB view details)

Uploaded Python 3

File details

Details for the file hermead-0.2.0.tar.gz.

File metadata

  • Download URL: hermead-0.2.0.tar.gz
  • Upload date:
  • Size: 38.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hermead-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3ddaa4b12c86a1fa324a876796d1dfe852560a80468183cad1b847567d15a75f
MD5 ce7d08f61daca05256f1ccbd69e394b7
BLAKE2b-256 47266fec4e68d5f09b853aeb678b7af8e64fa87d5330c74607776bce22565063

See more details on using hashes here.

File details

Details for the file hermead-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: hermead-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 38.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hermead-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fcc25a60213f44ab395423a963be37a31016786443a23083efe0532b32a52833
MD5 32b33f6d35c57e61f6decefc6d975b03
BLAKE2b-256 d3eae9dc13fd224057cd522da3531e8f5e2599054a1936a6bce142f437f0a25c

See more details on using hashes here.

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