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 本身。