shiwenwen/hope-agent/skills/ha-mac-control/SKILL.md
ha-mac-control
Use it for design tasks; the detail page covers purpose, installation, and practical steps.
- Source repository stars
- 1,485
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-24
- Source checked
- 2026-08-25
Decision brief
What it does: where it fits
maccontrol 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.
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/shiwenwen/hope-agent --skill "skills/ha-mac-control"Inspect the Agent Skill "ha-mac-control" from https://github.com/shiwenwen/hope-agent/blob/ee2d729bd514209508989a70f9bdfb6b169b2925/skills/ha-mac-control/SKILL.md at commit ee2d729bd514209508989a70f9bdfb6b169b2925. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Verification and Recovery
After apps.launch / apps.activate, verify frontmost before menu or input actions.
After apps.launch / apps.activate, verify frontmost before menu or input actions.After any action that changes UI, re-snapshot or call the relevant list/inspect command before using old ids.Tool approval restores the previously frontmost app and focused window before the approved maccontrol mutation runs, but treat it as best-effort. After an approval, verify frontmost or take a fresh observation before ch… - 02
Standard Loop
Use this loop unless the user explicitly asks for a single read-only query:
Use this loop unless the user explicitly asks for a single read-only query:For a concrete app workflow: - 03
Targeting Rules
Prefer bundleId over appName for mutations. Use apps.search / apps.installed when the app name is uncertain, then retry with bundleId.
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. - 04
Actions
Use visual positioning when AX labels are missing, the UI is canvas-like, or the user refers to something visible on screen rather than a stable element.
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. - 05
Apps
Use apps.frontmost to know what macOS will receive menu and keyboard actions.
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.
Permission review
Static risk signals and limitations
Reads files
The documentation asks the agent to read local files, directories, or repositories.
`visual.observe` is read-only. It returns an image file marker for model vision plus a compact JSON payload with `snapshotId`, screenshot metadata, displays, and windows.Evidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 90/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 1,485 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- shiwenwen/hope-agent
- Skill path
- skills/ha-mac-control/SKILL.md
- Commit
- ee2d729bd514209508989a70f9bdfb6b169b2925
- License
- MIT
- Collected
- 2026-08-25
- Default branch
- main
View the original SKILL.md
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
bundleIdoverappNamefor mutations. Useapps.search/apps.installedwhen the app name is uncertain, then retry withbundleId. appNameMatchdefaults toexact. Usecontainsonly for read-only discovery or when the user clearly gave a partial name.- Prefer
windowIdfrom the latestwindows.listorsnapshotfor window mutations. target.windowTitleMatchdefaults toexact. Usecontainsonly after listing windows and confirming a partial title is intentional.- Prefer
elementIdfrom the latestsnapshot/visual.observe/elements.findfor precise clicks and set-value actions, and pass the matchingtarget.snapshotIdwith it.snapshotId + elementIdlets the runtime verify the original AX fingerprint and re-resolve staleel_Nids instead of blindly trusting a new traversal. - Use
elements.findwhen 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 withtarget.elementIdfrom the chosen candidate plus the resultsnapshotId. - 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
snapshotand retry withelementId,target.windowTitle,target.role, or more specifictarget.text.
Actions
Apps
- Use
apps.frontmostto know what macOS will receive menu and keyboard actions. - Use
apps.activate bundleId=...before operating an app that is not frontmost. - Use
apps.searchorapps.installedwhen launch/activate by name fails. apps.quitis destructive. Verify the target app and preferbundleId.
Dock and Spaces
- Use
dock.listbeforedock.launch; preferdockItemIdorbundleIdover a loose app name. - Use
dock.menuto open a Dock item's context menu and inspectmenuItems; usedock.select_menuwithmenuItemwhen possible, ormenuIndexonly when titles are unavailable. If both are present,menuItemis treated as the intended target. dock.hideanddock.showchange the user's Dock autohide setting and restart Dock, so be explicit before approval.- Use
spaces.listbeforespaces.switchwhen targeting a numbered Space.spaceIndexis 1-based. spaces.switch direction="left"|"right"/spaceIndex/spaceIdpass 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 withspaces.listor a fresh screenshot after switching.spaces.move_windowmoves one explicit window tospaceIndex/spaceIdthrough SkyLight/CGS. Resolve the window first withwindows.list windowScope="all"and preferwindowId; if post-move verification warns, usespaces.listor a fresh screenshot to confirm.
Windows
- Use
windows.listbeforewindows.close,move,resize, orminimizeunless the user supplied an exactwindowId. windowScopedefaults tofrontmost. Usewindows.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 likeUntitled/未命名when multiple similar windows exist. UsewindowId. - 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=truewhen visual context matters. - Default screenshots capture the primary display. Use
displayIdfromsnapshot.displayswhen the user points at a specific monitor. - For a focused-window image, use
snapshot includeScreenshot=true screenshotTarget="window". PasswindowIdfrom 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 and retry with a precise
windowId.
Elements and Text
- Use
elements.find op="find"before clicking or typing into ambiguous UI. Useful examples:target.role="AXButton",target.text="Save",target.windowTitle="Untitled". elements.findreturnstotalMatchesplus candidatescore,reasons,element, andwindow. Prefer high-score candidates whose reasons include the user's intended text/role/window.- Browser/WebView snapshots may focus the dominant
AXWebAreaand re-traverse when no text input is exposed. If a result warning mentions this fallback, use the refreshed candidates first; if it still exposes only web/canvas content, switch tovisual.observe annotate=true, OCR, orvisual.point. - Use
act.dry_runwhen the next mutation should use the exact same target resolver, but you want to verify the resolved element first. PassdryRunOpfor the intended real op, such asclick,type, orset_value; the result returns resolvedtargetpluspreview.executionPlan,fallbackPlan,verificationPlan, andwarningswithout changing the UI. - Read mutation
verificationwhen present.verifiedmeans the low-level expected state was observed,failedmeans the action returned but the observed state did not match, andunverifiedmeans the tool could not prove the result. For ordinary clicks without a clear state change, still verify withwait,snapshot,elements.find, ordialog.inspect. - Use
explain=trueonly when you need the same preview attached to an executed action result; for pre-approval review, preferact.dry_run. - Use
act.perform_actionfor a named AX action when a higher-level op is not enough. It requirestargetandaxAction; common aliases such aspressandshow_menunormalize to AX names, while other valid AX action strings are attempted directly even if the target did not advertise them inactions[]. act.clickis for AX targets only. It requirestargetand should not consume rawx/y.act.clickfirst attemptsAXPress; if that fails and the target has bounds, the runtime may click the target center and report anAXPressFailed+CGEventFallback(...)execution marker.- Use
act.click_pointonly when the user explicitly wants a coordinate click or AX cannot represent the target. This includes valid coordinates like(0, 0). - Use
act.move_cursorwhen the user wants the pointer moved without clicking. It accepts eitherx/yor a target, and can smooth the path withdurationMs/steps/motionProfile. - Use
act.pressfor single-key or repeated key presses. Usehotkeyfor one chord such as Cmd+N; usepresswhen you need sequential keys, repeat, holdMs, intervalMs, or shared modifiers. - Use
act.swipefor smooth pointer drag gestures fromx/y,fromX/fromY, or a target todeltaX/deltaY,toX/toY, ortoTarget; useact.dragfor deliberate drag/drop between coordinate or AX element endpoints. PassmotionProfile="human"only when the gesture benefits from eased, less mechanical pointer motion. act.typeandact.set_valueshould target text input roles (AXTextArea,AXTextField,AXSearchField, etc.).act.typedefaults to AXSetValue. Only passtypingProfile/typingDelayMswhen the app needs real character-by-character keyboard input.- For replacement-style text entry, failed
AXSetValuecan fall back to focus + Cmd+A + protected pasteboard replace; still inspect the returnedverificationbefore assuming the text changed. - Use
act.pastefor long text or apps that do not acceptAXValuereliably. It stages text on the pasteboard, invokes paste, and reports only clipboard restore status. act,wait, anddialogresults are compact by default and do not return a full AX snapshot. SetincludeSnapshot=trueonly when full AX tree debugging is needed; otherwise verify withwait,elements.find,windows.list, ordialog.inspect.- Do not type passwords, OTPs, or private credentials unless the user explicitly supplied them in the current flow.
Visual Positioning
Use visual positioning when AX labels are missing, the UI is canvas-like, or the user refers to something visible on screen rather than a stable element.
Standard visual loop:
visual.observe screenshotTarget="window" | "display" annotate=true
act.click target.elementId="el_..." target.snapshotId="macsnap_..." # when the annotated id is clear
visual.ocr or visual.find_text text="..." # when the target is visible text
read the returned image and choose an image pixel point # when OCR is not enough
visual.point snapshotId=... coordinateSpace="image_pixels" x=... y=...
act.click target=<suggestedAction.target> # if suggestedAction.op is click
act.click_point x=<suggestedAction.x> y=<suggestedAction.y> # if suggestedAction.op is click_point
verify with snapshot, visual.observe, wait, or elements.find
Rules:
visual.observeis read-only. It returns an image file marker for model vision plus a compact JSON payload withsnapshotId, screenshot metadata, displays, and windows.- Prefer
visual.observe annotate=truefor ambiguous visual UI. The returned image is labeled with AX element ids and includesuiMap; when an id clearly identifies the target, useact.click target.elementId=... target.snapshotId=<observe snapshotId>instead of a coordinate click. - If the annotated id is unclear or the target is not in
uiMap, use OCR or image-pixel positioning. visual.ocris read-only. Use it when visible text matters but you do not need to filter for one phrase yet.visual.find_textis read-only. Use it before coordinate clicking visible words or text-only buttons; passtextMatch="contains"only for intentional partial text.visual.find_textreturns OCRtextMatcheswith center points, AXhitElements/nearestElements, a top-levelsuggestedAction, andsuggestedActions[]ordered from stable AX target to coordinate fallback.- Image pixel coordinates use the screenshot top-left as origin.
(0, 0)is valid. Never pass image pixels directly toact.click_point. - Always call
visual.pointbefore coordinate clicks chosen from a screenshot. It converts image pixels to macOS screen points and returns AXhitElements/nearestElements. - Prefer
suggestedActionfromvisual.pointorvisual.find_text; follow itsop. If it includestarget, callact.clickwith that target. If it isclick_point, use itsx/y. IfinsideFrame=false, do not click; adjust the point or observe again. - If
suggestedActions[]has multiple entries, use the first clear AX target first and keepclick_pointas a fallback after re-observing uncertainty. - If OCR returns no match, do not click blindly. Retry with
textMatch="contains", OCRlanguages, a fresh window screenshot, or use image-pixel visual positioning. - If the snapshot expired or lacks screenshot metadata, call
visual.observeagain instead of reusing old points.
Menus
- Prefer
menu.clickover hotkeys for app commands. menu.scopedefaults toapp, which targets the current frontmost app menu bar.- Use
menu.list scope="system"before operating macOS menu bar extras/status items. System menu entries include 0-basedindex, optionalboundsPoints, and may expose usefuldescription,value, andactionseven whentitleis empty. - For status items, prefer
menu.click scope="system" menuIndex=<index> verify=trueafter listing when the title is empty or localized. Verification returns likely popovers and OCR screenshot metadata when available. - Menu clicks use a native chain before giving up:
AXShowMenu, thenAXPress, then center-point click when bounds are available. - After opening a status item or menu bar extra popover, use
menu.popover appHint="..."to identify the floating panel. It ranks all-app AX windows with menu-bar geometry, host app hints, and optional OCR text; it does not click anything. - If a menu path fails, call
menu.listwith the samescopeand check the localized titles/descriptions of the current menu surface. - If the user says "do not use shortcuts", never call
act.hotkey. Use menus or AX actions.
Clipboard
clipboard.getreads user clipboard text and may expose secrets. Use it only when the user asked for clipboard content or it is clearly necessary, and keepmaxCharstight.clipboard.setis useful before a deliberate paste workflow. It does not echo the written text in the result; verify by pasting into the intended target, not by reading the clipboard back unless needed.- Prefer
act.pasteover separateclipboard.set+act.hotkeyfor text insertion; it backs up and restores the previous pasteboard items. - Use
clipboard.clearonly when the user asked to clear the clipboard or after a sensitive paste workflow.
Dialogs and Sheets
- Use
dialog.list/dialog.inspectbefore mutating dialogs when the button or field label is not already known. - macOS sheets and lightweight prompts may appear as
AXSheetorAXPopoverelements attached to normalAXWindows; inspect with highermaxElementswhen needed. - When several dialogs are present, target by dialog text/window or use the button id from the inspected result.
dialog.clickrequiresbuttonText; use the visible label. Examples:取消,保存,删除,Cancel,Save,Don't Save.dialog.inputrequirestext; usefield,fieldIndex, ortarget.elementIdwhen more than one dialog field exists. Setclear=trueto replace the value.- Dialog button presses and
clear=truetext input share the same fallbacks asact.click/act.set_value. dialog.filecan enterfilePath, setfileName, then clickselectButton(or the default accept button). It returnsfileDialog.nameField,requestedButton, and the actualselectedButtonwhen clicked. UseselectButton="none"when you only want to fill path/name.dialog.dismissmeans a cancel/close-style action. If the user wants to discard changes, choose the explicit discard button such as删除orDon't Save, not a generic dismiss guess.
Verification and Recovery
- After
apps.launch/apps.activate, verifyfrontmostbefore menu or input actions. - After any action that changes UI, re-snapshot or call the relevant list/inspect command before using old ids.
- Tool approval restores the previously frontmost app and focused window before the approved
mac_controlmutation runs, but treat it as best-effort. After an approval, verifyfrontmostor take a fresh observation before chaining another focus-sensitive action. - If an element becomes stale, take a fresh snapshot and reselect by role + label/text + window.
- If
act.perform_actionreturns an AX unsupported/action error, do not retry the same call blindly. Use freshelements.find/snapshotand choose a supported action, or switch toact.click/act.click_pointfallback. - If
dialog.inspectreturns empty but the UI visibly has a sheet, retry withmaxElements: 300or500and confirm the frontmost app. - If
menu.clicksays a path component was not found, check frontmost app andmenu.list; do not retry the same path blindly. - If a mutation succeeds but the expected state did not change, use
waitor a fresh snapshot to verify before deciding the next action. - If a failure is hard to reproduce, call
diagnostics.summaryto inspect readiness, recent errors, cached snapshot summaries, and the focus anchor. Usediagnostics.exportwhen the user/developer needs a managed JSON bundle under~/.hope-agent/mac-control/diagnostics/for replay analysis.
Approval Awareness
Treat these as higher risk and be extra explicit about the target:
windows.closeapps.quitdock.hide/dock.showspaces.switchmenu.clickon destructive menu itemsclipboard.get/clipboard.set/clipboard.cleardialog.accept/ explicit discard buttons- raw coordinate clicks, cursor moves, swipes, and drags
The approval system will enforce policy, but the model should still choose precise targets and explain uncertainty before asking the user to approve.
Frequently asked questions
What to verify before installation and use
What does the ha-mac-control source document cover?
maccontrol 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.
How do I install ha-mac-control?
The source record exposes this install command: npx skills add https://github.com/shiwenwen/hope-agent --skill "skills/ha-mac-control". Inspect the command and pinned source before running it.
Which permission-related actions were detected?
Static rules flagged read-files in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
coreyhaines31/marketingskills
ab-testing
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
churn-prevention
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
prowler-cloud/prowler
postgresql-indexing
PostgreSQL indexing best practices for Prowler: index design, partial indexes, partitioned table indexing, EXPLAIN ANALYZE validation, concurrent operations, monitoring, and maintenance. Trigger: When creating or modifying PostgreSQL indexes, analyzing query performance with EXPLAIN, debugging slow queries, reviewing index usage statistics, reindexing, dropping indexes, or working with partitioned table indexes. Also trigger when discussing index strategies, partial indexes, or index maintenance
oaustegard/claude-skills
featuring
Generate hierarchical _FEATURES.md files that describe what a codebase DOES from a user/consumer perspective, anchored to source symbols via tree-sitting. Supports large complex codebases through feature-driven decomposition into sub-feature files. Uses a multi-pass synthesis: orientation → detail → overview rewrite. Use when someone says "what does this do", "document features", "feature inventory", "_FEATURES.md", or needs to understand a codebase's purpose before modifying it. Complements tre