tg-relay 能否驱动非 tmux 的 Claude Code session?

tg-relay 的 inbound 路由依赖 tmux pane ID(%NN)——收到 Telegram 消息后,它调 tmux send-keys/tmp/tg-*.md 注入对应 pane。mux.driver local 跑的是前台进程,没有 tmux pane,所以 relay 找不到投递目标,直接失败。

Outbound 没问题:notify_shuke 不依赖 tmux,local driver 下照常发 TG,reply index 里用 MUX_DRIVER_SLUG 代替 %NN 记录身份。问题只在 inbound。

可行路径:named FIFO + Stop hook exit 2

每个 local session 启动时用 slug 创建一个 named FIFO:

mkfifo /tmp/mux-tg-${MUX_DRIVER_SLUG}.fifo

tg-relay 看到 reply index 里的 pane ID 是 slug 而非 %NN,就写这个 FIFO 而非调 tmux:

echo "$message" > /tmp/mux-tg-${slug}.fifo

Claude Code 的 Stop hook 在每个 turn 结束时检查这条 FIFO:

# Stop hook
fifo="/tmp/mux-tg-${MUX_DRIVER_SLUG}.fifo"
if read -t 0.1 msg < "$fifo" 2>/dev/null; then
    echo "$msg"
    exit 2   # 拦住 stop,把消息作为 additionalContext 注入
fi
exit 0

exit 2 的语义:Claude 不停止,stdout 作为 additionalContext(system feedback)注入同一个 turn,Claude 继续处理。技术上不是新的 user message,是 same-turn 的 system context,但效果上 Claude 会读到并响应 TG 消息。

局限

  • hook 只在 turn 边界触发。FIFO 里的消息要等当前 turn 结束才被拉取。如果turn结束时FIFO里是空的,那这个turn就正常结束了。没有机会再接到后续FIFO的内容。这是一个致命缺陷。让整个方案变得不再可行。
  • additionalContext ≠ user message:conversation history 里这不是一条用户消息,边角行为可能和正常 TG 路由有差异。
  • FIFO 阻塞:写端无读端时 echo > fifo 会阻塞,relay 需要用 O_NONBLOCK 或超时保护。

不完美,但架构上可行,不需要改动 Claude Code 本身。

Comments

  1. Markdown is allowed. HTML tags allowed: <strong>, <em>, <blockquote>, <code>, <pre>, <a>.