{
  "schema": "snappy-card/1",
  "skill": "snappy-ai-models",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Use this skill when you need **direct provider API access** to OpenAI, Anthropic, or Replicate. This is the right choice for first-party features that OpenRouter cannot proxy: gpt-5 Responses API, Anthropic prompt caching/computer use, OpenAI image/audio/embeddings, and Replicate hosted models. For multi-vendor routing or cheap open-source models, use `snappy-openrouter`. For Gemini, use `snappy-gemini`.",
  "verbs": [
    {
      "name": "chat",
      "args": [
        "prompt",
        "model"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ai-models/api.ts chat \"<prompt>\" <model>"
    },
    {
      "name": "embed",
      "args": [
        "text"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ai-models/api.ts embed \"<text>\""
    },
    {
      "name": "image",
      "args": [
        "prompt"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-ai-models/api.ts image \"<prompt>\""
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [],
  "used_by": [
    "snappy-image",
    "snappy-openrouter"
  ],
  "checks": {
    "pass": 25,
    "fail": 9,
    "defer": 27,
    "line": "25 of 34 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-specwatch"
      },
      {
        "id": 5,
        "rule": "Description is valid, third-person, and says what plus when",
        "says": "1037 chars"
      },
      {
        "id": 8,
        "rule": "Skill body and reference graph stay within disclosure budgets",
        "says": "338 lines; ~4564 tokens; anthropic/README.md >100 lines without ToC; replicate/README.md >100 lines without ToC; anthropic/README.md >100 lines without ToC; replicate/README.md >100 lines without ToC"
      },
      {
        "id": 9,
        "rule": "Time-sensitive prose is isolated under Old patterns",
        "says": "3 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": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~260 tokens; body ~4564 tokens"
      },
      {
        "id": 54,
        "rule": "At least three eval scenarios precede ready status",
        "says": "0 eval scenario(s); ready=true"
      },
      {
        "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",
    "anthropic/README.md",
    "anthropic/chat.sh",
    "anthropic/stream.sh",
    "anthropic/tool-use.sh",
    "api.ts",
    "contract.test.ts",
    "lib/auth.sh",
    "models.md",
    "openai/README.md",
    "openai/audio.sh",
    "openai/chat.sh",
    "openai/embed.sh",
    "openai/image.sh",
    "replicate/README.md",
    "replicate/flux.sh",
    "replicate/run.sh",
    "replicate/whisper.sh"
  ],
  "total_size": 112108,
  "checksum": "sha256:5caf4d42e1b55b74dadb7c14dfbf5a5511bf70eec958db5d94f43b41f62f81ce",
  "built_at": "2026-09-09T22:08:03.122Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-ai-models",
      "version": "0.0.0",
      "description": "Direct-API interface to OpenAI, Anthropic, and Replicate for the Snappy system -- the three model providers that don't already have a dedicated skill (Gemini lives in snappy-gemini; routed/cheap multi-vendor calls live in snappy-openrouter). Provides curl-backed scripts for chat, image, audio, embeddings, tool-use, streaming, and Replicate predictions with transparent polling. Pairs with snappy-settings for credential loading. Triggers on: openai, anthropic, claude, gpt, gpt-5, gpt-4o, o1, o3, dall-e, gpt-image-1, gpt-image-2, whisper, tts, openai embeddings, text-embedding-3, anthropic claude, claude opus, claude sonnet, claude haiku, claude api, messages api, tool use, function calling, replicate, flux, flux schnell, flux pro, sdxl, stable diffusion, llava, whisperx, ai model, model catalog, model id, openai api key, anthropic api key, replicate token, prediction polling, x-api-key, anthropic-version header, responses api, chat completions, prompt caching, system prompt anthropic, direct api, not openrouter, not gemini."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-ai-models/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/chat": {
        "post": {
          "operationId": "snappy_ai_models_chat",
          "summary": "snappy-ai-models chat",
          "x-snappy-effect": "draft",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "prompt": {
                      "type": "string",
                      "description": "The text sent to the model",
                      "x-snappy-position": 0
                    },
                    "model": {
                      "type": "string",
                      "description": "Model id to answer with; omit for the skill's default",
                      "x-snappy-flag": "--model"
                    }
                  },
                  "required": [
                    "prompt",
                    "model"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/embed": {
        "post": {
          "operationId": "snappy_ai_models_embed",
          "summary": "snappy-ai-models embed",
          "x-snappy-effect": "draft",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "The text to embed as a vector",
                      "x-snappy-position": 0
                    }
                  },
                  "required": [
                    "text"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/image": {
        "post": {
          "operationId": "snappy_ai_models_image",
          "summary": "snappy-ai-models image",
          "x-snappy-effect": "draft",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "prompt": {
                      "type": "string",
                      "description": "What the generated image should show",
                      "x-snappy-position": 0
                    },
                    "size": {
                      "x-snappy-flag": "--size"
                    }
                  },
                  "required": [
                    "prompt"
                  ]
                }
              }
            }
          },
          "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-requires": [
      "OPENAI_API_KEY"
    ]
  }
}