{"owner":"NousResearch","repo":"hermes-agent","hasSkills":true,"totalSkillsCount":4,"totalTokensCount":3916,"categories":["root-instruction","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"hermes-agent":{"command":"npx","args":["-y","@modelcontextprotocol/server-hermes-agent"]}}},"found":["AGENTS.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# Hermes Agent - Development Guide\n\nFor AI coding assistants and developers working on hermes-agent. This root file is a hub: what\napplies everywhere, then a routing table. Each area's `AGENTS.md` loads automatically when you work\nin that directory; read it before editing there. `python scripts/check` caps this file at 12k chars\nand every root-to-area chain at 30k, so it loads whole on 128k+ models: long form goes in the guide.\n\n**Never give up on the right solution.**\n\n## What Hermes Is\n\nHermes is a personal AI agent that runs the same agent core across a CLI, a messaging\ngateway (Telegram, Discord, Slack, ~20 platforms), a TUI, and an Electron desktop app. It\nlearns across sessions (memory + skills), delegates to subagents, runs scheduled jobs, and\ndrives a real terminal and browser. It is extended primarily through **plugins and skills**,\nnot by growing the core.\n\nTwo invariants shape almost every design decision and are the lens for reviewing any change:\n\n- **Per-conversation prompt caching is sacred.** Mutating past context, swapping toolsets,\n  reloading memories or rebuilding the system prompt mid-conversation breaks the cached prefix and\n  multiplies the user's cost; the ONE exception is context compression. Slash commands that change\n  system-prompt state defer to the next session, with an opt-in `--now` (`/skills install --now`).\n- **The core is a narrow waist; capability lives at the edges.** Every model tool is sent on\n  every API call, so the bar for a new *core* tool is high. New capability should arrive as a\n  CLI command + skill, a service-gated tool, or a plugin — not as core surface.\n\n## Contribution rubric\n\nThe project's intent layer, for contributors and for the triage sweeper (which may only close on\n`implemented_on_main`, `cannot_reproduce` or `incoherent`; taste-based closes are a maintainer's\ncall, and when in doubt a PR stays open). Long form with examples:\n`website/docs/developer-guide/contributing.md` § Contribution rubric.\n\n**Wanted:** real bug fixes (repro on `main`, the exact line, the whole class incl. sibling paths);\nreach at the edges (adapters, providers, models, UI features) wired into the existing setup UX;\ngod-file → module refactors; extending before duplicating (3+ PRs in one category → an ABC +\norchestrator); behaviour-contract tests; E2E with real imports against a temp `HERMES_HOME` for\nresolution, config, security and I/O changes; salvage by cherry-pick so authorship survives.\n\n**Rejected even when well-built:** hooks with no concrete consumer; new `HERMES_*` env vars for\nnon-secret config (`.env` is secrets only, behaviour goes in `config.yaml`); a new core tool when\nterminal + file or a skill already does the job; `offset`/`limit` pagination on instructional tools;\n\"fixes\" that destroy the feature they secure; outbound telemetry without an opt-in gate;\nchange-detector tests; plugins that touch core files; third-party products in the core tree (ship a\nstandalone plugin repo).\n\n**Before you call it a bug,** verify the claim AND the intent (`git log -p -S \"<symbol>\"`): the\nisolation is often the design (profiles are islands on purpose), an absence can be load-bearing,\nand a fix that cannot point to the line where the bug manifests has an unverified premise.\n\n**Security:** `SECURITY.md` is the scope authority. A §3.1 finding goes private (GitHub Security\nAdvisories or security@nousresearch.com), never into a public issue, PR, commit or comment; §3.2\nhardening is ordinary public work. Name the §2 boundary crossed, with a repro on `main`.\n\n**Footprint ladder** (take the highest rung that solves it): extend existing code → CLI command +\nskill → service-gated tool (`check_fn` answers reachability/opt-in, never per-session surface:\n`tools/AGENTS.md`) → plugin → MCP server in the catalog → new core tool (fundamental, broadly useful,\nunreachable otherwise).\n\n## Development Environment\n\n`source ./activate` (fish: `activate.fish`, PowerShell: `activate.ps1`) provisions and activates the\nPM environment; pick an isolated `HERMES_HOME`/`HERMES_RUNTIME_DIR` first\n(`website/docs/reference/package-management.md#developer-workflow`). Tests need the separate test\nenvironment in `CONTRIBUTING.md`. **`python scripts/check`** runs every blocking lint check CI\nruns, with CI's pinned tools; `--install-hook pre-push` runs it on every push (re-run after\npulling to refresh the hook). `# noqa` does not waive a ratchet finding:\n`# health: allow <RULE> -- <why>` does.\n\n## Project Structure\n\nCounts shift constantly; the filesystem is canonical. Load-bearing entry points:\n\n```\nhermes-agent/\n├── run_agent.py          # AIAgent facade; the turn loop lives in agent/turn_*.py\n├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()\n├── toolsets.py           # TOOLSETS dict, _HERMES_CORE_TOOLS\n├── cli.py                # HermesCLI (REPL, slash dispatch) + hermes_cli/cli_*_mixin.py\n├── hermes_state.py       # SessionDB facade; hermes_state_*.py siblings\n├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths\n├── agent/                # turn loop phases, providers, memory, compression, prompt builder\n├── hermes_cli/           # CLI subcommands, setup, config, plugins loader, updater, web_routers/\n├── tools/                # Tool implementations (tools/registry.py) + environments/ backends\n├── gateway/              # run.py facade + run_*.py phases + session*.py + platforms/\n├── plugins/              # memory/, context_engine/, model-providers/, kanban/, image_gen/, ...\n├── skills/               # Built-in skills (by category)   optional-skills/: shipped, not active\n├── ui-tui/, tui_gateway/ # Ink terminal UI + its Python JSON-RPC backend (also serves Desktop)\n├── apps/desktop/         # Electron desktop app (+ apps/shared)   web/: dashboard SPA\n├── cron/                 # jobs.py + scheduler.py (+ scheduler_*.py)\n├── pm/, hermes_platform/ # dependency/environment manager; machine facts + executable lookup\n├── scripts/              # check, run_tests.sh, code_health/, ci/\n├── website/              # Docusaurus docs (developer-guide/ holds the long-form area docs)\n└── tests/                # Pytest suite, mirrors the source tree\n```\n\n**User state:** `~/.hermes/config.yaml` (settings), `.env` (secrets only), `logs/` (`hermes logs`);\nall profile-aware via `get_hermes_home()`.\n\n### Facade + siblings layout\n\nEvery former god file is a **facade** (public entry points + the names other packages import) plus\n**siblings** `<stem>_<topic>.py`, each owning one topic (`hermes_state.py`, `gateway/run.py`,\n`tools/mcp_tool.py`, `hermes_cli/kanban.py`, `hermes_cli/web_server.py`, `cli.py` →\n`hermes_cli/cli_*_mixin.py`, `run_agent.py` → `agent/turn_*.py`).\n\n- **Find code by topic:** `grep -rn \"def name\" <dir>/<stem>_*.py`, not by reading the facade.\n- **Siblings late-import the facade** inside functions; never a module-level cycle.\n- **Patch where production reads:** a sibling doing `from <facade> import name` inside the function\n  makes the facade the seam; a patch on the defining module passes silently.\n- **Size and complexity are ratcheted per unit** (`scripts/code_health/config.py`): new functions\n  CC ≤ 20, ≤ 300 lines, nesting ≤ 6; files ≤ 2,000 lines; units already over may only go down (move\n  a function into a sibling to offset growth, or put new tests in a new test file). Behaviour goes\n  in a sibling, never a facade; name ladders become a dict → handler.\n- **No re-export shims for internal moves;** internal paths are not API. Moving a symbol means\n  fixing its docs in the same PR (grep `website/docs`, `skills/`, every `AGENTS.md`).\n\n## Rules that apply everywhere\n\n- **No defensive clutter:** no wrappers or `try/except: pass` around code that cannot fail, no flags\n  nobody sets, no dead code wired in without E2E proof. Comments keep the WHY, cut the WHAT.\n- **Never infer process identity from argv substrings;** use\n  `gateway.status.looks_like_gateway_command_line` / `hermes_cli.update_cmd._hermes_holder_subcommand`\n  (HX003; details `hermes_cli/AGENTS.md`).\n- **Never hardcode `~/.hermes`:** `get_hermes_home()` for paths, `display_hermes_home()` for text\n  (HX001). `_get_profiles_root()` is HOME-anchored on purpose.\n- **One process serves many profiles.** Code that runs outside a turn (boot probes, eviction,\n  tickers, deferred callbacks, RPC methods, thread hops, child spawns) binds the owning profile scope\n  explicitly; `os.environ`, module globals and import-time values hold the launch profile's, so an\n  unbound read is a silent default-profile leak. Binding points and seams: `gateway/AGENTS.md`\n  § Profile scope (HX002/HX004/HX005/HX012, PS-P05/P06).\n- **Machine facts and executable lookup go through `hermes_platform`** (`hermes_platform/AGENTS.md`).\n- **Dependencies carry upper bounds** (`>=floor,<next_major`; git URLs and Actions pinned to a SHA);\n  after editing `pyproject.toml` run `hermes pm lock` and commit `uv.lock`; never mutate a Hermes\n  environment with raw pip/uv. Full policy: `pm/AGENTS.md`.\n- **TypeScript (desktop, TUI, website):** feature-owned nanostores over threaded state, thin route\n  roots, narrow hooks and colocated action modules, `interface` for props and shared shapes,\n  table-driven dispatch over condition ladders; `src/app` routes, `src/store` atoms, `src/lib` pure\n  helpers.\n- **Commits and PRs:** rebase onto `main` before merging (a squash from a stale branch silently\n  reverts newer fixes); 1–2 invariant tests per fix, proven red on the base.\n- **Tests:** always `scripts/run_tests.sh`, never bare `pytest`; behaviour contracts, never\n  change-detectors or source-reading tests; host-specific behaviour is tested on that host with\n  `@pytest.mark.platforms(...)`, never by faking `sys.platform`; tests never write to `~/.hermes/`.\n  Everything else: `tests/AGENTS.md`.\n\n## Routing Table — working in X → read X/AGENTS.md\n\n| Area | Read | Covers |\n|---|---|---|\n| `run_agent.py`, `agent/` | `agent/AGENTS.md` | turn phases, caching and message-flow invariants, compression, model/aux resolution |\n| `cli.py`, `hermes_cli/` | `hermes_cli/AGENTS.md` | CLI mixins, slash registry, config system, skins, `hermes update`, profiles / multiplex |\n| `gateway/` | `gateway/AGENTS.md` | adapters, message guards, streaming, notifications, token locks, § Profile scope |\n| `gateway/platforms/` new adapter | `gateway/platforms/ADDING_A_PLATFORM.md` | step-by-step adapter guide |\n| `tools/`, `toolsets.py`, `model_tools.py` | `tools/AGENTS.md` | adding tools, registry, toolsets, delegation, session-scoped surface tools |\n| `plugins/`, `hermes_cli/plugins*.py` | `plugins/AGENTS.md` | plugin kinds, native compat contract, in-tree policy |\n| `plugin-catalog/` | `plugin-catalog/README.md` | catalog admission rules (mirrored in the developer guide; keep identical) |\n| `tui_gateway/`, `ui-tui/` | `tui_gateway/AGENTS.md` | process model, JSON-RPC transport, slash flow |\n| `web/`, `hermes_cli/web_routers/` | `web/AGENTS.md` | dashboard embeds the real TUI |\n| `apps/desktop/` | `apps/desktop/AGENTS.md`, `apps/desktop/src/AGENTS.md` | `serve` backend, slash palette, Bot Mode |\n| `skills/`, `optional-skills/`, `agent/curator*.py` | `skills/AGENTS.md` | frontmatter, authoring standards, curator |\n| `cron/`, kanban | `cron/AGENTS.md` | scheduler invariants, job fields, kanban dispatcher |\n| `tests/` | `tests/AGENTS.md` | runner, placement, OS markers, `wine2e`, banned test shapes |\n| `pm/`, `pyproject.toml` | `pm/AGENTS.md` | pinning policy, PM-owned environments, plugin quarantine |\n| `hermes_platform/` | `hermes_platform/AGENTS.md` | host facts, resolvers |\n\nLong-form background: `website/docs/developer-guide/`. Workflow rules (PR/issue/review/salvage\nprocess) live in the `hermes-agent-dev` skill, not here.\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# Hermes Agent - Development Guide\n\nFor AI coding assistants and developers working on hermes-agent. This root file is a hub: what\napplies everywhere, then a routing table. Each area's `AGENTS.md` loads automatically when you work\nin that directory; read it before editing there. `python scripts/check` caps this file at 12k chars\nand every root-to-area chain at 30k, so it loads whole on 128k+ models: long form goes in the guide.\n\n**Never give up on the right solution.**\n\n## What Hermes Is\n\nHermes is a personal AI agent that runs the same agent core across a CLI, a messaging\ngateway (Telegram, Discord, Slack, ~20 platforms), a TUI, and an Electron desktop app. It\nlearns across sessions (memory + skills), delegates to subagents, runs scheduled jobs, and\ndrives a real terminal and browser. It is extended primarily through **plugins and skills**,\nnot by growing the core.\n\nTwo invariants shape almost every design decision and are the lens for reviewing any change:\n\n- **Per-conversation prompt caching is sacred.** Mutating past context, swapping toolsets,\n  reloading memories or rebuilding the system prompt mid-conversation breaks the cached prefix and\n  multiplies the user's cost; the ONE exception is context compression. Slash commands that change\n  system-prompt state defer to the next session, with an opt-in `--now` (`/skills install --now`).\n- **The core is a narrow waist; capability lives at the edges.** Every model tool is sent on\n  every API call, so the bar for a new *core* tool is high. New capability should arrive as a\n  CLI command + skill, a service-gated tool, or a plugin — not as core surface.\n\n## Contribution rubric\n\nThe project's intent layer, for contributors and for the triage sweeper (which may only close on\n`implemented_on_main`, `cannot_reproduce` or `incoherent`; taste-based closes are a maintainer's\ncall, and when in doubt a PR stays open). Long form with examples:\n`website/docs/developer-guide/contributing.md` § Contribution rubric.\n\n**Wanted:** real bug fixes (repro on `main`, the exact line, the whole class incl. sibling paths);\nreach at the edges (adapters, providers, models, UI features) wired into the existing setup UX;\ngod-file → module refactors; extending before duplicating (3+ PRs in one category → an ABC +\norchestrator); behaviour-contract tests; E2E with real imports against a temp `HERMES_HOME` for\nresolution, config, security and I/O changes; salvage by cherry-pick so authorship survives.\n\n**Rejected even when well-built:** hooks with no concrete consumer; new `HERMES_*` env vars for\nnon-secret config (`.env` is secrets only, behaviour goes in `config.yaml`); a new core tool when\nterminal + file or a skill already does the job; `offset`/`limit` pagination on instructional tools;\n\"fixes\" that destroy the feature they secure; outbound telemetry without an opt-in gate;\nchange-detector tests; plugins that touch core files; third-party products in the core tree (ship a\nstandalone plugin repo).\n\n**Before you call it a bug,** verify the claim AND the intent (`git log -p -S \"<symbol>\"`): the\nisolation is often the design (profiles are islands on purpose), an absence can be load-bearing,\nand a fix that cannot point to the line where the bug manifests has an unverified premise.\n\n**Security:** `SECURITY.md` is the scope authority. A §3.1 finding goes private (GitHub Security\nAdvisories or security@nousresearch.com), never into a public issue, PR, commit or comment; §3.2\nhardening is ordinary public work. Name the §2 boundary crossed, with a repro on `main`.\n\n**Footprint ladder** (take the highest rung that solves it): extend existing code → CLI command +\nskill → service-gated tool (`check_fn` answers reachability/opt-in, never per-session surface:\n`tools/AGENTS.md`) → plugin → MCP server in the catalog → new core tool (fundamental, broadly useful,\nunreachable otherwise).\n\n## Development Environment\n\n`source ./activate` (fish: `activate.fish`, PowerShell: `activate.ps1`) provisions and activates the\nPM environment; pick an isolated `HERMES_HOME`/`HERMES_RUNTIME_DIR` first\n(`website/docs/reference/package-management.md#developer-workflow`). Tests need the separate test\nenvironment in `CONTRIBUTING.md`. **`python scripts/check`** runs every blocking lint check CI\nruns, with CI's pinned tools; `--install-hook pre-push` runs it on every push (re-run after\npulling to refresh the hook). `# noqa` does not waive a ratchet finding:\n`# health: allow <RULE> -- <why>` does.\n\n## Project Structure\n\nCounts shift constantly; the filesystem is canonical. Load-bearing entry points:\n\n```\nhermes-agent/\n├── run_agent.py          # AIAgent facade; the turn loop lives in agent/turn_*.py\n├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()\n├── toolsets.py           # TOOLSETS dict, _HERMES_CORE_TOOLS\n├── cli.py                # HermesCLI (REPL, slash dispatch) + hermes_cli/cli_*_mixin.py\n├── hermes_state.py       # SessionDB facade; hermes_state_*.py siblings\n├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths\n├── agent/                # turn loop phases, providers, memory, compression, prompt builder\n├── hermes_cli/           # CLI subcommands, setup, config, plugins loader, updater, web_routers/\n├── tools/                # Tool implementations (tools/registry.py) + environments/ backends\n├── gateway/              # run.py facade + run_*.py phases + session*.py + platforms/\n├── plugins/              # memory/, context_engine/, model-providers/, kanban/, image_gen/, ...\n├── skills/               # Built-in skills (by category)   optional-skills/: shipped, not active\n├── ui-tui/, tui_gateway/ # Ink terminal UI + its Python JSON-RPC backend (also serves Desktop)\n├── apps/desktop/         # Electron desktop app (+ apps/shared)   web/: dashboard SPA\n├── cron/                 # jobs.py + scheduler.py (+ scheduler_*.py)\n├── pm/, hermes_platform/ # dependency/environment manager; machine facts + executable lookup\n├── scripts/              # check, run_tests.sh, code_health/, ci/\n├── website/              # Docusaurus docs (developer-guide/ holds the long-form area docs)\n└── tests/                # Pytest suite, mirrors the source tree\n```\n\n**User state:** `~/.hermes/config.yaml` (settings), `.env` (secrets only), `logs/` (`hermes logs`);\nall profile-aware via `get_hermes_home()`.\n\n### Facade + siblings layout\n\nEvery former god file is a **facade** (public entry points + the names other packages import) plus\n**siblings** `<stem>_<topic>.py`, each owning one topic (`hermes_state.py`, `gateway/run.py`,\n`tools/mcp_tool.py`, `hermes_cli/kanban.py`, `hermes_cli/web_server.py`, `cli.py` →\n`hermes_cli/cli_*_mixin.py`, `run_agent.py` → `agent/turn_*.py`).\n\n- **Find code by topic:** `grep -rn \"def name\" <dir>/<stem>_*.py`, not by reading the facade.\n- **Siblings late-import the facade** inside functions; never a module-level cycle.\n- **Patch where production reads:** a sibling doing `from <facade> import name` inside the function\n  makes the facade the seam; a patch on the defining module passes silently.\n- **Size and complexity are ratcheted per unit** (`scripts/code_health/config.py`): new functions\n  CC ≤ 20, ≤ 300 lines, nesting ≤ 6; files ≤ 2,000 lines; units already over may only go down (move\n  a function into a sibling to offset growth, or put new tests in a new test file). Behaviour goes\n  in a sibling, never a facade; name ladders become a dict → handler.\n- **No re-export shims for internal moves;** internal paths are not API. Moving a symbol means\n  fixing its docs in the same PR (grep `website/docs`, `skills/`, every `AGENTS.md`).\n\n## Rules that apply everywhere\n\n- **No defensive clutter:** no wrappers or `try/except: pass` around code that cannot fail, no flags\n  nobody sets, no dead code wired in without E2E proof. Comments keep the WHY, cut the WHAT.\n- **Never infer process identity from argv substrings;** use\n  `gateway.status.looks_like_gateway_command_line` / `hermes_cli.update_cmd._hermes_holder_subcommand`\n  (HX003; details `hermes_cli/AGENTS.md`).\n- **Never hardcode `~/.hermes`:** `get_hermes_home()` for paths, `display_hermes_home()` for text\n  (HX001). `_get_profiles_root()` is HOME-anchored on purpose.\n- **One process serves many profiles.** Code that runs outside a turn (boot probes, eviction,\n  tickers, deferred callbacks, RPC methods, thread hops, child spawns) binds the owning profile scope\n  explicitly; `os.environ`, module globals and import-time values hold the launch profile's, so an\n  unbound read is a silent default-profile leak. Binding points and seams: `gateway/AGENTS.md`\n  § Profile scope (HX002/HX004/HX005/HX012, PS-P05/P06).\n- **Machine facts and executable lookup go through `hermes_platform`** (`hermes_platform/AGENTS.md`).\n- **Dependencies carry upper bounds** (`>=floor,<next_major`; git URLs and Actions pinned to a SHA);\n  after editing `pyproject.toml` run `hermes pm lock` and commit `uv.lock`; never mutate a Hermes\n  environment with raw pip/uv. Full policy: `pm/AGENTS.md`.\n- **TypeScript (desktop, TUI, website):** feature-owned nanostores over threaded state, thin route\n  roots, narrow hooks and colocated action modules, `interface` for props and shared shapes,\n  table-driven dispatch over condition ladders; `src/app` routes, `src/store` atoms, `src/lib` pure\n  helpers.\n- **Commits and PRs:** rebase onto `main` before merging (a squash from a stale branch silently\n  reverts newer fixes); 1–2 invariant tests per fix, proven red on the base.\n- **Tests:** always `scripts/run_tests.sh`, never bare `pytest`; behaviour contracts, never\n  change-detectors or source-reading tests; host-specific behaviour is tested on that host with\n  `@pytest.mark.platforms(...)`, never by faking `sys.platform`; tests never write to `~/.hermes/`.\n  Everything else: `tests/AGENTS.md`.\n\n## Routing Table — working in X → read X/AGENTS.md\n\n| Area | Read | Covers |\n|---|---|---|\n| `run_agent.py`, `agent/` | `agent/AGENTS.md` | turn phases, caching and message-flow invariants, compression, model/aux resolution |\n| `cli.py`, `hermes_cli/` | `hermes_cli/AGENTS.md` | CLI mixins, slash registry, config system, skins, `hermes update`, profiles / multiplex |\n| `gateway/` | `gateway/AGENTS.md` | adapters, message guards, streaming, notifications, token locks, § Profile scope |\n| `gateway/platforms/` new adapter | `gateway/platforms/ADDING_A_PLATFORM.md` | step-by-step adapter guide |\n| `tools/`, `toolsets.py`, `model_tools.py` | `tools/AGENTS.md` | adding tools, registry, toolsets, delegation, session-scoped surface tools |\n| `plugins/`, `hermes_cli/plugins*.py` | `plugins/AGENTS.md` | plugin kinds, native compat contract, in-tree policy |\n| `plugin-catalog/` | `plugin-catalog/README.md` | catalog admission rules (mirrored in the developer guide; keep identical) |\n| `tui_gateway/`, `ui-tui/` | `tui_gateway/AGENTS.md` | process model, JSON-RPC transport, slash flow |\n| `web/`, `hermes_cli/web_routers/` | `web/AGENTS.md` | dashboard embeds the real TUI |\n| `apps/desktop/` | `apps/desktop/AGENTS.md`, `apps/desktop/src/AGENTS.md` | `serve` backend, slash palette, Bot Mode |\n| `skills/`, `optional-skills/`, `agent/curator*.py` | `skills/AGENTS.md` | frontmatter, authoring standards, curator |\n| `cron/`, kanban | `cron/AGENTS.md` | scheduler invariants, job fields, kanban dispatcher |\n| `tests/` | `tests/AGENTS.md` | runner, placement, OS markers, `wine2e`, banned test shapes |\n| `pm/`, `pyproject.toml` | `pm/AGENTS.md` | pinning policy, PM-owned environments, plugin quarantine |\n| `hermes_platform/` | `hermes_platform/AGENTS.md` | host facts, resolvers |\n\nLong-form background: `website/docs/developer-guide/`. Workflow rules (PR/issue/review/salvage\nprocess) live in the `hermes-agent-dev` skill, not here.\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Hermes Agent - Development Guide\n\nFor AI coding assistants and developers working on hermes-agent. This root file is a hub: what\napplies everywhere, then a routing table. Each area's `AGENTS.md` loads automatically when you work\nin that directory; read it before editing there. `python scripts/check` caps this file at 12k chars\nand every root-to-area chain at 30k, so it loads whole on 128k+ models: long form goes in the guide.\n\n**Never give up on the right solution.**\n\n## What Hermes Is\n\nHermes is a personal AI agent that runs the same agent core across a CLI, a messaging\ngateway (Telegram, Discord, Slack, ~20 platforms), a TUI, and an Electron desktop app. It\nlearns across sessions (memory + skills), delegates to subagents, runs scheduled jobs, and\ndrives a real terminal and browser. It is extended primarily through **plugins and skills**,\nnot by growing the core.\n\nTwo invariants shape almost every design decision and are the lens for reviewing any change:\n\n- **Per-conversation prompt caching is sacred.** Mutating past context, swapping toolsets,\n  reloading memories or rebuilding the system prompt mid-conversation breaks the cached prefix and\n  multiplies the user's cost; the ONE exception is context compression. Slash commands that change\n  system-prompt state defer to the next session, with an opt-in `--now` (`/skills install --now`).\n- **The core is a narrow waist; capability lives at the edges.** Every model tool is sent on\n  every API call, so the bar for a new *core* tool is high. New capability should arrive as a\n  CLI command + skill, a service-gated tool, or a plugin — not as core surface.\n\n## Contribution rubric\n\nThe project's intent layer, for contributors and for the triage sweeper (which may only close on\n`implemented_on_main`, `cannot_reproduce` or `incoherent`; taste-based closes are a maintainer's\ncall, and when in doubt a PR stays open). Long form with examples:\n`website/docs/developer-guide/contributing.md` § Contribution rubric.\n\n**Wanted:** real bug fixes (repro on `main`, the exact line, the whole class incl. sibling paths);\nreach at the edges (adapters, providers, models, UI features) wired into the existing setup UX;\ngod-file → module refactors; extending before duplicating (3+ PRs in one category → an ABC +\norchestrator); behaviour-contract tests; E2E with real imports against a temp `HERMES_HOME` for\nresolution, config, security and I/O changes; salvage by cherry-pick so authorship survives.\n\n**Rejected even when well-built:** hooks with no concrete consumer; new `HERMES_*` env vars for\nnon-secret config (`.env` is secrets only, behaviour goes in `config.yaml`); a new core tool when\nterminal + file or a skill already does the job; `offset`/`limit` pagination on instructional tools;\n\"fixes\" that destroy the feature they secure; outbound telemetry without an opt-in gate;\nchange-detector tests; plugins that touch core files; third-party products in the core tree (ship a\nstandalone plugin repo).\n\n**Before you call it a bug,** verify the claim AND the intent (`git log -p -S \"<symbol>\"`): the\nisolation is often the design (profiles are islands on purpose), an absence can be load-bearing,\nand a fix that cannot point to the line where the bug manifests has an unverified premise.\n\n**Security:** `SECURITY.md` is the scope authority. A §3.1 finding goes private (GitHub Security\nAdvisories or security@nousresearch.com), never into a public issue, PR, commit or comment; §3.2\nhardening is ordinary public work. Name the §2 boundary crossed, with a repro on `main`.\n\n**Footprint ladder** (take the highest rung that solves it): extend existing code → CLI command +\nskill → service-gated tool (`check_fn` answers reachability/opt-in, never per-session surface:\n`tools/AGENTS.md`) → plugin → MCP server in the catalog → new core tool (fundamental, broadly useful,\nunreachable otherwise).\n\n## Development Environment\n\n`source ./activate` (fish: `activate.fish`, PowerShell: `activate.ps1`) provisions and activates the\nPM environment; pick an isolated `HERMES_HOME`/`HERMES_RUNTIME_DIR` first\n(`website/docs/reference/package-management.md#developer-workflow`). Tests need the separate test\nenvironment in `CONTRIBUTING.md`. **`python scripts/check`** runs every blocking lint check CI\nruns, with CI's pinned tools; `--install-hook pre-push` runs it on every push (re-run after\npulling to refresh the hook). `# noqa` does not waive a ratchet finding:\n`# health: allow <RULE> -- <why>` does.\n\n## Project Structure\n\nCounts shift constantly; the filesystem is canonical. Load-bearing entry points:\n\n```\nhermes-agent/\n├── run_agent.py          # AIAgent facade; the turn loop lives in agent/turn_*.py\n├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()\n├── toolsets.py           # TOOLSETS dict, _HERMES_CORE_TOOLS\n├── cli.py                # HermesCLI (REPL, slash dispatch) + hermes_cli/cli_*_mixin.py\n├── hermes_state.py       # SessionDB facade; hermes_state_*.py siblings\n├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths\n├── agent/                # turn loop phases, providers, memory, compression, prompt builder\n├── hermes_cli/           # CLI subcommands, setup, config, plugins loader, updater, web_routers/\n├── tools/                # Tool implementations (tools/registry.py) + environments/ backends\n├── gateway/              # run.py facade + run_*.py phases + session*.py + platforms/\n├── plugins/              # memory/, context_engine/, model-providers/, kanban/, image_gen/, ...\n├── skills/               # Built-in skills (by category)   optional-skills/: shipped, not active\n├── ui-tui/, tui_gateway/ # Ink terminal UI + its Python JSON-RPC backend (also serves Desktop)\n├── apps/desktop/         # Electron desktop app (+ apps/shared)   web/: dashboard SPA\n├── cron/                 # jobs.py + scheduler.py (+ scheduler_*.py)\n├── pm/, hermes_platform/ # dependency/environment manager; machine facts + executable lookup\n├── scripts/              # check, run_tests.sh, code_health/, ci/\n├── website/              # Docusaurus docs (developer-guide/ holds the long-form area docs)\n└── tests/                # Pytest suite, mirrors the source tree\n```\n\n**User state:** `~/.hermes/config.yaml` (settings), `.env` (secrets only), `logs/` (`hermes logs`);\nall profile-aware via `get_hermes_home()`.\n\n### Facade + siblings layout\n\nEvery former god file is a **facade** (public entry points + the names other packages import) plus\n**siblings** `<stem>_<topic>.py`, each owning one topic (`hermes_state.py`, `gateway/run.py`,\n`tools/mcp_tool.py`, `hermes_cli/kanban.py`, `hermes_cli/web_server.py`, `cli.py` →\n`hermes_cli/cli_*_mixin.py`, `run_agent.py` → `agent/turn_*.py`).\n\n- **Find code by topic:** `grep -rn \"def name\" <dir>/<stem>_*.py`, not by reading the facade.\n- **Siblings late-import the facade** inside functions; never a module-level cycle.\n- **Patch where production reads:** a sibling doing `from <facade> import name` inside the function\n  makes the facade the seam; a patch on the defining module passes silently.\n- **Size and complexity are ratcheted per unit** (`scripts/code_health/config.py`): new functions\n  CC ≤ 20, ≤ 300 lines, nesting ≤ 6; files ≤ 2,000 lines; units already over may only go down (move\n  a function into a sibling to offset growth, or put new tests in a new test file). Behaviour goes\n  in a sibling, never a facade; name ladders become a dict → handler.\n- **No re-export shims for internal moves;** internal paths are not API. Moving a symbol means\n  fixing its docs in the same PR (grep `website/docs`, `skills/`, every `AGENTS.md`).\n\n## Rules that apply everywhere\n\n- **No defensive clutter:** no wrappers or `try/except: pass` around code that cannot fail, no flags\n  nobody sets, no dead code wired in without E2E proof. Comments keep the WHY, cut the WHAT.\n- **Never infer process identity from argv substrings;** use\n  `gateway.status.looks_like_gateway_command_line` / `hermes_cli.update_cmd._hermes_holder_subcommand`\n  (HX003; details `hermes_cli/AGENTS.md`).\n- **Never hardcode `~/.hermes`:** `get_hermes_home()` for paths, `display_hermes_home()` for text\n  (HX001). `_get_profiles_root()` is HOME-anchored on purpose.\n- **One process serves many profiles.** Code that runs outside a turn (boot probes, eviction,\n  tickers, deferred callbacks, RPC methods, thread hops, child spawns) binds the owning profile scope\n  explicitly; `os.environ`, module globals and import-time values hold the launch profile's, so an\n  unbound read is a silent default-profile leak. Binding points and seams: `gateway/AGENTS.md`\n  § Profile scope (HX002/HX004/HX005/HX012, PS-P05/P06).\n- **Machine facts and executable lookup go through `hermes_platform`** (`hermes_platform/AGENTS.md`).\n- **Dependencies carry upper bounds** (`>=floor,<next_major`; git URLs and Actions pinned to a SHA);\n  after editing `pyproject.toml` run `hermes pm lock` and commit `uv.lock`; never mutate a Hermes\n  environment with raw pip/uv. Full policy: `pm/AGENTS.md`.\n- **TypeScript (desktop, TUI, website):** feature-owned nanostores over threaded state, thin route\n  roots, narrow hooks and colocated action modules, `interface` for props and shared shapes,\n  table-driven dispatch over condition ladders; `src/app` routes, `src/store` atoms, `src/lib` pure\n  helpers.\n- **Commits and PRs:** rebase onto `main` before merging (a squash from a stale branch silently\n  reverts newer fixes); 1–2 invariant tests per fix, proven red on the base.\n- **Tests:** always `scripts/run_tests.sh`, never bare `pytest`; behaviour contracts, never\n  change-detectors or source-reading tests; host-specific behaviour is tested on that host with\n  `@pytest.mark.platforms(...)`, never by faking `sys.platform`; tests never write to `~/.hermes/`.\n  Everything else: `tests/AGENTS.md`.\n\n## Routing Table — working in X → read X/AGENTS.md\n\n| Area | Read | Covers |\n|---|---|---|\n| `run_agent.py`, `agent/` | `agent/AGENTS.md` | turn phases, caching and message-flow invariants, compression, model/aux resolution |\n| `cli.py`, `hermes_cli/` | `hermes_cli/AGENTS.md` | CLI mixins, slash registry, config system, skins, `hermes update`, profiles / multiplex |\n| `gateway/` | `gateway/AGENTS.md` | adapters, message guards, streaming, notifications, token locks, § Profile scope |\n| `gateway/platforms/` new adapter | `gateway/platforms/ADDING_A_PLATFORM.md` | step-by-step adapter guide |\n| `tools/`, `toolsets.py`, `model_tools.py` | `tools/AGENTS.md` | adding tools, registry, toolsets, delegation, session-scoped surface tools |\n| `plugins/`, `hermes_cli/plugins*.py` | `plugins/AGENTS.md` | plugin kinds, native compat contract, in-tree policy |\n| `plugin-catalog/` | `plugin-catalog/README.md` | catalog admission rules (mirrored in the developer guide; keep identical) |\n| `tui_gateway/`, `ui-tui/` | `tui_gateway/AGENTS.md` | process model, JSON-RPC transport, slash flow |\n| `web/`, `hermes_cli/web_routers/` | `web/AGENTS.md` | dashboard embeds the real TUI |\n| `apps/desktop/` | `apps/desktop/AGENTS.md`, `apps/desktop/src/AGENTS.md` | `serve` backend, slash palette, Bot Mode |\n| `skills/`, `optional-skills/`, `agent/curator*.py` | `skills/AGENTS.md` | frontmatter, authoring standards, curator |\n| `cron/`, kanban | `cron/AGENTS.md` | scheduler invariants, job fields, kanban dispatcher |\n| `tests/` | `tests/AGENTS.md` | runner, placement, OS markers, `wine2e`, banned test shapes |\n| `pm/`, `pyproject.toml` | `pm/AGENTS.md` | pinning policy, PM-owned environments, plugin quarantine |\n| `hermes_platform/` | `hermes_platform/AGENTS.md` | host facts, resolvers |\n\nLong-form background: `website/docs/developer-guide/`. Workflow rules (PR/issue/review/salvage\nprocess) live in the `hermes-agent-dev` skill, not here.\n","isInternal":false,"tokens":3016,"sizeBytes":11952},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":204},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":190},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":183}],"systemPromptSnippet":"<yakaai_skills repo=\"NousResearch/hermes-agent\">\n<!-- File: AGENTS.md (Tokens: ~3016 | Category: root-instruction) -->\n# Hermes Agent - Development Guide\n\nFor AI coding assistants and developers working on hermes-agent. This root file is a hub: what\napplies everywhere, then a routing table. Each area's `AGENTS.md` loads automatically when you work\nin that directory; read it before editing there. `python scripts/check` caps this file at 12k chars\nand every root-to-area chain at 30k, so it loads whole on 128k+ models: long form goes in the guide.\n\n**Never give up on the right solution.**\n\n## What Hermes Is\n\nHermes is a personal AI agent that runs the same agent core across a CLI, a messaging\ngateway (Telegram, Discord, Slack, ~20 platforms), a TUI, and an Electron desktop app. It\nlearns across sessions (memory + skills), delegates to subagents, runs scheduled jobs, and\ndrives a real terminal and browser. It is extended primarily through **plugins and skills**,\nnot by growing the core.\n\nTwo invariants shape almost every design decision and are the lens for reviewing any change:\n\n- **Per-conversation prompt caching is sacred.** Mutating past context, swapping toolsets,\n  reloading memories or rebuilding the system prompt mid-conversation breaks the cached prefix and\n  multiplies the user's cost; the ONE exception is context compression. Slash commands that change\n  system-prompt state defer to the next session, with an opt-in `--now` (`/skills install --now`).\n- **The core is a narrow waist; capability lives at the edges.** Every model tool is sent on\n  every API call, so the bar for a new *core* tool is high. New capability should arrive as a\n  CLI command + skill, a service-gated tool, or a plugin — not as core surface.\n\n## Contribution rubric\n\nThe project's intent layer, for contributors and for the triage sweeper (which may only close on\n`implemented_on_main`, `cannot_reproduce` or `incoherent`; taste-based closes are a maintainer's\ncall, and when in doubt a PR stays open). Long form with examples:\n`website/docs/developer-guide/contributing.md` § Contribution rubric.\n\n**Wanted:** real bug fixes (repro on `main`, the exact line, the whole class incl. sibling paths);\nreach at the edges (adapters, providers, models, UI features) wired into the existing setup UX;\ngod-file → module refactors; extending before duplicating (3+ PRs in one category → an ABC +\norchestrator); behaviour-contract tests; E2E with real imports against a temp `HERMES_HOME` for\nresolution, config, security and I/O changes; salvage by cherry-pick so authorship survives.\n\n**Rejected even when well-built:** hooks with no concrete consumer; new `HERMES_*` env vars for\nnon-secret config (`.env` is secrets only, behaviour goes in `config.yaml`); a new core tool when\nterminal + file or a skill already does the job; `offset`/`limit` pagination on instructional tools;\n\"fixes\" that destroy the feature they secure; outbound telemetry without an opt-in gate;\nchange-detector tests; plugins that touch core files; third-party products in the core tree (ship a\nstandalone plugin repo).\n\n**Before you call it a bug,** verify the claim AND the intent (`git log -p -S \"<symbol>\"`): the\nisolation is often the design (profiles are islands on purpose), an absence can be load-bearing,\nand a fix that cannot point to the line where the bug manifests has an unverified premise.\n\n**Security:** `SECURITY.md` is the scope authority. A §3.1 finding goes private (GitHub Security\nAdvisories or security@nousresearch.com), never into a public issue, PR, commit or comment; §3.2\nhardening is ordinary public work. Name the §2 boundary crossed, with a repro on `main`.\n\n**Footprint ladder** (take the highest rung that solves it): extend existing code → CLI command +\nskill → service-gated tool (`check_fn` answers reachability/opt-in, never per-session surface:\n`tools/AGENTS.md`) → plugin → MCP server in the catalog → new core tool (fundamental, broadly useful,\nunreachable otherwise).\n\n## Development Environment\n\n`source ./activate` (fish: `activate.fish`, PowerShell: `activate.ps1`) provisions and activates the\nPM environment; pick an isolated `HERMES_HOME`/`HERMES_RUNTIME_DIR` first\n(`website/docs/reference/package-management.md#developer-workflow`). Tests need the separate test\nenvironment in `CONTRIBUTING.md`. **`python scripts/check`** runs every blocking lint check CI\nruns, with CI's pinned tools; `--install-hook pre-push` runs it on every push (re-run after\npulling to refresh the hook). `# noqa` does not waive a ratchet finding:\n`# health: allow <RULE> -- <why>` does.\n\n## Project Structure\n\nCounts shift constantly; the filesystem is canonical. Load-bearing entry points:\n\n```\nhermes-agent/\n├── run_agent.py          # AIAgent facade; the turn loop lives in agent/turn_*.py\n├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()\n├── toolsets.py           # TOOLSETS dict, _HERMES_CORE_TOOLS\n├── cli.py                # HermesCLI (REPL, slash dispatch) + hermes_cli/cli_*_mixin.py\n├── hermes_state.py       # SessionDB facade; hermes_state_*.py siblings\n├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths\n├── agent/                # turn loop phases, providers, memory, compression, prompt builder\n├── hermes_cli/           # CLI subcommands, setup, config, plugins loader, updater, web_routers/\n├── tools/                # Tool implementations (tools/registry.py) + environments/ backends\n├── gateway/              # run.py facade + run_*.py phases + session*.py + platforms/\n├── plugins/              # memory/, context_engine/, model-providers/, kanban/, image_gen/, ...\n├── skills/               # Built-in skills (by category)   optional-skills/: shipped, not active\n├── ui-tui/, tui_gateway/ # Ink terminal UI + its Python JSON-RPC backend (also serves Desktop)\n├── apps/desktop/         # Electron desktop app (+ apps/shared)   web/: dashboard SPA\n├── cron/                 # jobs.py + scheduler.py (+ scheduler_*.py)\n├── pm/, hermes_platform/ # dependency/environment manager; machine facts + executable lookup\n├── scripts/              # check, run_tests.sh, code_health/, ci/\n├── website/              # Docusaurus docs (developer-guide/ holds the long-form area docs)\n└── tests/                # Pytest suite, mirrors the source tree\n```\n\n**User state:** `~/.hermes/config.yaml` (settings), `.env` (secrets only), `logs/` (`hermes logs`);\nall profile-aware via `get_hermes_home()`.\n\n### Facade + siblings layout\n\nEvery former god file is a **facade** (public entry points + the names other packages import) plus\n**siblings** `<stem>_<topic>.py`, each owning one topic (`hermes_state.py`, `gateway/run.py`,\n`tools/mcp_tool.py`, `hermes_cli/kanban.py`, `hermes_cli/web_server.py`, `cli.py` →\n`hermes_cli/cli_*_mixin.py`, `run_agent.py` → `agent/turn_*.py`).\n\n- **Find code by topic:** `grep -rn \"def name\" <dir>/<stem>_*.py`, not by reading the facade.\n- **Siblings late-import the facade** inside functions; never a module-level cycle.\n- **Patch where production reads:** a sibling doing `from <facade> import name` inside the function\n  makes the facade the seam; a patch on the defining module passes silently.\n- **Size and complexity are ratcheted per unit** (`scripts/code_health/config.py`): new functions\n  CC ≤ 20, ≤ 300 lines, nesting ≤ 6; files ≤ 2,000 lines; units already over may only go down (move\n  a function into a sibling to offset growth, or put new tests in a new test file). Behaviour goes\n  in a sibling, never a facade; name ladders become a dict → handler.\n- **No re-export shims for internal moves;** internal paths are not API. Moving a symbol means\n  fixing its docs in the same PR (grep `website/docs`, `skills/`, every `AGENTS.md`).\n\n## Rules that apply everywhere\n\n- **No defensive clutter:** no wrappers or `try/except: pass` around code that cannot fail, no flags\n  nobody sets, no dead code wired in without E2E proof. Comments keep the WHY, cut the WHAT.\n- **Never infer process identity from argv substrings;** use\n  `gateway.status.looks_like_gateway_command_line` / `hermes_cli.update_cmd._hermes_holder_subcommand`\n  (HX003; details `hermes_cli/AGENTS.md`).\n- **Never hardcode `~/.hermes`:** `get_hermes_home()` for paths, `display_hermes_home()` for text\n  (HX001). `_get_profiles_root()` is HOME-anchored on purpose.\n- **One process serves many profiles.** Code that runs outside a turn (boot probes, eviction,\n  tickers, deferred callbacks, RPC methods, thread hops, child spawns) binds the owning profile scope\n  explicitly; `os.environ`, module globals and import-time values hold the launch profile's, so an\n  unbound read is a silent default-profile leak. Binding points and seams: `gateway/AGENTS.md`\n  § Profile scope (HX002/HX004/HX005/HX012, PS-P05/P06).\n- **Machine facts and executable lookup go through `hermes_platform`** (`hermes_platform/AGENTS.md`).\n- **Dependencies carry upper bounds** (`>=floor,<next_major`; git URLs and Actions pinned to a SHA);\n  after editing `pyproject.toml` run `hermes pm lock` and commit `uv.lock`; never mutate a Hermes\n  environment with raw pip/uv. Full policy: `pm/AGENTS.md`.\n- **TypeScript (desktop, TUI, website):** feature-owned nanostores over threaded state, thin route\n  roots, narrow hooks and colocated action modules, `interface` for props and shared shapes,\n  table-driven dispatch over condition ladders; `src/app` routes, `src/store` atoms, `src/lib` pure\n  helpers.\n- **Commits and PRs:** rebase onto `main` before merging (a squash from a stale branch silently\n  reverts newer fixes); 1–2 invariant tests per fix, proven red on the base.\n- **Tests:** always `scripts/run_tests.sh`, never bare `pytest`; behaviour contracts, never\n  change-detectors or source-reading tests; host-specific behaviour is tested on that host with\n  `@pytest.mark.platforms(...)`, never by faking `sys.platform`; tests never write to `~/.hermes/`.\n  Everything else: `tests/AGENTS.md`.\n\n## Routing Table — working in X → read X/AGENTS.md\n\n| Area | Read | Covers |\n|---|---|---|\n| `run_agent.py`, `agent/` | `agent/AGENTS.md` | turn phases, caching and message-flow invariants, compression, model/aux resolution |\n| `cli.py`, `hermes_cli/` | `hermes_cli/AGENTS.md` | CLI mixins, slash registry, config system, skins, `hermes update`, profiles / multiplex |\n| `gateway/` | `gateway/AGENTS.md` | adapters, message guards, streaming, notifications, token locks, § Profile scope |\n| `gateway/platforms/` new adapter | `gateway/platforms/ADDING_A_PLATFORM.md` | step-by-step adapter guide |\n| `tools/`, `toolsets.py`, `model_tools.py` | `tools/AGENTS.md` | adding tools, registry, toolsets, delegation, session-scoped surface tools |\n| `plugins/`, `hermes_cli/plugins*.py` | `plugins/AGENTS.md` | plugin kinds, native compat contract, in-tree policy |\n| `plugin-catalog/` | `plugin-catalog/README.md` | catalog admission rules (mirrored in the developer guide; keep identical) |\n| `tui_gateway/`, `ui-tui/` | `tui_gateway/AGENTS.md` | process model, JSON-RPC transport, slash flow |\n| `web/`, `hermes_cli/web_routers/` | `web/AGENTS.md` | dashboard embeds the real TUI |\n| `apps/desktop/` | `apps/desktop/AGENTS.md`, `apps/desktop/src/AGENTS.md` | `serve` backend, slash palette, Bot Mode |\n| `skills/`, `optional-skills/`, `agent/curator*.py` | `skills/AGENTS.md` | frontmatter, authoring standards, curator |\n| `cron/`, kanban | `cron/AGENTS.md` | scheduler invariants, job fields, kanban dispatcher |\n| `tests/` | `tests/AGENTS.md` | runner, placement, OS markers, `wine2e`, banned test shapes |\n| `pm/`, `pyproject.toml` | `pm/AGENTS.md` | pinning policy, PM-owned environments, plugin quarantine |\n| `hermes_platform/` | `hermes_platform/AGENTS.md` | host facts, resolvers |\n\nLong-form background: `website/docs/developer-guide/`. Workflow rules (PR/issue/review/salvage\nprocess) live in the `hermes-agent-dev` skill, not here.\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/NousResearch/hermes-agent/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}