diff --git a/docs/adopters.md b/docs/adopters.md index f3a52f5..6b3bb42 100644 --- a/docs/adopters.md +++ b/docs/adopters.md @@ -36,6 +36,7 @@ Or open a PR that adds a row to the table below: | [loop-engineering](https://github.com/cobusgreyling/loop-engineering) (maintainer) | Post-Merge Cleanup | Grok + GitHub Actions | L1→L2 | Off-peak scan; verifier caught doc/API drift — see [story](../stories/post-merge-cleanup-honest-win.md) | | [loop-engineering](https://github.com/cobusgreyling/loop-engineering) (maintainer) | Issue Triage + Daily Triage | Grok | L1 | Issue queue feeder: propose labels only week one; pairs with morning `STATE.md` triage | | [loop-engineering](https://github.com/cobusgreyling/loop-engineering) (maintainer) | PR Babysitter, Dependency Sweeper | Grok / Claude Code | L2 | Assisted fixes in worktrees; human gate on merges; patch-only deps | +| [Hermes Agent](https://github.com/NousResearch/hermes-agent) by [Nous Research](https://nousresearch.com) | Daily Triage | Hermes | L1 | Six loop primitives in one binary — `hermes cron` + skill + `delegate_task` + MCP + memory. Reference: [examples/hermes/daily-triage.md](../examples/hermes/daily-triage.md) | *Your project here — see [CONTRIBUTING.md](../CONTRIBUTING.md).* diff --git a/docs/primitives-matrix.md b/docs/primitives-matrix.md index fd708b6..769f26d 100644 --- a/docs/primitives-matrix.md +++ b/docs/primitives-matrix.md @@ -1,44 +1,44 @@ -# Primitives Matrix — Grok, Claude Code, Codex, OpenClaw, Opencode, Cursor, Windsurf +# Primitives Matrix — Grok, Claude Code, Codex, OpenClaw, Opencode, Cursor, Windsurf, Hermes -Tool-agnostic loop design: the **capability** is what matters, not the product name. This matrix maps each primitive to how it appears in seven major agent environments. +Tool-agnostic loop design: the **capability** is what matters, not the product name. This matrix maps each primitive to how it appears in eight major agent environments. -| Primitive | Job in the Loop | Grok Build TUI | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | -|-----------|-----------------|----------------|-------------|-------|----------|----------|--------|----------| -| **Automations / Scheduling** | Discovery + triage on a cadence | `/loop [interval] `, `scheduler_create` / `scheduler_list` / `scheduler_delete` (`recurring`, `durable`, `fireImmediately`), `monitor` for streaming events | `/loop`, scheduled tasks, cron, hooks, GitHub Actions | [Automations tab](https://developers.openai.com/codex/app/automations): project, prompt, cadence, environment; Triage inbox | [`openclaw cron`](https://docs.openclaw.ai/automation/cron-jobs) (`--cron` / `--every` / `--at`, isolated or main session); webhooks (`POST /hooks/agent`, `/hooks/wake`); heartbeat | OS cron / systemd timer / GitHub Action invokes `opencode run "..."`; headless server via `opencode serve` | Cloud Agents + **Automations** (cron, webhooks, Linear/GitHub/Slack triggers); foreground Agent chat for ad-hoc `/loop`-style prompts | Cascade **Workflows** (`/workflow-name`, manual invoke); pair with GitHub Actions or external cron for true scheduling | -| **Run-until-done** | Keep working until a verifiable condition holds | [`/goal`](https://github.com/cobusgreyling/goal-engineering) + `update_goal` — persistent objective across turns ([Goal Engineering](https://github.com/cobusgreyling/goal-engineering)) | `/goal` — separate model checks completion | `/goal` — pause/resume, verifiable stop condition | Recurring isolated cron with explicit stop condition in `--message`; delegate via `coding-agent` skill to external CLI; hand off bounded work to Goal Engineering | Bounded `opencode run ""` sessions; follow with verifier agent via `--agent verifier` | Agent mode + **hooks** (`.cursor/hooks.json`) for grind-until-green loops | Workflow steps with explicit verification checkpoints; **Memories** for cross-session continuity | -| **Worktrees** | Safe parallel execution | Subagents with `isolation: "worktree"`, background tasks | `git worktree`, `--worktree`, `isolation: worktree` on subagents | Built-in worktree per thread | `exec` + `git worktree` in agent workspace; `coding-agent` delegates to CLI backends; optional sandbox per agent | Explicit `git worktree` per implementer run; pass worktree path with `--dir` | Git worktree per Composer / Cloud Agent task | Workspace isolation; multiple simultaneous Cascade sessions | -| **Skills** | Persistent project knowledge | `SKILL.md` in `.grok/skills/` or `~/.grok/skills/`; invoked by name | `SKILL.md` in `.claude/skills/` or project skills | [Agent Skills](https://developers.openai.com/codex/skills) — `$name` or implicit match | `SKILL.md` in `/skills/`, `.agents/skills`, or `~/.openclaw/skills`; [AgentSkills](https://agentskills.io) spec; [ClawHub](https://clawhub.ai) + `openclaw skills install` | `SKILL.md` in `skills//`; `AGENTS.md` for always-on repo rules | `.cursor/rules/*.mdc` (globs, `alwaysApply`), `AGENTS.md`, `.cursor/skills/` | `.devin/rules/` or `.windsurf/rules/` (persistent context); `.windsurf/workflows/` (reusable recipes) | -| **Plugins & Connectors** | Reach into real tools | MCP servers via `CallMcpTool` | MCP servers + plugins | Connectors (MCP) + plugins for distribution | MCP + channel plugins (Slack, Telegram, WhatsApp, etc.); browser automation plugin | MCP servers in `opencode.json`; GitHub/Linear/Slack via CLI or MCP bridge | MCP in settings; Cloud Agent sandbox with full connector access | MCP via Cascade settings / `mcp_config.json` | -| **Sub-agents** | Maker / checker split | `Task` tool with `subagent_type`, worktree isolation | Task subagents in `.claude/agents/`, agent teams | Subagents as TOML in `.codex/agents/` | `agents.list` multi-agent routing; isolated cron subagent orchestration; separate verifier agent id | Named agents via `opencode agent`; invoke one role per run with `--agent verifier` or `--agent implementer` | Multi-agent mode, review mode, custom agents in `.cursor/agents/` | Multiple Cascades in parallel; workflow-orchestrated implementer → reviewer steps | -| **State / Memory** | Track what's done across runs | `STATE.md`, todos, durable scheduler state | `AGENTS.md`, progress files, Linear via MCP | Markdown or Linear via connector | `STATE.md`, `HEARTBEAT.md` in workspace; cron persisted in Gateway SQLite; Skill Workshop for skill proposals | `STATE.md`, `LOOP.md`, `AGENTS.md`, session export via `opencode export ` | `STATE.md`, `LOOP.md`, Cloud Agent memories | `STATE.md`, Cascade **Memories**, workflow run notes | +| Primitive | Job in the Loop | Grok Build TUI | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | Hermes | +|-----------|-----------------|----------------|-------------|-------|----------|----------|--------|----------|--------| +| **Automations / Scheduling** | Discovery + triage on a cadence | `/loop [interval] `, `scheduler_create` / `scheduler_list` / `scheduler_delete` (`recurring`, `durable`, `fireImmediately`), `monitor` for streaming events | `/loop`, scheduled tasks, cron, hooks, GitHub Actions | [Automations tab](https://developers.openai.com/codex/app/automations): project, prompt, cadence, environment; Triage inbox | [`openclaw cron`](https://docs.openclaw.ai/automation/cron-jobs) (`--cron` / `--every` / `--at`, isolated or main session); webhooks (`POST /hooks/agent`, `/hooks/wake`); heartbeat | OS cron / systemd timer / GitHub Action invokes `opencode run "..."`; headless server via `opencode serve` | Cloud Agents + **Automations** (cron, webhooks, Linear/GitHub/Slack triggers); foreground Agent chat for ad-hoc `/loop`-style prompts | Cascade **Workflows** (`/workflow-name`, manual invoke); pair with GitHub Actions or external cron for true scheduling | [`hermes cron create "" --skill … --deliver local\|origin\|\|platform:chat_id:thread_id --workdir "$PWD"`](https://hermes-agent.nousresearch.com/docs); webhooks via `POST /hooks/agent`; per-job `context_from` chains upstream job stdout into downstream prompt | +| **Run-until-done** | Keep working until a verifiable condition holds | [`/goal`](https://github.com/cobusgreyling/goal-engineering) + `update_goal` — persistent objective across turns ([Goal Engineering](https://github.com/cobusgreyling/goal-engineering)) | `/goal` — separate model checks completion | `/goal` — pause/resume, verifiable stop condition | Recurring isolated cron with explicit stop condition in `--message`; delegate via `coding-agent` skill to external CLI; hand off bounded work to Goal Engineering | Bounded `opencode run ""` sessions; follow with verifier agent via `--agent verifier` | Agent mode + **hooks** (`.cursor/hooks.json`) for grind-until-green loops | Workflow steps with explicit verification checkpoints; **Memories** for cross-session continuity | Chained cron jobs via `hermes cron edit --context-from `; skill loops using `delegate_task` until a verifiable stop condition holds; `hermes cron edit --schedule` adjusts cadence live | +| **Worktrees** | Safe parallel execution | Subagents with `isolation: "worktree"`, background tasks | `git worktree`, `--worktree`, `isolation: worktree` on subagents | Built-in worktree per thread | `exec` + `git worktree` in agent workspace; `coding-agent` delegates to CLI backends; optional sandbox per agent | Explicit `git worktree` per implementer run; pass worktree path with `--dir` | Git worktree per Composer / Cloud Agent task | Workspace isolation; multiple simultaneous Cascade sessions | Standard `git worktree` inside the cron job; `--workdir` pins tool cwd + injects `AGENTS.md` per job so parallel jobs cannot collide | +| **Skills** | Persistent project knowledge | `SKILL.md` in `.grok/skills/` or `~/.grok/skills/`; invoked by name | `SKILL.md` in `.claude/skills/` or project skills | [Agent Skills](https://developers.openai.com/codex/skills) — `$name` or implicit match | `SKILL.md` in `/skills/`, `.agents/skills`, or `~/.openclaw/skills`; [AgentSkills](https://agentskills.io) spec; [ClawHub](https://clawhub.ai) + `openclaw skills install` | `SKILL.md` in `skills//`; `AGENTS.md` for always-on repo rules | `.cursor/rules/*.mdc` (globs, `alwaysApply`), `AGENTS.md`, `.cursor/skills/` | `.devin/rules/` or `.windsurf/rules/` (persistent context); `.windsurf/workflows/` (reusable recipes) | `SKILL.md` under `~/.hermes/skills//` (user) or `.hermes/skills//` (project); `hermes skills install/list/inspect`; invoked via `--skill ` on cron jobs, or auto-loaded by description match | +| **Plugins & Connectors** | Reach into real tools | MCP servers via `CallMcpTool` | MCP servers + plugins | Connectors (MCP) + plugins for distribution | MCP + channel plugins (Slack, Telegram, WhatsApp, etc.); browser automation plugin | MCP servers in `opencode.json`; GitHub/Linear/Slack via CLI or MCP bridge | MCP in settings; Cloud Agent sandbox with full connector access | MCP via Cascade settings / `mcp_config.json` | MCP servers via `hermes mcp add`; built-in home channels (Feishu, Slack, Discord, Telegram, WhatsApp, SMS); `hermes send` delivers to any connected channel | +| **Sub-agents** | Maker / checker split | `Task` tool with `subagent_type`, worktree isolation | Task subagents in `.claude/agents/`, agent teams | Subagents as TOML in `.codex/agents/` | `agents.list` multi-agent routing; isolated cron subagent orchestration; separate verifier agent id | Named agents via `opencode agent`; invoke one role per run with `--agent verifier` or `--agent implementer` | Multi-agent mode, review mode, custom agents in `.cursor/agents/` | Multiple Cascades in parallel; workflow-orchestrated implementer → reviewer steps | `delegate_task(goal=..., role='leaf'\|'orchestrator', toolsets=[...])` — background execution, isolated context, result re-enters as a new message; up to N children in parallel per `delegation.max_concurrent_children` | +| **State / Memory** | Track what's done across runs | `STATE.md`, todos, durable scheduler state | `AGENTS.md`, progress files, Linear via MCP | Markdown or Linear via connector | `STATE.md`, `HEARTBEAT.md` in workspace; cron persisted in Gateway SQLite; Skill Workshop for skill proposals | `STATE.md`, `LOOP.md`, `AGENTS.md`, session export via `opencode export ` | `STATE.md`, `LOOP.md`, Cloud Agent memories | `STATE.md`, Cascade **Memories**, workflow run notes | `STATE.md` in `--workdir`; `HEARTBEAT.md` for periodic polls; persistent facts via `hermes memory` (survive across sessions); cron jobs stored in gateway SQLite | **Reference MCP server:** this repo ships [`tools/mcp-server/`](../tools/mcp-server/) — patterns, skills, state, budget, and safety docs as runtime-queryable MCP resources (reduces prompt stuffing). Config example: [`examples/mcp/loop-engineering.mcp.json`](../examples/mcp/loop-engineering.mcp.json). ## Scheduling Quick Reference -| Use case | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | -|----------|------|-------------|-------|----------|----------|--------|----------| -| Every 5 minutes | `/loop 5m ` | `/loop 5m ` | Automation, 5m cadence | `openclaw cron create "*/5 * * * *" --session isolated --message "..."` | Cron/systemd calls `opencode run "..."` | Automation cron trigger | External cron + `/workflow` or Action | -| Daily morning | `/loop 1d ` | Cron / `/loop 1d` | Automation, daily | `openclaw cron create "0 7 * * *" --tz ... --session isolated` + optional `--announce` | Cron/systemd calls `opencode run "Run loop-triage"` | Automation daily + `AGENTS.md` context | Daily workflow + Memories | -| Until tests pass | [`/goal`](https://github.com/cobusgreyling/goal-engineering/blob/main/patterns/tests-green.md) + `goal-verifier` skill (or loop + verifier) | `/goal all tests pass` | `/goal` | Isolated cron + verifier in message, or `coding-agent` + external CLI | `opencode run "Goal: all tests pass. Stop when verifier approves."` | Hooks grind-until-green | Workflow with test/fix loop | -| Survive restart | `scheduler_create` with `durable: true` | Hooks + persisted config | Automation (server-side) | Cron jobs persist in Gateway SQLite | systemd timer + committed `STATE.md` + exported sessions | Cloud Agent + repo-persisted state | Memories + committed `STATE.md` | -| Event-driven (CI fail) | `monitor` or GitHub Action | GitHub Action + webhook | Automation + webhook | `POST /hooks/agent` or mapped webhooks | GitHub Action / webhook bridge calls `opencode run` | Automation on PR/issue events | GitHub Action triggers + `/workflow` | +| Use case | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | Hermes | +|----------|------|-------------|-------|----------|----------|--------|----------|--------| +| Every 5 minutes | `/loop 5m ` | `/loop 5m ` | Automation, 5m cadence | `openclaw cron create "*/5 * * * *" --session isolated --message "..."` | Cron/systemd calls `opencode run "..."` | Automation cron trigger | External cron + `/workflow` or Action | `hermes cron create "*/5 * * * *" --deliver local --skill loop-triage "..."` | +| Daily morning | `/loop 1d ` | Cron / `/loop 1d` | Automation, daily | `openclaw cron create "0 7 * * *" --tz ... --session isolated` + optional `--announce` | Cron/systemd calls `opencode run "Run loop-triage"` | Automation daily + `AGENTS.md` context | Daily workflow + Memories | `hermes cron create "0 7 * * *" --name "Daily triage" --deliver local --skill loop-triage --workdir "$PWD" "..."` | +| Until tests pass | [`/goal`](https://github.com/cobusgreyling/goal-engineering/blob/main/patterns/tests-green.md) + `goal-verifier` skill (or loop + verifier) | `/goal all tests pass` | `/goal` | Isolated cron + verifier in message, or `coding-agent` + external CLI | `opencode run "Goal: all tests pass. Stop when verifier approves."` | Hooks grind-until-green | Workflow with test/fix loop | Bounded skill loop using `delegate_task` for the maker + a second `delegate_task` as checker; or chained cron jobs with `context_from` | +| Survive restart | `scheduler_create` with `durable: true` | Hooks + persisted config | Automation (server-side) | Cron jobs persist in Gateway SQLite | systemd timer + committed `STATE.md` + exported sessions | Cloud Agent + repo-persisted state | Memories + committed `STATE.md` | Cron jobs persist in gateway SQLite; `--workdir` re-injects project context on every tick | +| Event-driven (CI fail) | `monitor` or GitHub Action | GitHub Action + webhook | Automation + webhook | `POST /hooks/agent` or mapped webhooks | GitHub Action / webhook bridge calls `opencode run` | Automation on PR/issue events | GitHub Action triggers + `/workflow` | `POST /hooks/agent` with `{"message":"…","name":"…","deliver":"local"}` | ## Skill Packaging -| Concept | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | -|---------|------|-------------|-------|----------|----------|--------|----------| -| Authoring format | `SKILL.md` + optional scripts/references | Same | Same | Same ([AgentSkills](https://agentskills.io)) | Same (`SKILL.md` under `skills//`) | `SKILL.md` or `.mdc` rules with frontmatter | Markdown rules + workflow files | -| Distribution | Copy to `.grok/skills/` or user skills dir | Plugin / copy to project | Plugin bundle | `/skills/`, ClawHub, `openclaw skills install` | Copy to `skills/`; keep project rules in `AGENTS.md` | `.cursor/skills/` or `.cursor/rules/` | `.windsurf/rules/` + `.windsurf/workflows/` in repo | -| Invocation | Skill name in prompt or auto-match on description | `$skill-name` or implicit | `$skill-name` | Slash command or auto-injected in system prompt | Name the skill in the `opencode run` message, or configure named agents in `opencode.json` | Rules auto-apply by glob; skills on demand | `/workflow-name` or Rules always-on in Cascade | +| Concept | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | Hermes | +|---------|------|-------------|-------|----------|----------|--------|----------|--------| +| Authoring format | `SKILL.md` + optional scripts/references | Same | Same | Same ([AgentSkills](https://agentskills.io)) | Same (`SKILL.md` under `skills//`) | `SKILL.md` or `.mdc` rules with frontmatter | Markdown rules + workflow files | `SKILL.md` + optional `references/`, `templates/`, `scripts/`, `assets/` ([AgentSkills](https://agentskills.io) spec) | +| Distribution | Copy to `.grok/skills/` or user skills dir | Plugin / copy to project | Plugin bundle | `/skills/`, ClawHub, `openclaw skills install` | Copy to `skills/`; keep project rules in `AGENTS.md` | `.cursor/skills/` or `.cursor/rules/` | `.windsurf/rules/` + `.windsurf/workflows/` in repo | `~/.hermes/skills//` (user) or `.hermes/skills//` (project); `hermes skills install ` from skills.sh, ClawHub, well-known endpoints, GitHub | +| Invocation | Skill name in prompt or auto-match on description | `$skill-name` or implicit | `$skill-name` | Slash command or auto-injected in system prompt | Name the skill in the `opencode run` message, or configure named agents in `opencode.json` | Rules auto-apply by glob; skills on demand | `/workflow-name` or Rules always-on in Cascade | `--skill ` on cron jobs; auto-loaded by description match mid-session; `--skills X,Y` on `hermes chat` for one-off preload | ## Sub-agent Patterns -| Split | When to use | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | -|-------|-------------|------|-------------|-------|----------|----------|--------|----------| -| Implementer → Verifier | Any unattended code change | `Task` + different instructions/model | `.claude/agents/reviewer.md` | TOML agent with higher `reasoning_effort` | Separate `agents.list` id or verifier block in cron message | `opencode run "..." --agent implementer` in worktree, then `opencode run "Verify diff" --agent verifier --file diff.patch` | Review mode or second Cloud Agent pass | Second Cascade or workflow review step | -| Explorer → Implementer | Large unfamiliar codebase | `explore` subagent_type | Explorer agent | Fast read-only subagent | `--light-context` cron + follow-up isolated job | First `opencode run "read-only exploration..."`, then follow-up implementer in a worktree | `@codebase` + plan mode first | Audit workflow (read-only) then implement | -| Triage only | Report-first loops | `loop-triage` skill | `$loop-triage` | Automation calls skill | `loop-triage` + isolated cron; restrict `--tools` | `opencode run "Run loop-triage. Do not edit code."` | `AGENTS.md` + report-only rule | Triage workflow, no edit steps | +| Split | When to use | Grok | Claude Code | Codex | OpenClaw | Opencode | Cursor | Windsurf | Hermes | +|-------|-------------|------|-------------|-------|----------|----------|--------|----------|--------| +| Implementer → Verifier | Any unattended code change | `Task` + different instructions/model | `.claude/agents/reviewer.md` | TOML agent with higher `reasoning_effort` | Separate `agents.list` id or verifier block in cron message | `opencode run "..." --agent implementer` in worktree, then `opencode run "Verify diff" --agent verifier --file diff.patch` | Review mode or second Cloud Agent pass | Second Cascade or workflow review step | Two sequential `delegate_task` calls (first `role='leaf'` with terminal+file; second `role='leaf'` with review-only toolsets); or two chained cron jobs via `context_from` | +| Explorer → Implementer | Large unfamiliar codebase | `explore` subagent_type | Explorer agent | Fast read-only subagent | `--light-context` cron + follow-up isolated job | First `opencode run "read-only exploration..."`, then follow-up implementer in a worktree | `@codebase` + plan mode first | Audit workflow (read-only) then implement | First `delegate_task(toolsets=['file'], goal='read-only exploration…')`, then follow-up `delegate_task(toolsets=['terminal','file'], goal='implement…')` in a worktree | +| Triage only | Report-first loops | `loop-triage` skill | `$loop-triage` | Automation calls skill | `loop-triage` + isolated cron; restrict `--tools` | `opencode run "Run loop-triage. Do not edit code."` | `AGENTS.md` + report-only rule | Triage workflow, no edit steps | `loop-triage` skill + `hermes cron` with `--deliver local`; restrict skill's tool list; no `delegate_task` in the prompt | ## State Conventions @@ -75,6 +75,7 @@ For opencode, the transfer usually means `skills/`, `STATE.md`, `AGENTS.md`, and | OpenClaw | [examples/openclaw/daily-triage.md](../examples/openclaw/daily-triage.md) — copy `skills/` + `STATE.md`; no `loop-init` yet | | Opencode | [starters/minimal-loop-opencode](../starters/minimal-loop-opencode/) | | Cursor / Windsurf | Copy `SKILL.md` + `STATE.md` from any starter; map scheduling to editor Automations or Workflows (see appendix) | +| Hermes | [examples/hermes/daily-triage.md](../examples/hermes/daily-triage.md) — copy `starters/minimal-loop/STATE.md.example` to project root; install `loop-triage` skill under `~/.hermes/skills/`; schedule with `hermes cron create`. No `loop-init --tool hermes` yet — this bridge is the current path. | Audit after copying: `npx @cobusgreyling/loop-audit . --suggest` diff --git a/examples/hermes/daily-triage.md b/examples/hermes/daily-triage.md new file mode 100644 index 0000000..3f6546d --- /dev/null +++ b/examples/hermes/daily-triage.md @@ -0,0 +1,156 @@ +# Daily Triage — Hermes Agent + +Same pattern as Grok, Claude Code, and OpenClaw; scheduling runs on the Hermes **gateway** (`hermes cron`) instead of a TUI `/loop`. Hermes ships the six loop primitives (**cronjob / skill / STATE / delegate_task / MCP / memory**) in one binary, so a full L1 daily-triage loop needs no extra runtime — just a scheduled job + a skill + a state file. + +Optional **channel delivery** (Feishu, Slack, Telegram, Discord, WhatsApp, SMS) is the main reason to run triage here — the same cron job can post its summary into any connected home channel. + +## Prerequisites + +1. [Hermes Agent](https://hermes-agent.nousresearch.com/docs) installed and configured (`hermes setup`). +2. `STATE.md` at the repo root — copy from `starters/minimal-loop/STATE.md.example`. +3. `loop-triage` skill — copy `templates/SKILL.md.loop-triage` into `~/.hermes/skills/loop-triage/SKILL.md` (or the workspace-local `.hermes/skills/` directory for project-scoped skills). + +```bash +# Project-scoped state +cp starters/minimal-loop/STATE.md.example STATE.md + +# User-scoped skill (available to every Hermes session) +mkdir -p ~/.hermes/skills/loop-triage +cp templates/SKILL.md.loop-triage ~/.hermes/skills/loop-triage/SKILL.md +``` + +Verify: + +```bash +hermes skills list | grep loop-triage +``` + +## Report-Only (Week 1) + +Isolated cron job: fresh session each run, writes to `STATE.md`, no code edits. Delivery pinned to `local` so nothing leaks into the human's DM history until you trust the output. + +```bash +hermes cron create "0 7 * * 1-5" \ + --name "Daily triage" \ + --deliver local \ + --skill loop-triage \ + --workdir "$PWD" \ + "Run the loop-triage skill. Read STATE.md. Merge findings into High Priority and Watch List. Update Last run timestamp. Do not edit source code. End with a 5-line summary." +``` + +- `--workdir "$PWD"` injects `AGENTS.md` / `CLAUDE.md` / `.cursorrules` from the project into the system prompt and pins the terminal cwd to the repo — cross-project isolation without a `git worktree` per run. +- `--deliver local` writes output to `~/.hermes/cron/output/` only. Swap for `--deliver origin` (current chat), a home channel name (e.g. `feishu`, `slack`), or `platform:chat_id:thread_id` for a specific thread. +- Repeat `--skill` to attach multiple skills (e.g. `--skill loop-triage --skill github-workflow` if the loop reads PRs). + +Faster cadence during active periods: + +```bash +hermes cron create "0 */2 * * *" \ + --name "Triage pulse" \ + --deliver local \ + --skill loop-triage \ + --workdir "$PWD" \ + "Run loop-triage. Report obvious small wins only. Update STATE.md. No code changes." +``` + +Announce the summary into a Feishu chat instead of keeping it local: + +```bash +hermes cron create "0 9 * * 1-5" \ + --name "Daily triage → Feishu" \ + --deliver feishu \ + --skill loop-triage \ + --workdir "$PWD" \ + "Run loop-triage. Post a 5-line summary of STATE.md changes to the home channel. No code edits." +``` + +## With Small Auto-Fixes (Week 3+) + +Add a **verifier sub-agent** via Hermes's `delegate_task` tool inside the skill, or split the loop into two cron jobs chained with `--context-from` (upstream job's stdout is injected into the downstream job's prompt). + +```bash +# 1. Triage job produces STATE.md diff + a bounded fix proposal +TRIAGE_ID=$(hermes cron create "0 7 * * 1-5" \ + --name "Triage + propose" \ + --deliver local \ + --skill loop-triage \ + --workdir "$PWD" \ + "Run loop-triage. For high-priority single-file bugfixes, propose a minimal diff in a fenced patch block. Update STATE.md. Do not apply the patch." \ + | tail -1) + +# 2. Fixer job reads the triage output, applies the patch in an isolated worktree, +# runs tests, and has a verifier pass review the diff before commit. +hermes cron create "5 7 * * 1-5" \ + --name "Triage → apply + verify" \ + --deliver local \ + --skill loop-triage \ + --workdir "$PWD" \ + "Read the injected triage output. If it contains a fenced patch: create an isolated git worktree, apply the patch, run tests, then delegate a verifier subagent to review the diff. Escalate ambiguous or denylisted paths. Update STATE.md with the outcome." +``` + +Chain the two jobs with: + +```bash +hermes cron edit --context-from "$TRIAGE_ID" +``` + +The fixer's prompt is prefixed with the triage job's most recent completed output on every tick — Hermes's built-in inter-job pipeline. + +## Event-Triggered Triage + +Webhook instead of cron — useful after deploys, CI failures, or GitHub Actions notifications: + +```bash +curl -X POST http://127.0.0.1:8765/hooks/agent \ + -H "Authorization: Bearer $HERMES_WEBHOOK_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Run loop-triage on recent CI failures. Update STATE.md. Report only.", + "name": "CI triage", + "deliver": "local" + }' +``` + +Keep hook endpoints on loopback or a trusted tailnet. See [Hermes webhooks](https://hermes-agent.nousresearch.com/docs) and the [`webhook-subscriptions`](https://github.com/nousresearch/hermes/blob/main/skills/devops/webhook-subscriptions/SKILL.md) skill. + +## Verification Split + +| Role | Hermes shape | +|------|--------------| +| Triage | `loop-triage` skill + `hermes cron` with `--deliver local` | +| Implementer | Main agent or `delegate_task(role='leaf', toolsets=['terminal','file'])` in a `git worktree` | +| Verifier | Second `delegate_task` call with a review-only prompt, or a chained cron job | + +Hermes cron runs prefer the **agent's final message** as delivered output — structure verifier work as explicit sub-steps in the prompt or delegate them so intermediate tool output stays out of the summary. + +## Safety (L1 defaults) + +- `--deliver local` — do not pollute human chat history with routine triage turns until you trust the output. +- Restrict which toolsets the sub-agents can call: pass `enabled_toolsets` on `delegate_task`, or keep the skill's tool list minimal. +- Home-channel `allowFrom` / mention rules should be set before switching `--deliver` away from `local`. +- Week one: **report-only**; human reads `STATE.md` and the local output before enabling channel delivery. +- Approvals: set `hermes config set approvals.mode smart` so low-risk commands don't stall the loop on manual gateway approvals. + +## Operations + +```bash +hermes cron list +hermes cron status +hermes cron run # fire on next scheduler tick, one-off +hermes cron pause +hermes cron resume +hermes cron edit --prompt "..." +hermes cron remove +``` + +Pause without deleting: `hermes cron pause `. Or set `loop-pause-all` inside `STATE.md` and teach the skill to short-circuit when it sees that flag — the loop keeps ticking but produces no side effects, which preserves scheduler history for audit. + +Audit readiness: `npx @cobusgreyling/loop-audit . --suggest` + +## References + +- Peter Steinberger — design loops, not one-off prompts ([sources](../../resources/sources.md)) +- [primitives-matrix.md](../../docs/primitives-matrix.md) — Hermes column +- [patterns/daily-triage.md](../../patterns/daily-triage.md) +- [docs/safety.md](../../docs/safety.md) +- [Hermes docs](https://hermes-agent.nousresearch.com/docs)