/ha-mac-control
Hope Agent native macOS desktop control — the standard `mac_control` status / diagnostics / apps / dock / spaces / snapshot / visual / windows / menu / clipboard / dialog loop, target-first action rules, no-blind-coordinate policy, and recovery for stale AX/window/menu/dialog
$ npx -y skills add shiwenwen/hope-agent --skill ha-mac-control --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/ha-mac-control
Context preview
The summary Claude sees to decide when to auto-load this skill.
Hope Agent native macOS desktop control — the standard `mac_control` status / diagnostics / apps / dock / spaces / snapshot / visual / windows / menu / clipboard / dialog loop, target-first action rules, no-blind-coordinate policy, and recovery for stale AX/window/menu/dialog
SKILL.md
ha-mac-control.SKILL.mdname: ha-mac-control
description: "Hope Agent native macOS desktop control — the standard `mac_control` status / diagnostics / apps / dock / spaces / snapshot / visual / windows / menu / clipboard / dialog loop, target-first action rules, no-blind-coordinate policy, and recovery for stale AX/window/menu/dialog state. Load whenever using `mac_control`, or when the user asks to control local Mac apps, Dock, Spaces, click/type/menu/window/dialog/clipboard, automate Finder/TextEdit/System Settings, visually locate UI, or says 控制 Mac, macOS 自动化, 点按钮, 打开应用, Dock, Space, 关闭窗口, 菜单点击, 视觉定位."
version: 1.0.0
author: Hope Agent
license: MIT
allowed-tools: [mac_control, ask_user_question]
status: active
Hope Agent Mac Control
`mac_control` operates the user's macOS desktop from the authorized Hope Agent app process. macOS UI state is volatile: apps steal focus, AX IDs expire, sheets attach to windows, and multiple windows often share similar titles. Use a fresh observation before every meaningful action.
Standard Loop
Use this loop unless the user explicitly asks for a single read-only query:
1. mac_control(action="status")
2. mac_control(action="apps", op="frontmost" | "search" | "installed")
3. observe: snapshot / visual.observe / elements.find / windows.list / dock.list / spaces.list / menu.list / menu.popover / dialog.inspect
4. act: apps.activate/launch, dock.launch, spaces.switch, windows.*, act.*, menu.click, dialog.*
5. verify: wait, snapshot, windows.list, or dialog.inspect
For a concrete app workflow:
apps.launch bundleId=...
apps.frontmost # verify focus if the next step depends on menus/input
snapshot, elements.find, or windows.list # get fresh window/element ids
act/menu/windows/clipboard/dialog # one action burst
wait or snapshot # verify the expected change
Targeting Rules
- Prefer `bundleId` over `appName` for mutations. Use `apps.search` / `apps.installed` when the app name is uncertain, then retry with `bundleId`.
- `appNameMatch` defaults to `exact`. Use `contains` only for read-only discovery or when the user clearly gave a partial name.
- Prefer `windowId` from the latest `windows.list` or `snapshot` for window mutations.
- `target.windowTitleMatch` defaults to `exact`. Use `contains` only after listing windows and confirming a partial title is intentional.
- Prefer `elementId` from the latest `snapshot` / `visual.observe` / `elements.find` for precise clicks and set-value actions, and pass the matching `target.snapshotId` with it. `snapshotId + elementId` lets the runtime verify the original AX fingerprint and re-resolve stale `el_N` ids instead of blindly trusting a new traversal.
- Use `elements.find` when a full snapshot is too noisy or when an action target is ambiguous. It is read-only and returns scored candidates with reasons; retry mutations with `target.elementId` from the chosen candidate plus the result `snapshotId`.
- If two windows, dialogs, text fields, or buttons match, do not guess. Use a more specific target or ask the user.
- Element mutations reject equally ranked AX candidates instead of choosing the first match. When this happens, take a fresh `snapshot` and retry with `elementId`, `target.windowTitle`, `target.role`, or more specific `target.text`.
Actions
Apps
- Use `apps.frontmost` to know what macOS will receive menu and keyboard actions.
- Use `apps.activate bundleId=...` before operating an app that is not frontmost.
- Use `apps.search` or `apps.installed` when launch/activate by name fails.
- `apps.quit` is destructive. Verify the target app and prefer `bundleId`.
Dock and Spaces
- Use `dock.list` before `dock.launch`; prefer `dockItemId` or `bundleId` over a loose app name.
- Use `dock.menu` to open a Dock item's context menu and inspect `menuItems`; use `dock.select_menu` with `menuItem` when possible, or `menuIndex` only when titles are unavailable. If both are present, `menuItem` is treated as the intended target.
- `dock.hide` and `dock.show` change the user's Dock autohide setting and restart Dock, so be explicit before approval.
- Use `spaces.list` before `spaces.switch` when targeting a numbered Space. `spaceIndex` is 1-based.
- `spaces.switch direction="left"|"right"` / `spaceIndex` / `spaceId` pass exactly one selector. Direction and adjacent targets use Mission Control Control+Left/Right first; non-adjacent exact targets may fall back to Control+number or SkyLight/CGS. Verify with `spaces.list` or a fresh screenshot after switching.
- `spaces.move_window` moves one explicit window to `spaceIndex` / `spaceId` through SkyLight/CGS. Resolve the window first with `windows.list windowScope="all"` and prefer `windowId`; if post-move verification warns, use `spaces.list` or a fresh screenshot to confirm.
Windows
- Use `windows.list` before `windows.close`, `move`, `resize`, or `minimize` unless the user supplied an exact `windowId`.
- `windowScope` defaults to `frontmost`. Use `windows.list windowScope="all"` to discover background app windows before activating or focusing them.
- Prefer all-scope ids like `win_<pid>_<index>` for cross-app window mutations; they are safer than generic titles.
- For `windows.close`, avoid generic titles like `Untitled` / `未命名` when multiple similar windows exist. Use `windowId`.
- Hope Agent's own window cannot be mutated through the Accessibility worker; if the target is Hope Agent itself, explain the limitation.
Screenshots
- Use `snapshot includeScreenshot=true` when visual context matters.
- Default screenshots capture the primary display. Use `displayId` from `snapshot.displays` when the user points at a specific monitor.
- For a focused-window image, use `snapshot includeScreenshot=true screenshotTarget="window"`. Pass `windowId` from the latest snapshot/list when several windows are possible.
- Window screenshot matching uses the current AX window state; if it fails, take a fresh snapshot a
Read more
name: ha-mac-control description: "Hope Agent native macOS desktop control — the standard `mac_control` status / diagnostics / apps / dock / spaces / snapshot / visual / windows / menu / clipboard / dialog loop, target-first action rules, no-blind-coordinate policy, and recovery for stale AX/window/menu/dialog state. Load whenever using `mac_control`, or when the user asks to control local Mac apps, Dock, Spaces, click/type/menu/window/dialog/clipboard, automate Finder/TextEdit/System Settings, visually locate UI, or says 控制 Mac, macOS 自动化, 点按钮, 打开应用, Dock, Space, 关闭窗口, 菜单点击, 视觉定位." version: 1.0.0 author: Hope Agent license: MIT allowed-tools: [mac_control, ask_user_question] status: active
Hope Agent Mac Control
`mac_control` operates the user's macOS desktop from the authorized Hope Agent app process. macOS UI state is volatile: apps steal focus, AX IDs expire, sheets attach to windows, and multiple windows often share similar titles. Use a fresh observation before every meaningful action.
Standard Loop
Use this loop unless the user explicitly asks for a single read-only query:
1. mac_control(action="status") 2. mac_control(action="apps", op="frontmost" | "search" | "installed") 3. observe: snapshot / visual.observe / elements.find / windows.list / dock.list / spaces.list / menu.list / menu.popover / dialog.inspect 4. act: apps.activate/launch, dock.launch, spaces.switch, windows.*, act.*, menu.click, dialog.* 5. verify: wait, snapshot, windows.list, or dialog.inspect
For a concrete app workflow:
apps.launch bundleId=... apps.frontmost # verify focus if the next step depends on menus/input snapshot, elements.find, or windows.list # get fresh window/element ids act/menu/windows/clipboard/dialog # one action burst wait or snapshot # verify the expected change
Targeting Rules
- Prefer `bundleId` over `appName` for mutations. Use `apps.search` / `apps.installed` when the app name is uncertain, then retry with `bundleId`.
- `appNameMatch` defaults to `exact`. Use `contains` only for read-only discovery or when the user clearly gave a partial name.
- Prefer `windowId` from the latest `windows.list` or `snapshot` for window mutations.
- `target.windowTitleMatch` defaults to `exact`. Use `contains` only after listing windows and confirming a partial title is intentional.
- Prefer `elementId` from the latest `snapshot` / `visual.observe` / `elements.find` for precise clicks and set-value actions, and pass the matching `target.snapshotId` with it. `snapshotId + elementId` lets the runtime verify the original AX fingerprint and re-resolve stale `el_N` ids instead of blindly trusting a new traversal.
- Use `elements.find` when a full snapshot is too noisy or when an action target is ambiguous. It is read-only and returns scored candidates with reasons; retry mutations with `target.elementId` from the chosen candidate plus the result `snapshotId`.
- If two windows, dialogs, text fields, or buttons match, do not guess. Use a more specific target or ask the user.
- Element mutations reject equally ranked AX candidates instead of choosing the first match. When this happens, take a fresh `snapshot` and retry with `elementId`, `target.windowTitle`, `target.role`, or more specific `target.text`.
Actions
Apps
- Use `apps.frontmost` to know what macOS will receive menu and keyboard actions.
- Use `apps.activate bundleId=...` before operating an app that is not frontmost.
- Use `apps.search` or `apps.installed` when launch/activate by name fails.
- `apps.quit` is destructive. Verify the target app and prefer `bundleId`.
Dock and Spaces
- Use `dock.list` before `dock.launch`; prefer `dockItemId` or `bundleId` over a loose app name.
- Use `dock.menu` to open a Dock item's context menu and inspect `menuItems`; use `dock.select_menu` with `menuItem` when possible, or `menuIndex` only when titles are unavailable. If both are present, `menuItem` is treated as the intended target.
- `dock.hide` and `dock.show` change the user's Dock autohide setting and restart Dock, so be explicit before approval.
- Use `spaces.list` before `spaces.switch` when targeting a numbered Space. `spaceIndex` is 1-based.
- `spaces.switch direction="left"|"right"` / `spaceIndex` / `spaceId` pass exactly one selector. Direction and adjacent targets use Mission Control Control+Left/Right first; non-adjacent exact targets may fall back to Control+number or SkyLight/CGS. Verify with `spaces.list` or a fresh screenshot after switching.
- `spaces.move_window` moves one explicit window to `spaceIndex` / `spaceId` through SkyLight/CGS. Resolve the window first with `windows.list windowScope="all"` and prefer `windowId`; if post-move verification warns, use `spaces.list` or a fresh screenshot to confirm.
Windows
- Use `windows.list` before `windows.close`, `move`, `resize`, or `minimize` unless the user supplied an exact `windowId`.
- `windowScope` defaults to `frontmost`. Use `windows.list windowScope="all"` to discover background app windows before activating or focusing them.
- Prefer all-scope ids like `win_<pid>_<index>` for cross-app window mutations; they are safer than generic titles.
- For `windows.close`, avoid generic titles like `Untitled` / `未命名` when multiple similar windows exist. Use `windowId`.
- Hope Agent's own window cannot be mutated through the Accessibility worker; if the target is Hope Agent itself, explain the limitation.
Screenshots
- Use `snapshot includeScreenshot=true` when visual context matters.
- Default screenshots capture the primary display. Use `displayId` from `snapshot.displays` when the user points at a specific monitor.
- For a focused-window image, use `snapshot includeScreenshot=true screenshotTarget="window"`. Pass `windowId` from the latest snapshot/list when several windows are possible.
- Window screenshot matching uses the current AX window state; if it fails, take a fresh snapshot a
🦭 会记忆、能持续推进目标、会动态编排多 Agent 的跨端桌面 AI 助手,也可服务化常驻 NAS / 云端 | A cross-device desktop AI agent with memory, autonomous goals, dynamic workflows, and headless deployment
Repo: shiwenwen/hope-agent
Other skills on hope-agent.
- /email-draft
Use when the user asks to draft, polish, translate, or reply to an email. Produces a clean draft with subject line, greeting, body, and sign-off, plus a pre-send self-check.
Open skill - /feishu
Use when the user mentions 飞书 / Feishu / Lark workspace operations: docx (云文档) read/write, bitable (多维表格) records / views / dashboards, drive (云盘) upload/download, wiki (知识库) link resolution, approval (审批) instance create/cancel/query, calendar (日历) event create/list/update +
Open skill - /ha-browser
Hope Agent browser automation — the standard `status → tabs → snapshot → act` loop, stale-ref recovery rules, and what to do when login / 2FA / captcha / camera-prompt / dialog blocks progress. Load this skill whenever you reach for the `browser` tool. Trigger on: user asks the
Open skill - /ha-code-review
Hope-native review of uncommitted, staged, commit, branch, or PR changes: discover concrete regressions, independently verify candidates, and report actionable findings first without speculative noise.
Open skill - /ha-coding-common
Hope-native baseline for implementing, fixing, refactoring, and maintaining code: inspect the repository first, protect user changes, keep scope narrow, and finish with direct evidence.
Open skill - /ha-coding-plan
Hope-native implementation planning for non-trivial code changes: ground the plan in repository evidence, order dependencies, name critical files and risks, define verification, then continue execution when allowed.
Open skill

