{
  "schema": "snappy-card/1",
  "skill": "snappy-openrouter",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Single canonical interface to OpenRouter for any Snappy skill that needs multi-vendor LLM calls. OpenRouter proxies 200+ models (Anthropic, OpenAI, Google, Meta, DeepSeek, Qwen, Mistral) behind one OpenAI-compatible API. Use this when you need cost-flexible model routing, multi-model comparison, or provider fallback -- not when you need native provider features (use `snappy-ai-models` or `snappy-gemini` for those).",
  "verbs": [
    {
      "name": "chat",
      "args": [
        "prompt"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-openrouter/api.ts chat \"<prompt>\""
    },
    {
      "name": "fallback",
      "args": [
        "prompt"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-openrouter/api.ts fallback \"<prompt>\""
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [
    "snappy-settings",
    "snappy-ai-models",
    "snappy-gemini"
  ],
  "used_by": [],
  "checks": {
    "pass": 26,
    "fail": 8,
    "defer": 27,
    "line": "26 of 34 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-whatsapp"
      },
      {
        "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": 39,
        "rule": "Verb sets consolidate intent rather than mirror endpoints",
        "says": "2 verbs, 3 literal endpoint(s); one-to-one heuristic=true"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~230 tokens; body ~3151 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",
    "api.ts",
    "examples.md",
    "models.md",
    "refusals.test.ts",
    "routing-strategies.md",
    "scripts/chat.sh",
    "scripts/compare.sh",
    "scripts/lib/auth.sh",
    "scripts/route.sh",
    "scripts/stream.sh"
  ],
  "total_size": 69947,
  "checksum": "sha256:7f62211e203b94177a465a2534fc1de440491848c9bec58c3ff483206904a0a2",
  "built_at": "2026-09-09T22:09:58.734Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-openrouter",
      "version": "0.0.0",
      "description": "Single canonical interface to OpenRouter for the Snappy system. OpenRouter is a unified API that proxies requests to many different LLM providers (Anthropic, OpenAI, Google, Meta, Mistral, DeepSeek, Qwen, etc.) under a single API key. The cost-flexible way to call multi-vendor models from one place. Provides chat completion, streaming, auto-routing, and multi-model comparison scripts. All requests use the OpenAI-compatible chat completions format. Triggers on: openrouter, model routing, multi-model, multi-vendor llm, llm proxy, llm gateway, cheapest llm, cheapest model, model comparison, anthropic via openrouter, claude via openrouter, gpt via openrouter, openai via openrouter, gemini via openrouter, llama via openrouter, deepseek, qwen, mistral, model fallback, auto routing, cost optimization llm, fan out models, compare models, openai-compatible api, chat completion proxy, transforms, openrouter api key."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-openrouter/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/chat": {
        "post": {
          "operationId": "snappy_openrouter_chat",
          "summary": "snappy-openrouter 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 prompt text sent to the model",
                      "x-snappy-position": 0
                    },
                    "model": {
                      "x-snappy-flag": "--model"
                    }
                  },
                  "required": [
                    "prompt"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/fallback": {
        "post": {
          "operationId": "snappy_openrouter_fallback",
          "summary": "snappy-openrouter fallback",
          "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 prompt text sent to the model",
                      "x-snappy-position": 0
                    },
                    "models": {
                      "x-snappy-flag": "--models"
                    }
                  },
                  "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": [
      "OPENROUTER_API_KEY"
    ]
  }
}