克劳德·法布尔始终积极进取
阅读原文· simonwillison.netSimon 的亲身实战把 Claude Fable 5 的「死磕」能力展现得淋漓尽致——为修复一个两行 CSS 问题,它自建截图工具、写 CORS 服务器、注入模板代码。这既是编程 AI 的新疆界,也暴露出沙箱外运行的巨大风险,每个用 AI 写代码的人都该警惕。
Hacker News 上的一篇文章指出,Claude Fable 被描述为始终积极进取(relentlessly proactive)。该文发布在 simonwillison.net,标题为“Claude Fable is relentlessly proactive”,在 HN 上获得 119 个点赞。
Simon Willison 的博客
Claude Fable 具有不懈的主动性
2026年6月11日
在使用 Claude Fable 5 两天后,我觉得最能形容它的词语是“不懈的主动性”。它掌握大量技巧,并且会调用几乎所有技巧来达成目标。
我来举例说明。今天我在捣鼓 Datasette Agent 时发现了一个小问题:跳转菜单的聊天提示框中出现了一条不该存在的水平滚动条。我截了个图:

然后我在 datasette-agent 仓库目录下启动了一个新的 claude 会话,把截图拖进去,告诉它:
查看依赖以帮助找出这里出现水平滚动条的原因
我隐约觉得问题出在 Datasette Agent 的某个依赖里(很可能是 Datasette 本身),而且我知道 Fable 很擅长深入检查依赖代码——要么通过检查自己虚拟环境 site-packages 里的已安装文件,要么引用本地磁盘上的仓库副本。让它从依赖入手,感觉是个不错的思路。
我被家务事分了心,走开了电脑前。
几分钟后我回来时,看到我的电脑在常用的 Firefox 里打开了一个浏览器窗口,然后导航到有问题的那个对话框。我并没有指示 Claude Code 使用任何浏览器自动化操作,而且我相当确定它不可能在窗口内触发鼠标移动或键盘快捷键,那它是怎么做到的?
我着迷地看着它继续探索,然后看到它打开了一个 Safari 窗口,而不是 Firefox。我还从 Claude 终端抓取到了这张截图:

它在用 uv run --with pyobjc-framework-Quartz 干什么?
原来 Fable 自己编写了一套截取浏览器窗口屏幕截图的方法。它通过 Python 遍历我电脑上所有可用的窗口,然后过滤出窗口名称中包含 "textarea" 等预期字符串的 Safari 窗口。它用这个方式找到了窗口编号——一个像 153551 这样的整数——然后通过 screencapture 命令行工具来获取 PNG 截图。
好吧,这确实是一种巧妙的截图方式。但它在截什么图呢?
结果发现,它一直在编写自己的临时 HTML 页面来尝试复现那个 bug,然后打开 Safari 并截图。
下面是它创建的 /tmp/textarea-scrollbar-test.html 页面,以及用命令 `screencapture -x -o -l 153551 /tmp/safari-cases.png` 截取到的截图:
(我开的标签页实在太多了!)
好,我明白它是如何打开测试页面并截图的了,但它究竟是怎么触发那个待测试的模态对话框的呢?这个对话框只能通过点击或键盘快捷键才能调出,而我找不到它在 Safari 里执行这些操作的方式。
我最后终于搞清楚了它的做法。
Claude 运行在一个包含该应用源代码的文件夹里。它足够了解 Datasette,能自己启动本地开发服务器。原来它修改了 Datasette 自己的模板,加入 JavaScript 代码,让窗口一打开就触发正确的键盘快捷键,添加的代码如下:
<script> window.addEventListener("load", function () { setTimeout(function () { document.dispatchEvent(new KeyboardEvent("keydown", {key: "/", bubbles: true})); }, 1200); }); </script>
窗口打开后 1.2 秒,这段代码触发一个模拟的 / 键,也就是打开模态对话框的键盘快捷键。
还剩一个挑战。为了理解发生了什么,Claude 需要在页面上执行 JavaScript 来自行获取测量数据。
它编写了自己的自定义 Web 应用,通过 CORS 来抓取信息,然后将其作为本地服务器运行,并打开一个包含 JavaScript 的页面,该 JavaScript 会直接向它发送 POST 请求!
下面是它编写的 Python Web 应用,使用了标准库中的 http.server 包:
from http.server import HTTPServer, BaseHTTPRequestHandler class H(BaseHTTPRequestHandler): def do_POST(self): n = int(self.headers.get("Content-Length", 0)) open("/tmp/diag.json", "w").write(self.rfile.read(n).decode()) self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") self.end_headers() def do_OPTIONS(self): self.send_response(200) self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Access-Control-Allow-Headers", "*") self.end_headers() def log_message(self, *a): # quiet pass HTTPServer(("127.0.0.1", 9999), H).serve_forever()
这个程序所做的就是接收一个包含 JSON 数据的 POST 请求,并将数据写入 `/tmp/diag.json` 文件。它会发送 `Access-Control-Allow-Origin: *` 头(包括来自 OPTIONS 请求的),这样在其他域名上运行的代码仍然能与之通信。
然后 Claude 将这段代码注入到浏览器中加载的模板里:
const host = document.querySelector("navigation-search"); const ta = host.shadowRoot.querySelector("textarea"); const cs = getComputedStyle(ta); fetch("http://127.0.0.1:9999/diag", { method: "POST", body: JSON.stringify({ dpr: window.devicePixelRatio, scrollWidth: ta.scrollWidth, clientWidth: ta.clientWidth, whiteSpace: cs.whiteSpace, width: cs.width, }), });
这段代码测量 `<navigation-search>` Web 组件内部的 `<textarea>` 元素,并将测量结果发送到服务器,服务器再将结果写入磁盘上的文件,Claude 随后就能读取该文件。
在掌握了所有这些技巧之后,Fable... 触发了某个无形的安全护栏,将自己降级为 Opus。幸运的是,Opus 能够访问完整的对话记录,可以继续使用 Fable 开创的技巧,并且在不久之后找到了、测试并验证了修复方案。
我提示 Opus 执行以下操作:
在 /tmp/automation-report.md 中写一份报告,记录你在本次会话中用来在我电脑上测试真实浏览器的所有技巧,并附上可运行的代码示例。
它生成了这份报告,对于拼凑出这篇文章中事件发生的细节来说,这份报告价值连城。
我还分享了 Claude Code 会话的完整终端记录。
对其所做一切事情的回顾
基于一张截图和一行提示词,Claude Fable 5 + Claude Code 完成了以下操作:
- 搞清楚了运行本地开发服务器的方案(包括启动所需的伪造环境变量)
- 启动了一个 Playwright Chrome 会话
- 开启 Chrome 的可见滚动条设置(defaults write com.google.chrome.for.testing AppleShowScrollBars Always),之后又将其关闭
- 在 Playwright 中依次尝试了 Firefox 和 WebKit,未能复现该 bug
- 发现我的默认浏览器是 Safari
- 创建了一个 textarea-scrollbar-test.html 的 HTML 文档
- 在真实的(而非 Playwright 中的)Firefox 中打开该文档
- 发现 osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1' 被阻止,因为“osascript 未被允许辅助访问”
- 想到了用 uv run --with pyobjc-framework-Quartz python 这个变通方案,如上文所述
- 在网站模板中添加了 JavaScript,用于触发 / 键
- 搭建了一个自己的小型 Python CORS Web 服务器,用于捕获 JSON 数据
- 重写了模板,使其捕获数据并将其发送到服务器
- 通过 Web Component 的 shadow DOM 一路编写脚本,获取所需信息
- 打开 Safari 确认 bug 的来源
- 修改其自定义模板,尝试植入一个潜在的修复方案
- 确认这个临时修复方案有效
- 报告了如何修复该问题
就像我说的,非常主动!
成本估算
我现在用的是每月 100 美元的 Claude Max 套餐,这个套餐包含了 Fable 的大量用量配额,到 6 月 22 日为止;之后 Anthropic 表示会按完整 API 价格对它收费。
我正用 AgentsView 来追踪自己的花费(详见这篇 TIL)。以下是 AgentsView 显示的这次对话如果按全价付费会花多少钱:
~ % uvx agentsview session usage be8850a7-6119-46a0-b5d6-79c7fff5ae2b
Session: be8850a7-6119-46a0-b5d6-79c7fff5ae2b
Agent: claude
Output: 68606
Peak ctx: 113178
Cost: ~$12.11 (claude-fable-5, claude-opus-4-8)
如果不盯紧一点,Fable 会很愉快地烧掉 12 美元的 token,去发明调试 CSS 的新方法。
我真的得把这东西锁起来。
一方面,看着 Fable 费尽周折去获取它为了调试——最终只是修复两行 CSS 的问题——所需的信息,真是令人着迷。
但另一方面……这强有力地提醒我们:编程智能体可以做到你通过终端输入命令能做到的任何事——而且前沿模型知道书里记载的所有技巧,显然还知道一些之前从未有人写下来过的技巧。
如果 Fable 当初是在执行恶意指令——隐藏在代码或 issue 线程中的提示词注入攻击,或者我粗心粘贴到终端里的什么东西——它能走多远来窃取数据或制造其他破坏,想起来是令人警觉的。
在沙箱之外运行编程智能体一直是个坏主意——这是我认为最可能酿成“挑战者号”式灾难的情形,正如 Johann Rehberger 在《AI 中的异常常态化》中所描述的那样。
可以说 Fable 更聪明,因此对潜在恶意指令也更为怀疑。但这种聪明是把双刃剑:如果它确实被指令所颠覆,考虑到其不知疲倦的主动性,它能造成的破坏程度令人恐惧。
更多近期文章
- Datasette Apps:在 Datasette 内部托管自定义 HTML 应用——2026 年 6 月 18 日
- GLM-5.2 可能是目前功能最强大的纯文本开放权重大语言模型——2026 年 6 月 17 日
- 将 WASM 轮子发布到 PyPI 供 Pyodide 使用——2026 年 6 月 13 日
这是 Simon Willison 于 2026 年 6 月 11 日发布的《Claude Fable 不知疲倦地主动出击》。
ai 2,081 prompt-injection 152 generative-ai 1,838 llms 1,806 ai-assisted-programming 390 coding-agents 211 claude-code 117 claude-mythos 17下一篇:将 WASM 轮子发布到 PyPI 供 Pyodide 使用
上一篇:Claude Fable 5 的初步印象
月度简报
每月赞助我 10 美元,即可收到一份精选邮件摘要,汇总本月最重要的大语言模型发展动态。
付钱给我,让我少给你发东西!
Sponsor & subscribe- 披露声明
- 版本说明
- ©