cli-anything-safari

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

cli-anything-safari

cli-anything-safari

A command-line interface for Safari browser automation on macOS. Wraps the
safari-mcp
Node.js MCP server in a Python Click CLI.
Feature parity is guaranteed. Every Click command is generated automatically from
safari-mcp
's tool schema (bundled as
resources/tools.json
). All 84 tools are reachable with the exact argument names and types the MCP server expects.
一款用于macOS平台Safari浏览器自动化的命令行界面工具。基于Python Click CLI封装了
safari-mcp
Node.js MCP 服务器。
保证功能完全一致。所有Click命令均从
safari-mcp
的工具模式自动生成(打包为
resources/tools.json
)。全部84个工具均可通过MCP服务器要求的精确参数名称和类型调用。

When to use this CLI

何时使用此CLI

Each CLI invocation spawns a fresh subprocess, so there is per-call overhead. If your agent speaks MCP natively (Claude Code, Cursor, Cline, etc.), using
safari-mcp
directly over MCP stdio will be faster.
Use this CLI when:
  • Your agent framework does not speak MCP (Codex CLI, GitHub Copilot CLI, custom scripts, older agent frameworks).
  • You need to script browser automation from bash
    cli-anything-safari --json tool snapshot | jq '...'
    .
  • You run in CI/CD and want cron-able, subprocess-friendly output.
  • You're debugging interactively from Terminal.
每次CLI调用都会启动一个全新的子进程,因此存在单次调用的开销。如果你的Agent原生支持MCP(如Claude Code、Cursor、Cline等),直接通过MCP标准输入输出使用
safari-mcp
会更快。
在以下场景使用此CLI:
  • 你的Agent框架不支持MCP(如Codex CLI、GitHub Copilot CLI、自定义脚本、旧版Agent框架)。
  • 你需要通过bash编写浏览器自动化脚本——例如
    cli-anything-safari --json tool snapshot | jq '...'
  • 你在CI/CD环境中运行,需要支持定时任务、子进程友好的输出。
  • 你在终端中交互式调试

Installation

安装

Prerequisites

前置条件

  1. macOS — Safari MCP is macOS-only.
  2. Safari — already installed on macOS.
  3. Node.js 18+
    brew install node
    or from https://nodejs.org/
  4. Python 3.10+
  5. Enable Apple Events for Safari: Safari → Develop → Allow JavaScript from Apple Events
  1. macOS — Safari MCP仅支持macOS。
  2. Safari — macOS默认已安装。
  3. Node.js 18+ — 可通过
    brew install node
    安装,或从https://nodejs.org/下载。
  4. Python 3.10+
  5. 为Safari启用Apple事件:Safari → 开发 → 允许来自Apple事件的JavaScript

Install the CLI

安装CLI

bash
cd safari/agent-harness
pip install -e .
The first
tool
call will download the
safari-mcp
npm package (one-time, a few MB).
bash
cd safari/agent-harness
pip install -e .
首次调用
tool
命令时会下载
safari-mcp
npm包(仅一次,大小约数MB)。

Command Structure

命令结构

The CLI has 5 top-level commands:
CommandPurpose
tool
Call any of safari-mcp's 84 tools (dynamic, schema-driven)
tools
Inspect the bundled tool registry (
list
,
describe
,
count
)
raw
Escape hatch — call a tool by full name with raw JSON args
session
In-memory session state (last URL, current tab)
repl
Interactive REPL (default when no subcommand given)
CLI包含5个顶级命令:
命令用途
tool
调用safari-mcp的任意84个工具(动态生成,基于模式)
tools
查看已打包的工具注册表(
list
列出、
describe
描述、
count
统计)
raw
应急入口——通过完整工具名和原始JSON参数调用工具
session
内存中的会话状态(最后访问的URL、当前标签页)
repl
交互式REPL(未指定子命令时默认启动)

Usage Examples

使用示例

Discover the tool surface

探索工具范围

bash
undefined
bash
undefined

