bunwv

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

bunwv

bunwv

Headless browser automation using a persistent WebView session. The daemon keeps a single WebView instance alive so page state (DOM, modals, forms, SPA routes, scroll position) persists across commands.
基于持久化WebView会话的无头浏览器自动化工具。守护进程会维持单个WebView实例的存活状态,因此页面状态(DOM、模态框、表单、SPA路由、滚动位置)可在多个命令间保持。

Commands

命令

Run all commands with
bunwv <command>
(installed globally via
bun install -g @naticha/bunwv
).
All commands accept
--session <name>
to target a named session (default: "default").
bunwv start [--width N] [--height N] [--data-store PATH] [--idle-timeout ms]
      [--backend webkit|chrome] [--chrome-path PATH]
bunwv navigate <url>
bunwv click <selector> | <x> <y>
bunwv click-text <text> [--tag <selector>]
bunwv type <text>
bunwv press <key> [--mod meta,ctrl,shift]
bunwv clear <selector>
bunwv submit [--form <selector>] [--button <text>]
bunwv scroll <dx> <dy> | <selector>
bunwv screenshot [filename] [--format png|jpeg|webp] [--quality 0-100]
bunwv eval <expression>
bunwv console [--clear] [--since <timestamp>]
bunwv cdp <method> [--params '{}']
bunwv wait-for <selector> [--timeout ms]
bunwv wait-for-gone <selector> [--timeout ms]
bunwv status
bunwv resize <width> <height>
bunwv back
bunwv forward
bunwv reload
bunwv sessions
bunwv stop
Default viewport is 1920x1080 for readable screenshots.
所有命令通过
bunwv <command>
运行(可通过
bun install -g @naticha/bunwv
全局安装)。
所有命令均支持
--session <name>
参数,用于指定目标命名会话(默认值:"default")。
bunwv start [--width N] [--height N] [--data-store PATH] [--idle-timeout ms]
      [--backend webkit|chrome] [--chrome-path PATH]
bunwv navigate <url>
bunwv click <selector> | <x> <y>
bunwv click-text <text> [--tag <selector>]
bunwv type <text>
bunwv press <key> [--mod meta,ctrl,shift]
bunwv clear <selector>
bunwv submit [--form <selector>] [--button <text>]
bunwv scroll <dx> <dy> | <selector>
bunwv screenshot [filename] [--format png|jpeg|webp] [--quality 0-100]
bunwv eval <expression>
bunwv console [--clear] [--since <timestamp>]
bunwv cdp <method> [--params '{}']
bunwv wait-for <selector> [--timeout ms]
bunwv wait-for-gone <selector> [--timeout ms]
bunwv status
bunwv resize <width> <height>
bunwv back
bunwv forward
bunwv reload
bunwv sessions
bunwv stop
默认视口尺寸为1920x1080,以确保截图清晰可读。

Session Management

会话管理

Sessions are named and isolated. Each session runs its own daemon on a separate Unix socket. The default session is named "default".
bunwv start                          # starts "default" session
bunwv start --session cmais          # starts a separate "cmais" session
bunwv navigate http://localhost:3000 --session cmais
bunwv sessions                       # list all running sessions
bunwv stop --session cmais           # stop a specific session
Auto-shutdown: Daemons automatically exit after 30 minutes of inactivity. Override with
--idle-timeout
:
bunwv start --idle-timeout 3600000   # 1 hour
bunwv start --idle-timeout 0         # never auto-shutdown
Reuse detection: If you
start
a session that's already running, it reports the existing session's URL so you know its current state:
$ bunwv start
Reusing existing session "default" (PID: 12345)
  URL:   http://localhost:3000/dashboard
Best practice: Always run
bunwv sessions
at the start of a testing session to check for orphaned daemons from previous conversations. Stop any you don't need.
会话支持命名与隔离。每个会话会在独立的Unix套接字上运行自己的守护进程。默认会话名称为"default"。
bunwv start                          # 启动"default"会话
bunwv start --session cmais          # 启动独立的"cmais"会话
bunwv navigate http://localhost:3000 --session cmais
bunwv sessions                       # 列出所有运行中的会话
bunwv stop --session cmais           # 停止指定会话
自动关闭:守护进程在闲置30分钟后会自动退出。可通过
--idle-timeout
参数覆盖默认设置:
bunwv start --idle-timeout 3600000   # 1小时
bunwv start --idle-timeout 0         # 永不自动关闭
复用检测:如果尝试启动一个已在运行的会话,工具会返回该会话当前的URL,以便你了解其状态:
$ bunwv start
Reusing existing session "default" (PID: 12345)
  URL:   http://localhost:3000/dashboard
最佳实践:在测试会话开始时,务必运行
bunwv sessions
检查之前操作遗留的孤儿守护进程,并停止不需要的进程。

Core Interaction Loop

核心交互流程

Always follow this pattern: look, then act, then look again.
  1. Start the daemon if not running:
    bunwv start
  2. Navigate:
    bunwv navigate http://localhost:3000
  3. Screenshot:
    bunwv screenshot /tmp/bunwv-screenshot.png
  4. Read the screenshot with the Read tool to see the page
  5. Decide what to do (click, type, etc.)
  6. Act:
    bunwv click "button.submit"
  7. Screenshot again to verify the result
  8. Repeat steps 4-7 as needed
  9. Stop when done:
    bunwv stop
请始终遵循以下模式:查看→操作→再次查看。
  1. 若守护进程未运行则启动:
    bunwv start
  2. 导航至目标页面:
    bunwv navigate http://localhost:3000
  3. 截图:
    bunwv screenshot /tmp/bunwv-screenshot.png
  4. 使用读取工具查看截图内容
  5. 决定下一步操作(点击、输入等)
  6. 执行操作:
    bunwv click "button.submit"
  7. 再次截图以验证操作结果
  8. 根据需要重复步骤4-7
  9. 完成后停止会话:
    bunwv stop

Clicking Elements by Text

通过文本点击元素

When you don't know the CSS selector, use
click-text
to click by visible text:
bunwv click-text "Save Changes"
bunwv click-text "Sign In"
bunwv click-text "Delete" --tag "button, a, div"
By default searches
button, a, [role='button'], input[type='submit']
. Use
--tag
to widen the search to other elements.
当你不知道CSS选择器时,可使用
click-text
命令通过可见文本点击元素:
bunwv click-text "Save Changes"
bunwv click-text "Sign In"
bunwv click-text "Delete" --tag "button, a, div"
默认搜索范围为
button, a, [role='button'], input[type='submit']
。可使用
--tag
参数扩大搜索范围至其他元素。

Clearing and Editing Input Fields

清除与编辑输入字段

IMPORTANT: Do NOT use Cmd+A / Backspace to clear React inputs — it does not reliably update React state. Use the
clear
command instead, which uses the native value setter and dispatches proper React-compatible events:
bunwv clear "input[name='email']"
bunwv click "input[name='email']"
bunwv type "new-value@example.com"
Always
clear
then
click
then
type
when editing existing input values.
重要提示:请勿使用Cmd+A/退格键清除React输入框内容——这种方式无法可靠更新React状态。请改用
clear
命令,该命令会使用原生值设置器并触发符合React要求的事件:
bunwv clear "input[name='email']"
bunwv click "input[name='email']"
bunwv type "new-value@example.com"
编辑已有输入值时,请始终遵循“清除→点击→输入”的步骤。

Waiting for Elements

等待元素加载

Use
wait-for
after actions that trigger page changes (navigation, form submission, modal open):
bunwv click-text "Save Changes"
bunwv wait-for-gone "[role='dialog']"       # wait for modal to close
bunwv screenshot /tmp/bunwv-screenshot.png     # then screenshot

bunwv click-text "Edit"
bunwv wait-for "[role='dialog']"             # wait for modal to appear
bunwv screenshot /tmp/bunwv-screenshot.png
Default timeout is 10 seconds. Override with
--timeout
:
bunwv wait-for ".results" --timeout 30000
在触发页面变化的操作(导航、表单提交、模态框打开)后,使用
wait-for
命令等待元素状态变化:
bunwv click-text "Save Changes"
bunwv wait-for-gone "[role='dialog']"       # 等待模态框关闭
bunwv screenshot /tmp/bunwv-screenshot.png     # 然后截图

bunwv click-text "Edit"
bunwv wait-for "[role='dialog']"             # 等待模态框出现
bunwv screenshot /tmp/bunwv-screenshot.png
默认超时时间为10秒。可通过
--timeout
参数覆盖:
bunwv wait-for ".results" --timeout 30000

Extracting Page Data

提取页面数据

Use
eval
to get text content, check elements, or read form values. Statements (
const
,
let
,
var
,
if
, etc.) are auto-wrapped in an IIFE — no need to manually wrap:
bunwv eval "document.title"
bunwv eval "document.querySelector('h1')?.textContent"
bunwv eval "document.querySelectorAll('.error').length"
bunwv eval "const rows = document.querySelectorAll('tr'); return rows.length;"
使用
eval
命令获取文本内容、检查元素或读取表单值。语句(
const
let
var
if
等)会自动包装在IIFE中——无需手动包装:
bunwv eval "document.title"
bunwv eval "document.querySelector('h1')?.textContent"
bunwv eval "document.querySelectorAll('.error').length"
bunwv eval "const rows = document.querySelectorAll('tr'); return rows.length;"

Submitting Forms

提交表单

IMPORTANT: Use
submit
instead of
click-text
for form submission.
click-text
uses JS
.click()
which produces
isTrusted: false
events — many React forms ignore these. The
submit
command uses
form.requestSubmit()
which properly triggers React form handlers.
bunwv submit                                    # submit the first form on the page
bunwv submit --button "Save Changes"            # submit via a specific button
bunwv submit --form "form.edit-quote"            # target a specific form
bunwv submit --form "form" --button "Save"       # both
After submitting, use
wait-for-gone
to wait for the dialog/form to close, or
wait-for
to wait for a success message:
bunwv submit --button "Save Changes"
bunwv wait-for-gone "[role='dialog']"
bunwv screenshot /tmp/bunwv-screenshot.png
重要提示:提交表单时请使用
submit
命令而非
click-text
click-text
使用JS的
.click()
方法,会产生
isTrusted: false
的事件——许多React表单会忽略这类事件。
submit
命令使用
form.requestSubmit()
方法,可正确触发React表单处理程序。
bunwv submit                                    # 提交页面上的第一个表单
bunwv submit --button "Save Changes"            # 通过指定按钮提交表单
bunwv submit --form "form.edit-quote"            # 提交指定表单
bunwv submit --form "form" --button "Save"       # 同时指定表单和按钮
提交后,使用
wait-for-gone
等待对话框/表单关闭,或使用
wait-for
等待成功消息出现:
bunwv submit --button "Save Changes"
bunwv wait-for-gone "[role='dialog']"
bunwv screenshot /tmp/bunwv-screenshot.png

Filling Forms

填写表单

Click the input first, then type. Use Tab to move between fields:
bunwv click "input[name='email']"
bunwv type "user@example.com"
bunwv press Tab
bunwv type "password123"
bunwv submit --button "Sign In"
For credentials, use environment variables in
.env
(Bun auto-loads them). The shell expands
$VAR
in CLI args:
bunwv type "$TEST_EMAIL"
先点击输入框,再输入内容。使用Tab键在字段间切换:
bunwv click "input[name='email']"
bunwv type "user@example.com"
bunwv press Tab
bunwv type "password123"
bunwv submit --button "Sign In"
对于凭据信息,可在
.env
文件中使用环境变量(Bun会自动加载)。Shell会在CLI参数中展开
$VAR
bunwv type "$TEST_EMAIL"

Persistent Auth

持久化认证

Use
--data-store
to preserve cookies and localStorage across daemon restarts:
bunwv start --data-store ./bunwv-session
Log in once, and future sessions with the same data store stay authenticated. Note: DOM state (open modals, form inputs) only persists within a single daemon session, not across restarts.
使用
--data-store
参数可在守护进程重启后保留Cookie和localStorage:
bunwv start --data-store ./bunwv-session
登录一次后,使用相同数据存储的后续会话会保持已认证状态。注意:DOM状态(打开的模态框、表单输入内容)仅在单个守护进程会话内保持,无法跨重启保留。

Debugging with Console Capture

通过控制台捕获调试

Page console output (
console.log
,
console.error
, etc.) is automatically captured. Use this to debug page behavior without writing eval hacks:
bunwv navigate http://localhost:3000
bunwv click "button.submit"
bunwv console                    # see any errors or logs from the page
bunwv console --clear            # read and clear the buffer
Use
--since <timestamp>
to only see new messages since your last check. The buffer holds 1000 messages.
页面控制台输出(
console.log
console.error
等)会被自动捕获。可使用此功能调试页面行为,无需编写eval代码:
bunwv navigate http://localhost:3000
bunwv click "button.submit"
bunwv console                    # 查看页面的错误或日志
bunwv console --clear            # 读取并清空缓冲区
使用
--since <timestamp>
参数可仅查看自上次检查以来的新消息。缓冲区最多可存储1000条消息。

Screenshot Format Options

截图格式选项

Screenshots default to PNG. Use
--format
and
--quality
for smaller file sizes:
bunwv screenshot --format jpeg --quality 80    # saves /tmp/bunwv-screenshot.jpg
bunwv screenshot --format webp --quality 90    # saves /tmp/bunwv-screenshot.webp
bunwv screenshot output.jpg --format jpeg      # custom filename
截图默认格式为PNG。可使用
--format
--quality
参数减小文件大小:
bunwv screenshot --format jpeg --quality 80    # 保存为/tmp/bunwv-screenshot.jpg
bunwv screenshot --format webp --quality 90    # 保存为/tmp/bunwv-screenshot.webp
bunwv screenshot output.jpg --format jpeg      # 自定义文件名

Chrome Backend & CDP

Chrome后端与CDP

On macOS, bunwv defaults to WebKit. On Linux/Windows, it automatically uses Chrome. You can override on any platform:
bunwv start --backend chrome                # force Chrome on macOS
bunwv start --chrome-path /path/to/chromium # custom Chrome path
With Chrome, you can make raw DevTools Protocol calls:
bunwv cdp "Page.getLayoutMetrics"
bunwv cdp "Network.enable"
bunwv cdp "Runtime.evaluate" --params '{"expression": "1+1"}'
CDP is only available with the Chrome backend — it will error on WebKit.
在macOS上,bunwv默认使用WebKit。在Linux/Windows上,会自动使用Chrome。你可在任意平台上手动指定:
bunwv start --backend chrome                # 在macOS上强制使用Chrome
bunwv start --chrome-path /path/to/chromium # 指定自定义Chrome路径
使用Chrome时,你可直接调用DevTools Protocol(CDP):
bunwv cdp "Page.getLayoutMetrics"
bunwv cdp "Network.enable"
bunwv cdp "Runtime.evaluate" --params '{"expression": "1+1"}'
CDP仅在使用Chrome后端时可用——使用WebKit时会报错。

Error Recovery

错误恢复

If a command fails or times out:
  1. Take a screenshot to see what the page looks like
  2. Use
    eval
    to inspect the DOM
  3. If the daemon crashed, start it again (the data store preserves auth)
若命令执行失败或超时:
  1. 截图查看当前页面状态
  2. 使用
    eval
    命令检查DOM
  3. 若守护进程崩溃,重新启动它(数据存储会保留认证状态)

Screenshot Default

截图默认设置

Screenshots default to
/tmp/bunwv-screenshot.png
(or
.jpg
/
.webp
when using
--format
). Use the Read tool to view them. The same path is overwritten each time, keeping the project directory clean.
截图默认保存路径为
/tmp/bunwv-screenshot.png
(使用
--format
参数时会变为
.jpg
.webp
)。可使用读取工具查看截图。每次截图会覆盖同一路径,保持项目目录整洁。

Known Limitations

已知限制

  • macOS: defaults to WebKit (no dependencies). Linux/Windows: automatically uses Chrome (must be installed). Override with
    --backend
    .
  • click
    with CSS selector auto-waits
    for actionability (visible, stable, unobscured) but times out after 10s
  • click-text
    uses JS
    .click()
    (isTrusted: false)
    — use it for navigation links and non-form buttons. For form submission, always use
    submit
    instead.
  • clear
    is required for React inputs
    — keyboard-based clearing (Cmd+A, Backspace) doesn't update React's internal state
  • Coordinate clicks (
    click x y
    ) produce native
    isTrusted: true
    events but require knowing exact coordinates. Use
    eval
    with
    getBoundingClientRect()
    to find them when CSS selectors don't work.
  • macOS:默认使用WebKit(无依赖)。Linux/Windows:自动使用Chrome(需预先安装)。可通过
    --backend
    参数覆盖。
  • 使用CSS选择器的
    click
    命令会自动等待
    元素可交互(可见、稳定、未被遮挡),但超时时间为10秒
  • click-text
    使用JS的
    .click()
    方法(isTrusted: false)
    ——适用于导航链接和非表单按钮。表单提交请始终使用
    submit
    命令。
  • React输入框必须使用
    clear
    命令
    ——基于键盘的清除方式(Cmd+A、退格键)无法更新React内部状态
  • 坐标点击
    click x y
    )会产生原生
    isTrusted: true
    事件,但需要知道精确坐标。当CSS选择器无效时,可使用
    eval
    结合
    getBoundingClientRect()
    获取坐标。