{
  "schema": "snappy-card/1",
  "skill": "snappy-browse",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "You are operating the browser automation primitive for the Snappy stack. Every web interaction (Skool, LinkedIn, Canva, YouTube Studio, Instagram, Luma, GitHub web UI) routes through this skill. ActiveCampaign is NOT in use. The full SKILL.md has platform recipes and troubleshooting; the rules below are load-bearing.",
  "verbs": [
    {
      "name": "clear-requests",
      "args": [],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts clear-requests"
    },
    {
      "name": "click",
      "args": [
        "ref"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts click <ref>"
    },
    {
      "name": "close",
      "args": [],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts close"
    },
    {
      "name": "extract",
      "args": [
        "js-expression"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts extract <js-expression>"
    },
    {
      "name": "metrics",
      "args": [
        "metric-name"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts metrics <metric-name>"
    },
    {
      "name": "navigate",
      "args": [
        "url"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts navigate <url>"
    },
    {
      "name": "requests",
      "args": [
        "filter?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts requests"
    },
    {
      "name": "snapshot",
      "args": [],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-browse/api.ts snapshot"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [],
  "used_by": [
    "snappy-cleanshot",
    "snappy-client-ray",
    "snappy-image",
    "snappy-inbox-sweep",
    "snappy-playbook"
  ],
  "checks": {
    "pass": 37,
    "fail": 8,
    "defer": 16,
    "line": "37 of 45 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-client-feisst, snappy-runner"
      },
      {
        "id": 7,
        "rule": "Promised and declared verbs have no set difference",
        "says": "promised-only=[templates, dataset, upload, autofill, export, designs, folders, folder-items, create-folder, move, scan, import, import-url, canva, resize, comment, get-comment]; loader-missing=[]"
      },
      {
        "id": 8,
        "rule": "Skill body and reference graph stay within disclosure budgets",
        "says": "416 lines; ~5130 tokens; platforms.md >100 lines without ToC; deep reference ../snappy-infra/auth-reference.md; platforms.md >100 lines without ToC; troubleshooting.md >100 lines without ToC; deep reference ../snappy-infra/auth-reference.md"
      },
      {
        "id": 10,
        "rule": "One term names each concept",
        "says": "mixed synonym sets: endpoint/url/route/path, field/box/element"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~186 tokens; body ~5130 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",
    "canva-api.ts",
    "canva-import-design.ts",
    "canva-oauth.ts",
    "canva-pipeline.ts",
    "canva-upload-to-folder.ts",
    "contract.test.ts",
    "keepalive.sh",
    "metrics.json",
    "patch-daemon-idle.mjs",
    "patch-daemon-idle.sh",
    "platforms.md",
    "session.ts",
    "troubleshooting.md"
  ],
  "total_size": 154312,
  "checksum": "sha256:74c43e44a55014d03b1686e383d046c9b6c0c8fb235769f8b2da220fa6f2447e",
  "built_at": "2026-09-09T22:08:17.280Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-browse",
      "version": "0.0.0",
      "description": "THE DEFAULT for actually driving a browser on this machine -- Snappy stack and client sites via agent-browser CLI (Playwright under the hood), cookie auth via --state, unique --session per run. Owns the house rules NEVER use Charlotte MCP browser tools and NEVER guess URLs -- navigate like a human. NOT the agent-browser CLI flag reference (see agent-browser) and NOT Playwright MCP tooling (see playwright-browser-automation). Triggers on browse, browser automation, scrape website, fill form, web automation, click button, screenshot page, Skool browser, LinkedIn browser, Canva editor, YouTube Studio, Instagram, Luma, headless browser, cookie auth, web SPA, contenteditable composer, navigate site, snapshot page, extract data, web table."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-browse/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/clear-requests": {
        "post": {
          "operationId": "snappy_browse_clear_requests",
          "summary": "snappy-browse clear-requests",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true
          },
          "requestBody": {
            "required": false,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/click": {
        "post": {
          "operationId": "snappy_browse_click",
          "summary": "snappy-browse click",
          "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": {
                    "ref": {
                      "type": "string",
                      "description": "Element reference from the most recent snapshot",
                      "x-snappy-position": 0
                    }
                  },
                  "required": [
                    "ref"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/close": {
        "post": {
          "operationId": "snappy_browse_close",
          "summary": "snappy-browse close",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true
          },
          "requestBody": {
            "required": false,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/extract": {
        "get": {
          "operationId": "snappy_browse_extract",
          "summary": "snappy-browse extract",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "js-expression",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "JavaScript expression evaluated in the page; its value is returned",
                "x-snappy-position": 0
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/metrics": {
        "get": {
          "operationId": "snappy_browse_metrics",
          "summary": "snappy-browse metrics",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "parameters": [
            {
              "name": "metric-name",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Name of the browse metric to compute",
                "x-snappy-position": 0
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/navigate": {
        "post": {
          "operationId": "snappy_browse_navigate",
          "summary": "snappy-browse navigate",
          "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": {
                    "url": {
                      "type": "string",
                      "description": "Absolute URL to open in the session",
                      "x-snappy-position": 0
                    }
                  },
                  "required": [
                    "url"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/requests": {
        "get": {
          "operationId": "snappy_browse_requests",
          "summary": "snappy-browse requests",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "filter",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Substring a recorded request URL must contain",
                "x-snappy-position": 0
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/snapshot": {
        "get": {
          "operationId": "snappy_browse_snapshot",
          "summary": "snappy-browse snapshot",
          "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`."
            }
          }
        }
      }
    },
    "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": [
      "CANVA_CLIENT_ID",
      "CANVA_CLIENT_SECRET"
    ]
  }
}