* feat: restructure skills for ClawHub publishing with CI auto-publish
- Sync core skill to 54 commands (add notification commands)
- Move macOS skill from .claude/skills/ to git-tracked skills/
- Extract Notification Center section to references/notifications.md
- Add ClawHub metadata (version, tags, requirements) to all SKILL.md
- Remove macos.md from core skill (moved to platform skill)
- Create scripts/link-skills.sh for local dev symlinks
- Add publish-skills CI job to release.yml (ClawHub auto-publish)
- Add skill install prompt to npm postinstall
* refactor: consolidate macOS into single agent-desktop skill
Merge agent-desktop-macos back into agent-desktop/references/macos.md
as a single publishable skill. Includes Notification Center content
inline rather than as a separate reference file.
Activate the existing --compact CLI flag (previously a no-op) to reduce
tree verbosity by collapsing pass-through container nodes that carry no
semantic information (no ref, no name, no value, no description, no
states, exactly one child).
Slack with -i --compact: 264 → 214 nodes, ~5,967 → ~5,117 tokens (14%
reduction). All 161 refs preserved. Finder unaffected (3% reduction).
Handles Electron's empty-string-vs-None pattern using is_none_or.
Skip depth budget for non-semantic AXGroup/AXGenericElement wrappers with
empty name and value, allowing default --max-depth 10 to find 100+ refs
in Electron apps like Slack and VS Code (previously found only 3).
Raise resolver search depth from 20 to ABSOLUTE_MAX_DEPTH (50) so ref
resolution succeeds for deeply nested Electron elements.
Fix surface detection to check if focused window itself is the target
surface (Electron reports dialogs as focused window, not as children)
and check both AXRole and AXSubrole for surface matching.
Update Phase 2 (Windows) and Phase 3 (Linux) docs with equivalent
web/Electron compatibility patterns for their respective APIs.
NcSession now captures the frontmost application before opening
Notification Center and reactivates it on close, preventing the
source app (e.g. Script Editor) from stealing focus during dismiss.
AXPress "clicks" the notification body (opening the source app) but
does not actually dismiss it. Removing it from the initial action list
forces the code to fall through to the hover-and-close-button strategy,
which reliably removes the notification from Notification Center.
- fix(core): wait --notification uses index-diff detection instead of
count, passes text filter, checks deadline before sleep
- fix(core): dismiss-all-notifications uses single NC session with
batch adapter method and reports individual failures
- refactor(macos): extract dismiss_entry helper to eliminate duplicate
dismiss logic between single and batch operations
- refactor(macos): restrict nc_session visibility to pub(crate), use
absolute paths for pgrep/osascript, add bounded wait with kill
fallback
- refactor(macos): single-pass is_notification_group check using
matches! macro
- refactor: extract notification CLI args and dispatch into separate
files to keep cli_args.rs and dispatch.rs under 400 LOC
- refactor: rename DismissAllNotificationsArgs to
DismissAllNotificationsCliArgs for consistency
- fix(core): remove unused timestamp field from NotificationInfo
- fix: remove poll_interval_ms from wait command (hardcode 500ms)
- docs: update phases.md with completed notification status and
cross-platform reference notes
Try AXDismiss/AXRemoveFromParent/AXPress on the notification group
element before falling back to cursor hover. Extract try_dismiss_button
helper. Cursor-based hover only triggers if all headless strategies
fail.
CGWindowList requires Screen Recording permission on macOS Sequoia to
read other processes' window names, and SystemUIServer blocks AX access
to its menu bar (crashes with Obj-C foreign exception). Switch to pgrep
for PID lookup and osascript clicking ControlCenter's Clock menu bar
item, spawned async to avoid blocking.
Add error code serialization and notification_not_found tests in core.
Add matches_filters unit tests in macOS list module covering app,
text, combined, and no-filter cases.
Dismiss synthesizes mouse hover to reveal close button (Sequoia), then
finds and AXPress it. Falls back to AXPress on notification group.
Notification action finds matching AXButton by name and presses it.
Both reuse shared list_entries for AX element access.
Traverses NC's AX tree to extract notification info (app, title, body,
actions). Handles variable nesting depth across Sonoma/Sequoia via
recursive heuristic matching. Supports --app, --text, and --limit
filters applied during traversal for early termination.
Implements NcSession for safe Notification Center lifecycle management
(open via AX press on clock, close via Escape, with Drop fallback).
Wires list_notifications, dismiss_notification, and notification_action
adapter methods to placeholder stubs pending Phase 3/4 implementation.
Rect deserialization now tolerates null/missing fields (defaults to 0.0),
preventing corrupt refmaps from breaking all subsequent click commands.
read_bounds rejects NaN/Inf at the source. Sidebar cells now resolve via
parent row AXSelected instead of falling through to CGClick. Extracted
chain step functions into chain_steps.rs to stay within 400 LOC limit.
- dispatch.rs: 460 → 392 LOC by removing duplicate command_name(),
using cmd.name() from cli.rs, and moving cli_surface_to_core to
Surface::to_core() in cli_args.rs
- ElementCaps: trim from 8 to 3 used fields, remove has_action() and
unused discovery calls (actions, role, has_children, pid, settable_value)
- chain.rs: deduplicate ChainStep/ChainDef/ChainContext out of cfg gates
- ax_helpers.rs: delete dead set_ax_string
Adds tracing::debug! calls throughout command and adapter layers,
activated via -v flag. Logs command dispatch, ref resolution, chain
step execution, clipboard/keyboard/mouse synthesis, and system ops.
Command layer logging (free for all platforms):
- dispatch: command name
- resolve: ref lookup with pid/role/name, match result
- tree: snapshot app/window/ref_count
Adapter layer logging (macOS, other platforms add their own):
- chain: step-by-step [N/total] with success/skip for each
- action: perform entry
- clipboard/keyboard/mouse: operation details
- system: app focus/launch/close, window ops, screenshots
Graph of skills covering all 50 commands with platform-specific sub-skills:
- Main index skill with core concepts, ref system, JSON contract
- Observation, interaction, and system command references
- Common workflow patterns (forms, menus, dialogs, drag-drop)
- macOS platform skill (permissions, AX API, troubleshooting)
- /desktop slash command for quick reference
- PRD addendum for skill maintenance across phases