forge-browser
v1.2.0
Published
Browser automation CLI for Forge QA. Merges Playwright's mocking/injection with agent-friendly exploration.
Downloads
79
Maintainers
Readme
forge-browser
Agent-first 浏览器自动化 CLI,基于 playwright-core,面向 AI Agent 的页面探索、动作执行,以及强大的 debug / evidence / verification 生态。当前在 Forge QA 场景打磨,但不局限于 Forge。
文档入口:
- 功能真相源:
docs/FEATURES.md - 路线:
docs/ROADMAP.md - 命令文档:
docs/commands/*.md - 验证基线:
docs/testing/validation-baselines.md - 已发布变化:
CHANGELOG.md - 差异化策略与执行层边界:
docs/solutions/agent-first-runtime-refactor.md - 外部参考能力对比(仅参考,不是真相源):
docs/archive/2026-04/BROWSER-AUTOMATION-COMPARISON.md
当前产品定位
forge-browser 不是通用浏览器平台、adapter marketplace、generic DevTools server,也不是整条软件工厂流程。
它当前的产品中心是:
- Agent-first browser CLI:优先让 agent 在 current page / current session 心智下稳定完成探索与动作
- 强大的 debug / evidence / verification 生态:
mock、trace、har、perf、console、network、a11y等能力用于帮助 agent 真正定位问题,而不是把默认主路径做重 - 共享浏览器执行层优先:浏览器 primitive 默认交给 Playwright;
forge-browser重点自持snapshot -i、@ref、current-page truth 与 artifact trust 这类产品契约
如果你只需要一个通用浏览器控制层,竞品已经很多;forge-browser 的差异点在于它把 agent 工作流与 debug/evidence/verification 更紧地收成一个可信闭环。
为什么不是直接用竞品
browser-use更像通用 browser CLI + operator UXagent-browser更像低 token agent substrateOpenCLI / AutoCLI更像 adapter 平台chrome-devtools-mcp更像 inspect/debug substrateplaywright-cli更像官方 operator cockpitgstack更像 QA workflow orchestration
forge-browser 的差异点不在于“录制功能更多”,而在于:它把 Agent-first 浏览器操作、current-page truth、artifact trust,以及 debug/evidence/verification 更紧地收成一个可信闭环。
核心差异化能力是 snapshot -i:把页面交互元素转换成带 @ref 标签的语义快照,例如:
@e1 [button] "Submit"
@e2 [textbox] "Email"Agent 可以直接基于这些 @ref 执行动作,而不是依赖脆弱的 CSS selector 或视觉识别。
同时,snapshot -i 现在支持按阶段裁剪输出,例如只拿 refs、只拿 rendered,或显式附加 semantic locator recipe,兼顾:
- 结构化协议稳定性
- Agent 的低熵阅读效率
- 更低的 token 消耗
当前能力
- 页面探索:
open/snapshot -i/snapshot --urls/snapshot --locators/snapshot --selector/read-text - 页面动作:
click/drag/upload/download/fill/type/scroll/wait/press/eval/page switch - 实时流控制:
stream set/list/events/clear(当前 v1 支持SSE/EventSource phase mock与WebSocket passthrough diagnostics) - 环境控制:
mock/inject/clock/offline/geolocation/permissions - 证据链:
screenshot/screencast/trace show/trace analyze/har - 代码生成:
codegen start/stop(当前导出 TS 草稿 + 原始 action/signal JSONL) - 诊断:
console/network/a11y audit/perf analyze - 运行过程真相源:默认输出
session-log.jsonl - 状态复用:
state save/load/--session-namedaemon session /profile list/inspect/--profile <path|name> - 浏览器接入:
connect --browser-url/--ws-endpoint/--cdp/--user-data-dir/--chrome-live --channel - 插件系统:
--plugin/plugin list/plugin info/plugin run
Auth 边界
- forge-browser 核心只提供 auth framework:
auth --plugin <name>PluginRuntime- 加密 state 导出(统一保存 cookie / localStorage,并按当前 live pages best-effort 补采 sessionStorage)
- session / state 复用
- 具体登录逻辑应优先作为 plugin 实现,而不是写死在核心里
- 当前内置
tap-dev只是一个认证插件示例,不代表 forge-browser 只服务 Forge 项目 - 如果后续要支持其他平台(例如小红书、其他内部系统、统一登录平台),应优先新增 plugin,而不是重写核心 auth 模型
tap-dev 一键登录配置
tap-dev 当前支持从用户级插件配置目录读取默认账号:
~/.forge-browser/plugins/tap-dev/accounts.json最小示例:
{
"defaultAccount": "user_a",
"accounts": {
"user_a": {
"phone": "19545672859",
"smsCode": "000000",
"instance": 0
}
}
}认证时的解析优先级:
- CLI 参数:
--phone/--sms-code/--base-url/--account/--instance - 环境变量:
FORGE_TEST_PHONE/FORGE_TEST_SMS_CODE/FORGE_E2E_BASE_URL ~/.forge-browser/plugins/tap-dev/accounts.json- 若仍未拿到
baseURL,插件会尝试按本机局域网 IP + forge 实例编号推导 tap.dev 地址
示例:
forge-browser auth -p tap-dev --output ~/.forge-browser/auth/forge.state
forge-browser auth -p tap-dev --account user_a --output ~/.forge-browser/auth/forge.state
forge-browser auth -p tap-dev --instance 1 --output ~/.forge-browser/auth/forge.state若插件无法自动解析 Forge dev 地址,会返回结构化错误,并提示先启动 Forge 开发环境(例如 pnpm dev)以及候选访问 URL。
安装与运行
环境要求
- macOS(当前
1.2.0明确只支持 macOS CLI / daemon 主链路) - Node
>=24.12.0 <26(发版固定基线仍为 Volta24.12.0) - pnpm
10.33.0 - Bun
>=1.0.0(仅源码开发态使用,通过pnpm dev*脚本调用) - 本机可用的 Chrome / Chromium,或通过 Playwright 管理的 Chromium
安装依赖
pnpm install
pnpm build
forge-browser install说明:
forge-browser install是当前唯一推荐的浏览器准备主路径。- 它直接复用 Playwright 的 browser registry/install 逻辑下载 Chromium。
- 不在
pnpm install阶段自动下载浏览器。
开发运行
pnpm dev -- open https://example.com
pnpm dev:watch连接已运行的 Chrome / Chromium
forge-browser connect --browser-url http://127.0.0.1:9222
forge-browser connect --ws-endpoint ws://127.0.0.1:9222/devtools/browser/<id>
forge-browser connect --cdp 9222
forge-browser connect --user-data-dir /path/to/automation-profile
forge-browser connect --chrome-live --channel stable说明:
9222只是兼容 alias,不再被当成默认前提--user-data-dir会读取该目录下的DevToolsActivePort--chrome-live --channel <name>会尝试按 well-known channel profile 读取DevToolsActivePort- 成功返回里会包含
resolvedVia,明确本次连接是通过显式 endpoint、ActivePort 还是 chrome-live 发现得来的
检查可复用 profile
forge-browser profile list
forge-browser profile inspect "QA Profile"
forge-browser profile inspect ~/ChromeAutomationProfile说明:
profile list/inspect只做 discovery,不启动浏览器- 输出会显示 profile path、profile-scoped state 文件位置、存在性和风险 warning
- 继续推荐专用 automation profile;默认个人 profile 会带 warning
构建
pnpm build
pnpm verify:package
pnpm pack --dry-run --json说明:
pnpm build生成 npm package 主分发产物:dist/cli.cjspnpm verify:package会基于真实 tarball 验证--version/--help/install --helpprepack会自动触发pnpm build,避免未构建就打出缺少dist/cli.cjs的 tarball
真实页面 / attach / auth 验证
pnpm test:real-page说明:
- 当前 real-page baseline 是 opt-in,不进入默认
pnpm test:release - 需要按
docs/testing/validation-baselines.md配置环境变量 - 默认覆盖 ambient/current-page 页面探索、diagnostics、existing browser attach,以及
auth --plugin主路径
给别人安装 forge-browser(推荐)
最短安装路径:
npm install -g [email protected]
forge-browser --version
forge-browser install说明:
npm install -g [email protected]安装 CLI 本体forge-browser install负责下载 Playwright 管理的 Chromium;包安装阶段不会自动下载浏览器- 安装完成后,可以先用
forge-browser --help/forge-browser --version确认命令可用
如果对方机器本身使用 Volta,推荐直接:
volta install [email protected]
forge-browser --version
forge-browser install如果安装成功但命令仍然找不到,优先排查:
npm prefix -g
which forge-browser
forge-browser --version补充:
- 如果
npm install -g [email protected]成功,但which forge-browser为空,优先检查 global prefix 的bin是否在当前 shellPATH中 - 在 Volta / 多 Node 管理器环境下,这类 PATH 差异更常见
- 本仓库通过
package.json.volta.node = 24.12.0固定发版基线,但 package engine 允许 Node 24.12+ 到 Node 25
随包分发的 agent skill
npm package 会同时包含:
skills/forge-browser/安装后可在 package root 下读取同版本 agent 使用指导,例如:
node_modules/forge-browser/skills/forge-browser/SKILL.md
node_modules/forge-browser/skills/forge-browser/references/command-reference.md说明:
- 这只是版本对齐的分发方式,不会自动写入用户全局 skill 目录
- package smoke 会验证关键 skill 文件存在
- 需要机器可读路径时,使用
forge-browser skill path - 若要把 skill 安装到某个 agent runtime,仍由外层 agent/工具链显式处理
示例:
forge-browser skill path命令文档
docs/commands/install.mddocs/commands/skill.mddocs/commands/open.mddocs/commands/read-text.mddocs/commands/snapshot.mddocs/commands/click.mddocs/commands/batch.mddocs/commands/session.mddocs/commands/connect.md- 其余命令继续见
docs/commands/
快速示例
1. 页面探索
forge-browser install
forge-browser snapshot -i --url https://example.com
forge-browser --detail minimal snapshot -i --url https://example.com
forge-browser snapshot -i --refs-only --limit 20 --url https://example.com
forge-browser snapshot -i --locators --url https://example.com
forge-browser read-text --url https://example.com --selector main --max-chars 1200默认返回结果以 data.refs[] 为主,例如:
[
{ "ref": "@e1", "role": "button", "name": "Submit" },
{ "ref": "@e2", "role": "textbox", "name": "Email" }
]需要区分同名控件或查看 stale-ref 刷新依据时,显式加 --locators:
[
{
"ref": "@e1",
"role": "button",
"name": "Submit",
"locator": { "kind": "role", "role": "button", "name": "Submit", "exact": true, "nth": 1 }
}
]iframe 内元素会额外带 frameScoped: true 和 snapshot-local frameId,只用于说明当前快照 scope;后续动作仍使用 @ref。
locator 是当前快照的定位 recipe,用来辅助判断;后续动作仍使用 @ref。
如果需要紧凑文本树,显式改成:
forge-browser snapshot -i --rendered-only --url https://example.com证据类命令现在会在顶层 artifacts[] 中附带稳定 ref,例如 run-...:screenshot:1、run-...:session-log:1,便于后续按 artifact 追溯历史。
2. 在同一 runtime 内执行连续动作
forge-browser batch \
"open https://example.com" \
"snapshot -i" \
"click @e1"2.1 上传文件 / 触发下载
forge-browser upload @e1 ./fixtures/resume.pdf --url https://example.com/upload
forge-browser download @e2 ./downloads/report.csv --url https://example.com/export说明:
upload支持一个或多个本地文件路径download不传输出路径时,会默认写入当前 run 的 artifacts 目录
2.2 拖拽一个元素到另一个元素
forge-browser drag @e1 @e2 --url https://example.com/kanban说明:
drag以@ref -> @ref的语义执行拖放- 当前仍保持单 page model,不引入 popup/page switching 语义
2.3 popup auto-switch / page switch
forge-browser --session-name qa open https://example.com
forge-browser --session-name qa snapshot -i
forge-browser --session-name qa click @e1
forge-browser --session-name qa page switch p1说明:
- 当
click @ref触发 popup / 新 tab 时,runtime 会自动切换到新 active page - 成功 envelope 里的
page.id会从p1变成p2等新 identity - 若要回到主页面,可显式执行
page switch <pageId> - 切页后原来的
@ref默认视为失效,需要重新snapshot -i
2.4 被遮挡点击的错误语义
- 当
click/upload/download的点击点被 overlay、弹层或 sticky UI 覆盖时,CLI 会返回结构化error.details.obstruction - 这条能力优先解决“为什么点不到”而不是盲目重试
2.5 分阶段 Mock EventSource / SSE
forge-browser batch \
'stream set --file ./fixtures/sse-spec.json' \
'open https://example.com/stream-page' \
'stream events' \
'wait --text "status:done"'最小 spec 例子:
{
"protocol": "sse",
"mode": "mock",
"urlPattern": "**/events",
"phases": [
{
"afterMs": 0,
"events": [
{ "type": "open" },
{ "type": "message", "event": "status", "data": { "text": "thinking" } }
]
},
{
"afterMs": 400,
"events": [
{ "type": "message", "event": "token", "data": { "text": "Hello" } }
]
},
{
"afterMs": 800,
"events": [
{ "type": "message", "event": "done", "data": { "finishReason": "stop" } },
{ "type": "close" }
]
}
]
}说明:
- 当前
streamv1 是 spec-first,不要求 agent 记很多 flags - v1 当前支持:
protocol=sse+mode=mockprotocol=websocket+mode=mockprotocol=websocket+mode=passthrough
- 最稳定的执行路径是
batch或 named session;这样 stream 规则和页面生命周期在同一个 runtime 内 stream events会返回当前 runtime 内已经发出的结构化流事件,适合 Agent 做诊断和断言
WebSocket passthrough spec 例子:
{
"protocol": "websocket",
"mode": "passthrough",
"urlPattern": "**/ws"
}WebSocket mock spec 例子:
{
"protocol": "websocket",
"mode": "mock",
"urlPattern": "**/mock-ws",
"phases": [
{
"afterMs": 10,
"events": [
{ "type": "message", "data": "server:first" }
]
},
{
"afterMs": 30,
"events": [
{ "type": "message", "data": "server:second" },
{ "type": "close", "closeCode": 1000, "closeReason": "done" }
]
}
]
}3. 录制 screencast 视频
forge-browser batch \
"open https://example.com" \
"screencast start --output ./.forge-browser/artifacts/demo.webm" \
"snapshot -i" \
"click @e1" \
"screencast stop"说明:
- 当前稳定闭环路径是
batch或--session-nameshared runtime - 视频默认输出
.webm - screencast 会透传 Playwright 的 annotate 选项,用于动作标注
4. 录制 codegen 草稿
forge-browser batch \
"open https://example.com" \
"codegen start --output ./.forge-browser/artifacts/demo.ts" \
"snapshot -i" \
"click @e1" \
"codegen stop"说明:
- 当前稳定闭环路径是
batch或--session-nameshared runtime - stop 后会落两份 artifact:
*.ts:Playwright 草稿代码*.actions.jsonl:原始 recorder action/signal 事件
5. 录制 trace / HAR / perf
当前版本这三类录制命令的稳定闭环路径是 batch:
forge-browser batch \
"open https://example.com" \
"trace start" \
"har start" \
"perf start" \
"eval 'document.title'" \
"perf stop" \
"har stop" \
"trace stop"说明:
trace start/stophar start/stopperf start/stop
当前都不承诺 standalone 跨独立 CLI 调用闭环。
4. 结构化分析
forge-browser trace analyze ./trace.zip
forge-browser network --url https://example.com --wait 500
forge-browser perf analyze ./perf.json
forge-browser console --url https://example.com
forge-browser a11y audit --url https://example.com当前 trace analyze 会输出:
actions[]:动作时间线consoleMessages[]/consoleErrors[]:浏览器 console 事实requests[]/failedRequests[]:request/response 摘要、headers、body 预览与失败请求聚合
Session Log
每次 runtime 驱动的命令都会默认生成:
./.forge-browser/artifacts/<run>/session-log.jsonl
它记录 forge-browser 自己的运行语义,而不是只记录 Playwright 原始录制:
- run lifecycle
- command lifecycle
- page opened
- console / network 事实
- artifact created
默认会对常见敏感字段做脱敏,包括:
token/sessionToken/access_tokenpasswordauthorizationcookiesmsCode/phone
5. 执行期网络等待
forge-browser wait --request /api/login --method POST --url https://example.com/login
forge-browser wait --response /api/login --method POST --status 200 --url https://example.com/login
forge-browser network --url https://example.com/login --match-url /api/login --method POST --resource apinetwork 当前支持:
--match-url <text>:只保留 URL 包含指定文本的事件--method <method>:只保留指定 HTTP method--status <code>:只保留指定 response status--resource <all|api|document>:最小 noise control,区分文档导航和业务接口事件
另外:
wait --request/wait --response失败时,failure envelope 会附带error.details.recentNetworkEvents- 这个字段面向 Agent 诊断链路,方便直接利用最近的 request / response facts 做重试和推理
6. 环境模拟
forge-browser clock install --time 2026-04-18T10:00:00.000Z
forge-browser offline on
forge-browser geolocation set --lat 37.7749 --lng -122.4194 --accuracy 50
forge-browser permissions grant geolocation notifications --origin https://example.com说明:
- 这些命令直接复用 Playwright 原生能力
batch和 named session 会复用同一份环境状态geolocation不会隐式授予权限,需配合permissions grant geolocation
7. 状态复用
forge-browser state save ./auth.json --url https://example.com
forge-browser open https://example.com --auth ./auth.json
forge-browser --viewport tablet open https://example.com
forge-browser --session-name qa open https://example.com
forge-browser --session-name qa --wait-session-idle 5000 snapshot -i
forge-browser --session-name qa --session-reset --headed --viewport desktop open https://example.com
forge-browser --session-name qa snapshot -i
forge-browser --session-name qa click @e1
forge-browser --profile ~/ChromeAutomationProfile open https://example.com说明:
--session-name在1.2.0继续表示 macOS live daemon session。- 同一个 session 会复用同一个 live browser/context/page。
snapshot -i、click、fill、type、wait、press、eval、screenshot在 named session 中不再要求每次都传--url。storageState现在默认以加密格式落盘,不再明文保存 cookie / localStorage。- 若设置
FORGE_BROWSER_ENCRYPTION_KEY,显式文件和内部 session/profile 持久化都会使用该 key。 - 若未设置
FORGE_BROWSER_ENCRYPTION_KEY,会自动使用本机~/.forge-browser/keys/storage-state.key作为默认本地加密 key。
重要约束
--headed / FORGE_BROWSER_HEADED
- 可以通过全局 CLI 选项
--headed开启有头模式 - 也可以通过环境变量
FORGE_BROWSER_HEADED=1开启有头模式 - named session 会把 headed 视为 launch shape 的一部分;同名 session 不能静默切换 headed 模式,必须先
session stop
--viewport <preset|WIDTHxHEIGHT> / FORGE_BROWSER_VIEWPORT
- 可以通过全局 CLI 选项
--viewport或环境变量FORGE_BROWSER_VIEWPORT指定初始页面尺寸 - 内置预设:
mobile=390x844,tablet=834x1112,desktop=1440x960 - headed 模式下,
--viewport会把浏览器初始窗口放大到对应尺寸,并让页面 viewport 跟随窗口实时变化,便于手动拖拽观察响应式状态 - headless 模式下,
--viewport会作为固定 Playwright viewport 生效,适合稳定截图和断言 - named session 会把显式
--viewport视为 launch shape 的一部分;同名 session 不能静默切到另一组尺寸,必须先session stop
--profile <path|name>
- 通过 persistent profile context 复用指定 Chrome / Chromium profile
- 推荐仅复用专用 automation profile
- 不建议直接复用默认个人 profile
- 当前不会隐式删除 profile lock 文件;若 profile 正被其他浏览器实例占用,会返回结构化错误
--session-name <name>
- 当前只支持 macOS
- 当前语义是 per-session daemon,不是历史上的纯 state 自动恢复语义
session start/status/stop/list是显式生命周期控制面session info <name>会在当前 status 基础上补充 manifest-backed history 摘要session status/info在可用时会显示当前 launch shape(如headed、viewport)和 busy 中的活动命令SESSION_BUSY会附带activeCommand、busySince、safeToRetry- launch shape mismatch 会附带
currentLaunchShape/requestedLaunchShape,并明确提示是复用原参数还是先session stop --wait-session-idle <ms>:对 busy session 做有限等待,适合把同一 session 上的多条命令串成轻量排队--session-reset:显式丢弃当前 live session 并重建,适合想复用同一个 session 名但需要换--headed/--viewport的场景- 当前不兼容
--profile、connect --browser-url、--ws-endpoint、--cdp、state save/load的 daemon 复用路径
artifacts 默认输出目录
未显式传路径时,证据链产物默认写入:
./.forge-browser/artifacts/<run>/并且默认不覆盖已存在的显式输出路径。
工程验证
提交前执行:
pnpm lint:fix
pnpm typecheck
pnpm test:releasepnpm test:release 不跑会打开可见窗口的 headed suite。改 --headed、viewport 或 launch shape 时再手动执行:
pnpm test:headed每轮执行完毕后做综合 dogfood:
pnpm test:dogfoodtest:dogfood 会先跑完整 release gate,再跑 opt-in real-page baseline;未配置真实页面 / attach / auth 环境变量时,real-page suite 只能按 skip 记录。
相关文档
- 功能真相源:
docs/FEATURES.md - 路线:
docs/ROADMAP.md - 命令文档:
docs/commands/ - 文档索引:
docs/README.md - 分发 skill:
skills/forge-browser/
