cli-anything-safari

Safari browser automation CLI on macOS via safari-mcp. Controls real Safari (native, keeps logins) by wrapping the safari-mcp MCP server. Every one of the 84 MCP tools is exposed 1:1 with schema-accurate arguments — guaranteed parity, no manual drift.

By hkuds · 414 installs

npx skills add hkuds/cli-anything --skill cli-anything-safari

Source repository · Upstream listing

cli anything safari A command line interface for Safari browser automation on macOS. Wraps the [ safari mcp ](https://github.com/achiya automation/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. When to use this 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. 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 Install the CLI The first tool call will download the safari mcp npm package (one time, a few MB). Command Structure The CLI has 5 top level commands: Command Purpose 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) Usage Examples Discover the tool surface Call a tool (schema driven) Navigate and read in one round trip Form fill (bulk) safari fill form takes an array of {selector, value} objects. Pass it as a JSON string: Run cli anything safari tools describe safari fill form to see the exact schema, including any new fields safari mcp adds upstream. Network monitoring Storage Raw JSON escape hatch When you need to pass a complex nested object or want to drive the CLI from a pre built JSON blob: Interactive REPL The REPL banner prints the absolute path to this SKILL.md so agents can self discover capabilities. JSON Output All commands support json as a global flag: 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. 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 For AI Agents 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". Agent Specific Guidance Finding the right tool Use the introspection commands. The CLI is guaranteed to reflect the MCP server 1:1: 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. 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. 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 ... . 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) URL Validation 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. 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. Links [Safari MCP GitHub](https://github.com/achiya automation/safari mcp) [Safari MCP on npm](https://www.npmjs.com/package/safari mcp) [CLI Anything](https://github.com/HKUDS/CLI Anything) [MCP Backend Pattern Guide](https://github.com/HKUDS/CLI Anything/blob/main/cli anything plugin/guides/mcp backend.md) Security Considerations URL Validation 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 ). Tab Isolation Safari MCP enforces per session tab ownership upstream — tools cannot operate on tabs the session did not open. Profile Isolation Set SAFARI PROFILE env var to use a separate Safari profile for automation: This keeps cookies/logins/history separate from the user's main browsing. JavaScript Execution 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. 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. Regenerating the tool registry If you upgrade safari mcp , regenerate the bundled schema: The parity test ( test parity.py ) pins the expected tool count; update it when the upstream tool list changes. 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 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.