Skip to content
Automation
Skill

/channel-responder

Handles inbound messages tagged <channel source=...> from Claude Code Channels, routing replies, task work, approvals, and operator controls with session context.

From plugin
hermitd
8489 skills14 agents

Claude Code

$ npx -y skills add gtapps/hermitd --skill channel-responder --agent claude-code

SKILL.md

channel-responder.SKILL.md
name: channel-responder
description: Handles inbound messages tagged <channel source=...> from Claude Code Channels, routing replies, task work, approvals, and operator controls with session context.

Channel Responder

When a message arrives via a channel:

Commands

  • `leftover-check`: `bun ${CLAUDE_PLUGIN_ROOT}/scripts/evolve-plan.ts .hermit leftover-check`
  • `routines-health`: `bun ${CLAUDE_PLUGIN_ROOT}/scripts/routines.ts health .hermit`
  • `settings-get-routines`: `bun ${CLAUDE_PLUGIN_ROOT}/scripts/settings-edit.ts .hermit/config.json get routines`

0. Reply via the channel

Every response to `<channel source="..." chat_id="..." ...>` must use the channel's reply tool, including acknowledgements. Terminal narration is secondary and invisible to the operator.

Build `mcp__plugin_<plugin-name>_<server-name>__reply` from both segments of the raw `source="plugin:<plugin-name>:<server-name>"`. For example, `plugin:discord:discord` maps to `mcp__plugin_discord_discord__reply`, while `plugin:acme-crm:crm` maps to `mcp__plugin_acme-crm_crm__reply`. Do not double one segment. Configuration keys use the normalized bare server name (`discord`, not the qualified source; see `lib/channel-envelope.ts`'s `normalizeChannelSource`).

When only a bare `<sourceKey>` is available (a `later` row's `chat` or a binding key), require exactly one loaded `mcp__plugin_<plugin-name>_<sourceKey>__reply` tool with that server segment. No match or multiple matches means the chat is unreachable: report the undelivered message per § Operator Notification.

Pass the inbound `chat_id`; optionally set `reply_to` to its `message_id`. The result `sent (id: N)` identifies the message for the same plugin's `edit_message`. Without that tool, use short threaded replies in place of progress-card edits and record no `Progress card` line.

**Exception, checked first.** A `[harness-command] … requested` line means stop: no bookkeeping, no tool call and no reply. A `[pause] Hermit paused by …` line containing "Only the channel reply tool works" permits only that reply tool: no bookkeeping or other tools. A `[harness-command] refused "…"` line is replyable; relay its reason. A `[pause] Hermit resumed by …` line is an ordinary turn.

Message formatting

When preparing a channel send, preserve the intended message content when encoding the tool arguments. Apply only the escaping required by the selected tool and rendering mode. Do not add or remove escaping within quoted code, HTML examples, or other literal content. Before sending, compare the final message body with the intended text. Normal JSON encoding still applies. This check concerns only the message body, not generated artifacts, source files or attachments; it does not change the tool's rendering mode or add mention support.

1. Load Context

Apply `MEMORY.md` hook lines tagged `[role]` hermit-wide; apply `[role <key>:<chat_id>]` only to the matching normalized bare channel key (§1c) and chat. Roles apply only to messages addressed to you: every 1:1 DM, or a group/server message mentioning your `bot_user_id`/`bot_username` (the §2 self-mention test). Silently ignore other chats' roles. The hook line suffices; do not Read the topic file. A `[chat instructions]` line is operator-set policy: follow it over memory roles here. Route any admitted sender's change to **Settings change request** without refusing it yourself; the native prompt decides.

Use the injected TASKS.md policy. Before replying, the only bookkeeping calls are `bun ${CLAUDE_PLUGIN_ROOT}/scripts/task.ts list .hermit --open --conversation <sourceKey>:<chat_id>` and the §1d `record-operator-action.ts --force` call after authorization; role checks excepted. Do not reread TASKS.md or runtime.json. The shutdown gate supplies any pending shutdown refusal.

Route every reply to a pending task decision through `task answer [<id>] --chat <key> --user <sender-id> --reply <token>`; map meaning in any language to yes, no, a number, an option label or a deferral ("later"). With exactly one decision pending in this chat, a bare yes, no or later is its answer, including acceptance of a posted result: call `task answer` before replying, adding `--result-rev <result_rev>` from the hook's waiting line when the row has one. Only a `none`/`no_pending` receipt sends a plain result row to the hook's `task close` line, even if the wording feels loose, and never answer or ask about it in chat alone. With two or more pending, ask which one first, naming them, and record nothing. Read [approvals.md](approvals.md) § Answering a wait for its match, ambiguity, refusal and stale outcomes. Never bypass the script with a clear-wait note or a close. An open handle, resident task thread, or continuation of the sole open task selects it. For an ambiguous continuation of other work, ask once naming the tasks and record nothing. Plain questions open nothing. Reply before further record mutations or classification tool calls.

1c. Check Authorization

Use hook-provided authorization and loaded `config.json` → `channels.<channel>.allowed_users`, with the normalized bare key from §0:

  • Use the envelope's `user_id`; fall back to `user` only when `user_id` is absent. Never allowlist-match `user` when `user_id` is present: the sender controls that display name.
  • Ignore non-allowlisted senders silently: no response or log, including for status requests.
  • If `allowed_users` is absent for this channel: accept all messages
  • If `allowed_users` is an empty array `[]`: accept from no one (explicit lockdown)

**Primary operator:** If `channels.<channel>.operators` is set, any listed user id is primary. Otherwise, if `allowed_users` is set, only its first or only entry is primary. Otherwise, the sender must be in the channel's maintainer chat (`maintainer_channel_id`), or in its home chat (`default_chat_id`) with `operator_profile` other than `non-technical`. Empty lists name nobody; where none of these fields exist, nobody is prima

Read more
@gtapps
Ships withhermitd

Run an always-on Claude Code agent on your own machine, for you or your team. Start and orchestrate sessions from chat in any project it can reach. Take over the same session in the Claude app or the CLI.

8489 skills14 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
84
Star history of gtapps/claude-code-hermit on GitHub, a chart by star-history.com

Other skills on hermitd.

bump-core-req

bump-core-req

Updates the minimum core version requirement for a fleet plugin in all three canonical places: `required_core_version` and…

@gtapps@gtappsInstall Skill
commit

commit

Changelog and commit — lightweight motion for day-to-day plugin dev work in the monorepo. One commit per plugin scope; CHANGELOG…

@gtapps@gtappsInstall Skill
docs-drift

docs-drift

Documentation-drift audit for the plugin monorepo. Audits either each scoped plugin's unreleased changelog claims or its latest…

@gtapps@gtappsInstall Skill
downstream-impact

downstream-impact

Explain in plain language what a fix, feature, PR, or plan will actually change for downstream hermits and the operators chatting…

@gtapps@gtappsInstall Skill
fleet-release

fleet-release

Use this skill whenever the user wants to release, ship, prep, or cut versions for two or more plugins together on the current…

@gtapps@gtappsInstall Skill
pipeline-digest

pipeline-digest

Daily release-pipeline digest with a change gate — reports which plugins are pending release, whether main's CI is green, which…

@gtapps@gtappsInstall Skill

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n12d209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

@browser-use@browser-useInstall Skill
agent-browser

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…

@vercel-labs-2@vercel-labs-2Install Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about channel-responder.

Which coding agents can use channel-responder?
channel-responder installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.