From claude-code-hermit
Handles inbound messages from Claude Code Channels (Telegram, Discord, webhooks) with session context awareness, state checks, user authorization, and message classification.
npx claudepluginhub gtapps/claude-code-hermit --plugin claude-code-homeassistant-hermitThis skill uses the workspace's default tool permissions.
When a message arrives via a channel:
Sends and receives direct messages between active Claude Code sessions on the same machine. Use for coordinating parallel sessions via dm, broadcast, active checks, and project-scoped messaging.
Displays status (installed/authenticated/active) of messaging channels (WhatsApp, Telegram, Discord, iMessage, Slack, Fakechat) and launch commands via /agent:channels variants.
Manages Claude Code sessions mirrored to Slack via slaude CLI: start/stop/join in channels/users, list running sessions, configure access modes/flags.
Share bugs, ideas, or general feedback.
When a message arrives via a channel:
Read .claude-code-hermit/sessions/SHELL.md for current task context.
Read state/runtime.json for lifecycle state (session_state is the source of truth — never parse SHELL.md Status: for decisions).
If runtime.json session_state is idle (no active task):
If runtime.json session_state is waiting (alive but blocked on input):
Read waiting_reason from runtime.json to understand why:
"unclean_shutdown" or "dead_process" → operator reply is an archive/resume choice: (1) = archive as partial and start fresh, (2) = resume as-is. Handle accordingly via claude-code-hermit:session-mgr — session-mgr owns the full state transition including clearing waiting_reason.
"operator_input", "conservative_pickup", or null → treat as normal task resumption.
Status request → respond with current context, stay waiting
New instruction or answer to a question → update runtime.json session_state to in_progress, clear waiting_reason to null, update SHELL.md Status to in_progress (cosmetic), resume work
Anything else → respond, stay waiting
Read config.json → channels.<channel>.allowed_users for the inbound channel:
allowed_users list: ignore the message silently — do not respond, do not log. Applies to ALL message types including status requests.allowed_users is absent for this channel: accept all messages (backwards compatible)allowed_users is an empty array []: accept from no one (explicit lockdown)The allowlist is per-channel inside the channels object in config.json:
{
"channels": {
"discord": { "enabled": true, "allowed_users": ["user-id-1"] },
"telegram": { "enabled": true, "allowed_users": ["user-id-1"] }
}
}
After authorization passes, store the inbound chat_id to config.json → channels.<channel>.dm_channel_id (e.g. channels.discord.dm_channel_id) if it differs from the currently stored value or hasn't been stored yet.
This is how the agent learns the DM channel ID for proactive outbound notifications. In Discord, the DM channel ID differs from the user ID and is only discoverable from an inbound message. Write back to config.json only when the value has changed to avoid unnecessary writes.
Slash command (message starts with /, e.g. /simplify, /plugin:command)
Status request ("what are you working on?", "status", "progress")
idle: respond with session summary — tasks completed, cumulative cost, "ready for what's next"in_progress: respond with a concise summary of SHELL.md: task, current step, blockersTask assignment (only when Status is idle: "work on X", "next task: Z", "start Y", or any message describing work to be done)
/claude-code-hermit:session-start to begin the new task (idle → in_progress)Micro-approval response ("yes", "no", "MP-… yes/no", or similar while any pending micro-proposal exists)
state/micro-proposals.json → pending. Filter to status: "pending" entries.MP-YYYYMMDD-N yes): match that entry by id.yes/no and exactly one pending entry: apply to that entry.yes/no and multiple pending entries: reply listing the pending IDs and ask the operator to specify (e.g. "MP-20260422-0 yes"). Do not resolve yet.question from the entry before modifying.status: "approved". Append micro-resolved event via append-metrics.js: {"ts":"<now ISO>","type":"micro-resolved","micro_id":"<id>","action":"approved","question":"<question>"}/claude-code-hermit:proposal-create, queue for next idle, set status: "approved". Append micro-resolved event with "action":"approved".status: "rejected". Append micro-resolved event with "action":"rejected","question":"<question>".pending. Write the file.Proposal approval ("accept PROP-", "go ahead with PROP-", "approve PROP-", or referencing proposal numbers)
/claude-code-hermit:proposal-act accept PROP-NNN for each referenced proposal/claude-code-hermit:proposal-list to resolve to PROP-NNN IDs. If no match, tell the operator.New instruction ("work on X", "switch to Y", "prioritize Z")
idle: treat as Task assignment (above)Question ("why did you...", "what about...", "how does X work?")
Emergency ("stop", "abort", "revert", "rollback")
blocked and reasonThis skill is a stub for the Channels research preview (Claude Code v2.1.98+). As Channels matures, extend this skill with: