mcpField
I
Interceptor

Interceptor

github.com/danielmiessler测试与质量19.6k64 次安装1 天前更新
代码仓库

关于 Interceptor

Interceptor 是用于浏览器和 macOS 操作的自动化技能,面向需要测试真实网页与原生应用的 Agent。它通过实际浏览器界面工作,并可读取 DOM、运行 JavaScript、捕获网络活动及录制操作。

主要功能

  1. 01控制真实 Chrome 和 Brave
  2. 02读取 DOM 并运行 JavaScript
  3. 03捕获网络请求与响应
  4. 04执行浏览器及 macOS 输入操作
  5. 05录制和回放用户流程

适用场景

  1. 01在已登录会话中测试网页
  2. 02检查页面运行错误与网络问题
  3. 03验证部署后的页面表现

MCP 相关

README 提到可选 MCP server 安装命令 `interceptor mcp install`,但此技能中明确不使用该功能。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/danielmiessler/lifeos --skill interceptor

安装后在 Claude Code 中输入/interceptor确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.gitignore
Flows/
README.md
References/
CommandReference.md
Tools/
FrameScrub.ts
HealBridge.sh
CleanupTabs.sh
LaunchTestProfile.sh
EnsureTestProfile.sh
Capture.sh
VerifyImageProbe.ts
VerifyViewport.ts
Pin.sh
Zoom.ts
PreflightIsolation.sh
Workflows/
DispatchAppleEvent.md
CaptureBackgroundedApp.md
DriveBackgroundedApp.md
DriveRichEditor.md
LaunchTestProfile.md
MultiPageCompare.md
OverrideXhr.md
ReadAndExtract.md
ReadAxTree.md
RecordAndReplayMacFlow.md
RecordFlow.md
Reproduce.md
ReplayFlow.md
ScreenshotForVlm.md
TestForm.md
TrustedInputGate.md

详细介绍

自定义

执行前,请检查用户自定义设置是否位于: ~/.claude/LIFEOS/USER/CUSTOMIZATIONS/SKILLS/Interceptor/

如果此目录存在,请加载并应用其中的 PREFERENCES.md、配置或资源。这些内容优先于默认行为。如果目录不存在,则使用技能默认设置。

强制要求:语音通知(执行任何操作前必须完成)

调用此技能时,必须先发送此通知,然后才能做任何其他事情。

  1. 发送语音通知:

    curl -s -X POST http://localhost:31337/notify \
      -H "Content-Type: application/json" \
      -d '{"message": "Running the WORKFLOWNAME workflow in the Interceptor skill to ACTION"}' \
      > /dev/null 2>&1 &
    
  2. 输出文本通知:

    Running the **WorkflowName** workflow in the **Interceptor** skill to ACTION...
    

此步骤不可省略。调用技能后,请立即执行此 curl 命令。

Interceptor — 真实浏览器自动化 + macOS 计算机操控

首要规则,高于一切:如果你发现自己正要让操作人员在浏览器中执行某项操作——打开 URL、点击、填写表单、登录、粘贴值、批准 OAuth/同意页面——这个念头本身就是使用 Interceptor 的触发条件。由你亲自操作。唯一的例外是需要你确实不掌握的机密信息(未知密码、需要硬件 2FA 验证);即便如此,也要由你驱动整个流程,直到确切需要人工操作的那一步,然后只指出这一项必须由人完成的操作。描述让人亲自执行点击操作的步骤,正是此技能旨在避免的失误。

功能

Interceptor 可在 Chrome/Brave 浏览器内部操控真实浏览器;安装桥接程序后,也可操控 macOS 原生应用。它包含六类能力,各自有独立的动词树:视觉捕获、DOM 读取、JS 求值、网络捕获、输入和录制/回放。它会保持你真实会话的登录状态,通过所有主要的机器人检测,并且是进行视觉部署验证的必备工具。

问题所在

无头浏览器工具通过 CDP 通信,网站可以识别并拦截它们,因此自动化浏览器看到的页面可能与已登录用户看到的不同,甚至会被直接拦截。它们还会以独立的浏览器实例运行,没有身份验证,因此无法访问你已登录的内容。而且,页面出现问题时——例如挂载后显示空白屏幕、hydration 不匹配,或卡片闪现后消失——截图无法说明原因。Interceptor 一次解决这三个问题:它通过实际浏览器 UI 操作(不会留下 CDP 指纹),使用你真实的登录会话,并读取实时 DOM、控制台错误和网络流量,从而解释截图无法说明的故障。

工作原理

Interceptor 是一个 Chrome 扩展,可通过实际浏览器 UI 操作;它还可选配 macOS 桥接程序,将相同的控制能力扩展到原生应用、OS 级输入和本地设备上的 VM。

工具: interceptor CLI — Chrome/Brave 扩展,可从浏览器内部控制真实浏览器;另有 macOS 桥接程序,可操控原生应用、OS 级输入和完整 VM 生命周期。 仓库: https://github.com/Hacker-Valley-Media/Interceptor 安装: 从上游发布页面获取已签名的 Interceptor-Browser-<v>.pkg / Interceptor-Full-<v>.pkg,或在现有安装上运行 interceptor upgrade --full。从源代码构建是可选的 — 参见 Workflows/Update.md。 Chrome 扩展: 已签名的安装程序会为你完成注册。如果改为从源代码构建,Tools/Pin.sh 会将构建好的 extension/dist 复制到 ~/.claude/skills/Interceptor/Extension/ — 该目录不会随技能一起提供,而是由 Pin.sh 创建 — 然后 Chrome 通过“Load unpacked”加载它。来源信息记录在 Extension/PINNED_FROM.txt 中(源路径、manifest 版本、内容 SHA256、时间戳)。每次 manifest 版本更新后,Chrome 都会停用未打包的扩展,因此每次重新构建源代码后,都必须重新固定并重新加载副本。它不会自动跟随上游更新。 固定的二进制文件: 任何 interceptor >= 0.23.16 都能与此技能配合使用。(维护者机器说明 — 不代表公开安装:维护者的二进制文件基于本地分支 local-0.23.16 构建,即上游标签 v0.23.16 加上一个经过 cherry-pick 的 screenshot --save 修复,该修复会遵循 --out 并默认保存到 ~/Downloads;在上游合并之前,每次升级都要重新 cherry-pick,并且应从源代码构建,而不是运行 interceptor update,因为自动更新程序会移除补丁。在标准安装中,screenshot --save 会写入当前工作目录 — 请显式传入 --out。)上游采用三端控制平面:Browser + macOS + iOS(通过 WiFi 使用设备上的 XCUITest 运行器,操控自有且已启用开发者模式的 iPhone — interceptor ios *)。标签页生命周期策略(0.23.3 新增): 默认启用命名组复用,空闲的托管组会在 10 min 后自动关闭 — 参见下文的标签页管理。

能力概览 — 六类动词树

每一行都是独立的能力类别。每类在守护进程→扩展的边界使用不同的 WebSocket 消息类型,因此某一类出问题很少会影响其他类别。调试故障页面时,每一行都是独立的诊断路径——切勿因为 screenshot 卡住就放弃 Interceptor,而不先尝试 eval、net log 或 monitor。

动词树顶层动词可获取内容
视觉screenshot(默认采用 DOM 渲染——后台运行时也可用)、screenshot --region、screenshot --pixel --full(窗口必须可见)任意尺寸的 PNG/WebP、选择器、区域截图或滚动拼接的整页截图。通过 Tools/Capture.sh 操作,切勿直接使用 interceptor screenshot。使用 Tools/Zoom.ts 放大查看细节。
DOM 读取read [--markdown]、tree、text、html <ref>、find无障碍树、结构化 Markdown、原始标记、引用
JS 求值eval <code>、eval --main在隔离世界或主世界中运行 JavaScript——用于读取控制台错误、运行时异常、hydration 警告和运行时 DOM 状态
网络net log、net headers、net export --format har|pcapng|json、override、headers add/remove被动捕获请求,完全不留下 CDP 指纹;提供 HAR 1.2 和供 Wireshark 使用的 pcapng
输入click、type、keys、act <ref> [--trusted]、drag、scroll、select、focus浏览器与 macOS 原生输入;使用 --trusted 获取操作系统级 HID 源状态。click --selector <css> 可按 CSS 选择器点击(0.23.6+),返回可点击的 e<ref>,并在合成点击被拒绝时自动升级为操作系统级点击
录制/回放monitor start/stop、monitor export --plan、monitor export --format har将真实用户流程捕获为确定性回放脚本;支持多会话,以及浏览器和 macOS AX 事件

读取控制台错误是一种操作方法,而不是单独的动词:通过 eval --main 注入 console.error / window.error 监听器,将事件存储在 window.__errs 中,然后再次运行 eval 读取事件。此方法适用于 hydration 不匹配、React 错误边界、加载时的 JS 异常,以及任何无提示的运行时故障。在安装监听器和读取事件之间触发重新加载,会丢失捕获的错误——捕获发生在加载之后,因此通过重新加载来复现并无帮助;应改为从下一次用户操作开始捕获,或轮询 getEventListeners(window) / DOM 突变观察器以寻找故障证据。

这在实际工作中的意义。 Astro 页面上的 hydration 故障、React 挂载后的空白页、“卡片闪现后消失”——这些问题都能通过 eval 读取实时 DOM 状态和捕获控制台错误来发现,而不是通过截图。screenshot 卡住并不会妨碍诊断;仍可通过其他所有动词树检查页面。

新增界面与动词(0.17 → 0.22.37)

0.22.2 → 0.22.37 的新增内容(2026-07 发布):

  • 截图自动回退(0.22.37) — DOM 渲染捕获失败后,现在会自动重试 --pixel(结果中会披露副作用;可通过 --no-fallback 禁用)。此功能适用于渲染失败(页面注入被阻止、导航过程中失败),而非静默的合成错误——OPERATIONAL_RULES 中针对动画页面的 --pixel/DOM 几何交叉检查规则仍然适用。
  • 半开 WebSocket 检测(0.22.37) — 守护进程的 keepalive-ack 会捕获已失效但仍保持打开状态的扩展连接,以前这类连接会无声卡住。
  • 确定性标签页定位(0.22.9–10) — tab close <id> / tab switch <id> 会操作你传入的 ID(严格为数字),绝不会操作当前工作标签页。
  • 文件上传全面改进(0.22.21) — 支持任意大小、拖放区域和原生文件选择器。
  • **Safari 界面(0.22.32)**和 MCP 服务(0.22.35,interceptor mcp install) — 此处有意不使用二者:我们通过 CLI 驱动 Chrome 测试配置文件。
  • 扩大无障碍树范围(0.22.37) — 不再从树中剪除零面积的内联包装元素。

上面的六个浏览器动词树仍是核心。从 0.16.9 以来新增的内容:

  • iOS(interceptor ios *)— 通过设备端 XCUITest 运行器(不是 WebDriverAgent),经 WiFi 驱动已解锁且归你所有、已启用开发者模式的 iPhone。动词:tree、find、click、type、scroll、screenshot、app launch|activate|terminate。设置方式包括通过 Xcode 自行完成,或不使用 Xcode、通过 login 使用你的 Apple ID 重新签署运行器。
  • interceptor diagnose — 失败后一次性快照:守护进程(包含实际执行路径)、并行探测的每个已连接上下文、监控器状态。可捕获守护进程脑裂——Chrome 启动了一个守护进程二进制文件,而 CLI 却与另一个通信,以前这会导致静默等待 15 秒后超时。遇到任何卡顿时,先运行它。
  • interceptor manifest — 50 多个动词的机器可读规格(用法、标志、返回值语义)。无需抓取帮助文本即可了解接口约定。
  • 按 Agent 分组标签页(--group <label> / INTERCEPTOR_GROUP)— 将每个 Agent 固定到独立、带颜色且完全隔离的标签页组中,让多个 Agent 共用一个浏览器而互不干扰。interceptor group list|close <label>。这是 --context 之外的第二层隔离。
  • interceptor save — 直接从打开的页面将原始字节(Blob / ArrayBuffer / blob:)保存到磁盘,无需下载文件夹;返回 sha256。
  • interceptor ocr / canvas ocr — 离线 Tesseract 像素 OCR,已捆绑到扩展中(无需桥接,也无需 macOS)。
  • interceptor macos cdp * — 以驱动浏览器标签页的相同方式,驱动 Electron / Chromium 桌面应用的网页内容(Slack、VS Code、Notion、Descript)。

**CLI 接口约定(0.22.1):**参数现在可以按任意顺序传入(open --text-only <url> 可正确解析),仅支持浏览器的安装会隐藏 macOS/iOS 动词(可通过 --all-surfaces / INTERCEPTOR_ALL_SURFACES 覆盖)。直接运行 interceptor / --help 会打印简明的功能卡片;使用 help <cmd> 或 interceptor manifest 查看完整接口约定。

为什么选择 Interceptor?

基于 CDP 的浏览器自动化会被网站检测到。Interceptor 是一个通过实际浏览器 UI 操作的 Chrome 扩展。无需调试器、无需自动化标志,也无需单独的浏览器实例。你保持登录状态、通过机器人检测,Agent 看到的就是你看到的。可选的 macOS 桥接功能将相同的控制界面扩展到原生应用、操作系统级输入和设备端 VM——在此技能中,这种组合就是“计算机使用”所指的含义。

Interceptor vs Apify vs BrightData——如何按规模 × 身份验证选择

这三种工具都能“从网页获取数据”,但它们之间的功能重叠并不多。选择时应考虑页面数量以及是否需要登录状态,而不是上次用的是哪个工具。

  • Interceptor——你操控的一个真实登录浏览器。需要使用自己的登录会话、目标网站会主动拦截机器人,或任务需要交互时使用,例如验证部署、完成 OAuth/登录/表单流程、调试,或从少量受身份验证保护的页面提取数据。判断标准:你可以手动打开每个页面,而且页面会显示你的登录身份。
  • Apify——用于从指定平台(Instagram、LinkedIn、TikTok、YouTube、Facebook、Google Maps、Amazon)批量提取数据的托管云端 Actor。需要并行获取数百到数千条结构化数据,并轮换代理时使用。判断标准:这些页面你绝不会手动打开,而且对应平台有专用 Actor。
  • BrightData——针对任意网站(没有指定平台的 Actor)的四层渐进式抓取;在大规模爬取时,如果遇到强力机器人检测/CAPTCHA,会自动升级到住宅代理。

一句话判断:只需登录一个页面 → Interceptor;要获取指定平台上的 N 条数据 → Apify;要抓取一个受到强力机器人检测保护的任意网站 → BrightData。 Interceptor 是这台 Mac 上的一个浏览器——它不提供托管并行处理、代理池或按平台划分的数据提取器;用它串行处理数千个个人资料既慢,也会危及你的真实账号。不要用它替代 Apify 的规模化能力;如果你需要在一两个页面上以登录用户身份操作,也不要使用 Apify。

严禁事项——每次调用均须遵守

视觉验证只能通过 Interceptor 进行。以下行为绝对禁止,不存在任何例外:

  • screencapture——macOS 原始截图二进制程序。不能作为主要工具,不能在 Interceptor 卡住时作为备用方案,也不能“只截一张图”。严禁使用。
  • 使用 osascript 控制 Chrome——禁止使用 tell application "Google Chrome" to activate、set frontmost of process、set bounds of window、set active tab index、set index of window,以及任何其他窗口状态更改操作。
  • 通过 osascript System Events 发送按键——禁止使用 key code、keystroke、key down。这些操作会向当前获得焦点的对象发送输入,从而打断操作者。严禁使用。
  • 为自动化而抢占焦点——禁止将 Chrome(或任何应用)置于最前,以便截取截图。桥接程序的 CGS/DOM 渲染路径无需改变焦点即可捕获画面。
  • 任何窗口状态更改——禁止移动、调整大小、重新定位或重新排列 Chrome 窗口。窗口排列由操作者管理,Agent 不得更改。
  • 通过 AppleScript 切换标签页——set active tab index of window N 属于双重违规:既会抢占焦点,也会更改操作者正在查看的标签页。

Interceptor 故障时,这些规则依然有效。 Interceptor 卡住并不意味着可以改用原始 OS 工具。如果 Interceptor 无法提供证据,应修复 Interceptor(参见下文“WebSocket 卡死问题”),或者停止并告知操作者本次运行无法完成验证——绝不能改用其他工具。

通过桥接程序路由的 Computer Use 不同。 interceptor macos open <app>、interceptor macos act <ref>、interceptor act <ref> --trusted(以前是 --os)以及其他通过桥接程序路由的操作,都经由获准的桥接接口执行;当工作流明确需要控制原生应用时,允许使用。上述禁令针对的是:(a)绕过 Interceptor 的原始 OS 级操作路径;以及(b)纯粹为了截图而抢占焦点。

预检隔离门(强制)

每个浏览器工作流的第一步。无一例外。

在任何 interceptor open|read|act|inspect|screenshot|navigate|tab|monitor|net|cookies|scroll|click|type 命令进入 Chrome 之前,工作流都必须运行隔离门。优先使用自动恢复入口——它会运行隔离门;如果测试配置文件窗口尚未打开,就会启动该窗口并重新验证,然后才返回:

bash ~/.claude/skills/Interceptor/Tools/EnsureTestProfile.sh   # runs the gate; auto-launches the test profile on exit 5/6; prints READY on success

EnsureTestProfile.sh 封装了 PreflightIsolation.sh(原始隔离门——需要禁用自动启动时,仍可直接调用)。两者遇到任何无法恢复的失败都会以非零状态码退出;如果返回非零状态码,立即停止并报告——绝不要回退到 Default。隔离门会验证以下不变量:

  1. 二进制版本 >= 0.16.0——较旧版本会静默忽略 --context,并回退到守护进程能找到的任意 Chrome 连接。这种回退会导致标签页落入操作员的 Default 窗口。
  2. 已连接固定的测试上下文——根据 UUID 列进行完整字段匹配(而非子字符串 grep,因此不会因表头或部分匹配而误通过)。若未连接该上下文,操作员的 Default 配置文件就是唯一可用目标。
  3. 目标不是 Default。 在触碰任何标签页之前,先解析并检查下一条命令将使用的上下文,确认它既不是 Default,也不在 INTERCEPTOR_WORKING_PROFILE_IDS 拒绝列表中。若匹配 Default 或工作配置文件,必须立即停止(退出码 7)。
  4. 扩展程序是否为最新(宽松处理)。 将 Extension/PINNED_FROM.txt(清单版本 + 内容 SHA256)与上游 $INTERCEPTOR_SRC/extension/dist 进行比较,前提是该目录存在。不匹配 → 失败并提供重新固定版本的处理建议。上游目录不存在(目前如此)→ 发出警告并继续。这项检查不会依据 status --verbose,因为该命令不会公开扩展程序构建字段。

如果任何检查失败,脚本都会以非零状态码退出,并向 stderr 输出结构化的处理建议。**工作流必须在退出码非零时立即停止。**报告该消息。**绝不要回退到针对 Default 配置文件执行操作。**不要“无论如何都试试”。不要使用 screencapture 或 osascript 作为替代方案。

需要区分情况的处理程序可使用以下退出码:

  • 2 — PATH 中找不到 interceptor 二进制文件
  • 3 — 无法解析版本字符串
  • 4 — 版本低于最低要求(通过 Workflows/Update.md 升级)
  • 5 — 未连接任何浏览器上下文(Chrome 已关闭或扩展程序失效)
  • 6 — 找不到固定的测试上下文(需要进行一次性配置文件设置)
  • 7 — 解析出的目标是 Default 或工作配置文件(必须立即停止)

隔离门是不可违背的规范。它必须无条件运行——无论是只读获取公共页面、验证已认证工具,还是截取屏幕截图,任何情况都不例外。不存在“可以安全跳过”的情况,因为任何静默回退到 Default 的行为都会违反操作员对窗口的规定。

隔离规范(关键——代码强制执行的硬性规则)

