{
  "schema": "snappy-card/1",
  "skill": "snappy-ax",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Four shipping codebases left their AX scars in comments; this skill is the extraction.",
  "verbs": [
    {
      "name": "at-point",
      "args": [
        "app",
        "x",
        "y"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts at-point <app> <x> <y>"
    },
    {
      "name": "find",
      "args": [
        "app"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts find <app>"
    },
    {
      "name": "focused",
      "args": [
        "app?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts focused"
    },
    {
      "name": "macos-use",
      "args": [
        "tool",
        "json-args?"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts macos-use <tool>"
    },
    {
      "name": "permissions",
      "args": [],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts permissions"
    },
    {
      "name": "press",
      "args": [
        "app"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts press <app>"
    },
    {
      "name": "raw",
      "args": [
        "json-envelope"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts raw <json-envelope>"
    },
    {
      "name": "set-value",
      "args": [
        "app"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts set-value <app>"
    },
    {
      "name": "text",
      "args": [
        "app"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts text <app>"
    },
    {
      "name": "tree",
      "args": [
        "app"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ax/api.ts tree <app>"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [
    "snappy-voice-control",
    "snappy-agent-host",
    "snappy-cleanshot",
    "snappy-desktop",
    "snappy-faces"
  ],
  "used_by": [
    "snappy-voice-control"
  ],
  "checks": {
    "pass": 36,
    "fail": 9,
    "defer": 16,
    "line": "36 of 45 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-client-feisst, snappy-gateway, snappy-runner"
      },
      {
        "id": 5,
        "rule": "Description is valid, third-person, and says what plus when",
        "says": "1082 chars; XML/HTML tag"
      },
      {
        "id": 8,
        "rule": "Skill body and reference graph stay within disclosure budgets",
        "says": "257 lines; ~7771 tokens"
      },
      {
        "id": 9,
        "rule": "Time-sensitive prose is isolated under Old patterns",
        "says": "1 time-sensitive instruction line(s) outside Old patterns"
      },
      {
        "id": 10,
        "rule": "One term names each concept",
        "says": "mixed synonym sets: endpoint/url/route/path"
      },
      {
        "id": 11,
        "rule": "Each task presents one default, not a menu",
        "says": "1 line(s) present three-way alternative menus"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~271 tokens; body ~7771 tokens"
      },
      {
        "id": 55,
        "rule": "Eval scenarios are multi-call with ground truth",
        "says": "eval manifest missing"
      },
      {
        "id": 57,
        "rule": "Eval manifest contains a disjoint holdout",
        "says": "0 disjoint holdout scenario(s)"
      }
    ]
  },
  "coverage": null,
  "spec": null,
  "evals": null,
  "files": [
    "AGENTS.md",
    "SKILL.md",
    "api.ts",
    "contract.test.ts",
    "references/extract-ax-layer.md"
  ],
  "total_size": 185189,
  "checksum": "sha256:b159d7d986c896559c6fa95f000d420ee7033b556f9912fd3eb006b49a583a75",
  "built_at": "2026-09-09T22:08:10.605Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-ax",
      "version": "0.0.0",
      "description": "Drive any Mac app through the Accessibility tree (AXUIElement) the way the shipping tools actually do it — extracted with path:line citations from AXorcist (steipete), MacosUseSDK + mcp-server-macos-use (mediar-ai), and AgentAccess (the policy layer inside Agent!). Coordinates and their two origins, why AXChildren lies for Electron, container-role pruning that skips tables, AXPress vs CGEvent click vs AXSelected vs AXValue, messaging timeouts, observers, TCC identity, and the exact CLI/JSON protocol. Use when Robert says: /snappy-ax, 'click the button in <app>', 'read the UI of <app>', 'what's on screen in <app>', 'drive Finder / Mail / Messages / Slack', 'the click didn't land', 'it can't find the element', 'AXUIElement', 'accessibility tree', 'use axorc', 'use macos-use'. NOT vision/pixel automation (see snappy-desktop). NOT AppleScript (see desktop-automation). NOT voice input (see snappy-voice-control). NOT hosting Claude Code in the app (see snappy-agent-host). Triggers on: accessibility, AXUIElement, axorc, macos-use, AXorcist, click element, UI tree, AXPress."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-ax/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/at-point": {
        "get": {
          "operationId": "snappy_ax_at_point",
          "summary": "snappy-ax at-point",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "app",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Application name or bundle id to inspect",
                "x-snappy-position": 0
              }
            },
            {
              "name": "x",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "Screen x coordinate in points",
                "x-snappy-position": 1
              }
            },
            {
              "name": "y",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "Screen y coordinate in points",
                "x-snappy-position": 2
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/find": {
        "get": {
          "operationId": "snappy_ax_find",
          "summary": "snappy-ax find",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "app",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Application name or bundle id to search",
                "x-snappy-position": 0
              }
            },
            {
              "name": "role",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--role"
              }
            },
            {
              "name": "title",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--title"
              }
            },
            {
              "name": "identifier",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--identifier"
              }
            },
            {
              "name": "value",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--value"
              }
            },
            {
              "name": "contains",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--contains"
              }
            },
            {
              "name": "depth",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--depth"
              }
            },
            {
              "name": "attribute",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--attribute"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/focused": {
        "get": {
          "operationId": "snappy_ax_focused",
          "summary": "snappy-ax focused",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "app",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Application to read the focused element of; omit for the frontmost app",
                "x-snappy-position": 0
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/macos-use": {
        "post": {
          "operationId": "snappy_ax_macos_use",
          "summary": "snappy-ax macos-use",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string",
                      "description": "macos-use tool name to invoke",
                      "x-snappy-position": 0
                    },
                    "json-args": {
                      "type": "string",
                      "description": "JSON object of arguments for that tool",
                      "x-snappy-position": 1
                    }
                  },
                  "required": [
                    "tool"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/permissions": {
        "get": {
          "operationId": "snappy_ax_permissions",
          "summary": "snappy-ax permissions",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/press": {
        "post": {
          "operationId": "snappy_ax_press",
          "summary": "snappy-ax press",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app": {
                      "type": "string",
                      "description": "Application owning the element to press",
                      "x-snappy-position": 0
                    },
                    "role": {
                      "x-snappy-flag": "--role"
                    },
                    "title": {
                      "x-snappy-flag": "--title"
                    },
                    "identifier": {
                      "x-snappy-flag": "--identifier"
                    },
                    "value": {
                      "x-snappy-flag": "--value"
                    },
                    "contains": {
                      "x-snappy-flag": "--contains"
                    }
                  },
                  "required": [
                    "app"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/raw": {
        "get": {
          "operationId": "snappy_ax_raw",
          "summary": "snappy-ax raw",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "json-envelope",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "JSON query envelope passed straight to the accessibility bridge",
                "x-snappy-position": 0
              }
            },
            {
              "name": "scanAll",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--scan-all"
              }
            },
            {
              "name": "noStopFirst",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--no-stop-first"
              }
            },
            {
              "name": "timeout",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--timeout"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/set-value": {
        "post": {
          "operationId": "snappy_ax_set_value",
          "summary": "snappy-ax set-value",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app": {
                      "type": "string",
                      "description": "Application owning the element whose value is set",
                      "x-snappy-position": 0
                    },
                    "value": {
                      "x-snappy-flag": "--value"
                    },
                    "role": {
                      "x-snappy-flag": "--role"
                    },
                    "title": {
                      "x-snappy-flag": "--title"
                    },
                    "identifier": {
                      "x-snappy-flag": "--identifier"
                    },
                    "contains": {
                      "x-snappy-flag": "--contains"
                    }
                  },
                  "required": [
                    "app"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/text": {
        "get": {
          "operationId": "snappy_ax_text",
          "summary": "snappy-ax text",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "app",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Application whose visible text is read",
                "x-snappy-position": 0
              }
            },
            {
              "name": "role",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--role"
              }
            },
            {
              "name": "title",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--title"
              }
            },
            {
              "name": "depth",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--depth"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/tree": {
        "get": {
          "operationId": "snappy_ax_tree",
          "summary": "snappy-ax tree",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "app",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Application whose accessibility tree is walked",
                "x-snappy-position": 0
              }
            },
            {
              "name": "depth",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--depth"
              }
            },
            {
              "name": "role",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--role"
              }
            },
            {
              "name": "scanAll",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--scan-all"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      }
    },
    "components": {
      "schemas": {
        "SnappyRefusal": {
          "type": "object",
          "required": [
            "outcome",
            "code",
            "message"
          ],
          "properties": {
            "outcome": {
              "type": "string",
              "const": "refused"
            },
            "code": {
              "type": "string",
              "description": "A row of the closed refusal table."
            },
            "message": {
              "type": "string"
            },
            "fix": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}