Safari Control
Use this skill when the task must happen in Safari itself:
- - The user is already logged in there
- Safari extensions, cookies, or profiles matter
- You need the current tab, tab list, page URL, or page text
- A headless browser would not reflect the real session
Do not force Safari to behave like Playwright. Prefer Safari's session access and DOM helpers first, Safari native UI automation second, and desktop-control only for pointer-heavy UI.
Core Tool
Run commands from the safari-control skill directory so the relative scripts/ path resolves correctly.
CODEBLOCK0
Recommended Flow
Use this exact flow unless the task clearly starts in one specific layer:
- 1. Check environment and active page:
CODEBLOCK1
INLINECODE3 is the branch point:
- -
safari_js=false: do not use DOM commands until the user enables JavaScript from Apple Events. - INLINECODE5 : do not use native Safari chrome commands.
- INLINECODE6 : use
screenshot --mode foreground when you need an image. - If Safari is missing required permissions or features, tell the user before proceeding. In particular, check whether Safari allows Automation, JavaScript in the Smart Search field, and JavaScript from Apple Events. Enabling these unlocks more functionality, but also increases risk because automation and scripted interactions gain more power over the user's Safari session. If the user refuses, do not keep pushing the recommendation and continue with the reduced feature set.
- 2. If Safari session state matters, inspect it before mutating anything:
CODEBLOCK2
- 3. If you need page content or web-page actions, verify DOM access:
CODEBLOCK3
- 4. Choose the lowest layer that fits:
- - Prefer DOM commands for page content, forms, links, and standard web controls.
- Use native Safari controls or menus for the smart search field, toolbar buttons, tab groups, and menu bar commands.
- Use desktop-control only for extension popups, native pickers, pointer-heavy drag/drop, or UI Accessibility cannot expose.
- When you want to draw the user's attention to important content on the page, you may use JavaScript to visually highlight it, such as adding a red outline, background tint, or temporary annotation.
Command Layers
1. Environment and Session
Use for machine-readable state and tab/window management.
CODEBLOCK4
Rules:
- - Prefer
--json for agent-readable output. - Most read-only page commands support
--window N --tab M, so you can inspect background tabs without switching focus. - INLINECODE10 before invasive work when preserving the user's layout matters.
- INLINECODE11 is additive: it recreates windows and tabs, it does not merge with or close current ones.
2. Page Read and Inspect
Use when JavaScript from Apple Events is enabled and the target is inside the web page.
CODEBLOCK5
Rules:
- - Prefer
snapshot before manual probing on unfamiliar pages. - Prefer
snapshot --interactive-only when you only need actionable controls and want smaller output. - Prefer
get-text --mode article before body; it is usually less noisy. - Prefer
element-info when a selector exists but behaves unexpectedly.
3. Page Actions and Waits
Use for standard DOM interactions after confirming the target is inside the page.
CODEBLOCK6
Rules:
- - Prefer
exists, count, wait-*, and snapshot to branch explicitly before acting. - After an action, wait on a concrete condition instead of sleeping.
- Use
press-key and press-shortcut only for page-level DOM handlers, not Safari chrome. - INLINECODE23 ,
forward, and reload return structured before/after state for change detection.
4. Native Safari UI
Use when the target is Safari chrome, not the page.
CODEBLOCK7
Rules:
- - The menu examples in this section assume Safari is running with an English UI.
- Start with
list-native-controls --json before guessing identifiers. - The native control JSON now includes
pressable, focusable, settable, and menuable fields. Use those before choosing press-native-control, focus-native-control, set-native-value, or menu actions. - INLINECODE34 and
native-search default to --confirm-mode ax. Use enter or both only if Safari's native confirm path is insufficient on that machine. - Use
list-menu-items or list-native-menu-items before clicking when Safari is localized.
Common Task Templates
Read the current page
CODEBLOCK8
Fill a form in the real Safari session
CODEBLOCK9
Operate Safari's own address bar or toolbar
CODEBLOCK10
Export and Evidence
Use when you need durable files instead of transient terminal output.
CODEBLOCK11
Rules:
- -
auto screenshot mode tries background capture first and falls back to foreground. - INLINECODE42 and
save-page-bundle can read a background tab via --window / --tab, but the screenshot still comes from the visible Safari window.
JavaScript Access Requirement
If check-js reports disabled, tell the user to enable:
- 1. Safari Settings
- Advanced
- Developer features if needed
- Developer
- INLINECODE47
Then retry check-js.
If native Safari automation or script-driven workflows are blocked, also tell the user to verify Safari settings such as:
- 1. Allow Automation
- Allow JavaScript in the Smart Search field
- Allow JavaScript from Apple Events
Explain that these settings enable more Safari-control features, but they also grant more power to automation and scripted interactions. If the user declines, continue with only the features that remain available.
Release and Distribution
These are maintenance commands, not the normal interaction path:
CODEBLOCK12
Use these when you want a compiled binary, a release directory, zip artifacts, or build metadata with git and environment information.
Limits
- - Safari scripting is strong for session state, structured page inspection, waits, and standard DOM interactions.
- Safari scripting is not a robust replacement for full browser automation.
- Complex form workflows, native pickers, extension UIs, canvas apps, and pointer-heavy interactions should move to
desktop-control. - INLINECODE50 is for small files injected into
input[type=file], not large native picker workflows. - INLINECODE52 is filesystem polling, not a Safari download API.
- INLINECODE53 exposes
document.cookie, not HttpOnly cookies or the full Safari cookie jar. - INLINECODE55 only sees the current origin.
Safari 控制
当任务必须在 Safari 本身中执行时使用此技能:
- - 用户已在该浏览器中登录
- Safari 扩展、Cookie 或配置文件很重要
- 你需要当前标签页、标签页列表、页面 URL 或页面文本
- 无头浏览器无法反映真实会话
不要强制 Safari 像 Playwright 那样运行。优先使用 Safari 的会话访问和 DOM 辅助工具,其次是 Safari 原生 UI 自动化,desktop-control 仅用于重度指针操作的 UI。
核心工具
从 safari-control 技能目录运行命令,以便相对路径 scripts/ 能正确解析。
bash
swift scripts/safari_control.swift
推荐流程
除非任务明确从某个特定层开始,否则使用以下精确流程:
- 1. 检查环境和活动页面:
bash
swift scripts/safari_control.swift doctor
swift scripts/safari_control.swift current --json
doctor 是分支点:
- - safarijs=false:在用户通过 Apple Events 启用 JavaScript 之前,不要使用 DOM 命令。
- accessibility=false:不要使用原生 Safari chrome 命令。
- screenshotbackground=false:当需要图像时,使用 screenshot --mode foreground。
- 如果 Safari 缺少所需的权限或功能,请在继续之前告知用户。特别要检查 Safari 是否允许自动化、智能搜索字段中的 JavaScript 以及来自 Apple Events 的 JavaScript。启用这些功能可以解锁更多功能,但也会增加风险,因为自动化和脚本交互对用户的 Safari 会话拥有更多控制权。如果用户拒绝,不要继续推荐,并在功能受限的情况下继续操作。
- 2. 如果 Safari 会话状态很重要,在修改任何内容之前先进行检查:
bash
swift scripts/safari_control.swift list-windows --json
swift scripts/safari_control.swift list-tabs --json
- 3. 如果需要页面内容或网页操作,验证 DOM 访问:
bash
swift scripts/safari_control.swift check-js
swift scripts/safari_control.swift snapshot --interactive-only --limit 30
- 4. 选择最合适的底层:
- - 对于页面内容、表单、链接和标准网页控件,优先使用 DOM 命令。
- 对于智能搜索字段、工具栏按钮、标签组和菜单栏命令,使用原生 Safari 控件或菜单。
- 仅对扩展弹窗、原生选择器、重度指针拖放或无障碍无法暴露的 UI,使用 desktop-control。
- 当你想将用户注意力吸引到页面上的重要内容时,可以使用 JavaScript 进行视觉高亮,例如添加红色轮廓、背景色调或临时注释。
命令层
1. 环境和会话
用于机器可读的状态和标签页/窗口管理。
bash
swift scripts/safari_control.swift doctor
swift scripts/safari_control.swift current --json
swift scripts/safari_control.swift list-windows --json
swift scripts/safari_control.swift list-tabs --json
swift scripts/safari_control.swift save-session ./session.json --front-only
swift scripts/safari_control.swift restore-session ./session.json
swift scripts/safari_control.swift new-window https://example.com
swift scripts/safari_control.swift switch-window 2
swift scripts/safari_control.swift switch-tab 2 --window 1
swift scripts/safari_control.swift switch-tab-title Dashboard
swift scripts/safari_control.swift switch-tab-url /dashboard
swift scripts/safari_control.swift duplicate-tab
swift scripts/safari_control.swift close-tab --tab 2 --window 1
swift scripts/safari_control.swift close-window --window 2
规则:
- - 对于代理可读的输出,优先使用 --json。
- 大多数只读页面命令支持 --window N --tab M,因此你可以在不切换焦点的情况下检查后台标签页。
- 在需要保留用户布局的侵入性操作之前,使用 save-session。
- restore-session 是累加性的:它会重新创建窗口和标签页,不会合并或关闭当前窗口和标签页。
2. 页面读取和检查
当来自 Apple Events 的 JavaScript 已启用且目标在网页内部时使用。
bash
swift scripts/safari_control.swift snapshot --limit 20 --heading-limit 10 --form-limit 5
swift scripts/safari_control.swift snapshot --interactive-only --limit 30
swift scripts/safari_control.swift interactive --json
swift scripts/safari_control.swift query form input --json
swift scripts/safari_control.swift element-info button[type=\submit\]
swift scripts/safari_control.swift find-text Buy now --json
swift scripts/safari_control.swift exists button[data-testid=\submit\]
swift scripts/safari_control.swift count button
swift scripts/safari_control.swift get-text --mode article
swift scripts/safari_control.swift extract-links --json
swift scripts/safari_control.swift extract-tables --json
swift scripts/safari_control.swift run-js document.title
swift scripts/safari_control.swift eval-js document.querySelectorAll(\a\).length
规则:
- - 在不熟悉的页面上进行手动探测之前,优先使用 snapshot。
- 当只需要可操作的控件并希望输出更小时,优先使用 snapshot --interactive-only。
- 优先使用 get-text --mode article 而不是 body;它通常噪音更少。
- 当选择器存在但行为异常时,优先使用 element-info。
3. 页面操作和等待
在确认目标在页面内部后,用于标准 DOM 交互。
bash
swift scripts/safari_control.swift focus input[name=\email\]
swift scripts/safari_control.swift focus-text Email --selector input, textarea, select
swift scripts/safari_control.swift fill input[name=\email\] user@example.com
swift scripts/safari_control.swift click button[type=\submit\]
swift scripts/safari_control.swift click-text Continue --exact
swift scripts/safari_control.swift select-option select[name=\country\] CN --by value
swift scripts/safari_control.swift check #agree
swift scripts/safari_control.swift uncheck #agree
swift scripts/safari_control.swift upload input[type=\file\] ./avatar.png
swift scripts/safari_control.swift submit form
swift scripts/safari_control.swift wait-selector form --visible
swift scripts/safari_control.swift wait-text Success
swift scripts/safari_control.swift wait-count .result-item 10 --op ge
swift scripts/safari_control.swift wait-title Success
swift scripts/safari_control.swift wait-url /success
swift scripts/safari_control.swift wait-download report-*.csv
swift scripts/safari_control.swift reload
swift scripts/safari_control.swift back
swift scripts/safari_control.swift forward
规则:
- - 在操作前优先使用 exists、count、wait-* 和 snapshot 进行显式分支判断。
- 操作后,等待具体条件而不是休眠。
- 仅对页面级 DOM 处理程序使用 press-key 和 press-shortcut,不用于 Safari chrome。
- back、forward 和 reload 返回结构化的前后状态以进行变更检测。
4. 原生 Safari UI
当目标是 Safari chrome 而非页面时使用。
bash
swift scripts/safari_control.swift list-menu-bar --json
swift scripts/safari_control.swift list-menu-items View --json
swift scripts/safari_control.swift click-menu View Reload Page
swift scripts/safari_control.swift list-native-controls --json
swift scripts/safaricontrol.swift focus-native-control WEBBROWSERADDRESSANDSEARCHFIELD --field identifier --exact
swift scripts/safaricontrol.swift set-native-value WEBBROWSERADDRESSANDSEARCHFIELD https://example.com --field identifier --exact
swift scripts/safari_control.swift press-native-control ReloadButton --field identifier --exact
swift scripts/safaricontrol.swift perform-native-action WEBBROWSERADDRESSANDSEARCHFIELD AXConfirm --field identifier --exact
swift scripts/safari_control.swift list-native-menu-items NewTabGroupButton --field identifier --exact --json
swift scripts/safari_control.swift click-native-menu-item NewTabGroup