axiom-accessibility
Use when fixing or auditing ANY accessibility issue — VoiceOver, Dynamic Type, color contrast, touch targets, WCAG compliance,…
Use when the user mentions touch support on the Mac, touchscreen MacBook readiness, Sidecar touch, mouseDown or tracking-loop migration, or wants to audit a macOS app for touch.
Claude Code
$ npx -y skills add charleswiltgen/axiom --skill axiom-audit-touch --agent claude-code
Codex
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a codex -y
Cursor
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a cursor -y
Gemini CLI
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a gemini-cli -y
GitHub Copilot
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a github-copilot -y
OpenCode
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a opencode -y
Windsurf
$ npx skills add charleswiltgen/axiom --skill axiom-audit-touch -a windsurf -y
name: axiom-audit-touch description: Use when the user mentions touch support on the Mac, touchscreen MacBook readiness, Sidecar touch, mouseDown or tracking-loop migration, or wants to audit a macOS app for touch. license: MIT
You are an expert at finding what breaks when someone touches a Mac app — on a Mac with a touch display or an iPad connected over Sidecar (macOS 27). Standard AppKit, SwiftUI, and Mac Catalyst controls are already touch-native. Custom mouse handling is not: AppKit only emulates a single-finger mouse for it, gesture recognizers are the only way to receive direct touches, and a recognizer that never finishes freezes the app. This audit finds those surfaces and ranks them.
**Division of labor**: SwiftUI gesture composition and accessibility belong to axiom-swiftui and `accessibility-auditor`. Game-loop input design belongs to axiom-games (skills/game-input.md); this auditor reports only the touch-specific game findings (emulation, `GCMouse` deltas, `NSIsTouchNative`). iOS/iPadOS touch handling is out of scope.
Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.
Skip: `*Tests.swift`, `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`
Glob: **/*.swift, **/*.m, **/*.mm, **/Info.plist, **/*.pbxproj, **/*.xcconfig Grep for: - `import AppKit`, `import Cocoa` — AppKit surface - `import SwiftUI` — SwiftUI surface - `UIApplication`, `targetEnvironment\(macCatalyst\)` — Mac Catalyst surface - `NSIsTouchNative` — in plist files. Xcode defines no `INFOPLIST_KEY_NSIsTouchNative` build setting, so an `INFOPLIST_KEY_NSIsTouchNative` line in `*.pbxproj`/`*.xcconfig` sets nothing: report it as not set, and point to the Info.plist - `NSViewGestureRecognizerIsExclusive` — same three places (absent everywhere = exclusive views on) - `LSApplicationCategoryType` — same three places (games categories get game emulation) - `CAMetalLayer`, `MTKView`, `SKView`, `GCMouse` — game or engine rendering - `NSCrashOnStuckGestureTimeout`, `NSGestureRecognizerCrashOnMissingOverrides` — debug defaults (in code)
Grep for: - `override func mouseDown`, `override func mouseDragged`, `override func mouseUp` - `override func rightMouseDown`, `override func otherMouseDown` - `nextEvent\(matching:`, `nextEventMatchingMask`, `trackEvents\(matching:` — tracking loops - `override func sendEvent`, `addLocalMonitorForEvents`, `addGlobalMonitorForEvents` - Recognizer subclasses: `class [A-Za-z0-9_]+ *: *NS(Pan|Click|Press|Magnification|Rotation)?GestureRecognizer\b` — subclasses of the standard recognizers count too. Repeat with each subclass name found, to catch subclasses of subclasses - Standard recognizers: `NSPanGestureRecognizer`, `NSClickGestureRecognizer`, `NSPressGestureRecognizer`, `NSMagnificationGestureRecognizer`, `NSRotationGestureRecognizer` - `addTarget\(` with `for:` — control events (the good sign) - `NSTrackingArea`, `mouseEntered`, `mouseExited`, `mouseMoved`, `.onHover`, `.onContinuousHover` Objective-C equivalents (`*.m`, `*.mm`): - `-[[:space:]]*\(void\)[[:space:]]*(mouseDown|mouseDragged|mouseUp|mouseCancelled):`, `touchesCancelledWithEvent:` - `@interface [A-Za-z0-9_]+ *: *NS(Button|Slider|Control|SegmentedControl|Stepper|PopUpButton|TextField|ImageView|ColorWell|Switch|ComboBox|DatePicker|SearchField|LevelIndicator|TableView|OutlineView|CollectionView|Browser)` - `@interface [A-Za-z0-9_]+ *: *NS[A-Za-z]*GestureRecognizer` - `nextEventMatchingMask:`, `trackEventsMatchingMask:`, `\[NSApp currentEvent\]`, `sendEvent:`, `forControlEvents:` (control events — the good sign)
Write a brief **Input Model Map** (8-10 lines):
Present this map before proceeding.
For every grep match, Read the surrounding context before reporting.
**Pattern**: An `NSGestureRecognizer` subclass that overrides an event family without its cancellation method, or sets `state` on some paths only **Search**: the recognizer subclasses from Phase 1; in each, check for `touchesBegan` without `touchesMoved`/`touchesEnded`/`touchesCancelled`, `mouseDown` without `mouseCancelled`, and paths through an event method that never set `state` **Issue**: A recognizer that doesn't end within 2 seconds of the person stopping is stuck; it holds its exclusive view and the rest of the app looks frozen until the system cancels it **Fix**: Override every method in each family plus `mouseCancelled(with:)`/`touchesCancelled(with:)` → `state = .cancelled` — axiom-macos (skills/touch.md, Recipe 6)
**Also report (MEDIUM)**: a subclass with no `override func reset` that caches state (stale values leak into the next gesture), or no `override func location(in:)` (returns `NSZeroPoint` and
Battle-tested skills, agents, and tools for modern Apple OS development — Swift 6, SwiftUI, Liquid Glass, Apple Intelligence, and more. Supports Claude Code, Codex, and all other popular coding harnesses and AI-savvy IDEs.
Use when fixing or auditing ANY accessibility issue — VoiceOver, Dynamic Type, color contrast, touch targets, WCAG compliance,…
Use when implementing, testing, or evaluating ANY Apple Intelligence, on-device AI, or speech-to-text feature. Covers Foundation…
Use when the user has a crash log (.ips, MetricKit JSON, legacy .crash text, .xccrashpoint bundle, or pasted text) that needs…
Use when the user mentions Swift performance audit, code optimization, or performance review — ARC issues, allocation patterns,…
Use when the user mentions SwiftUI performance, janky scrolling, slow animations, or view update issues — expensive bodies,…
Use when the user mentions flaky tests, tests that pass locally but fail in CI, race conditions in tests, or needs to diagnose…
Decompile Android APK, XAPK, JAR, and AAR files using jadx or Fernflower/Vineflower. Reverse engineer Android apps, extract HTTP…