Count of tools (sanity check — must match safari-mcp's registered tools)

统计工具数量( sanity检查——必须与safari-mcp注册的工具数一致)

cli-anything-safari tools count
cli-anything-safari tools count

→ 84

→ 84

List every tool

列出所有工具

cli-anything-safari tools list cli-anything-safari tools list --filter click # filter by substring
cli-anything-safari tools list cli-anything-safari tools list --filter click # 通过子字符串过滤

Full schema for one tool (JSON or human format)

查看单个工具的完整模式(JSON或人类可读格式)

cli-anything-safari tools describe safari_scroll cli-anything-safari --json tools describe safari_click
undefined
cli-anything-safari tools describe safari_scroll cli-anything-safari --json tools describe safari_click
undefined

Call a tool (schema-driven)

调用工具(基于模式)

bash
undefined
bash
undefined

Navigate

导航

cli-anything-safari tool navigate --url https://example.com
cli-anything-safari tool navigate --url https://example.com

Take a snapshot (preferred over screenshot — structured text with ref IDs)

生成快照(优于截图——包含引用ID的结构化文本)

cli-anything-safari --json tool snapshot
cli-anything-safari --json tool snapshot

Click by ref (refs come from snapshot; they expire on the next snapshot!)

通过引用点击(引用来自快照;下次快照时会失效!)

cli-anything-safari tool click --ref 0_5
cli-anything-safari tool click --ref 0_5

Click by selector or visible text

通过选择器或可见文本点击

cli-anything-safari tool click --selector "#submit" cli-anything-safari tool click --text "Log in"
cli-anything-safari tool click --selector "#submit" cli-anything-safari tool click --text "Log in"

Fill a field

填充字段

cli-anything-safari tool fill --selector "#email" --value "user@example.com"
cli-anything-safari tool fill --selector "#email" --value "user@example.com"

Scroll by direction/amount (NOT x/y — note the schema!)

按方向/数量滚动(注意:不是x/y——遵循模式!)

cli-anything-safari tool scroll --direction down --amount 500
cli-anything-safari tool scroll --direction down --amount 500

Drag one element onto another

将一个元素拖到另一个元素上

cli-anything-safari tool drag
--source-selector ".card"
--target-selector ".trash"
cli-anything-safari tool drag
--source-selector ".card"
--target-selector ".trash"

Screenshot — returns base64 JPEG in stdout. Decode with:

截图——在标准输出返回base64格式的JPEG。解码命令:

cli-anything-safari --json tool screenshot --full-page
| python3 -c "import sys,json,base64;
d=json.load(sys.stdin);
open('/tmp/shot.jpg','wb').write(base64.b64decode(d['data']))"
cli-anything-safari --json tool screenshot --full-page
| python3 -c "import sys,json,base64;
d=json.load(sys.stdin);
open('/tmp/shot.jpg','wb').write(base64.b64decode(d['data']))"

Save as PDF (this one writes to disk directly)

保存为PDF(此命令直接写入磁盘)

cli-anything-safari tool save-pdf --path /tmp/page.pdf
cli-anything-safari tool save-pdf --path /tmp/page.pdf

Evaluate JavaScript (note: parameter is --script, not --code)

执行JavaScript(注意:参数是--script,不是--code)

cli-anything-safari tool evaluate --script "document.title"
undefined
cli-anything-safari tool evaluate --script "document.title"
undefined

Navigate and read in one round-trip

一次往返完成导航与读取

bash
cli-anything-safari --json tool navigate-and-read --url https://example.com
bash
cli-anything-safari --json tool navigate-and-read --url https://example.com

Form fill (bulk)

批量填充表单

safari_fill_form
takes an array of
{selector, value}
objects. Pass it as a JSON string:
bash
cli-anything-safari tool fill-form --fields '[
  {"selector": "#email",    "value": "user@example.com"},
  {"selector": "#password", "value": "hunter2"}
]'
Run
cli-anything-safari tools describe safari_fill_form
to see the exact schema, including any new fields safari-mcp adds upstream.
safari_fill_form
接收一个
{selector, value}
对象的数组。需以JSON字符串形式传递:
bash
cli-anything-safari tool fill-form --fields '[
  {"selector": "#email",    "value": "user@example.com"},
  {"selector": "#password", "value": "hunter2"}
]'
运行
cli-anything-safari tools describe safari_fill_form
查看精确模式,包括safari-mcp上游新增的字段。

