{
  "schema": "snappy-card/1",
  "skill": "snappy-runner",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Read this when you want to DO something for this person and you are not sure",
  "verbs": [
    {
      "name": "address",
      "args": [],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-runner/api.ts address"
    },
    {
      "name": "loop",
      "args": [
        "intent",
        "limit?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-runner/api.ts loop <intent>"
    },
    {
      "name": "envelope",
      "args": [
        "code?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-runner/api.ts envelope"
    },
    {
      "name": "fix",
      "args": [
        "skill",
        "words"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-runner/api.ts fix <skill> <words>"
    }
  ],
  "faces": [],
  "agents": [
    {
      "name": "operator",
      "job": "Does what the person asked, through reads and staged decisions. The default.",
      "verbs": [
        "address",
        "loop",
        "envelope"
      ],
      "reaches": [
        "snappy-faces",
        "snappy-mac"
      ]
    },
    {
      "name": "fixer",
      "job": "Makes the collection better when a hand is wrong, missing or behind.",
      "verbs": [
        "fix",
        "envelope"
      ],
      "reaches": [
        "snappy-specwatch",
        "snappy-settings"
      ]
    }
  ],
  "uses": [
    "snappy-mac",
    "snappy-faces",
    "snappy-settings",
    "snappy-specwatch"
  ],
  "used_by": [],
  "checks": {
    "pass": 25,
    "fail": 10,
    "defer": 26,
    "line": "25 of 35 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-agent-host, snappy-artifact-loop, snappy-ax, snappy-blog, snappy-browse"
      },
      {
        "id": 5,
        "rule": "Description is valid, third-person, and says what plus when",
        "says": "first/second person"
      },
      {
        "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": 12,
        "rule": "Description contains no unauthorised imperative",
        "says": "unauthorised description imperatives: read"
      },
      {
        "id": 33,
        "rule": "Refusal codes form one tested closed table",
        "says": "5 refusal code(s); uncovered tests=[unknown_verb, missing_argument, missing_credential, service_unavailable, upstream_error]"
      },
      {
        "id": 39,
        "rule": "Verb sets consolidate intent rather than mirror endpoints",
        "says": "4 verbs, 3 literal endpoint(s); one-to-one heuristic=true"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~178 tokens; body ~3602 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"
  ],
  "total_size": 59284,
  "checksum": "sha256:df4ff7c3e8773af2fc1784fb10831049aa8dcb8f206c8751678635f70e5c7dcb",
  "built_at": "2026-09-09T22:10:35.209Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-runner",
      "version": "0.0.0",
      "description": "How any AI operates this person's skills: the three addresses (the public MCP, the machine, the local runner), search → info → execute as the one loop, what an envelope carries, which verbs are decisions, and how a fix run is started. Read this before calling any other hand through the snappy-skills MCP. NOT the local node road for an agent already on this Mac (see snappy-hands). NOT the Snappy OS app's operator MCP (see snappy-os-operator). NOT the skills.snappy.ai distribution worker (see snappy-gateway). Triggers on: snappy-runner, the snappy skills mcp, how do I use these skills, connect an AI, search info execute, what does this refusal mean, make it better, fix run, which address, is it signed in."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-runner/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/address": {
        "get": {
          "operationId": "snappy_runner_address",
          "summary": "snappy-runner address",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/loop": {
        "get": {
          "operationId": "snappy_runner_loop",
          "summary": "snappy-runner loop",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "intent",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "What you are trying to do, in the words a person would say it",
                "x-snappy-position": 0
              }
            },
            {
              "name": "limit",
              "in": "query",
              "required": false,
              "schema": {
                "type": "number",
                "description": "How many candidate hands to name",
                "default": 5,
                "minimum": 1,
                "maximum": 25,
                "x-snappy-position": 1
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            },
            {
              "name": "token-file",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--token-file"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/envelope": {
        "get": {
          "operationId": "snappy_runner_envelope",
          "summary": "snappy-runner envelope",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "parameters": [
            {
              "name": "code",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "One refusal code to explain; omit for every code the collection declares",
                "x-snappy-position": 0
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/fix": {
        "post": {
          "operationId": "snappy_runner_fix",
          "summary": "snappy-runner fix",
          "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": {
                    "skill": {
                      "type": "string",
                      "description": "The hand the note is about",
                      "x-snappy-position": 0
                    },
                    "words": {
                      "type": "string",
                      "description": "The person's own line about what it should do better, verbatim",
                      "x-snappy-position": 1
                    },
                    "token-file": {
                      "x-snappy-flag": "--token-file"
                    }
                  },
                  "required": [
                    "skill",
                    "words"
                  ]
                }
              }
            }
          },
          "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"
            }
          }
        }
      }
    },
    "x-snappy-vendor-spec": {
      "kind": "none",
      "reason": "The service this hand calls is ours — snappy-runner's own HTTP and MCP doors — so no vendor publishes a document to pin; the live revision from /health is the version, and address reads it."
    }
  }
}