{
  "schema": "snappy-card/1",
  "skill": "snappy-email",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "You handle Snappy's email channel: weekly newsletters and inbox triage via Gmail/Xano. **ActiveCampaign is NOT in use.** This file is the operational contract -- everything load-bearing lives here.",
  "verbs": [
    {
      "name": "draft",
      "args": [
        "to",
        "subject",
        "body",
        "account?"
      ],
      "effect": "draft",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts draft <to> \"<subject>\" \"<body>\""
    },
    {
      "name": "get",
      "args": [
        "message-id",
        "account?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts get <message-id>"
    },
    {
      "name": "label",
      "args": [
        "message-id",
        "label-name",
        "account?"
      ],
      "effect": "write",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts label <message-id> <label-name>"
    },
    {
      "name": "mark-read",
      "args": [
        "message-id",
        "account?"
      ],
      "effect": "write",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts mark-read <message-id>"
    },
    {
      "name": "read",
      "args": [
        "message-id",
        "account?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts read <message-id>"
    },
    {
      "name": "search",
      "args": [
        "query",
        "limit?",
        "account?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts search \"<query>\""
    },
    {
      "name": "send",
      "args": [
        "email",
        "subject",
        "body"
      ],
      "effect": "send",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts send <email> \"<subject>\" \"<body>\""
    },
    {
      "name": "thread",
      "args": [
        "thread-id",
        "account?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts thread <thread-id>"
    },
    {
      "name": "trash",
      "args": [
        "message-id",
        "account?"
      ],
      "effect": "delete",
      "firstCall": "npx tsx ~/.claude/skills/snappy-email/api.ts trash <message-id>"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [
    "snappy-post",
    "snappy-content",
    "snappy-publish",
    "snappy-ops",
    "snappy-website",
    "snappy-analytics"
  ],
  "used_by": [
    "snappy-calendar",
    "snappy-course",
    "snappy-inbox-sweep",
    "snappy-slack"
  ],
  "checks": {
    "pass": 33,
    "fail": 6,
    "defer": 22,
    "line": "33 of 39 checks pass",
    "failing": [
      {
        "id": 8,
        "rule": "Skill body and reference graph stay within disclosure budgets",
        "says": "286 lines; ~3655 tokens; templates.md >100 lines without ToC; templates.md >100 lines without ToC"
      },
      {
        "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": 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",
    "adapter.ts",
    "api.ts",
    "automation.md",
    "contract.test.ts",
    "data/drafts/2026-04-11-snappy-mcp-invoice-reply.md",
    "inbox-triage.md",
    "list-management.md",
    "templates.md",
    "workflow.md"
  ],
  "total_size": 103148,
  "checksum": "sha256:227650aaa7bf94068eceb2442fa1a5aaac5ec689daae533288be4776f94ce229",
  "built_at": "2026-09-09T22:08:58.480Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-email",
      "version": "0.0.0",
      "description": "Email operations for Snappy -- newsletter sends (3+/week, 30-min workflow), inbox triage, drafts, batch actions via Xano API. Gmail/Google is the email backend (ActiveCampaign is NOT in use). Triggers on: email marketing, newsletter, send newsletter, email campaign, email list, email automation, email schedule, weekly emails, email blast, draft email campaign, inbox triage, smart inbox, check inbox, send email, reply email, batch email, email triage, contact list, broadcast, vsl funnel email, no-show sequence."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-email/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/draft": {
        "post": {
          "operationId": "snappy_email_draft",
          "summary": "snappy-email draft",
          "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": {
                    "to": {
                      "type": "string",
                      "description": "Recipient address the draft is addressed to",
                      "x-snappy-position": 0
                    },
                    "subject": {
                      "type": "string",
                      "description": "Subject line",
                      "x-snappy-position": 1
                    },
                    "body": {
                      "type": "string",
                      "description": "Message body",
                      "x-snappy-position": 2
                    },
                    "account": {
                      "type": "string",
                      "description": "Which mailbox to act in; omit for the default account",
                      "x-snappy-position": 3
                    }
                  },
                  "required": [
                    "to",
                    "subject",
                    "body"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/get": {
        "get": {
          "operationId": "snappy_email_get",
          "summary": "snappy-email get",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "message-id",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Message id",
                "x-snappy-position": 0
              }
            },
            {
              "name": "account",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which mailbox to act in; omit for the default account",
                "x-snappy-position": 1
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/label": {
        "post": {
          "operationId": "snappy_email_label",
          "summary": "snappy-email label",
          "x-snappy-effect": "write",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message-id": {
                      "type": "string",
                      "description": "Message id to label",
                      "x-snappy-position": 0
                    },
                    "label-name": {
                      "type": "string",
                      "description": "Label applied to the message",
                      "x-snappy-position": 1
                    },
                    "account": {
                      "type": "string",
                      "description": "Which mailbox to act in; omit for the default account",
                      "x-snappy-position": 2
                    }
                  },
                  "required": [
                    "message-id",
                    "label-name"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/mark-read": {
        "post": {
          "operationId": "snappy_email_mark_read",
          "summary": "snappy-email mark-read",
          "x-snappy-effect": "write",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message-id": {
                      "type": "string",
                      "description": "Message id to mark read",
                      "x-snappy-position": 0
                    },
                    "account": {
                      "type": "string",
                      "description": "Which mailbox to act in; omit for the default account",
                      "x-snappy-position": 1
                    }
                  },
                  "required": [
                    "message-id"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/read": {
        "get": {
          "operationId": "snappy_email_read",
          "summary": "snappy-email read",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "message-id",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Message id",
                "x-snappy-position": 0
              }
            },
            {
              "name": "account",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which mailbox to act in; omit for the default account",
                "x-snappy-position": 1
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/search": {
        "get": {
          "operationId": "snappy_email_search",
          "summary": "snappy-email search",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "query",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Gmail search expression",
                "x-snappy-position": 0
              }
            },
            {
              "name": "limit",
              "in": "query",
              "required": false,
              "schema": {
                "type": "integer",
                "description": "Maximum messages returned",
                "default": 10,
                "maximum": 100,
                "x-snappy-position": 1
              }
            },
            {
              "name": "account",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which mailbox to act in; omit for the default account",
                "x-snappy-position": 2
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/send": {
        "post": {
          "operationId": "snappy_email_send",
          "summary": "snappy-email send",
          "x-snappy-effect": "send",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string",
                      "description": "Recipient address the message is sent to",
                      "x-snappy-position": 0
                    },
                    "subject": {
                      "type": "string",
                      "description": "Subject line",
                      "x-snappy-position": 1
                    },
                    "body": {
                      "type": "string",
                      "description": "Message body",
                      "x-snappy-position": 2
                    }
                  },
                  "required": [
                    "email",
                    "subject",
                    "body"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/thread": {
        "get": {
          "operationId": "snappy_email_thread",
          "summary": "snappy-email thread",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "thread-id",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "Thread id whose messages are returned",
                "x-snappy-position": 0
              }
            },
            {
              "name": "account",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which mailbox to act in; omit for the default account",
                "x-snappy-position": 1
              }
            },
            {
              "name": "limit",
              "in": "query",
              "required": false,
              "schema": {
                "type": "integer",
                "description": "How many messages of that conversation to return. The count is the FLAG --limit, never a positional word; default 20, ceiling 200",
                "default": 20,
                "minimum": 1,
                "maximum": 200,
                "x-snappy-flag": "--limit"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/trash": {
        "post": {
          "operationId": "snappy_email_trash",
          "summary": "snappy-email trash",
          "x-snappy-effect": "delete",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message-id": {
                      "type": "string",
                      "description": "Message id moved to trash",
                      "x-snappy-position": 0
                    },
                    "account": {
                      "type": "string",
                      "description": "Which mailbox to act in; omit for the default account",
                      "x-snappy-position": 1
                    }
                  },
                  "required": [
                    "message-id"
                  ]
                }
              }
            }
          },
          "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": [
      "GOOGLE_CLIENT_ID",
      "GOOGLE_CLIENT_SECRET",
      "GOOGLE_SERVICE_ACCOUNT_EMAIL",
      "GOOGLE_SERVICE_ACCOUNT_KEY",
      "XANO_METADATA_TOKEN"
    ]
  }
}