Network monitoring

网络监控

bash
cli-anything-safari tool start-network-capture
cli-anything-safari tool navigate --url https://example.com
cli-anything-safari --json tool network
cli-anything-safari tool performance-metrics
bash
cli-anything-safari tool start-network-capture
cli-anything-safari tool navigate --url https://example.com
cli-anything-safari --json tool network
cli-anything-safari tool performance-metrics

Storage

存储操作

bash
cli-anything-safari tool get-cookies
cli-anything-safari tool set-cookie --name session --value abc123 --domain example.com
cli-anything-safari tool local-storage --key theme
bash
cli-anything-safari tool get-cookies
cli-anything-safari tool set-cookie --name session --value abc123 --domain example.com
cli-anything-safari tool local-storage --key theme

export-storage returns JSON to stdout — no --path arg. Pipe to a file:

export-storage将JSON返回至标准输出——无--path参数。可将输出管道到文件:

cli-anything-safari --json tool export-storage > /tmp/storage.json
undefined
cli-anything-safari --json tool export-storage > /tmp/storage.json
undefined

Raw JSON escape hatch

原始JSON应急入口

When you need to pass a complex nested object or want to drive the CLI from a pre-built JSON blob:
bash
cli-anything-safari raw safari_evaluate \
    --json-args '{"code":"[...document.querySelectorAll(\"a\")].map(a => a.href)"}'
当你需要传递复杂嵌套对象,或希望通过预构建的JSON blob驱动CLI时:
bash
cli-anything-safari raw safari_evaluate \
    --json-args '{"code":"[...document.querySelectorAll(\"a\")].map(a => a.href)"}'

Interactive REPL

交互式REPL

bash
cli-anything-safari
The REPL banner prints the absolute path to this SKILL.md so agents can self-discover capabilities.
bash
cli-anything-safari
REPL横幅会打印SKILL.md的绝对路径,以便Agent自动发现功能。

JSON Output

JSON输出

All commands support
--json
as a global flag:
bash
cli-anything-safari --json tool snapshot
cli-anything-safari --json tool list-tabs
cli-anything-safari --json tools list
所有命令均支持全局
--json
标志:
bash
cli-anything-safari --json tool snapshot
cli-anything-safari --json tool list-tabs
cli-anything-safari --json tools list

State Management

状态管理

The CLI maintains a small amount of in-memory state for REPL display only:
  • last_url
    — last URL the CLI navigated to (updated after every successful
    tool navigate
    ,
    tool navigate-and-read
    , or
    tool new-tab
    )
  • current_tab_index
    — last known active tab index
There is no persistent session, no undo/redo, no document model. Every CLI invocation starts with fresh state. Safari MCP itself is stateless per-call: each
tool
command spawns a fresh
npx safari-mcp
subprocess, performs the action, and exits. This is a deliberate design choice; see
HARNESS.md
and
TEST.md
for the reasoning behind the deviation from the standard undo/redo pattern.
CLI仅为REPL显示维护少量内存状态:
  • last_url
    — CLI最后导航到的URL(每次成功执行
    tool navigate
    tool navigate-and-read
    tool new-tab
    后更新)
  • current_tab_index
    — 最后已知的活动标签页索引
无持久会话,无撤销/重做功能,无文档模型。每次CLI调用均从全新状态开始。Safari MCP本身是单次调用无状态的:每个
tool
命令都会启动一个全新的
npx safari-mcp
子进程,执行操作后退出。这是一个刻意的设计选择;如需了解偏离标准撤销/重做模式的原因,请查看
HARNESS.md
TEST.md

Output Formats

输出格式

All commands support dual output modes:
  • Human-readable (default): indented key-value text for
    dict
    results, bullet lists for arrays, plain text otherwise
  • Machine-readable (
    --json
    flag): structured JSON for agent consumption
bash
undefined
所有命令支持两种输出模式:
  • 人类可读格式(默认):字典结果为缩进的键值文本,数组为项目符号列表,其他为纯文本
  • 机器可读格式
    --json
    标志):结构化JSON,供Agent使用
bash
undefined

Human output

人类可读输出

