Claude Code Bridge
Bridge every incoming message to a live, persistent claude CLI process running
in a background tmux session. The user interacts via QQ/Telegram/any channel;
Claude Code responds as if they were typing in a real terminal.
Session State Detection (CRITICAL — CHECK EVERY TURN)
At the start of EVERY incoming message, determine session state:
CODEBLOCK0
- -
✅ Claude Code 会话运行中 → CC mode active, route message to CC - INLINECODE2 → CC mode off, respond normally
- INLINECODE3 → tell user and await their approval choice
Construct <SESSION_ID> as <channel>_<chat_id> using only [a-zA-Z0-9_].
Routing Logic
CODEBLOCK1
Startup Flow — Working Directory
When the user wants to start Claude Code without specifying a directory:
- 1. Ask briefly: INLINECODE7
- Parse the reply:
- User sends a path (e.g.
~/projects/paper) →
start ~/projects/paper
- User says "沙盒" / "随便" / "临时" / doesn't specify → INLINECODE10
When the user specifies a directory in the startup command itself:
- - "在 ~/Documents/Code 打开cc" → extract the path → INLINECODE11
- "沙盒打开cc" / "沙盒模式启动cc" → INLINECODE12
Do NOT ask if the path is already provided in the command.
Executing Actions
CODEBLOCK2
IMPORTANT — message quoting: Use tmux send-keys -l (literal mode) so
special characters ($, !, \) are sent verbatim. The script handles this
internally; just pass the raw message as argument 3.
CC Slash Commands — Direct Passthrough
CC's own slash commands work by sending them via send:
| User says | Forward as |
|---|
| INLINECODE18 | INLINECODE19 |
| INLINECODE20 |
send '/model sonnet' |
|
/compact |
send '/compact' |
|
/cost |
send '/cost' |
|
/help |
send '/help' |
|
/clear |
send '/clear' |
|
/diff |
send '/diff' |
|
/fast |
send '/fast' |
|
/vim |
send '/vim' |
|
/context |
send '/context' |
|
/export |
send '/export' |
|
/copy |
send '/copy' |
|
/rewind |
send '/rewind' |
|
/fork |
send '/fork' |
|
/permissions |
send '/permissions' |
|
/tasks |
send '/tasks' |
|
/status |
send '/status' |
|
/stats |
send '/stats' |
|
/review |
send '/review' |
|
/theme |
send '/theme' |
|
/sandbox |
send '/sandbox' |
| Any
/xxx command |
send '/xxx' |
These are NOT OpenClaw commands — forward them verbatim to CC.
All CC slash commands work via passthrough, including ones not listed above.
Handling CC Approval Prompts
When CC encounters a tool it needs permission to run, it shows a TUI selection
menu (arrow-key navigation, not text input). The approve action handles this:
CODEBLOCK3
The user's reply should be interpreted:
- - "y" / "是" / "好" / "1" / "同意" → INLINECODE63
- "2" / "允许" / "一直允许" → INLINECODE64
- "n" / "否" / "不" / "3" / "拒绝" → INLINECODE65
- "取消" / "cancel" → INLINECODE66
Long Tasks & Streaming
For tasks that take a long time (refactoring, writing large codebases):
- 1. Detect intent: if the user's message implies a large task (e.g. "重构整个项目",
"帮我写一个完整的 XXX"), use
--long flag (5-minute timeout)
- 2. If the output is empty after timeout, use
peek to check CC's current state - If CC is still working, inform the user: INLINECODE69
- Then use
peek or history to get progress updates
Formatting — Seamless Mode
Goal: make the user feel like they're talking to Claude Code directly.
When CC session is active:
- - Do NOT prefix every reply with
🤖 CC → — just relay CC's output directly - Only add brief status markers for:
· Session startup / shutdown
· Approval prompts (show the options)
· Errors / timeouts
- - CC's code blocks, file paths, tool output → relay as-is, no reformatting
- Empty output → brief
CC 处理中... then try peek after 3s - Output >3000 chars → show last 2000 chars, note
/cc history for full output - Approval prompt → show options directly, minimal decoration
Error Handling
| Situation | Action |
|---|
| INLINECODE76 returns empty | Wait 3s, run peek, relay result |
| Session not found |
Inform user, offer to
start |
| Session crashed | Detect via
status, offer
restart |
| CC shows error | Relay error verbatim |
| Timeout on long task | Inform user, suggest
peek or
history |
Additional Resources
- -
scripts/claude-code-bridge.sh — Full session management (start/send/approve/stop/restart/status/workdir/peek/history) references/usage.md — User-facing help text and example conversations
Claude Code 桥接
将每条传入消息桥接到后台 tmux 会话中运行的持久化 claude CLI 进程。用户通过 QQ/Telegram/任何渠道进行交互;Claude Code 会像用户在真实终端中输入一样进行响应。
会话状态检测(关键——每轮必查)
在每条传入消息开始时,确定会话状态:
bash
~/.openclaw/workspace/skills/claude-code-bridge/scripts/claude-code-bridge.sh status
- - ✅ Claude Code 会话运行中 → CC 模式激活,将消息路由到 CC
- ⭕ 没有活跃 → CC 模式关闭,正常响应
- ⚠️ CC 正在等待审批 → 告知用户并等待其审批选择
使用仅包含 [a-zA-Z0-9] 的字符构建 ID>,格式为 id>。
路由逻辑
每条传入消息:
1. 运行状态检查
2. 是否为 CC 控制命令?
──── 启动(带工作目录) ────
在 打开cc → 启动
沙盒打开cc / 沙盒模式 → 启动 --sandbox
启动cc(无路径) → 先询问工作目录(见下方启动流程)
──── 其他控制命令 ────
关闭cc → 停止
重启cc → 重启
cc状态 → 状态
cc在哪 / cc目录 → 工作目录
/cc peek → 窥视
/cc history [N] → 历史
3. CC 是否处于等待审批状态?
是 → 解析用户意图(y/n/1/2/3)→ 审批
4. CC 会话是否活跃?
是 → 转发为发送
否 → 作为 OpenClaw 智能体正常响应
启动流程——工作目录
当用户想要启动 Claude Code 但未指定目录时:
- 1. 简要询问:工作目录放哪?发路径就在那里打开,不指定就用临时沙盒。
- 解析回复:
- 用户发送路径(如 ~/projects/paper)→ start ~/projects/paper
- 用户说沙盒/随便/临时/未指定 → start --sandbox
当用户在启动命令本身中指定了目录时:
- - 在 ~/Documents/Code 打开cc → 提取路径 → start ~/Documents/Code
- 沙盒打开cc / 沙盒模式启动cc → start --sandbox
如果命令中已提供路径,请勿询问。
执行操作
bash
SCRIPT=$HOME/.openclaw/workspace/skills/claude-code-bridge/scripts/claude-code-bridge.sh
$SCRIPT start /path/to/workdir # 在指定目录启动
$SCRIPT start --sandbox # 沙盒模式启动
$SCRIPT send # 发送(90 秒超时)
$SCRIPT send --long # 长任务(5 分钟超时)
$SCRIPT approve 1 # 审批:选择是
$SCRIPT approve 2 # 审批:选择始终允许
$SCRIPT approve 3 # 审批:选择否
$SCRIPT approve esc # 审批:取消
$SCRIPT stop # 停止(沙盒自动清理)
$SCRIPT restart # 重启(保留原工作目录)
$SCRIPT restart /new/path # 重启到新目录
$SCRIPT status # 状态(含工作目录信息)
$SCRIPT workdir # 查询当前工作目录
$SCRIPT peek # 原始终端画面
$SCRIPT history 200 # 最近 200 行历史
重要——消息引用:使用 tmux send-keys -l(字面模式),以便特殊字符($、!、\)按原样发送。脚本内部处理此问题;只需将原始消息作为参数 3 传递。
CC 斜杠命令——直接透传
CC 自身的斜杠命令通过 send 发送:
| 用户说 | 转发为 |
|---|
| /plan | send /plan |
| /model sonnet |
send /model sonnet |
| /compact | send /compact |
| /cost | send /cost |
| /help | send /help |
| /clear | send /clear |
| /diff | send /diff |
| /fast | send /fast |
| /vim | send /vim |
| /context | send /context |
| /export | send /export |
| /copy | send /copy |
| /rewind | send /rewind |
| /fork | send /fork |
| /permissions | send /permissions |
| /tasks | send /tasks |
| /status | send /status |
| /stats | send /stats |
| /review | send /review |
| /theme | send /theme |
| /sandbox | send /sandbox |
| 任何 /xxx 命令 | send /xxx |
这些不是 OpenClaw 命令——按原样转发给 CC。
所有 CC 斜杠命令均通过透传工作,包括上述未列出的命令。
处理 CC 审批提示
当 CC 遇到需要权限才能运行的工具时,它会显示一个 TUI 选择菜单(箭头键导航,非文本输入)。approve 操作处理此情况:
CC 显示:
是否继续?
❯ 1. 是
2. 是,允许来自此项目
3. 否
用户的回复应被解释为:
- - y / 是 / 好 / 1 / 同意 → approve 1
- 2 / 允许 / 一直允许 → approve 2
- n / 否 / 不 / 3 / 拒绝 → approve 3
- 取消 / cancel → approve esc
长任务与流式处理
对于耗时较长的任务(重构、编写大型代码库):
- 1. 检测意图:如果用户的消息暗示是大任务(如重构整个项目、帮我写一个完整的 XXX),使用 --long 标志(5 分钟超时)
- 如果超时后输出为空,使用 peek 检查 CC 的当前状态
- 如果 CC 仍在处理,告知用户:CC 仍在处理中,稍后再查
- 然后使用 peek 或 history 获取进度更新
格式化——无缝模式
目标:让用户感觉直接在与 Claude Code 对话。
当 CC 会话活跃时:
- - 不要在每条回复前添加 🤖 CC →——直接转发 CC 的输出
- 仅在以下情况添加简短状态标记:
· 会话启动/关闭
· 审批提示(显示选项)
· 错误/超时
- - CC 的代码块、文件路径、工具输出——按原样转发,不重新格式化
- 空输出——简短提示 CC 处理中...,然后 3 秒后尝试 peek
- 输出超过 3000 字符——显示最后 2000 字符,提示 /cc history 查看完整输出
- 审批提示——直接显示选项,最小化装饰
错误处理
| 情况 | 操作 |
|---|
| send 返回空 | 等待 3 秒,运行 peek,转发结果 |
| 未找到会话 |
告知用户,提供 start 选项 |
| 会话崩溃 | 通过 status 检测,提供 restart 选项 |
| CC 显示错误 | 按原样转发错误 |
| 长任务超时 | 告知用户,建议使用 peek 或 history |
其他资源
- - scripts/claude-code-bridge.sh — 完整的会话管理(启动/发送/审批/停止/重启/状态/工作目录/