Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,563 changes: 200 additions & 1,363 deletions AGENTS.md

Large diffs are not rendered by default.

107 changes: 107 additions & 0 deletions docs/development/component-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Hermes Component Guide

This is the detailed routing map for contributors. Universal engineering rules
live in the repository root `AGENTS.md`; subsystem-specific rules live in
nested `AGENTS.md` files.

## Core conversation path

- `run_agent.py`: `AIAgent` construction and agent loop.
- `model_tools.py`: tool discovery, schema assembly, and function dispatch.
- `toolsets.py`: named tool bundles and `_HERMES_CORE_TOOLS`.
- `hermes_state.py`: SQLite-backed session state and search.
- `agent/`: providers, prompt construction, memory, caching, compression,
checkpoints, and supporting services.

The message loop must preserve strict role alternation and a byte-stable system
prompt for the life of a conversation. Agent-level tools such as todo and
memory may be intercepted before generic function dispatch.

## CLI and commands

- `cli.py`: classic interactive CLI orchestrator.
- `hermes_cli/main.py`: entry point and profile override.
- `hermes_cli/commands.py`: slash-command registry.
- `hermes_cli/config.py`: defaults, setup metadata, and merged configuration.
- `hermes_cli/curses_ui.py`: canonical interactive-menu implementation.

Read `hermes_cli/AGENTS.md` before changing these surfaces.

## Tools

Tools register through `tools/registry.py`. Built-in tools are discovered from
`tools/*.py`, but discovery does not expose them to an agent: their names must
also belong to a toolset in `toolsets.py`.

All handlers return JSON strings. Optional tools use requirement checks and are
absent when prerequisites are unavailable. State paths use
`get_hermes_home()`, and schema text uses `display_hermes_home()` for
profile-correct paths.

Prefer extending an existing tool, a CLI command plus skill, a gated tool,
plugin, or MCP server before adding a permanent core schema.

## User interfaces

- `ui-tui/`: Ink/React terminal UI.
- `tui_gateway/`: Python JSON-RPC backend for TUI clients.
- `web/`: dashboard frontend.
- `apps/desktop/`: Electron desktop client.
- `acp_adapter/`: editor integration through ACP.

The dashboard embeds the TUI through a PTY. Desktop is a separate client using
the shared gateway protocol. Read the nested guides under `ui-tui/` and
`apps/desktop/`.

## Gateway

- `gateway/run.py`: lifecycle, platform startup, command interception, and
background services.
- `gateway/session.py`: conversation routing and active sessions.
- `gateway/platforms/`: platform adapters.
- `gateway/config.py`: gateway-side configuration.

Adapters with unique credentials should acquire and release scoped token locks.
Control commands that must work while an agent is blocked need to bypass both
the base-adapter active-session queue and the runner's active-agent guard.

## Extensions

- `plugins/`: bundled plugin implementations and provider families.
- `skills/`: default skills.
- `optional-skills/`: opt-in skills.
- MCP catalog: reusable external structured tools.

Read the nested plugin and skill guides before editing these trees.

## Durable and background work

- `tools/delegate_tool.py`: process-local child-agent delegation.
- `cron/jobs.py` and `cron/scheduler.py`: durable scheduled work.
- `plugins/kanban/`: durable multi-agent board and dispatcher.
- `agent/curator.py`: lifecycle maintenance for agent-created skills.

Background delegation is detached from a turn but does not survive process
restart. Use cron or another durable mechanism when restart survival matters.
Leaf delegates cannot call `delegate_task`, `clarify`, `memory`,
`send_message`, or `cronjob`, but retain `execute_code` for programmatic tool
calling. Orchestrator delegates may spawn children within configured depth and
concurrency limits.
Kanban workers are board-isolated, and the dispatcher normally runs inside the
gateway.

## Configuration and state

`HERMES_HOME` is profile-specific. Use `get_hermes_home()` for runtime state and
`display_hermes_home()` in user-visible messages. Only profile discovery itself
is anchored to the default home.

User behavior is configured in `config.yaml`; `.env` contains secrets only.
Configuration has multiple loaders, so changes must be verified in each runtime
surface that consumes them.