cli-anything-safari tool snapshot
cli-anything-safari tool snapshot

JSON output for agents

供Agent使用的JSON输出

cli-anything-safari --json tool snapshot cli-anything-safari --json tools list cli-anything-safari --json tools describe safari_click
undefined
cli-anything-safari --json tool snapshot cli-anything-safari --json tools list cli-anything-safari --json tools describe safari_click
undefined

For AI Agents

面向AI Agent的说明

When using this CLI programmatically:
  1. Always use
    --json
    flag
    for parseable output.
  2. Check return codes — 0 for success, non-zero for errors (URL validation failures, MCP call failures, invalid JSON args).
  3. Parse stderr for error messages; use stdout for data.
  4. File-handling tools have inconsistent path arg names — always check
    tools describe <name>
    first:
    • tool save-pdf --path /tmp/x.pdf
    • tool upload-file --selector ... --file-path /tmp/x.txt
      (note:
      --file-path
      , not
      --path
      )
    • tool export-storage
      — no path arg; pipe JSON output to a file
    • tool import-storage --path /tmp/x.json
    • tool screenshot
      /
      screenshot-element
      — return base64 in the JSON response, no path arg (decode it yourself)
  5. Snapshot before click — refs from
    tool snapshot
    expire on the next snapshot. Always snapshot → find ref → click in close succession.
  6. Discover tools via
    tools list
    — the bundled registry is the source of truth for what's available. Do not hard-code tool names that may change upstream.
  7. Use
    tools describe <name>
    to learn the exact schema (required args, enum choices, JSON-typed args) before constructing a call. Never assume parameter names from the description — for example,
    safari_evaluate
    takes
    --script
    (not
    --code
    ) even though the description says "JavaScript code to execute".