**每条浏览器命令都必须针对固定且隔离的 Interceptor 测试上下文运行——始终使用该上下文,绝不使用操作员的 Default 配置文件,也绝不使用其工作或监控配置文件。**这是一项宪法级规则,而非偏好。

  • 目标上下文是 preferences.env 中的 INTERCEPTOR_TEST_CONTEXT_ID。 它通常被固定为原始上下文 UUID。长期解决方案:将原始 UUID 替换为在扩展弹出窗口中设置的友好名称 interceptor-test——友好名称在重新加载后仍然有效;原始 UUID 则会在每次扩展重新加载时失效(参见下文“UUID 失效”)。
  • 隔离边界是 Chrome 配置文件,而不是用户数据目录。 测试配置文件位于与操作者 Default 配置文件相同的 Chrome 安装中,但 Cookie、标签页和窗口相互独立。它已登录操作者的账户(Google、GitHub、Cloudflare、博客管理后台及其他管理面板)——这正是这样设计的全部目的。--user-data-dir 沙盒毫无用处,因为它没有任何身份验证信息,也无法访问操作者已登录的工具。
  • 默认情况下,操作者的 Default 配置文件为只读。 除非操作者明确提出要求(“在我的 Default 配置文件中验证”“使用主窗口”),否则绝不要在 Default 中打开标签页、点击、输入、导航或录制。如果操作者提出此类要求,先通过 interceptor contexts 确认连接,再使用 --context <default-id> 进行操作。
  • “使用不同的应用”并不是安全保障——操作者自己的浏览器也可能是 Chrome。 如果操作者在不同的应用中浏览,把他们的窗口误认为测试上下文会自行纠正;但如果两者都是 Chrome,就不会。因此,唯一能将他们的浏览与自动化操作隔开的是配置文件固定机制。要将每个无法识别的 Chrome 上下文都视为操作者的上下文,并通过 open -a "Google Chrome" "<url>"(使用他们的常规配置文件)提供链接,而不是在你控制的上下文中导航。
  • 一次性设置见 Workflows/LaunchTestProfile.md——操作者点击 Chrome 的头像菜单 → 添加配置文件 → 登录 → 加载 Interceptor 扩展 → 在弹出窗口中为上下文命名。

已废弃的行为——绝不要重新推导。 旧规则“找不到固定上下文时,回退到第一个可用上下文/Default”已删除。固定的上下文缺失或已失效时,必须立即停止并采取补救措施,绝不能回退。不存在自动将操作路由至 Default 的代码路径。

为何裸命令不安全。 连接 2 个或更多上下文时,守护进程会报错:multiple extensions connected, use --context <id>——如今只有这种快速失败机制能保护裸命令。一旦操作者关闭其他浏览器窗口(只剩 1 个上下文),裸命令就会静默地自动路由到剩余的唯一上下文。因此,每个浏览器操作命令都必须使用 --context "$INTERCEPTOR_TEST_CONTEXT_ID"(或通过 Tools/Capture.sh 进行路由),这不是可选项。

UUID 失效——长期解决方案。 上下文 ID 是由 chrome.storage.local 保存、在配置文件间保持稳定的 UUID,仅在扩展重新安装/重新加载时更改(Chrome 重启不会导致更改)。长期解决方案是在扩展弹出窗口中设置友好名称 interceptor-test,并固定该名称。在此之前,Tools/Capture.sh 会执行受保护的自动重新绑定——仅当恰好有一个非 Default 测试上下文已连接,且能确证 Default 已被排除时才会执行。固定项失效时,绝不会回退到 Default。

这是一条规范,而非偏好。 操作者的 Default 配置文件中有他们正在处理的标签页,也有他们的 DA 一直在操作的标签页。每条命令多加一个标志,代价为零;而在他们正在使用的窗口中误开一个测试标签页——一次点击、一次意外重定向——造成的影响则无法挽回,且会干扰工作。 允许在 context-not-connected 时自动恢复——通过 EnsureTestProfile.sh,绝不能直接启动。 当测试配置文件窗口未打开时(PreflightIsolation.sh 退出码为 5 = 没有上下文,或退出码为 6 = 固定的上下文未连接),Tools/EnsureTestProfile.sh 会启动已配置的测试配置文件,并重新运行检查,持续轮询,直到固定的上下文连接为止。这是安全的,因为有一条不变规则:只有在 PreflightIsolation.sh 本身退出码为 0 后,它才会继续执行——该脚本会将已连接的上下文与 INTERCEPTOR_TEST_CONTEXT_ID 进行完整匹配,并明确拒绝 Default/工作配置文件。因此,启动错误的 --profile-directory 绝不会导致 Agent 操作该配置文件;预检仍会失败,EnsureTestProfile 也仍会停止。安全性来自启动后的重新验证循环,而不是对配置文件参数的信任。退出码 7(解析出的目标是 Default/工作配置文件)和退出码 8(未设置测试上下文)绝不会触发启动——它们会显示错误并停止。即便单独使用、不进行重新验证,直接运行 LaunchTestProfile.sh 仍然不安全:始终应通过 EnsureTestProfile.sh 运行。如果启动成功,但固定的上下文始终未连接(扩展重新加载后 UUID 失效),EnsureTestProfile 会显示一次性的持久修复方法(在弹出窗口中将上下文命名为 interceptor-test),然后停止——它不会自行猜测。

渲染生命周期门控——隐藏标签页陷阱(动画/响应式工作必做)

对于窗口不可见的任何标签页——窗口最小化、被其他窗口完全遮挡,或处于非活动的 Space——Chrome 都会暂停整个渲染生命周期。 在这种状态下:

仍然有效(因此测量结果看起来正常)悄然失效
setTimeout / setInterval(限流至约 1 次/秒)requestAnimationFrame
getBoundingClientRect() — 按需强制执行布局ResizeObserver
CSS 媒体查询/静态布局IntersectionObserver
DOM 读取、screenshot(DOM 渲染路径)CSS 过渡和动画、延迟加载、滚动显示

这是最危险的一类故障:不会报错。响应式或动画页面会返回看似可靠、格式正常的数值,却显示什么也没发生,于是很容易得出“该功能没有触发”或“它能正常工作,没有检测到变化”的结论。2026-07-30 的实时测量结果:在 5 秒内执行两次真实元素大小调整时,固定测试上下文报告 visibilityState: hidden,rAF 触发 0 次,ResizeObserver 回调 0 次,而 setInterval 触发了 5 次。

规则:任何关于动画、过渡、ResizeObserver/IntersectionObserver 行为、延迟加载、滚动显示或视口响应式布局的结论,都必须来自 Tools/VerifyViewport.ts,不能来自标准测试上下文。 手动驱动组件自身重新计算来“证明”它有效,是用自己的手测试自己的代码,而不是验证浏览器。

bun ~/.claude/skills/Interceptor/Tools/VerifyViewport.ts check
bun ~/.claude/skills/Interceptor/Tools/VerifyViewport.ts probe <url> --widths 1440,1100,880 --expr @probe.js
bun ~/.claude/skills/Interceptor/Tools/VerifyViewport.ts shot  <url> --width 880 --out ~/Downloads/x.png
bun ~/.claude/skills/Interceptor/Tools/VerifyViewport.ts stop

它的工作原理,以及为何别无他法。 反限流开关(--disable-backgrounding-occluded-windows、--disable-renderer-backgrounding、--disable-background-timer-throttling)只有在启动浏览器进程时才会生效,而且一个浏览器进程只服务一个 --user-data-dir。因此,它们永远无法应用于已经运行的 Chrome;--profile-directory 也会共用该进程,所以无论怎样切换配置文件,都无法解决操作员浏览器的问题。VerifyViewport 会在独立的 --user-data-dir 中运行一个独立的无头 Chrome,并启用这些开关。无头模式不会创建任何窗口,因此不会占用操作员的桌面,也无需依赖任何窗口状态;同时,它运行的仍是同一个渲染器,完整的生命周期保持活动状态。需要亲眼观察流程时,设置 INTERCEPTOR_VERIFY_HEADFUL=1 即可打开一个真实窗口(放在一旁)。

它通过 CDP(interceptor macos cdp)驱动,而不是通过扩展,因为当前 Chrome 中的 --load-extension 已不可用(会被静默忽略——已在 152 上确认,包括功能标志变通方案),而自定义的 --user-data-dir 会拥有一份独立且为空的 NativeMessagingHosts。视口大小通过 Emulation.setDeviceMetricsOverride 设置,这会实际改变布局视口并触发页面自身的观察器,不会移动、调整大小或聚焦任何窗口——这正是关键所在:验证不能依赖操作员将窗口留在何处。

check 以及每个 probe/shot 都会断言生命周期处于活动状态(visibilityState === visible 且 rAF 确实在触发),否则以非零状态码退出。不存在降级模式;生命周期故障会立即停止,绝不会悄然进行测量。

这只是新增能力,不会影响任何原本有效的功能。 操作员的 Chrome、固定测试配置文件、隔离门控和零 CDP 指纹隐身路径都保持不变。经过身份验证的页面、真实会话以及对机器人检测敏感的工作,仍使用扩展驱动的测试上下文——验证实例没有登录状态,也不保证隐身。请将它用于需要测试随时间变化的行为的公开页面。

安装模式(0.16.x)

两种安装模式,共用同一个 CLI 二进制文件。运行 interceptor status,查看 mode: 行进行确认:

模式安装内容解锁的功能
mode: full(此技能的默认模式)CLI + 守护进程 + 扩展 + Swift 桥接 .app + LaunchAgent浏览器自动化 以及 Computer Use:AX 树、操作系统级可信输入、ScreenCaptureKit、Vision OCR、Speech、NLP、Apple Events、OSLogStore、文件监视、容器运行时、VM 生命周期管理
mode: browser-onlyCLI + 守护进程 + 扩展仅限浏览器自动化。interceptor macos * 会在 1 秒内返回结构化的 setup_required 错误。不会触发 TCC 提示。

运行 interceptor upgrade --full,将仅浏览器模式的安装升级为完整模式。运行 bash scripts/uninstall.sh --bridge-only,可降级安装。

安装渠道(pkg 安装程序自 v0.11 起提供):

  • Interceptor-Browser-<v>.pkg → mode: browser-only
  • Interceptor-Full-<v>.pkg → mode: full
  • bash scripts/install.sh --browser-only|--full → 开发者安装路径
  • 支持 Linux 仅浏览器模式(自 v0.13.4 起也可识别 Microsoft Edge 和 Vivaldi)

操作规则:如果用户要求使用原生功能,而 status 显示 mode: browser-only,请回复 “当前安装仅支持浏览器。运行 interceptor upgrade --full 即可启用该功能。” 不要照样运行 macos 命令来看看会发生什么——预检会提前终止,但会浪费轮次。

先决条件
  • 正在运行的 Chrome 或 Brave(或受支持平台上的 Edge/Vivaldi),并已加载 Interceptor 扩展——已签名的 .pkg 安装程序会注册该扩展;从源码构建时,通过 chrome://extensions/ → 开发者模式 → “Load unpacked” → Tools/Pin.sh 创建的 Extension/ 目录,加载一次扩展
  • interceptor CLI 已加入 PATH(/opt/homebrew/bin/interceptor)
  • interceptor-daemon 已加入 PATH(/opt/homebrew/bin/interceptor-daemon)
  • 已注册原生消息传递清单(已签名的 .pkg 会完成此操作;从源码安装时,运行 bash "$INTERCEPTOR_SRC"/scripts/install.sh --chrome --skip-extension)
  • macOS 桥接程序作为 LaunchAgent 运行(仅完整模式)——参见 Workflows/Update.md
  • Sparkle.framework 位于 /usr/local/Frameworks/Sparkle.framework(完整模式,v0.10.0+)——桥接程序依赖它进行自动更新

快速健康检查:

interceptor --version          # → "interceptor 0.23.16 (<hash>, <date>)" — 0.23.16+ is what matters
interceptor status             # → daemon: running, bridge: running, mode: full|browser-only
interceptor status --verbose   # → adds extension reachability (NO extension-build field; with 2+ contexts it nags "multiple extensions connected" even with --context)
interceptor contexts           # → list of connected browser contexts (multi-profile)
interceptor init               # → one-time write of ~/.config/interceptor/config.toml
后台优先约定(0.16.x)

整个产品以后台优先为设计理念。常规操作不会转移用户的焦点。

界面会转移焦点的动词其他所有操作
浏览器open --activate、tab new --activate、tab switch <id>、window focus <id>保持在操作人员当前查看的内容上——click、type、read、inspect、screenshot、net、cookies、scroll、act。新标签页默认在后台打开。
macOSapp activate <app>、open <app> --activate保持在当前最前台的内容上——open(不带 --activate)、所有输入动词、AX 读取、捕获、菜单、意图分发、视觉、叠加层。

如果调用“会转移焦点”列中未列出的任何动词后,最前台的内容发生变化,那就是一个 Bug。

复用路径:open --reuse 会在现有受管理的标签页中导航,不会留下无用标签页。它会保留被复用标签页的焦点状态——仅当用户明确要求将其切换到前台时,才与 --activate 配合使用。

多上下文路由(0.16.x)

连接多个浏览器配置文件时(例如,个人 Chrome + 隔离的测试配置文件 + 工作用 Brave),命令需要知道要控制哪一个。

interceptor contexts                                          # List connected context IDs
interceptor open <url> --context "$INTERCEPTOR_TEST_CONTEXT_ID"  # Route to the isolated test profile (DEFAULT)
interceptor open <url> --context <main-id>                    # Route to the operator's personal Chrome (only when explicitly requested)

未指定 --context 时,只有在恰好连接了一个上下文的情况下,浏览器命令才会自动路由;而当只剩一个上下文时,这意味着裸命令会悄无声息地命中剩余的上下文。连接了零个或 2 个以上上下文时,命令会快速失败并返回结构化错误。请始终传入 --context "$INTERCEPTOR_TEST_CONTEXT_ID"(或通过 Tools/Capture.sh 路由);切勿依赖自动路由。

通过 Interceptor 扩展弹出窗口设置上下文 ID(点击工具栏图标 → Context ID 字段 → Save)。只需设置一次;守护进程会在重启后记住该设置。在此处将友好名称设为 interceptor-test,以免 UUID 不断变化。

默认设置: --context "$INTERCEPTOR_TEST_CONTEXT_ID"。一次性设置请参阅 Workflows/LaunchTestProfile.md。

计算机操作 — macOS 原生辅助程序

该桥接程序是一个以当前用户身份运行的 Swift LaunchAgent,提供 Chrome 扩展本身无法提供的功能:

  • 操作系统级可信输入(interceptor act <ref> --trusted、macos type --trusted、macos keys --trusted — 通过 HID 源状态绕过 isTrusted 检查)
  • 原生 macOS 应用控制(interceptor macos open/read/act/inspect — 与浏览器相同的操作界面,可用于任何正在运行的应用)
  • 任何正在运行的应用的辅助功能树,可在不使用屏幕截图的情况下进行检查
  • Chrome 之外的屏幕捕获(全屏、标签页之外、多显示器、被遮挡的窗口)
  • 虚拟机生命周期管理(interceptor macos vm create/clone/start/exec/snapshot/restore/stop/delete — Linux + macOS 客户机,可替代 Lume/Tart/UTM)
  • 剪贴板读写、音频监听 + 语音识别、系统通知、Vision OCR、NLP、Apple Intelligence、HealthKit、显示信息
  • 无需激活即可向指定的 bundle ID 分发 Apple Events
  • OSLogStore 谓词查询、文件系统搜索/监视、URL 获取
  • 监视器(跨应用工作流录制,可选剪贴板/文件/网络/日志/通知/语音通道,并支持通过 --frames 捕获屏幕截图)

状态检查: interceptor status 会在桥接程序运行时报告 bridge: running,并显示 PID + socket;未运行时则报告 bridge: not running,并提供提示。

生命周期(安装 / 验证 / 故障排查 / 卸载)请参阅 Workflows/Update.md。 Update 工作流会按正确顺序处理二进制文件放置、Sparkle 框架安装、LaunchAgent plist、launchctl bootstrap 和 TCC 提示。

安全模型 — 安装前请阅读:

  • 传输使用位于 /tmp/interceptor-bridge.sock 的 UNIX 域套接字。仅限本地;不监听网络。
  • 套接字没有身份验证。 任何以当前用户身份运行的本地进程都可以连接并执行所有桥接操作。macOS TCC 权限(辅助功能、屏幕录制、麦克风 — trust 探测字段为 accessibility / screenRecording / microphone,没有 inputMonitoring 字段)只授予桥接程序一次,并由所有套接字客户端继承。
  • 额外风险主要来自供应链: 恶意本地软件包可以一步获得操作系统级输入/屏幕/剪贴板访问权限,无需自行申请权限。
  • 单用户 Mac 的威胁模型:可以接受,因为以你的身份运行的任何程序本来就能费些功夫做到这些。多用户 Mac 需要加固套接字。

复合命令(推荐)

这些命令将多步操作模式合并为单次调用 — 减少工具调用和 token 数量:

interceptor open <url>                              # Open + wait + return tree + text
interceptor open <url> --reuse                      # Navigate existing managed tab
interceptor open <url> --activate                   # Bring new/reused tab to front (explicit opt-in)
interceptor open <url> --tree-only|--text-only|--full|--no-wait|--include-frames
interceptor read                                    # Tree + text for active tab
interceptor read <ref>                              # Subtree
interceptor read --markdown                         # Render page as markdown (preserves headings/tables/emphasis)
interceptor read --markdown --text-only             # Markdown prose only, no tree
interceptor read --tree-only --tree-format compact  # Actionable refs only
interceptor read --include-style|--include-frames
interceptor act <ref>                               # Click + wait + return updated tree + diff
interceptor act <ref> "value"                       # Type + wait + return updated tree
interceptor act <ref> --trusted                     # OS-level HID-sourced input (was --os; --os is deprecated alias)
interceptor act <ref> --keys "Enter"                # Send keyboard shortcut
interceptor act <ref> --no-read                     # Skip post-action tree read
interceptor inspect                                 # Tree + text + network log + headers
interceptor inspect --net-only|--filter <pattern>

--trusted 与 --os: v0.13.3 将 --os 重命名为 --trusted(规范名称)。--os 仍作为已弃用的别名保留,并会发出警告。新代码请优先使用 --trusted。

命令参考(已迁移)

完整的逐动词 CLI 列表——macOS 原生(计算机使用)、VM 生命周期、核心浏览器命令、网络/导出、录制(会话监视器)、画布、场景图、LinkedIn、ChatGPT Agentic Bridge、批处理 + 元操作——位于 References/CommandReference.md。快速索引:

动词树参考章节
interceptor macos *(原生应用、AX、可信输入、Vision/Speech/NLP、Apple Events、日志、fs、叠加层)macOS 原生(计算机使用)
interceptor macos vm *(Linux + macOS 客户机、黄金镜像、克隆/快照)VM 生命周期 — 另见 Workflows/VmLifecycle.md
state、tree、find、click、type、navigate、tabs、screenshot、eval、style、cookies核心浏览器命令
net log/headers/export、override、network *、sse *、headers *网络 — 被动模式、CDP 和导出
monitor *(录制/回放)录制(会话监视器)
canvas *、scene *画布 / 场景图
linkedin *、chatgpt *、batch、status、contexts、init、upgradeLinkedIn / ChatGPT Bridge / 批处理 + 元操作

关键规则

  • 浏览器命令需要 Chrome/Brave 正在运行——这是一个扩展,而不是独立二进制文件。
  • act --trusted、macos *、全屏捕获和 VM 生命周期操作需要 bridge 正在运行——运行 interceptor status 可确认。
  • 引用使用 eN 语法——写作 e12,而不是 @e12。引用的有效期很短;导航、重新渲染或 DOM 变更后,请重新执行 read 或 find。
  • 跨框架引用——read --include-frames 会为非顶层框架返回类似 e<frameId>_<n> 的引用。
  • 默认使用纯文本。 仅在将输出传入脚本时使用 --json。经过散文训练的模型更容易理解树形/文本输出,而不是密集的 JSON。
  • 守护进程会自动启动——第一条命令会启动它;无需手动启动。
  • 优先使用组合命令(open、read、act、inspect),而不是手动串联 tab new + wait + tree。
  • 除非任务明确涉及视觉或像素,否则优先使用结构化读取,而非截图——树形/文本/网络/场景/AX 数据更快、更精简,也更确定。
  • --trusted 是规范选项;--os 是已弃用的别名。 v0.13.3+。新代码使用 --trusted。
  • --markdown 是结构化散文输出方式——保留标题、表格和强调格式。当视觉层级有助于区分答案时,请使用它,而不是 --text-only。
  • 按约定优先在后台操作。 只有 --activate/app activate/显式的 tab switch 会切换焦点。
  • 操作前后都用 frontmost 验证。 声称不会改变焦点的原生工作流必须证明这一点。
  • 绝不使用 screencapture。绝不使用 osascript 操作 Chrome 的焦点、边界、标签页或窗口。 根据 Hard Prohibitions,这些操作均被禁止。即使 Interceptor 出现故障,这些禁令仍然有效。
  • 任何依赖生命周期的操作都必须通过 Tools/VerifyViewport.ts——动画、过渡、ResizeObserver/IntersectionObserver、延迟加载、滚动显示、视口响应式布局。只要窗口不可见,标准测试上下文就会将所有这些操作的活动情况默默报告为零。请参阅 Rendering-Lifecycle Gate 部分。
  • 截图必须通过 Tools/Capture.sh 获取,绝不能直接使用 interceptor screenshot。 Capture.sh 会运行预检门禁、强制执行目标不得为 Default 的检查、处理 UUID 轮换后的重新绑定、优先使用 DOM 渲染路径,并将审查产物写入 $LIFEOS_DOWNLOADS_DIR(未设置时默认为 ~/Downloads/)。
  • 标签页卫生——上游现在会自行清理(Tab Lifecycle Policy,于 0.23.3 新增);CleanupTabs.sh 是兜底措施,不是主要机制。 两种内置行为都只能通过扩展弹出窗口配置(弹出窗口是唯一的设置写入方):(1)按命名组复用(默认开启)——interceptor open <url> --group <label> 会在该组最近使用的标签页中导航,而不是新开标签页(类似地址栏语义),因此 40 步自动化只会留下一个标签页,而不是 40 个。仅限命名组:在共享的默认组中,“最近使用的标签页”可能属于另一个 Agent,因此未分组的 open 仍会创建新标签页;--reuse 可在任何地方启用复用,--no-reuse 会强制新建标签页,tab new(即 ⌘T 这个动词)始终会新建。(2)空闲组关闭(默认 10 分钟)——托管组在一段时间内没有命令操作时会自动关闭(设为 0 可禁用),但绝不会触碰焦点窗口中的活动标签页、固定标签页、正在播放音频的标签页或窗口中的最后一个标签页;每次扫描都会记录日志,关闭的标签页可通过 ⌘⇧T/interceptor session restore 恢复。通过 interceptor status --verbose(tabLifecycle 字段)查看解析后的策略。任务期间优先使用 open --group <label>,让复用机制替你完成清理。任务结束时仍需运行一次 bash ~/.claude/skills/Interceptor/Tools/CleanupTabs.sh 作为兜底——它只会关闭 PINNED 测试上下文中的非活动标签页,保留活动标签页(窗口仍会保持打开),遵循 --keep-url <substr>,拒绝操作 Default/工作配置文件,并在上下文未连接时以状态码 0 退出。用于兜底清理尚未被空闲扫描处理的未分组标签页。(历史记录:2026-07-13 观察到 22 个过期标签页,当时生命周期策略尚不存在。)

委派给 Agent

为 Interceptor 工作启动 Agent 时:

Agent(subagent_type="general-purpose", prompt="
  Use interceptor CLI for all browser and macOS automation work.
  Browser: open <url> --context "$INTERCEPTOR_TEST_CONTEXT_ID", read [--markdown], act eN, inspect. Screenshots go through Tools/Capture.sh, never raw screenshot.
  Native (macOS): macos open <app>, macos read, macos act <ref>, macos inspect, macos vm *.
  Compound commands preferred — they return tree + text in one call.
  Refs use eN syntax (no @ prefix) from tree output. Treat refs as short-lived.
  Background-first: only --activate and app activate move focus.
  PROFILE ISOLATION (MANDATORY GATE): the FIRST action of this task is
    bash ~/.claude/skills/Interceptor/Tools/PreflightIsolation.sh
  If that script exits non-zero, STOP and surface the message verbatim — do NOT
  fall back to operating against the Default profile, and do NOT use screencapture
  or osascript as substitutes. After the preflight returns OK, every browser
  command carries `--context "$INTERCEPTOR_TEST_CONTEXT_ID"`. Never operate in the
  operator's main profile unless the parent agent explicitly says so.
  `act --trusted` for OS-level HID input (was --os).
  FINAL action after your work is done and evidence captured: run
    bash ~/.claude/skills/Interceptor/Tools/CleanupTabs.sh
  to close the tabs you opened in the test profile (keeps the active tab).
  [your specific task instructions here]
")

工作流路由

工作流触发词文件说明
LaunchTestProfile"测试配置文件", "启动测试配置文件", "隔离浏览器", "隔离浏览器配置文件", "单独的 Chrome 窗口", "启动 interceptor-test"Workflows/LaunchTestProfile.md通过 --profile-directory、加载扩展、命名 context ID,一次性设置并每日启动隔离的 Chrome 配置文件
VerifyDeploy"验证部署", "检查部署", "确认部署", "部署验证"Workflows/VerifyDeploy.md在真实 Chrome 中打开 URL(通过 --context interceptor-test),结构化读取、检查错误、收集证据
ScrubFlow"逐帧检查流程", "将流程录制为视频", "动作故障", "动画卡顿", "转场卡顿", "闪烁", "流程图库", "捕捉静态截图遗漏的动态效果"Workflows/ScrubFlow.md将 Web 流程录制为视频,提取经 SSIM 评分的帧(通过 Tools/FrameScrub.ts 浏览/逐帧检查),捕捉静态截图遗漏的动作/动画/流程故障
Reproduce"复现", "复现故障", "调试页面", "检查页面", "空白屏幕"Workflows/Reproduce.md在分析代码之前打开受影响的页面,捕获控制台错误和网络 404 错误
ReadAndExtract"提取值", "读取页面", "提取事实", "SPA 状态"Workflows/ReadAndExtract.md组合读取与 SPA 状态提取;根据任务选择合适界面;模式切换规则
DriveRichEditor"操作 Canva", "操作 Docs", "操作 Slides", "富文本编辑器", "场景", "场景图", "画布渲染"Workflows/DriveRichEditor.md适用于画布渲染型编辑器的场景图和分发事件操作方法
OverrideXhr"覆盖请求", "请求覆盖", "强制返回 500", "重写响应", "修改 XHR"Workflows/OverrideXhr.md安装被动覆盖、触发、验证、清除
ScreenshotForVlm"用于 VLM 的截图", "VLM 截图", "Agent 截图", "WebP 1568"Workflows/ScreenshotForVlm.md适用于 VLM 的预算限制截图方法;1 条命令的预算;--save --format webp --target-max-long-edge
MultiPageCompare"比较页面", "多页面比较", "多个页面间的事实", "由 X 还是 Y 设计"Workflows/MultiPageCompare.md依次对每个页面执行 open --text-only,避免反复切换标签页
CaptureBackgroundedApp"Brave / Signal / Mail / X 的截图", "捕获后台应用", "捕获被遮挡的窗口"Workflows/CaptureBackgroundedApp.md使用 CGS 捕获指定应用的窗口,无需激活该应用
DriveBackgroundedApp"滚动 Mail / 在 TextEdit 中输入", "操作后台应用", "无焦点点击"Workflows/DriveBackgroundedApp.md使用 AX 按下操作、设置值和 postToPid,向非前台应用输入
DispatchAppleEvent"在 Brave 中打开 URL", "Apple Event", "Apple 事件", "意图分发", "在指定应用中打开"Workflows/DispatchAppleEvent.mdintent dispatch --bundle <id> --script —— 脚本中不使用 activate
ReadAxTree"AX 树", "无障碍树", "Cursor / Slack 里有什么", "在应用中查找按钮"Workflows/ReadAxTree.md使用 macos tree,通过 AXManualAccessibility 唤醒 Electron
TrustedInputGate"可信输入", "OS 级输入", "isTrusted", "网站拒绝合成输入", "HID 来源状态"Workflows/TrustedInputGate.md--trusted 升级;浏览器端 __interceptor_trust 标记;何时使用哪种方式
VmLifecycle"创建 VM", "VM 生命周期", "Linux VM", "macOS VM", "黄金镜像", "克隆 VM", "VM 快照"Workflows/VmLifecycle.mdinterceptor macos vm * 完整生命周期 + Lume 迁移表
RecordFlow"录制流程", "录制工作流", "捕获流程", "监控启动"Workflows/RecordFlow.md通过监控系统录制浏览器操作,并导出可重放的计划脚本
RecordAndReplayMacFlow"录制 Mac 流程", "录制原生流程", "看我在 Cursor/Mail/Finder 中操作"Workflows/RecordAndReplayMacFlow.mdmacos monitor AX 事件录制、导出和重放
ReplayFlow"重放流程", "重放", "回归检查", "运行流程"Workflows/ReplayFlow.md逐步执行录制的计划脚本,验证每个步骤并报告回归问题
TestForm"测试表单", "填写表单", "表单测试", "检查表单"Workflows/TestForm.md查找表单字段,填写测试数据,提交并验证结果
Update"更新", "检查版本", "重新构建", "安装桥接程序", "启用 Computer Use"Workflows/Update.md拉取、重新构建、重新安装、为 Computer Use 安装桥接程序,并进行端到端验证

示例

  • “验证博客部署情况” → VerifyDeploy:预检隔离门,interceptor open <url> --context "$INTERCEPTOR_TEST_CONTEXT_ID",read --markdown,通过 Tools/Capture.sh 捕获,并附上证据进行报告。
  • “菜单动画看起来不太对 / 结账流程渲染得干净吗” → ScrubFlow:将流程录制为视频,bun Tools/FrameScrub.ts <recording> scrub --at <sec>,读取自动标记的帧,并引用清单。动态效果/交互 ISC 需要采用这种方式或使用流程图库,不能只用单张静态图(算法规则 1)。
  • “为什么部署后这个页面是空白的?” → 复现:先打开页面,再通过 eval --main 捕获控制台错误,用 net log 检查失败的请求,然后分析代码。
  • “记录我批准这个流程的操作,然后每晚重放” → RecordFlow + ReplayFlow:运行 monitor start,由操作人员执行操作,再运行 monitor export <sid> --plan,之后重放计划脚本。

注意事项

  • interceptor 立即退出,返回码为 137 且没有任何输出 = 代码签名无效,并非卡住。 内核会对签名已失效的临时签名二进制发送 SIGKILL(2026-06-10 一次系统事件后观察到;两个二进制均受影响)。诊断方法:将二进制 cp 到 /tmp,对副本运行 codesign -s - -f,再运行它;如果副本能正常工作,就重新签署原文件:codesign -s - -f /opt/homebrew/bin/interceptor && codesign -s - -f /opt/homebrew/bin/interceptor-daemon。两个文件都必须重新签署——CLI 会启动 interceptor-daemon --standalone;如果 daemon 仍有问题,就会报错 “daemon failed to start. Check /tmp/interceptor.log”,而且不会创建该日志。(2026-06-10。)
  • 截图——实际工作方式(0.22.2)。 所有截图都通过 Tools/Capture.sh 执行;下方说明的是它封装的原始行为。
    • 默认的 interceptor screenshot 使用 DOM 渲染路径——自 v0.18.3 起采用无需依赖的原生渲染器(已移除 html-to-image;按需通过 executeScript 注入)。它从实时 DOM 树渲染,不要求标签页处于前台或可见状态——位于另一个 macOS Space 中的后台标签页也可以,而且会快速失败(后台标签页不再卡满整个超时时间)。
    • --pixel 用于退出默认路径 → 使用旧版 captureVisibleTab。它会捕获窗口中当前活动的标签页,因此要捕获指定的后台标签页,就必须短暂激活该标签页并恢复焦点——画面闪一下是有意设计的。--pixel 要求窗口未最小化且可见;窗口最小化时会快速、如实地报错。--pixel 全页截图会以 1100ms 的间隔限制条带捕获速率(Chrome 每秒 2 次的上限),并在 service worker 中拼接。
    • 可靠性是默认路径的一部分,不是一个标志。 没有“可靠模式”开关。目前的稳健性来自扩展中的最小化窗口预检(快速失败,而不是卡住约 30 秒),以及 CLI 的 45 秒截图超时。cli/lib/screenshot-selfheal.ts 封装器已停用/未接入——不要引用它。
    • --save 会将文件写入 CLI 当前工作目录,并返回 filePath(不含 dataUrl)。它不会写入 /tmp/pai-screenshots/——工作流会先 cd 到该目录,正是因为 --save 的目标是当前工作目录。不存在 --output <path> 标志;位置参数路径会被静默忽略。根据 OPERATIONAL_RULES,审查产物应放在 $LIFEOS_DOWNLOADS_DIR(未设置时默认为 ~/Downloads/),流水线中间文件应放在 /tmp/;Tools/Capture.sh 会统一处理这些路径。
    • 不使用 --save 时,screenshot 会内联返回完整的 base64 dataUrl——超过 10MB 的 PNG 会塞满记录。Agent 上下文中始终使用 --save。
    • 标志 --target-max-long-edge N(限制长边,避开 16384 的 Skia 上限)、--scale、--selector、--element N、--region X,Y,W,H 会在 DOM 渲染路径中运行;--clip 是已弃用的 --region 别名。
  • DOM 渲染截图不会绘制 UA 默认的控件外观——按钮/输入框的对比度问题可能悄然漏过。 没有 CSS background 的裸 <button> 在真实浏览器中会显示 UA 的白色/#efefef 背景(iOS Safari 上尤其明显),但 DOM 渲染截图会将其绘制得像透明一样,因此白底上的白字对比度问题在截图中看起来正常(2026-08-07:Surface 分享按钮在截图看起来正常后发布,结果在移动设备上无法辨认)。验证表单控件的对比度时,必须使用 getComputedStyle(...).backgroundColor(透明值表示会显示 UA 背景)或 --pixel 截图,绝不能依赖默认的 DOM 渲染截图。通过属性设置的 textarea/input 值同样不会被绘制出来。
  • DOM 渲染截图会丢弃 CSS 伪元素生成的内容。 ::before/::after 内容——尤其是 CSS 计数器——会显示在实时浏览器中,却会从默认的 DOM 渲染截图中消失,因此页面可能在截图中看起来有问题,而屏幕上实际显示正常。尝试“修复”页面之前,应通过 eval --main 检查几何信息/计算样式;对于你编写的内容,优先使用实际 DOM 文本,而不是 CSS 计数器。(2026-07-11,通过一个缺失的编号轨道发现;eval 证明该内容实际存在。)
  • 默认情况下,DOM 渲染截图会忽略滚动位置。 interceptor screenshot 从文档的 y=0 位置捕获——window.scrollTo/scrollIntoView/keys End 都不会移动截图画面。对于长页面,请使用 --region X,Y,W,H、--selector <css>、--element <ref> 或 --pixel --full(滚动并拼接,要求窗口可见)。(2026-04-27;截至 2026-06-17 仍然适用。)
  • 对复选框执行 click 可能报告 clicked [eN],但复选框并未切换。 在真实表单中观察到两次(2026-07-18):对于由 label 包裹的 <input type="checkbox">,click 执行成功,表单提交时复选框仍未勾选;对同一元素执行 act <ref> 会报错 “unsupported input type”。点击后要验证复选框状态(eval --main '...checked');如果没有生效,则在表单上通过 eval --main 设置 checked=true,并提交真实表单(form.submit())——仍然走真实的会话/CSRF/POST 流程。绝不要假设报告点击成功就代表状态已切换。
  • 两个 Agent 会话共用测试上下文时,--current 捕获的内容以及裸 read/eval 所操作的对象都是活动标签页——而另一个会话会不断更改该标签页。 这与 --pixel 捕获错误页面的问题属于同一类(2026-06-11);2026-07-18 再次遇到:Capture.sh --current 截取了另一个会话的标签页。始终将 URL 传给 Capture.sh <url>(在受管标签页中,导航后再截图是原子操作),并在每组 read/eval 操作前重新执行 open --reuse;如果窗口中有另一个会话的标签页,就跳过 CleanupTabs.sh——关掉那些标签页比留下你自己的一个受管标签页更糟。
  • 多个标签页打开相同 URL 时,如果不带 --context,路由可能会混乱。 两个标签页都加载 localhost:5180/ 时,tab switch <id> 会报告 ok,但视觉上活动的 Chrome 标签页可能并未切换。应关闭重复标签页、使用刚打开的单个标签页,或传入 --context <id> 以明确指定上下文。
  • 大多数网站会通过 CSP 阻止 eval。 使用 eval --main 在页面主世界中运行。即使使用 --main,严格的 CSP(script-src 'self')仍会阻止字符串求值;请传入简单表达式,避免使用 Function 构造器模式。
  • Bridge 需要 Sparkle.framework。 在 Apple Silicon 上从源代码重新构建时,必须将 Sparkle.framework 安装到 /usr/local/Frameworks/,否则 bridge 无法加载。正在运行的 bridge 是 .app 包中的二进制文件 ~/.local/share/interceptor/interceptor-bridge.app/Contents/MacOS/interceptor-bridge(LaunchAgent com.interceptor.bridge,plist ~/Library/LaunchAgents/com.interceptor.bridge.plist),而不是 /usr/local/bin/interceptor-bridge(过时副本)。Update 工作流会处理此事;如果忘记安装,症状是出现 bridge: not running,并在 /tmp/interceptor-bridge.stderr.log 中看到 dyld[*]: Library not loaded: @rpath/Sparkle.framework/...。(2026-05-03;bridge 拓扑于 2026-06-17 更正。)
  • Manifest 版本升级 = 必须手动重新加载扩展并重新固定(适用于从源代码安装)。 Chrome 不会自动重新加载未打包的扩展,固定的 Extension/ 副本也不会自动跟随上游版本。源代码重新构建后,应通过 Update 工作流重新固定,然后在 chrome://extensions 中删除现有扩展卡片,再从固定目录执行 Load Unpacked。扩展 key 是确定性的,因此重新加载后扩展 ID 保持不变。对于签名的 .pkg 安装,安装程序会处理这些步骤。
  • “native port disconnected”不是截图错误。 这是 daemon 记录 Chrome 的 Native-Messaging stdio 端口断开(扩展 SW 被回收/Chrome 关闭)的日志;daemon 仍会运行,并切换到 WebSocket 传输。如果 WS 和 relay 都未启动,命令会排队(上限为 50 条)并超时。修复方法 = 重新连接扩展(重新加载标签页/重新打开已配置的浏览器),而不是重启 daemon。
  • “screenshot-runner.js could not load”= 单个 frame 的注入失败。(旧版的 “html-to-image library not loaded” 错误已消失——v0.18.3 用原生渲染器替换了该库。)页面禁止脚本注入(chrome://、Web Store、PDF 查看器、严格 CSP 的 frame),标签页在注入过程中发生了导航,或者——升级二进制后最常见的情况——已加载的扩展过期,其捆绑的 runner 与 daemon 不匹配。从 0.22.37 起,如果 DOM 渲染截图失败,系统会自动回退到 --pixel,因此通常仍能获得图像(结果会说明使用了回退路径;使用 --no-fallback 可关闭此行为)——但仍应修复扩展过期这一根本原因:重新加载扩展——重新安装签名的 .pkg,或者对于从源代码安装的情况,重新固定并从固定的 Extension/ 目录执行 Load Unpacked。
  • daemon 与扩展之间的 WebSocket 可能卡在半存活状态——在判定 Interceptor 无法使用之前,先尝试其他命令动词类别。 症状:status/contexts/tabs(控制面消息类型)能正常响应,但 screenshot/eval(数据面消息类型)会一直等到超时。Capabilities Overview 中的每个命令动词都使用不同的 WebSocket 消息类型,因此 screenshot 卡住很少会影响 eval、net log、tree、read --markdown、monitor 或 inspect。恢复步骤:(1)切换截图路径(pixel↔DOM 渲染——不同的消息类型通常能解除卡顿),或改用其他能力类别中的命令动词——用 read --markdown/eval --main document.body.innerText 代替 screenshot,用 net log 检查失败的请求;(2)执行一次 pkill -f interceptor-daemon,然后只重试一次;(3)重新加载扩展(提示:“Interceptor extension is wedged — please reload it from chrome://extensions/.”),然后停止。只有这三种方法都失败后,才告知操作人员无法捕获验证结果——**绝不要回退到 screencapture/osascript。**需要避免的常见错误:只因一次 screenshot 超时就声称“Interceptor 已损坏”,而 eval 本可以通过一次工具调用回答问题。 (2026-05-13,2026-06-17 修订。)
  • Bridge 无响应时的自愈(仅限 macOS macos_* 路径——浏览器截图不需要 bridge)。 “已加载”≠“正在运行”——通过 interceptor status 检查进程,而不只是查看 launchctl list:
    interceptor status | grep -A2 '^bridge:'                         # running + pid/socket, or not running
    launchctl print "gui/$(id -u)/com.interceptor.bridge" 2>&1 | grep -E 'state|program|pid'
    launchctl kickstart -k "gui/$(id -u)/com.interceptor.bridge"     # restart (loaded-but-dead)
    
    Agent 运行的是 .app 包中的二进制文件(~/.local/share/interceptor/interceptor-bridge.app/Contents/MacOS/interceptor-bridge),而不是 /usr/local/bin/interceptor-bridge(该副本已过时)。如果 bridge 被 SIGKILL,且临时签名已失效,它会每隔约 5 秒重启循环一次(ThrottleInterval)——应重新签署 .app 中的 MacOS 二进制文件,而不是 /usr/local/bin 副本。Tools/HealBridge.sh 封装了“已加载但未运行”检测和单次 kickstart。(2026-06-17。)
  • bridge 已移除 AXEnhancedUserInterface(将其解释为“VoiceOver 已启用”会导致 AppKit 应用被切换到前台)。bridge 仅使用 AXManualAccessibility 唤醒 Electron。应忽略旧代码中设置 AXEnhancedUserInterface 的过时说明。
  • screenshot --pixel --tab <id> 可能会捕获错误页面——--pixel 会跟随活动标签页。 --pixel 使用 captureVisibleTab;它会截取视觉上处于活动状态的任意标签页。如果之前的标签页激活操作没有生效,捕获的就是操作人员当前前台的标签页,而不是目标标签页(2026-06-11 观察到:请求截取待测 localhost 网站,结果却截取了操作人员前台的无关网站)。在将返回图像作为证据引用前,务必阅读并确认它确实是你请求的页面——这就是为什么 Tools/Capture.sh 会在 --pixel 回退路径中读回图像。此泄漏也可能捕获操作人员的敏感窗口(2026-07-18:部署验证期间再次使用 --pixel 截图,结果返回了操作人员已打开的实时私密管理面板——禁止截图;读回后已删除文件)。对于已在测试标签页中打开页面的再次验证截图,优先使用默认的 DOM 渲染路径并比较资源字节,而不要再次执行 --pixel。不要使用 AppleScript 激活标签页——这违反硬性禁令。应改用非视觉命令动词类别(read --markdown、eval --main、net log),或按照上方的 WebSocket 卡顿恢复步骤操作。(2026-06-11;AppleScript 变通方案已于 2026-06-13 移除。)
  • 全页截图无法确认关于细节外观的主张——先放大。 模型看到的图像会先缩小到长边约 1568px,因此在 2000px 宽的页面上,一个 40px 的 logo 会变成模糊的一团。裁剪已发送的截图无法恢复细节,因为细节在上游已被破坏。bun Tools/Zoom.ts <image> --x N --y N --w N --h N 会从全分辨率原图裁剪,并将该区域放大到预算允许的尺寸,使像素集中呈现待检查对象。凡是主张涉及 logo、字形、字体渲染、图标或几个像素的间距,都应使用此工具——这类主张曾导致 logo 错误事件(2026-07-19):确认了“元素存在”,却没有确认“它就是正确的元素”。坐标是源图中的绝对像素;通过 DOM 坐标读取(eval)可获得要传入的区域。后端:优先使用 magick,否则使用 ffmpeg。(公开 PR #1657,@elhoim。)
  • 敏感应用防护。 如果最前台应用属于拒绝列表中的 bundle(Keychain、1Password、Dashlane、LastPass、Bitwarden、System Settings、Chase、Bank of America、Wells Fargo),bridge 会拒绝 type/keys/click x,y/drag。应如实报告拒绝结果,不要绕过。
  • VM 的 paused-state 快照受限制。 --paused-state 要求 VM 配置中的 validateSaveRestoreSupport() 返回 true。macOS 来宾系统支持此功能;部分 Linux 配置不支持。--disk-only 始终可用。
  • VM 主机的 TCC 授权: bridge 需要 com.apple.security.virtualization 权限。如果 setup_required 报告安装位置有问题,请将 bridge 移出 ~/Documents 或 ~/Desktop。
  • 本地 extract.ts 自定义修改已过时。 v0.13 之前将切片限制提高到 10M 的补丁已不再需要——上游的 withTruncationMarker、--full 标志和每个操作的 maxChars 已能通过显式截断标记正确处理(... (truncated: showed X of Y chars ...))。
  • 过时二进制会静默路由到 Default——回退事件(2026-05-23)。 如果重新构建的文件写入 $INTERCEPTOR_SRC/dist/,但从未复制到 /opt/homebrew/bin/,CLI 就会停留在旧版本。旧版二进制无法识别 --context 或 contexts 子命令——它们不会报错,只会接受该标志,并将命令路由到 daemon 能找到的任意 Chrome 连接,而该连接通常是操作人员的 Default 配置文件。症状:Agent 调用 interceptor open <url> --context "$INTERCEPTOR_TEST_CONTEXT_ID",期望打开隔离标签页,结果却在操作人员的工作窗口中打开标签页。检测方法:interceptor --version 显示的版本早于 0.16.0,和/或 interceptor open --help 中没有与 --context 相关的标志,和/或 interceptor contexts 返回 “unknown command”。缓解措施:上文的预检隔离门禁会在版本不匹配时以退出码 4 硬性失败——每个工作流都会将其作为第零步运行。恢复方法是执行 Workflows/Update.md,然后运行 pkill -f interceptor-daemon,使下一次调用重新启动新 daemon。
  • 在云同步目录中构建桥接程序会破坏其代码签名——完整的签名修复流程。 如果源码检出目录位于 iCloud Drive、Dropbox 或 Google Drive 中(或通过符号链接指向这些位置),同步会移除构建出的 .app 的代码签名封套(codesign -v → "code has no resources but signature indicates they must be present")。将该程序包复制到目标位置会把损坏一并带过去,导致桥接程序陷入 SIGKILL 循环(launchctl print → last exit reason = OS_REASON_CODESIGNING)。真正的解决办法是将检出目录移到本地磁盘。 要修复已经损坏的程序包,请按顺序处理本地暂存副本(~/.local/share/interceptor/interceptor-bridge.app):先对其运行 xattr -cr → 对 .../Contents/Frameworks/Sparkle.framework 运行 codesign --force --deep --sign - → 对 MacOS 二进制文件,然后对 .app 运行 codesign --force --sign - --entitlements "$INTERCEPTOR_SRC"/scripts/entitlements-bridge.plist(这正是 build-bridge.sh 的开发签名回退流程)。不要对整个应用运行 codesign --deep——这会错误地签署嵌套的 Sparkle,导致 codesign -v 虽然通过,内核却仍会将其终止。
  • bash scripts/install.sh --chrome 会再次覆盖刚修好的桥接程序。 它会调用 install-bridge.sh,而该脚本会把原始(仍然损坏的)程序包重新复制到已修好的版本上。运行该命令后重新签名,或者桥接程序签名完成后就不要再运行它。
  • 多次运行 kickstart -k 后,launchd 的 job state = spawn failed。 快速重启循环会让 launchd 限流并进入失败状态(runs 持续增加;直接启动二进制文件则运行正常)。恢复方法是运行 launchctl bootout "gui/$(id -u)/com.interceptor.bridge",然后重新运行 launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/com.interceptor.bridge.plist——不要再次运行 kickstart。
  • 守护进程以持久 LaunchAgent 运行(com.interceptor.daemon,于 2026-07-04 添加)——这是彻底解决扩展程序控制台中 "native keepalive ping failed / forcing reconnect" 刷屏问题的办法。 守护进程短暂停机(升级、崩溃或运行 pkill)时会出现这些日志:停机会关闭扩展程序的原生消息中继端口,Service Worker 会持续记录 ping failed,直到重新连接。中继架构本身运行正常——单例拥有套接字,每个 Chrome 配置文件都会启动一个轻量级中继并将请求桥接到单例(relay: registered with singleton → received ping, sending pong)。让单例始终运行(RunAtLoad + KeepAlive,plist ~/Library/LaunchAgents/com.interceptor.daemon.plist → /opt/homebrew/bin/interceptor-daemon --standalone),可以确保中继始终能找到运行中的单例,从而立即成功重连,不再报错。升级守护进程二进制文件后,运行 launchctl kickstart -k "gui/$(id -u)/com.interceptor.daemon" 以使用新二进制文件(与桥接程序的处理方式相同)。验证方法:interceptor status 中的 daemon pid 与 launchd pid 相同;稳定运行时段的 /tmp/interceptor.log 窗口中,ping failed / forcing reconnect 均为 0。
  • 对桥接程序重新进行临时签名会重置其 TCC 授权。 新的临时签名会生成新的代码身份,因此 Accessibility / Screen Recording / Microphone 的授权会变为 denied,Computer Use 也会停止,直到重新授权(运行 interceptor macos trust --walkthrough,或前往 System Settings → Privacy & Security)。浏览器端不受影响(基于扩展程序,无需 TCC)。已公证的 Interceptor-Full-<v>.pkg 在 Sparkle 更新期间会保留稳定的 Developer-ID 身份,避免上述所有问题——如果 TCC 频繁变动造成困扰,请优先使用它来安装桥接程序。
  • 隐藏标签页在不报错的情况下显示动画/观察器活动为 0——这看起来就像“功能坏了”。 在断定 ResizeObserver、transition、lazy-load 或 scroll-reveal 没有触发之前,请先检查 document.visibilityState;如果值为 hidden,所有计划渲染 API 都会暂停,观察结果毫无意义。通过 Tools/VerifyViewport.ts 重新运行测试(参见“Rendering-Lifecycle Gate”部分)。能说明问题的迹象是:测量结果内部一致,计数器恰好为 0 或 1,而手动调用页面自身的回调后“问题”就消失了。(2026-07-30,在验证响应式导航时发现;固定的测试窗口停留在副显示器的非活动区域。)
  • interceptor macos cdp raw <method> '<json>' 会按位置接收参数——--params 和 --param 都会报错 error: Invalid parameters。存在多个 CDP 上下文后,还必须传入 --context;守护进程会在每次导航时创建一个以 URL 命名的别名上下文,因此请固定使用稳定的主机派生 ID(cdp:127-0-0-1),并清理这些别名。每个 CLI 响应前面都会有一行 [id] → verb 跟踪信息,解析 JSON 前必须将其去掉——而且其中包含 [,所以简单调用 indexOf('[') 找到的是跟踪信息,而不是负载。
  • interceptor macos windows --app "Google Chrome" 只会枚举 Chrome 主进程的窗口。 使用独立 --user-data-dir 启动的第二个 Chrome 虽然共享 bundle id,但其窗口不会出现,因此 AX 不是驱动或观察它的可用通道——请使用 CDP。
  • 遇到任何卡住的情况,首先运行 interceptor diagnose(0.22.2+)。 它会指出守护进程脑裂问题:套接字守护进程(CLI 与之通信)与 NMH 清单路径(Chrome 从中启动守护进程)不一致。解决方法是将清单中的 path 指向规范二进制文件——对 ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.interceptor.host.json(以及 Brave 的对应文件)运行 jq '.path="/opt/homebrew/bin/interceptor-daemon"'——然后运行 pkill -f interceptor-daemon,再运行一条活动命令(interceptor contexts),从正确位置重新启动守护进程。在升级到 0.22.37 时,发现了两个实际问题 (2026-07-28):Chrome NMH 清单是指向 $INTERCEPTOR_SRC/daemon/.generated/ 的符号链接(install.sh 会重新创建清单,使其指向仓库目录——请将其替换为一个指向 /opt/homebrew/bin 的普通文件);另一个问题是,来自旧 iCloud 检出目录的过期独立守护进程可能在运行 pkill -f interceptor-daemon 后仍然存活;请根据 diagnose 输出中的 pid 将其结束。
  • 原位覆盖 /opt/homebrew/bin/interceptor{,-daemon} 会触发 OS_REASON_CODESIGNING——用 cp 覆盖旧二进制文件后,即使构建过程已对其进行临时签名,com.interceptor.daemon LaunchAgent 启动时仍会被内核以 SIGKILL 终止(launchctl print → last exit reason = OS_REASON_CODESIGNING)。请对已安装的副本原位重新签名(运行 codesign --force --sign - /opt/homebrew/bin/interceptor-daemon 和 .../interceptor),然后运行 launchctl kickstart "gui/$(id -u)/com.interceptor.daemon"。(2026-07-28 升级;2026-08-10 再次出现——在一个 77 分钟的时段内产生了 92 份 SIGKILL 崩溃报告。更新工作流的第 4 步现已成为彻底解决办法:暂存 → 签名 → 原子 mv,绝不使用 cp 覆盖正在使用的路径。)
  • 从源码重新构建桥接程序会重置其 TCC 授权——重新切换旧记录的开关也没用。 临时签名会发生变化,因此 macOS 会移除 interceptor-bridge 的 Accessibility + Screen Recording 授权——症状是桥接程序正在运行,但对每个应用都返回空的 a11y 树和 windows: [],而 macos script run 会在 Apple Events 提示处超时。使用 interceptor macos trust 进行探测。System Settings 中过期的记录与旧签名绑定;切换它们的开关不会有任何变化(实际验证:已累积 5 条过期记录)。解决方法:运行 tccutil reset Accessibility com.interceptor.bridge && tccutil reset ScreenCapture com.interceptor.bridge,重启桥接程序,运行一次 macos windows 调用以重新注册,然后由用户在 System Settings → Privacy & Security → Accessibility 和 Screen Recording 中将新的记录切换为 ON(若记录不存在,请添加 ~/.local/share/interceptor/interceptor-bridge.app)。永久解决方法:构建前将 INTERCEPTOR_SIGNING_IDENTITY 设为真实的 Developer ID,这样签名和 TCC 授权就能在重新构建后保留。(2026-07-28 升级。)
  • 清单版本升级后,无需任何操作即可重新加载扩展程序。 尽管上文建议“删除卡片 + Load Unpacked”,但完全退出 Chrome 后重新启动,就会以新清单版本(0.22.2 → 0.22.37)重新启用已固定的未打包扩展程序,无需进行任何 GUI 操作——上下文会自动重新连接。请先尝试重启;只有扩展程序卡片重新出现且处于禁用状态时,才手动重新加载。(2026-07-28 升级。)
  • 在 bash 5.2+ 中运行 Tools/Pin.sh——波浪号清理操作悄无声息地不起作用(已于 2026-07-04 修复)。 ${SRC/#$HOME/~} 会将替换内容中的波浪号再次展开为 /Users/<name>,因此 PINNED_FROM.txt 中带有绝对 home 路径,且 Pin.sh 自身的泄露防护会触发 FATAL。现已改为使用带引号的 ~${SRC#$HOME} 形式(rel_home())。如果重新固定时因“清理后仍存在绝对 home 路径”而触发 FATAL,请检查 bash 版本以及该辅助函数。
  • 自动启动恢复(EnsureTestProfile.sh)——安全性来自重新验证循环,而不是 profile 参数(2026-07-07)。 当测试 profile 窗口未打开时,EnsureTestProfile.sh 会启动配置的 --profile-directory,并轮询 PreflightIsolation.sh,直到固定的上下文连接,然后继续。自动启动错误的 profile 不会带来任何风险,因为只有在预检对整个字段与 INTERCEPTOR_TEST_CONTEXT_ID 完全匹配并硬性拒绝 Default 后,它才会以状态码 0 退出——错误的启动只会持续无法通过预检,因此 Agent 绝不会操作它。有两个实际限制:(1)如果 Chrome 已在运行,macOS 的 open -a "Google Chrome" --args --profile-directory=… 会忽略这些参数(无操作)(只会激活 Chrome)——LaunchTestProfile.sh 通过直接使用 CHROME_BIN 的分支绕过了这一点,即使 Chrome 已在运行,也会打开新的 profile 窗口;如果启动“成功”却没有出现新窗口,就是 open 遇到 Chrome 已运行的情况,此时真正有效的是直接使用二进制文件的分支。(2)如果启动后连接的是新的上下文 UUID(扩展已重新加载 → UUID 轮换),预检将无法匹配固定值,EnsureTestProfile 会停止,并提示采用持久修复方案(在弹出窗口中将上下文命名为 interceptor-test)——它绝不会重新绑定到未识别的 UUID。只有退出码 5/6 会自动启动;退出码 7(Default/工作目标)和 8(配置未设置)不会。
Linux + Flatpak 浏览器——这堂四小时的课(2026-07-19,Fedora)

在 Fedora 上安装 Chrome Flatpak(com.google.Chrome)后,一次会话中就出现了全部四种情况。Chrome 通过 ~/.local/bin/google-chrome 启动脚本运行,该脚本会添加 --filesystem=/tmp --filesystem=home --die-with-parent。调试 Linux 安装前请先阅读本节;第一个症状看起来像扩展失效,但事实并非如此。(公开 PR #1682,@pkumaschow。)

  • 在 Flatpak 沙箱内部创建的守护进程套接字无法从主机 CLI 连接,即使套接字文件清晰可见。 /tmp 确实双向共享(主机写入的标记可在沙箱内读取,反之亦然),因此 ls -la /tmp/interceptor.sock 会显示该文件——而同一秒内,interceptor status 却报告 daemon: not running。端点位于沙箱的命名空间中;可见文件只是一个影子。解决方法是使用非沙箱浏览器,而不是调整 Flatpak 权限。Interceptor 支持原生版 Vivaldi;其中继的套接字可由主机访问,CLI 可立即连接。请先将 NMH 清单复制到该浏览器自己的目录(例如 ~/.config/vivaldi/NativeMessagingHosts/)。
  • 无窗口的孤立 Flatpak 实例可能会隐形占用端口 19222,而对可见 PID 执行 pkill 无法释放该端口。 操作者看不到 Chrome 窗口,合理地报告“没有打开 Chrome”,但 bwrap --args N -- chrome --profile-directory=X 仍在运行,其守护进程占有该端口,导致之后启动的所有中继都无法使用——包括其他浏览器的中继。对可见子进程执行 kill <pid> 不会传递到 bwrap。flatpak kill com.google.Chrome 才是可靠的清理方法。 如果中继报告端口已被占用,但看不到浏览器运行,请检查这种情况。
  • 中继只会连接到由它自身启动的单例;未能启动的重复实例会在退出时删除胜出实例的套接字。 日志特征为 spawning detached standalone daemon → ws port 19222 already held ... exiting this duplicate → detached standalone daemon did not become ready before timeout → falling back to in-process singleton → exiting so the existing daemon serves everyone。它绝不会退而连接为普通 ws 客户端。后果是:当另一个守护进程占有端口时,CLI 调用会自我破坏——每次调用都会自动启动一个重复实例,并删除现存套接字,因此诊断问题的操作反而会再次引发问题。如果套接字不断消失,请停止运行 CLI 命令,先解决占用问题。(值得向上游反馈:守护进程绝不应删除自己未创建的套接字。)
  • --load-extension 已失效(Chrome 137+;已确认在 150 上也会被忽略)。 启动后的配置文件只包含五个默认组件扩展。唯一可用的途径是通过 chrome://extensions →“加载已解压的扩展程序”选择器;在 Flatpak 浏览器中,该操作会经过 XDG Document Portal,因此任何错误中显示的路径都会带有 /run/flatpak/doc/<id>/... 前缀。这个前缀是正常的,并非故障原因。~/.claude 是点文件夹,GTK 选择器会隐藏点文件:请在选择器中按 Ctrl+H,否则操作者根本无法导航到扩展程序所在位置。

同一会话中 Agent 端的易错点: 从 Bash 运行 pkill -f interceptor-daemon 会匹配到调用它的 shell 自身的命令行并将其杀死——命令以退出码 144 结束,输出被截断,看起来像是卡死。可以拆分字面字符串(PAT="intercep""tor-daemon"; pkill -f "$PAT"),或按 PID 结束进程。

隐身验证

通过所有主要的机器人检测:

检查结果
BrowserScan正常
Pixelscan确认为真人
Sannysoft全部通过
CreepJS无头模式占比 0%
Fingerprint.com未检测到
AreyouHeadless非无头模式

执行日志

完成任何工作流后,追加一条 JSONL 记录:

echo '{"ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","skill":"Interceptor","workflow":"WORKFLOW_USED","input":"8_WORD_SUMMARY","status":"ok|error","duration_s":SECONDS}' >> ~/.claude/LIFEOS/MEMORY/SKILLS/execution.jsonl

评论

支持 Markdown