Skip to main content

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

Project description

HermeAd

PyPI version License Python

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.
  • Auto-detection. Reads pyproject.toml, package.json, go.mod, Cargo.toml, and .shellcheckrc 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).
  • 6 language runners. Python, JavaScript/TypeScript, Go, Rust, Shell, 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
Generic Dockerfile, Makefile, .gitignore, etc. semgrep semgrep

Inline Reports

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

╔══════════════════════════════════════════════════════════╗
║  HermeAd — lint results for src/main.py                 ║
╠══════════════════════════════════════════════════════════╣
║  tool: ruff  severity: error  line: 42  col: 5          ║
║  F841 — local variable 'x' is assigned to but never     ║
║  used                                                    ║
╠══════════════════════════════════════════════════════════╣
║  2 findings (1 error, 1 warning) — 0 blocked, 2 warned  ║
╚══════════════════════════════════════════════════════════╝

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.1.0.tar.gz (29.3 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.1.0-py3-none-any.whl (31.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for hermead-0.1.0.tar.gz
Algorithm Hash digest
SHA256 473de7029aae215a1506fb9b27ec705288a900547fdb6cb34c2c7ce60a34e493
MD5 b3705311294d30c4f8a6a2afd9426938
BLAKE2b-256 435d9f9fe2b147b0bad47dba172ac333df9b097072bd19e2a9be1887ce5c706b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: hermead-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.7 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a9f3b76142c92938183010cb6b9633c3b798e3f8d8cabd8dcba6f18c247947b7
MD5 4a7821a4421a8aaef2a4831d67e72a9b
BLAKE2b-256 9b686ac628981e0b258a09574199ae4689691ccf1cfb31a088a72f2a98dc6c04

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