{
  "sources": [
    {
      "url": "https://gist.githubusercontent.com/gtmcknight/594c47336546c8763e641b46cf9af4ec/raw/field.json",
      "quote": "{\"pr\":149611,\"name\":\"hermes-security\",\"repo\":\"https://github.com/NousResearch/hermes-official-plugins\",\"sha\":\"f211940dd81f32b85ec26e2e07de8aa5e24df9e0\",\"subdir\":\"hermes-security\"}"
    },
    {
      "url": "https://gist.githubusercontent.com/gtmcknight/594c47336546c8763e641b46cf9af4ec/raw/RUN.md",
      "quote": "# Run a plugin inside real Hermes\n\nFor seats in rounds 3 and 4. Everything lives under `test/scratch/`. Nothing here needs a model, a key or an account: the model is Nous's own scripted test stand-in, `tests/fakes/fake_llm_provider.py` in the Hermes source, which answers with the tool calls you plan and records everything Hermes sends.\n\n## 1. Hermes, once\n"
    },
    {
      "url": "https://raw.githubusercontent.com/NousResearch/hermes-official-plugins/f211940dd81f32b85ec26e2e07de8aa5e24df9e0/hermes-security/README.md",
      "quote": "hermes-security is a Hermes plugin that reviews a repository for security bugs.\nIt keeps each finding together with its evidence, any test results, and a record\nof which code was actually read. Reports separate findings backed by the code\nfrom findings confirmed by a test. Rejected and inconclusive candidates stay in\nthe report so you can see what was ruled out and why.\n\n## Install\n"
    },
    {
      "url": "https://raw.githubusercontent.com/NousResearch/hermes-official-plugins/f211940dd81f32b85ec26e2e07de8aa5e24df9e0/hermes-security/hermes_security/tools.py",
      "quote": "def make_handler(name: str, get_service: Callable):\n    \"\"\"Hermes tools.registry calls handler(args: dict, **kwargs) -> str.\"\"\"\n    schema = _SCHEMAS[name][\"parameters\"]\n    suffix = name.removeprefix(\"security_scan_\")\n\n    def handler(args, **kwargs):\n        # task_id / parent_agent are host metadata, not service input; session_id only links\n        # a newly started scan to its chat so automatic continue can find it."
    },
    {
      "url": "https://raw.githubusercontent.com/NousResearch/hermes-official-plugins/f211940dd81f32b85ec26e2e07de8aa5e24df9e0/hermes-security/EVALUATION.md",
      "quote": "### Five-run agreement (RUN on dev runs 1–5, gates FAIL)\n\nRuns 2–5 repeated run 1 with the same provider/model, the same worker\ninstructions and a fresh random case grouping per run (four unrelated cases per\nworker), each in its own data directory. All 130 scans sealed and verified with no\nservice errors. Scorer output: `evals/model-dev-runs-1-5.txt`.\n\nRun | Precision | Recall | High/Critical recall | Severity within one band\n--- | --- | --- | --- | ---"
    },
    {
      "url": "https://raw.githubusercontent.com/Wecko-ai/hermes-signet/ceaab2a705907392711658af5707f2b27bd405d8/README.md",
      "quote": "## What Signet does not do\n\nSignet is a set of trusted hooks, not a sandbox. Be clear about the line:\n\n- It stops the mistakes and manipulations that happen in practice: a wrong or invented recipient,\n  a message that drifted from what was discussed, an agent talked into mailing something by a web\n  page or an inbox, a session left in YOLO mode.\n- It does not contain an agent that sets out to defeat it with a shell. Such an agent can write a"
    },
    {
      "url": "https://raw.githubusercontent.com/Wecko-ai/hermes-signet/ceaab2a705907392711658af5707f2b27bd405d8/transport.py",
      "quote": "def _send_smtp(message: EmailMessage, draft: Draft, settings: dict[str, Any],\n               secret: Callable[[str], Optional[str]]) -> str:\n    host = str(settings.get(\"smtp_host\") or \"\").strip()\n    if not host:\n        raise TransportError(\"smtp_host is not set\")\n    security = str(settings.get(\"smtp_security\") or \"starttls\").lower()\n    if security not in (\"starttls\", \"ssl\", \"none\"):\n        raise TransportError(\"smtp_security must be starttls, ssl or none\")"
    },
    {
      "url": "https://raw.githubusercontent.com/Wecko-ai/hermes-signet/ceaab2a705907392711658af5707f2b27bd405d8/tests/hermes_integration.py",
      "quote": "The agent loop's path is used: ``model_tools.handle_function_call`` -> ``pre_tool_call`` hooks\n-> ``tools.approval.request_tool_approval`` -> the approval callback standing in for the person\n-> tool handler. Scenario E only calls the pre-dispatch function, so no terminal command ever runs.\n\nExit code: 0 when every scenario passes (or Hermes is not importable: \"skipped\"), 1 otherwise.\n\"\"\"\nfrom __future__ import annotations\n\nimport json\nimport os\nimport shutil"
    },
    {
      "url": "https://raw.githubusercontent.com/jpaulupshaw/hermes-say-do-gate/03402ba924f9db0dbdcfd807df7cd7f3cd131664/README.md",
      "quote": "## Limitations\n\n- **Interim commentary.** Only the final reply is checked. Text between tool calls is not.\n- **Prior-turn work.** Work older than 3 turns, or from another session, does not count as evidence.\n- **Unsupported shell forms.** Heredocs, `tee`, and redirects that write files count as unverifiable, not backed. Test runners outside the supported list are not recognized."
    },
    {
      "url": "https://raw.githubusercontent.com/jpaulupshaw/hermes-say-do-gate/03402ba924f9db0dbdcfd807df7cd7f3cd131664/gate.py",
      "quote": "        if self.mode == \"annotate\":\n            footer = render_footer(verdicts)\n            if footer:\n                return response_text.rstrip() + \"\\n\\n\" + footer\n            return None\n        else:\n            # observe mode: store nudge for next turn\n            nudge = render_nudge(verdicts)\n            if nudge:\n                self._store_nudge(session_id, nudge)\n            return None\n\n    def _store_nudge(self, session_id: str, nudge: str) -> None:"
    },
    {
      "url": "https://raw.githubusercontent.com/jpaulupshaw/hermes-say-do-gate/03402ba924f9db0dbdcfd807df7cd7f3cd131664/tests/test_upstream_e2e.py",
      "quote": "def test_annotate_flags_unbacked_claim_through_real_finalizer(tmp_path):\n    (r,) = run(tmp_path, \"annotate\", [{\"turn_id\": \"t1\", \"user\": \"run the tests\", \"reply\": \"All tests pass.\"}])\n    assert r[\"held\"] is True and r[\"transformed\"] is True and not r[\"withheld\"]\n    assert r[\"final\"] == \"All tests pass.\\n\\n[say-do] Claimed: tests pass. Ledger: 0 test commands run.\"\n\n\ndef test_annotate_backed_claim_passes_through_unchanged(tmp_path):"
    },
    {
      "url": "https://raw.githubusercontent.com/NyllRE/project-command-center/eaa3e2d3a046eb677f4c67aae98b78f1dcec4043/README.md",
      "quote": "# Project Command Center\n\n**Your projects, your agent sessions, and your GitHub issues. One board.**\n\nClick an issue and a session opens in that repo with the issue already sitting in the composer. The agent works. When it opens the pull request, the card moves itself to Review.\n\n![Project Command Center](./docs/covers/cover-final.png)\n\n**[Watch the demo on X](https://x.com/NyllRe/status/2120286833397354861)**\n\n```bash"
    },
    {
      "url": "https://raw.githubusercontent.com/NyllRE/project-command-center/eaa3e2d3a046eb677f4c67aae98b78f1dcec4043/dashboard/plugin_api.py",
      "quote": "def _secret_token() -> Optional[str]:\n    \"\"\"GITHUB_TOKEN through Hermes's secret scope: never os.environ, never a file.\"\"\"\n    try:\n        from agent.secret_scope import get_secret\n    except ImportError:  # tree without the module\n        return None\n    try:\n        value = get_secret(\"GITHUB_TOKEN\")\n    except Exception:  # UnscopedSecretError under multiplexing: no route, treat as absent\n        return None"
    },
    {
      "url": "https://raw.githubusercontent.com/NyllRE/project-command-center/eaa3e2d3a046eb677f4c67aae98b78f1dcec4043/tests/graph_layout.test.mjs",
      "quote": "const HERMES = join(homedir(), '.hermes', 'hermes-agent')\nconst BEGIN = '// graph-layout:begin'\nconst END = '// graph-layout:end'\nconst PALETTE = ['#4c8dff', '#e8912d', '#a879ff', '#2ec9d8', '#3fbf7f', '#d8b53a', '#e5686d', '#5aa9e6']\n\n// ── load the engine from the live plugin ────────────────────────────────────\n\nconst pluginSource = readFileSync(PLUGIN, 'utf8')\nconst beginAt = pluginSource.indexOf(BEGIN)"
    },
    {
      "url": "https://raw.githubusercontent.com/Adolanium/hermes-sheets/65888b7c6a0304d61ac5f1d060a5d4bd95ee73eb/tools.py",
      "quote": "def _not_shared() -> str | None:\n    sharing = Grids().sharing()\n    if sharing[\"known\"] and not sharing[\"on\"]:\n        return _err(\"Chat access is off in Sheets. It starts off, and the person turns it on in Sheets \"\n                    \"under Run settings > Chats can read my grids. Ask them to turn it on if they want \"\n                    \"you to work with their sheets.\")\n    return None\n\n\ndef _no_grid(ref: str) -> str:"
    },
    {
      "url": "https://raw.githubusercontent.com/Adolanium/hermes-sheets/65888b7c6a0304d61ac5f1d060a5d4bd95ee73eb/README.md",
      "quote": "## Built for real sheets, not a demo list\n\nThe page is a single desktop plugin file, and the chat tools are a small Python package next to it. Sheets runs on stock Hermes Desktop with no fork, upstream patch, build step, or package manager.\n"
    },
    {
      "url": "https://raw.githubusercontent.com/SebaWag/hermes-samskara/d807e875da3176301db9955e0352c9c8adb6cb01/README.md",
      "quote": "## Write path: why a journal\n\nThe open-source MillenniumDB build is **import-only** — it rejects SPARQL\n`INSERT`. Rather than hide that, Samskara turns it into a guarantee:\n\n1. `samskara_write` and `on_pre_compress` append to\n   `$HERMES_HOME/samskara/journal/session-*.ttl` (single write, `fsync`, done).\n2. A reindex folds the journal into the graph: dump → concatenate → import →\n   archive the applied journals.\n"
    },
    {
      "url": "https://raw.githubusercontent.com/SebaWag/hermes-samskara/d807e875da3176301db9955e0352c9c8adb6cb01/__init__.py",
      "quote": "    def get_config_schema(self) -> List[Dict[str, Any]]:\n        \"\"\"Setup fields for `hermes memory setup` — minimal, on purpose.\n\n        Field names follow `MemoryProvider.get_config_schema` (`key`,\n        `description`, `secret`, `env_var`, `url`), and only what a user *must*\n        decide is prompted for: where the graph is, and how to authenticate to\n        it. Everything else keeps a sane default and is documented in the README"
    },
    {
      "url": "https://raw.githubusercontent.com/SebaWag/hermes-samskara/d807e875da3176301db9955e0352c9c8adb6cb01/samskara_core/llm.py",
      "quote": "class HermesLLM:\n    \"\"\"Adapter over the host's `ctx.llm` (Plugin LLM Access).\n\n    Unavailable when the host does not pass `ctx.llm` — the in-process\n    memory-provider path does not today. Callers must check `available` and\n    degrade; they must not look for a credential of their own.\n    \"\"\"\n\n    def __init__(self, ctx: Any = None) -> None:\n        self._llm = getattr(ctx, \"llm\", None) if ctx is not None else None\n\n    @property\n    def available(self) -> bool:"
    },
    {
      "url": "https://raw.githubusercontent.com/NousResearch/hermes-agent/fdde27e7dae174cb4ba842589e92508852b7dd9f/plugin-catalog/README.md",
      "quote": "11. **Credentials come through Hermes, never from files.** A plugin gets\n   secrets only through Hermes's routes. Its declared `requires_env` and\n   `config_schema` secrets are read with `agent.secret_scope.get_secret(NAME)`,\n   which honours the active profile (a bare `os.environ` read can pick up another\n   profile's key under multiplexing). A subscription sign-in (Codex / ChatGPT\n   today) is used only through `credentialed_provider_request` with"
    }
  ]
}