以编程方式使用此CLI时:
  1. 始终使用
    --json
    标志
    以获得可解析的输出。
  2. 检查返回码 — 0表示成功,非0表示错误(URL验证失败、MCP调用失败、无效JSON参数)。
  3. 解析标准错误流获取错误信息;标准输出流用于返回数据。
  4. 文件处理工具的路径参数名称不一致 — 调用前务必先执行
    tools describe <name>
    • tool save-pdf --path /tmp/x.pdf
    • tool upload-file --selector ... --file-path /tmp/x.txt
      (注意:是
      --file-path
      ,不是
      --path
    • tool export-storage
      — 无路径参数;将JSON输出管道到文件
    • tool import-storage --path /tmp/x.json
    • tool screenshot
      /
      screenshot-element
      — 在JSON响应中返回base64,无路径参数(需自行解码)
  5. 点击前先快照
    tool snapshot
    返回的引用在下次快照时会失效。务必按快照→查找引用→点击的顺序连续操作。
  6. 通过
    tools list
    探索工具
    — 已打包的注册表是可用工具的权威来源。不要硬编码可能随上游变更的工具名称。
  7. **使用
    tools describe <name>
    **了解精确模式(必填参数、枚举选项、JSON类型参数)后再构建调用。切勿根据描述假设参数名称——例如,
    safari_evaluate
    接收
    --script
    (而非
    --code
    ),尽管描述中写的是“要执行的JavaScript代码”。

Agent-Specific Guidance

针对特定Agent的指南

Finding the right tool

查找合适的工具

Use the introspection commands. The CLI is guaranteed to reflect the MCP server 1:1:
bash
undefined
使用自省命令。CLI保证与MCP服务器1:1同步:
bash
undefined

Find all click-related tools

查找所有与点击相关的工具

cli-anything-safari tools list --filter click
cli-anything-safari tools list --filter click

Get the full schema (including every argument with type, description,

获取完整模式(包括每个参数的类型、描述、必填/可选、枚举选项、默认值)

required/optional, enum choices, defaults)

cli-anything-safari --json tools describe safari_click
undefined
cli-anything-safari --json tools describe safari_click
undefined

Tool selection strategy

工具选择策略

  1. tool snapshot
    over
    tool screenshot
    — structured text with ref IDs is orders of magnitude cheaper and carries the refs needed for clicks.
  2. tool click --ref
    over
    tool click --selector
    — refs are stable within a single snapshot, selectors may be brittle.
  3. tool navigate-and-read
    over
    navigate
    +
    read-page
    — saves one round-trip.
  4. tool click-and-read
    over
    click
    +
    read-page
    — saves one round-trip.
  5. tool native-click
    only when regular click fails with 405/403 (WAF blocks, G2, Cloudflare) — it physically moves the cursor.
  1. 优先使用
    tool snapshot
    而非
    tool screenshot
    — 带有引用ID的结构化文本成本低得多,且包含点击所需的引用。
  2. 优先使用
    tool click --ref
    而非
    tool click --selector
    — 引用在单个快照内稳定,选择器可能不稳定。
  3. 优先使用
    tool navigate-and-read
    而非
    navigate
    +
    read-page
    — 减少一次往返。
  4. 优先使用
    tool click-and-read
    而非
    click
    +
    read-page
    — 减少一次往返。
  5. 仅在常规点击返回405/403错误时使用
    tool native-click
    (如WAF拦截、G2、Cloudflare)——它会物理移动光标。

Refs Expire

引用会失效

Refs from
tool snapshot
expire when you take a new snapshot:
  • First snapshot: refs
    0_1
    ,
    0_2
    ,
    0_3
    ...
  • Second snapshot: refs
    1_1
    ,
    1_2
    ,
    1_3
    ...
Always snapshot → click in close succession. If in doubt, snapshot again.
tool snapshot
返回的引用在拍摄新快照时会失效:
  • 第一次快照:引用为
    0_1
    ,
    0_2
    ,
    0_3
    ...
  • 第二次快照:引用为
    1_1
    ,
    1_2
    ,
    1_3
    ...
务必按快照→点击的顺序连续操作。如有疑问,重新快照。

Tab Ownership Safety

标签页所有权安全

Safari MCP tracks tab ownership per session. Tools that modify a tab (navigate, click, fill) are blocked on tabs the session did not open. To operate on a specific page, always start with
tool new-tab --url ...
.
Safari MCP按会话跟踪标签页所有权。修改标签页的工具(导航、点击、填充)无法操作会话未打开的标签页。如需操作特定页面,请始终从
tool new-tab --url ...
开始。

Error Handling

错误处理

Common errors:
  • npx not found
    → install Node.js 18+
  • safari-mcp package not found on npm registry
    → check network
  • Not macOS
    → harness is macOS-only
  • AppleScript denied
    → enable "Allow JavaScript from Apple Events" in Safari → Develop
  • Blocked URL scheme: file
    → URL validation rejected the input (by design)
常见错误:
  • npx not found
    → 安装Node.js 18+
  • safari-mcp package not found on npm registry
    → 检查网络
  • Not macOS
    → 此工具仅支持macOS
  • AppleScript denied
    → 在Safari的“开发”菜单中启用“允许来自Apple事件的JavaScript”
  • Blocked URL scheme: file
    → URL验证拒绝了输入(设计如此)

URL Validation

URL验证

The CLI validates URLs before passing them to
safari_navigate
,
safari_navigate_and_read
, and
safari_new_tab
. Blocked schemes:
file
,
javascript
,
data
,
vbscript
,
about
,
chrome
,
safari
,
webkit
,
x-apple
, and other browser-internal schemes. The
raw
command also enforces this for navigation tools.
CLI会在将URL传递给
safari_navigate
safari_navigate_and_read
safari_new_tab
前进行验证。被阻止的协议包括:
file
javascript
data
vbscript
about
chrome
safari
webkit
x-apple
及其他浏览器内部协议。
raw
命令同样会对导航工具执行此验证。

Multi-Session Warning

多会话警告

Safari MCP enforces a single active session by killing stale Node.js processes older than 10 seconds. If you run two CLI instances at once, one will kill the other's backend. There is currently no daemon mode — for latency-sensitive workflows, drive the CLI from a long-lived Python script that imports
cli_anything.safari.utils.safari_backend.call()
directly to avoid re-spawning the subprocess on every invocation.
Safari MCP通过终止超过10秒的陈旧Node.js进程来强制执行单个活动会话。如果同时运行两个CLI实例,其中一个会终止另一个的后端进程。目前无守护进程模式——对于对延迟敏感的工作流,可从长期运行的Python脚本直接导入
cli_anything.safari.utils.safari_backend.call()
,避免每次调用都重新启动子进程。

Links

链接

Security Considerations

安全注意事项

URL Validation

URL验证

All navigation tools (
tool navigate
,
tool navigate-and-read
,
tool new-tab
, and
raw safari_navigate*
) pass the
url
argument through
utils/security.py
which blocks dangerous schemes and optionally blocks private networks (set
CLI_ANYTHING_SAFARI_BLOCK_PRIVATE=1
).
所有导航工具(
tool navigate
tool navigate-and-read
tool new-tab
以及
raw safari_navigate*
)都会将
url
参数传入
utils/security.py
进行验证,该模块会阻止危险协议,并可选择阻止私有网络(设置
CLI_ANYTHING_SAFARI_BLOCK_PRIVATE=1
)。

Tab Isolation

标签页隔离

Safari MCP enforces per-session tab ownership upstream — tools cannot operate on tabs the session did not open.
Safari MCP在上游强制执行按会话的标签页隔离——工具无法操作会话未打开的标签页。

Profile Isolation

配置文件隔离

Set
SAFARI_PROFILE
env var to use a separate Safari profile for automation:
bash
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
This keeps cookies/logins/history separate from the user's main browsing.
设置
SAFARI_PROFILE
环境变量,为自动化操作使用单独的Safari配置文件:
bash
export SAFARI_PROFILE="Automation"
cli-anything-safari tool navigate --url https://example.com
这样可将Cookie、登录信息、浏览历史与用户的主浏览会话隔离开。

JavaScript Execution

JavaScript执行

tool evaluate
and
tool run-script
run arbitrary JavaScript in the page context. Treat untrusted input with the same care as any dynamic code execution path.
tool evaluate
tool run-script
会在页面上下文中执行任意JavaScript。处理不受信任的输入时,需像对待任何动态代码执行路径一样谨慎。

Clipboard

剪贴板

tool clipboard-read
and
tool clipboard-write
touch the system clipboard. Be careful when running inside a user's active session — overwriting the clipboard mid-task is disruptive.
tool clipboard-read
tool clipboard-write
会访问系统剪贴板。在用户的活动会话中运行时需小心——在任务中途覆盖剪贴板会造成干扰。

Regenerating the tool registry

重新生成工具注册表

If you upgrade
safari-mcp
, regenerate the bundled schema:
bash
python scripts/extract_tools.py \
    "$(npm root -g)/safari-mcp/index.js" \
    cli_anything/safari/resources/tools.json
The parity test (
test_parity.py
) pins the expected tool count; update it when the upstream tool list changes.
如果你升级了
safari-mcp
,请重新生成已打包的模式:
bash
python scripts/extract_tools.py \
    "$(npm root -g)/safari-mcp/index.js" \
    cli_anything/safari/resources/tools.json
一致性测试(
test_parity.py
)固定了预期的工具数量;上游工具列表变更时请更新此测试。

More Information

更多信息

  • Full documentation:
    cli_anything/safari/README.md
    in the package
  • Test coverage:
    cli_anything/safari/tests/TEST.md
    in the package
  • Architecture analysis:
    safari/agent-harness/SAFARI.md
  • Methodology:
    cli-anything-plugin/HARNESS.md
  • MCP backend pattern:
    cli-anything-plugin/guides/mcp-backend.md
  • 完整文档:包内的
    cli_anything/safari/README.md
  • 测试覆盖:包内的
    cli_anything/safari/tests/TEST.md
  • 架构分析
    safari/agent-harness/SAFARI.md
  • 方法论
    cli-anything-plugin/HARNESS.md
  • MCP后端模式
    cli-anything-plugin/guides/mcp-backend.md

Version

版本

1.0.0 — targets safari-mcp 2.7.8 (84 tools). Bundled tool registry is regenerated via
scripts/extract_tools.py
when safari-mcp upgrades.
1.0.0 — 适配safari-mcp 2.7.8(84个工具)。当safari-mcp升级时,会通过
scripts/extract_tools.py
重新生成已打包的工具注册表。