## Testing

Read `tests/AGENTS.md`. Use `scripts/run_tests.sh`, temporary homes, behavioral
assertions, and real integration paths where discovery or configuration is
involved.
59 changes: 59 additions & 0 deletions hermes_cli/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Hermes CLI and Configuration Guide

These instructions apply under `hermes_cli/`.

## Commands

Slash commands are registered through `hermes_cli/commands.py`; do not add
another dispatch system. Commands declare aliases, gateway availability,
argument policy, and optional configuration gates. Keep aliases and discovery
data in the registry so CLI, gateway, help, and completion remain consistent.

Interactive menus should use `hermes_cli/curses_ui.py`. Do not add new
`simple_term_menu` call sites; existing uses are legacy fallback only.

## Configuration

Behavioral settings belong in `config.yaml`. `.env` is only for credentials:
API keys, tokens, and passwords.

For a new configuration key:

1. add it to `DEFAULT_CONFIG` in `hermes_cli/config.py`;
2. use deep-merge defaults for ordinary additions;
3. bump `_config_version` only for an active migration or structural change;
4. verify every runtime loader that consumes the setting.

Loaders differ:

- `load_cli_config()` serves interactive CLI mode;
- `load_config()` serves setup, tools, and most subcommands;
- gateway runtime also reads YAML through `gateway/run.py` and
`gateway/config.py`.

If CLI and gateway behavior disagree, trace the loaders before adding another
fallback.

Settings that internally require environment variables should be bridged from
`config.yaml`; user documentation must still point to YAML.

## Profile-safe paths

Use `get_hermes_home()` for state and `display_hermes_home()` for printed paths.
Do not hardcode `~/.hermes`.

Profile enumeration is intentionally anchored at
`Path.home() / ".hermes" / "profiles"` so every active profile can see its
siblings.

## Skins

Skins are data interpreted by `hermes_cli/skin_engine.py`. Add built-in skins
to `_BUILTIN_SKINS`; user skins load from `$HERMES_HOME/skins/*.yaml`.
Missing fields inherit from the default skin.

Do not add special-case rendering branches for a skin. New visual choices
should be represented in `SkinConfig` and consumed generically.

Validate CLI changes through the actual command entry point and configuration
loader, not only by constructing internal functions directly.
12 changes: 12 additions & 0 deletions optional-skills/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Optional Hermes Skills

The authoring standards in `../skills/AGENTS.md` apply here in full. Read that
file before changing an optional skill.

This tree is for dependency-heavy, platform-specific, experimental, or niche
skills that should not be active for every installation. Installation is
explicit through `hermes skills install official/<category>/<skill>`.

Do not move a skill into the default `skills/` tree merely to simplify setup.
First prove that its dependencies, platform coverage, prompt footprint, and
general usefulness justify default activation.
87 changes: 87 additions & 0 deletions plugins/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Hermes Plugin Development Guide

These instructions apply under `plugins/`. The root `AGENTS.md` remains
authoritative for cross-cutting policy.

## Boundary rule

Plugins must not modify core files such as `run_agent.py`, `cli.py`,
`gateway/run.py`, or `hermes_cli/main.py`. If a plugin needs something the
framework does not expose, add a generic hook, context method, or abstract
interface that can serve multiple plugins. Never hardcode one plugin into core.

Third-party product integrations do not belong in this repository. Vendor SaaS
connectors, observability backends, analytics products, and similar integrations
ship as standalone plugin repositories installed into `$HERMES_HOME/plugins/`
or via Python entry points. Existing in-tree integrations are not precedent for
adding more.

The in-tree memory-provider set is closed. New memory backends also ship as
standalone plugins; fixes to existing bundled providers remain welcome.

## General plugins

`hermes_cli/plugins.py` discovers:

1. bundled plugins under `<repo>/plugins/<name>/`;
2. user plugins under `$HERMES_HOME/plugins/<name>/`;
3. Python entry points in the `hermes_agent.plugins` group.

User plugins override bundled plugins of the same name.

A general plugin uses `plugin.yaml` and may register:

- lifecycle hooks;
- tools and toolsets;
- CLI commands;
- configuration defaults;
- setup steps or migrations.

Keep registration inside the plugin directory. If the plugin needs shared
surface, make that surface category-level and prove it with a real consumer.
Do not add speculative hooks.

## Memory providers

Memory providers implement the `MemoryProvider` abstract interface and register
through `plugins/memory/__init__.py`. Provider-specific CLI commands should be
exposed only when that provider is active so disabled providers do not clutter
help or command discovery.

Provider state must use `get_hermes_home()` and remain profile-local.

## Model providers

Model providers live under `plugins/model-providers/<name>/`. Their
`__init__.py` registers a `ProviderProfile`. Discovery is lazy and separate
from the general plugin manager:

1. bundled model providers;
2. user model providers;
3. legacy modules under `providers/`.

Registration is last-writer-wins, allowing user plugins to override bundled
profiles. The general plugin manager may record a `kind: model-provider`
manifest but must not import it a second time.

Full authoring documentation:
`website/docs/developer-guide/model-provider-plugin.md`.

## Other provider families

Context engines, image-generation providers, and similar families use an
abstract interface plus orchestrator and per-provider directories. Prefer that
pattern when three or more implementations share a category.

Reference/example plugins belong in the `hermes-example-plugins` companion
repository unless they are maintained, first-party runtime features.

## Review checklist

- No plugin-specific branch was added to core.
- State and configuration are profile-safe.
- Optional dependencies are gated and bounded.
- Tools are unavailable when prerequisites are absent.
- Setup uses existing Hermes configuration UX.
- The real discovery and registration path is tested.
- User plugins can override bundled implementations without double import.
72 changes: 72 additions & 0 deletions skills/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Hermes Skill Authoring Guide

These instructions apply to bundled skills under `skills/`. The same standards
apply to `optional-skills/`; niche or dependency-heavy skills belong there
instead of being active by default.

## Frontmatter

Use standard fields: `name`, `description`, `version`, `author`, `license`,
`platforms`, and `metadata.hermes` entries for tags, category, related skills,
and required configuration.

Hard requirements:

- `description` is one sentence, at most 60 characters, and ends with a period.
- State capability, not implementation; avoid marketing words.
- Credit the human contributor first in `author`.
- Audit `platforms` against actual scripts and imports.

POSIX-only primitives, `/proc`, hardcoded `/tmp`, `fcntl`, `termios`,
`os.setsid`, Unix signals, bash-only scripts, `osascript`, `apt`, or `systemctl`
require an appropriate platform declaration unless rewritten portably.

## Interaction surface

Skill prose should name native Hermes tools or explicitly required MCP servers.
Prefer `terminal`, `read_file`, `patch`, `search_files`, `web_extract`,
`vision_analyze`, `browser_navigate`, and `delegate_task` over presenting shell
utilities as the primary interface.

Third-party CLIs and pipelines are fine inside shipped scripts. Document MCP
prerequisites explicitly.

## Structure

Use this body order:

1. `# <Skill> Skill`
2. short introduction including what it does not do;
3. `## When to Use`;
4. `## Prerequisites`;
5. `## How to Run`;
6. `## Quick Reference`;
7. `## Procedure`;
8. `## Pitfalls`;
9. `## Verification`.

Target about 100 lines for a simple skill and 200 for a complex one. Remove
marketing prose and repeated environment-variable explanations.

Place non-trivial logic in `scripts/`, long-form material in `references/`, and
starter artifacts in `templates/`. Do not make the model recreate parsers,
walkers, or setup programs on every invocation.

## Tests

Tests live at `tests/skills/test_<skill>_skill.py`, use stdlib, pytest, and
`unittest.mock`, and make no live network calls.

```bash
scripts/run_tests.sh tests/skills/test_<skill>_skill.py -q
```

Keep `.env.example` edits inside a clearly delimited block for the skill and do
not rewrite unrelated surrounding content.

## External contributions

Load the `hermes-agent-dev` skill and read
`references/new-skill-pr-salvage.md` before modernizing an external skill PR.
Preserve human authorship and salvage useful contributor work rather than
reimplementing it.
Loading