hermes - ✅(Solved) Fix feat(gateway): `/cc` command — route messages to Claude Code CLI without going through Hermes [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#12122Fetched 2026-04-20 11:58:19
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×1referenced ×1

Fix Action

Fix / Workaround

  • hermes_cli/commands.py — one CommandDef("cc", …, gateway_only=True) entry so the command shows in /help and routes to the handler.
  • gateway/run.py — command dispatch, CC-mode hijack in the message handler, and two small methods (_handle_cc_command, _run_cc_task) plus two class-level state containers (_cc_sessions, _cc_mode).

PR fix notes

PR #12124: feat(gateway): add /cc command to route messages to Claude Code CLI

Description (problem / solution / changelog)

Closes #12122.

Summary

Adds a /cc gateway command that lets any connected chat channel (Feishu, Slack, Discord, Telegram, …) forward messages to the local claude CLI instead of running the Hermes agent. Useful for users on a Claude Max subscription who want access to Claude Code's full tool / skill ecosystem from a chat client.

Two modes:

  • One-shot/cc summarize the last 50 lines of ~/logs/app.log runs a single claude -p invocation and returns the result.
  • Sticky CC mode — bare /cc toggles a per-session mode; while enabled, every non-command message is forwarded to claude -p. Slash commands still dispatch normally. Users leave with /cc, quit, exit, or stop.

Multi-turn continuity is preserved: the session_id returned by Claude Code is cached per gateway session and passed back via --resume <id> on the next invocation, so context carries across turns in the same chat.

Behavior details

Subprocess invocation:

claude -p <task> --output-format json --max-turns 20 [--resume <prev_session_id>]
  • cwd=os.path.expanduser("~") — matches what the user sees when they run claude in a fresh terminal.
  • timeout=300.
  • JSON output parsed; reply = <result>\n\n---\n⏱ <num_turns> turns | 💰 $<total_cost_usd>.
  • FileNotFoundError❌ claude CLI not installed. Run: npm i -g @anthropic-ai/claude-code.
  • Non-zero exit → ❌ Claude Code error: <stderr first 500 chars>.

Scope

FileChange
hermes_cli/commands.py+2 lines: one CommandDef("cc", …, gateway_only=True) entry so the command appears in /help and routes to the handler.
gateway/run.py+99 lines: dispatch /cc in the command router; CC-mode hijack in the message handler; _cc_sessions / _cc_mode class state; _handle_cc_command + _run_cc_task methods.

No changes to platform adapters.

Test plan

  • pytest tests/hermes_cli/ tests/gateway/ — 2301 passed, 3 pre-existing unrelated failures on origin/main (WSL systemd-detection tests and one web-server schema test), none introduced by this change.
  • Module imports cleanly (import gateway.run; import hermes_cli.commands).
  • Manual: invoke /cc in a gateway-connected chat; verify toggle mode, one-off execution, and multi-turn --resume continuity.

Design questions worth discussing (see #12122)

  1. _cc_sessions / _cc_mode are in-memory class state — single gateway process only. Should they persist to the state DB?
  2. Per-user authorization within a channel — should /cc gate on operator identity, or is that the host's responsibility?
  3. Configurable max-turns / timeout / cwd — env vars or config.yaml section?
  4. Streaming vs single-reply for long runs.

Changed files

  • gateway/run.py (modified, +124/-0)
  • hermes_cli/commands.py (modified, +2/-0)

Code Example

/cc summarize the last 50 lines of ~/logs/app.log

---

/cc                   ← toggles mode on (or off if already on)
how many users signed up yesterday?
add a unit test for the signup handler
quit / exit / stop    ← leaves CC mode

---

claude -p <task> --output-format json --max-turns 20 [--resume <prev_session_id>]
RAW_BUFFERClick to expand / collapse

Motivation

Hermes already exposes many LLM providers through its gateway and the /model switch, but there is one surface it cannot reach directly: the local Claude Code CLI (claude -p …). For users on a Claude Max subscription, running through claude means work is billed against the subscription and inherits the CLI's full tool-use / skill ecosystem (Read/Write/Grep/Bash/MCP/skills/…), which Hermes cannot fully replicate from inside its own agent runtime.

Today, the only way to use Claude Code from a chat session is to open a terminal. That defeats the point of having Hermes wired into Feishu/Slack/Discord/Telegram/… in the first place — the chat client is the UI the user is already in.

Proposal

Add a /cc gateway command that lets any connected chat channel talk to Claude Code through the user's local claude CLI. Two modes:

One-shot

/cc summarize the last 50 lines of ~/logs/app.log

Runs a single claude -p <task> call and returns the response. Session-id is remembered for continuity (see below) but chat otherwise stays in normal Hermes mode.

Sticky "CC mode"

/cc                   ← toggles mode on (or off if already on)
how many users signed up yesterday?
add a unit test for the signup handler
quit / exit / stop    ← leaves CC mode

Once toggled on for a session, every subsequent non-command message is routed to Claude Code instead of Hermes. Slash commands still work (so /help, /model, etc. are unaffected). The user leaves CC mode with /cc, quit, exit, or stop.

Multi-turn continuity

_cc_sessions: Dict[str, str] maps gateway session_key → Claude Code session_id. On each /cc execution, if a prior session_id exists, it is passed back via --resume <id> so Claude Code keeps context across turns in the same chat. The returned session_id from the JSON output is stored for the next turn.

Subprocess invocation

claude -p <task> --output-format json --max-turns 20 [--resume <prev_session_id>]
  • cwd=os.path.expanduser("~") so Claude Code runs with the user's home as project root (same as claude in a fresh terminal).
  • timeout=300 seconds.
  • JSON output is parsed to extract result, session_id, num_turns, total_cost_usd.
  • Response to chat = <result>\n\n---\n⏱ <turns> turns | 💰 $<cost>.
  • FileNotFoundError → returns ❌ claude CLI not installed. Run: npm i -g @anthropic-ai/claude-code.

Scope

Touches 2 files:

  • hermes_cli/commands.py — one CommandDef("cc", …, gateway_only=True) entry so the command shows in /help and routes to the handler.
  • gateway/run.py — command dispatch, CC-mode hijack in the message handler, and two small methods (_handle_cc_command, _run_cc_task) plus two class-level state containers (_cc_sessions, _cc_mode).

No changes to platform adapters — the feature works on any platform the gateway already supports.

Open design questions

  1. Multi-process deployment. _cc_sessions / _cc_mode are class-level in-memory state, so they only work within a single gateway process. Is that acceptable, or should they be persisted (e.g. to the state DB)?
  2. Authorization. gateway_only=True restricts usage to sessions connected through the gateway, but there is no per-user allowlist — anyone in a whitelisted chat can invoke claude with the host user's credentials. Should /cc gate further on operator identity, or is that the user's responsibility when they expose the channel?
  3. Config. Should max-turns, timeout, and the cwd be configurable (env var / config.yaml section) instead of hardcoded?
  4. Streaming. First cut is blocking (wait for the subprocess, then reply once). Should long runs stream intermediate progress back, or is a 300 s ceiling with a single final reply good enough?

Happy to iterate on any of these before submitting the PR.

extent analysis

TL;DR

To integrate Claude Code with Hermes, implement a /cc gateway command that routes chat messages to the local claude CLI, handling one-shot and sticky modes with session continuity.

Guidance

  1. Implement command routing: Add a CommandDef("cc", …, gateway_only=True) entry in hermes_cli/commands.py to route the /cc command to its handler.
  2. Handle CC mode: In gateway/run.py, implement the _handle_cc_command and _run_cc_task methods to manage CC mode and execute Claude Code tasks.
  3. Manage session state: Decide on a persistence strategy for _cc_sessions and _cc_mode state, either keeping it in-memory or persisting to a state DB, considering multi-process deployment.
  4. Consider authorization and config: Evaluate the need for per-user allowlists and configurable settings like max-turns, timeout, and cwd to ensure secure and flexible usage.

Example

# hermes_cli/commands.py
CommandDef("cc", handler=_handle_cc_command, gateway_only=True)

# gateway/run.py
def _handle_cc_command(self, message):
    # Toggle CC mode or execute one-shot command
    if message == "/cc":
        # Toggle CC mode
        self._cc_mode = not self._cc_mode
    else:
        # Execute one-shot command
        self._run_cc_task(message)

def _run_cc_task(self, task):
    # Execute Claude Code task using subprocess
    subprocess.run(["claude", "-p", task, "--output-format", "json", "--max-turns", "20"])

Notes

The implementation should consider the open design questions, such as multi-process deployment, authorization, and configuration, to ensure a robust and secure feature.

Recommendation

Apply the proposed workaround by implementing the /cc gateway command and its associated handlers, considering the guidance points above. This will allow users to leverage Claude Code from within the chat client, enhancing the overall user experience.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING