{
  "schema_version": 1,
  "type": "skill",
  "slug": "claude-api",
  "title": "ClaudeApi — Claude API Playground",
  "brief": "Call Claude models (Haiku, Sonnet, Opus) from any AV widget or server-side code via the /api/claude proxy. Pick the right model for the job — cheap Haiku for quick lookups, Sonnet for code gen, Opus f",
  "version": "1.0.0",
  "tags": [],
  "license": "MIT",
  "source_path": "SKILL.md",
  "readme": "# ClaudeApi — Programmatic AI from AV Widgets\n\nCall Claude models (Haiku, Sonnet, Opus) from any AV widget or server-side code via the `/api/claude` proxy on the AV server (port 8770). This lets widgets, skills, and scripts trigger AI requests without a full Claude Code session — useful for deterministic code blocks that need AI assistance at a specific step.\n\n## Why This Exists\n\nSometimes you need a **deterministic block of code** — a function, a build step, a widget — to make its own AI request and use the result programmatically. Running the full Claude Code CLI for this is overkill and expensive (Opus). The `/api/claude` proxy lets you pick the right model for the job:\n\n| Model | ID | Input $/M tok | Output $/M tok | Claude Max 20x | Use for |\n|-------|----|---------------|----------------|----------------|---------|\n| **Haiku 4.5** | `claude-haiku-4-5-20251001` | $0.80 | $4.00 | $16 / $80 | Quick lookups, simple transforms, classification |\n| **Sonnet 4.6** | `claude-sonnet-4-6` | $3.00 | $15.00 | $60 / $300 | Code generation, analysis, structured output |\n| **Opus 4.6** | `claude-opus-4-6` | $15.00 | $75.00 | $300 / $1500 | Complex reasoning, architecture, long context |\n\n## AV Widget\n\nThe **ClaudeApi** view is a first-class AV citizen — find it in the AV dropdown under **Tools > ClaudeApi — Claude API Playground**.\n\n- **Vision card** — drop an image, Haiku suggests a filename\n- **Three model cards** — Haiku, Sonnet, Opus with editable prompts\n- **\"Run All\"** fires all three in parallel\n- **Dual cost display** — API base rate + Claude Max 20x multiplier\n- **Execution timing** — see how fast each model responds\n- **Token counts** — input/output tokens per request\n- **API docs** — scrollable reference at the bottom\n\nView ID: `ClaudeApi` | Dropdown key: `claudeapi` | HTML: `viewer/viewer/claude-api.html`\n\n## API Reference\n\n### Endpoint\n\n```\nPOST /api/claude   (on AV server, port 8770)\n```\n\n### Request Body (JSON)\n\n| Param | Type | Default | Description |\n|-------|------|---------|-------------|\n| `model` | string | `claude-haiku-4-5-20251001` | Model ID |\n| `messages` | array | *required* | Array of `{role, content}` objects |\n| `max_tokens` | number | 1024 | Max output tokens |\n| `system` | string | *none* | System prompt |\n| `temperature` | number | *API default* | 0.0 - 1.0 |\n\n### JavaScript (from an AV widget)\n\n```javascript\nconst API_BASE = (() => {\n  let path = location.pathname;\n  if (path === '/' || location.href.includes('about:srcdoc')) {\n    try { path = parent.location.pathname; } catch {}\n  }\n  const m = path.match(/^(\\/proxy\\/\\d+)\\//);\n  return m ? m[1] : '';\n})();\n\nasync function askClaude(prompt, model = 'claude-haiku-4-5-20251001') {\n  const res = await fetch(API_BASE + '/api/claude', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      model,\n      max_tokens: 1024,\n      messages: [{ role: 'user', content: prompt }],\n    }),\n  });\n  const data = await res.json();\n  if (data.error) throw new Error(data.error.message || data.error);\n  return {\n    text: data.content?.[0]?.text || '',\n    inputTokens: data.usage?.input_tokens || 0,\n    outputTokens: data.usage?.output_tokens || 0,\n    model: data.model,\n  };\n}\n```\n\n### Bash / curl\n\n```bash\ncurl -s http://localhost:8770/api/claude \\\n  -H \"content-type: application/json\" \\\n  -d '{\n    \"model\": \"claude-haiku-4-5-20251001\",\n    \"max_tokens\": 256,\n    \"messages\": [{\"role\": \"user\", \"content\": \"What is 2+2?\"}]\n  }'\n```\n\n## Architecture\n\nThe proxy lives in `viewer/server.js` as the `POST /api/claude` route. It reads the OAuth access token from the local credentials file, forwards the request to `api.anthropic.com/v1/messages`, and returns the raw response (including `usage` for cost calculation). 120-second timeout, CORS enabled. No API keys to manage — it reuses the Claude Code OAuth token automatically.\n\n## Vision Support\n\nThe Messages API supports image content blocks. Pass them in the `messages` array:\n\n```javascript\nmessages: [{\n  role: 'user',\n  content: [\n    { type: 'image', source: { type: 'base64', media_type: 'image/png', data: base64Data } },\n    { type: 'text', text: 'Describe this image' }\n  ]\n}]\n```\n\nThe ClaudeApi widget includes a built-in vision test card with drag-and-drop image support and a sample bridge image for testing.",
  "author": {
    "name": "Kyle Bergstedt",
    "email": "kyle@adom.inc"
  },
  "visibility": {
    "public": true
  },
  "hero": null,
  "sample_prompts": [],
  "discovery_triggers": [],
  "discovery_pitch": null,
  "metadata": {},
  "created_at": "2026-05-28T05:30:15.115Z",
  "updated_at": "2026-05-28T05:30:15.115Z",
  "sub_skills": [],
  "parent_app": null,
  "org": "adom"
}