如何在 AFK Ralph 中流式查看 Claude Code 输出
运行 AFK Ralph 时实时流式查看 Claude Code。学习使用 jq 获取 Claude 输出,而不是盯着空白屏幕。
本页目录
本指南面向已经尝试用 Claude Code 运行 Ralph、却遇到这一恼人问题的人:运行 AFK 脚本后,只能盯着空白屏幕。
如果从未听说过 Ralph,请从这里开始:
问题:空白屏幕
如果希望离开键盘后 Ralph 继续运行,可能会使用下面这样的脚本:
#!/bin/bashset -eif [ -z "$1" ]; thenecho "Usage: $0 <iterations>"exit 1fifor ((i=1; i<=$1; i++)); doresult=$(docker sandbox run --credentials host claude \--print \"<your prompt here>")if [[ "$result" == *"<promise>COMPLETE</promise>"* ]]; thenecho "Ralph complete after $i iterations."exit 0fidone
令人沮丧的问题是:使用 --print 标记运行 Claude 时,完全没有流式输出,终端一片空白。
离开后,你完全不知道发生了什么:Claude 在工作吗?卡住了吗?是不是出了问题?只有结束时才会知道。
AFK Ralph 的理想状态是兼得两者:既能实时看到 Claude 在做什么,又能在离开时让它继续运行。
想继续深入: 加入“面向真正工程师的 AI 编码”候补名单
解决方案:使用 jq 流式输出
Claude 可以输出 stream-json 格式,实时提供每一条消息,但输出极其冗长,难以阅读。
通过组合 stream-json with jq 过滤,可以只提取有用信息并实时流式显示到终端,同时捕获最终结果,以检查 <promise>COMPLETE</promise> 标记。
下面是完整脚本:
#!/bin/bashset -eif [ -z "$1" ]; thenecho "Usage: $0 <iterations>"exit 1fi# jq filter to extract streaming text from assistant messagesstream_text='select(.type == "assistant").message.content[]? | select(.type == "text").text // empty | gsub("\n"; "\r\n") | . + "\r\n\n"'# jq filter to extract final resultfinal_result='select(.type == "result").result // empty'for ((i=1; i<=$1; i++)); dotmpfile=$(mktemp)trap "rm -f $tmpfile" EXITdocker sandbox run --credentials host claude \--verbose \--print \--output-format stream-json \"<your prompt here>" \| grep --line-buffered '^{' \| tee "$tmpfile" \| jq --unbuffered -rj "$stream_text"result=$(jq -r "$final_result" "$tmpfile")if [[ "$result" == *"<promise>COMPLETE</promise>"* ]]; thenecho "Ralph complete after $i iterations."exit 0fidone
脚本接收一个参数:要运行的迭代次数。
逐步解析脚本结构
拆解流过滤器
流过滤器会执行几项重要操作:
- 选择 assistant 消息:
select(.type == "assistant")只获取 Claude 的响应 - 提取文本内容:
.message.content[]? | select(.type == "text").text只取出文本部分 - 修复行尾:
gsub("\n"; "\r\n")把换行替换为回车加换行 - 添加间距:
. + "\r\n\n"在消息之间插入额外空白
替换回车可以修复光标无法正确返回行首字符的问题。
数据管道
数据在脚本中的流动方式如下:
Docker 会流式输出 stream-json 格式的数据,但其中还夹杂一些无意义的非 JSON 行。 grep --line-buffered '^{' 过滤器可以确保只处理有效 JSON 行。
随后, tee "$tmpfile" 命令会在不中断数据流的情况下,把全部内容写入临时文件。稍后需要用该文件检查 Claude 是否完成。
最后, jq --unbuffered -rj "$stream_text" 应用流过滤器,并在终端中实时显示文本。
总结
我希望不久后就能删除本文,因为 Claude Code 会推出一项功能,在流式显示响应的同时仍能捕获最终输出。
OpenCode 已经支持这项能力,因此不需要为 OpenCode 写类似文章。在 Claude Code 支持之前,这仍是运行 AFK Ralph 时实时查看 Claude 流式输出的可行方案。