{
  "schema": "snappy-card/1",
  "skill": "snappy-github",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Centralized GitHub operations across all Snappy repos via gh CLI -- PRs, code review, CI/CD monitoring, issues, multi-repo workflows, commit history.",
  "verbs": [
    {
      "name": "issues",
      "args": [
        "owner",
        "repo",
        "state?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-github/api.ts issues <owner> <repo>"
    },
    {
      "name": "prs",
      "args": [
        "owner",
        "repo",
        "state?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-github/api.ts prs <owner> <repo>"
    },
    {
      "name": "repos",
      "args": [
        "org?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-github/api.ts repos"
    },
    {
      "name": "pr",
      "args": [
        "owner",
        "repo",
        "number"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-github/api.ts pr <owner> <repo> <number>"
    },
    {
      "name": "get",
      "args": [
        "owner",
        "repo",
        "number"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-github/api.ts get <owner> <repo> <number>"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [],
  "used_by": [
    "snappy-box",
    "snappy-client-template"
  ],
  "checks": {
    "pass": 45,
    "fail": 6,
    "defer": 10,
    "line": "45 of 51 checks pass",
    "failing": [
      {
        "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 ~233 tokens; body ~4388 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)"
      },
      {
        "id": 60,
        "rule": "Loader publishes the contract's derived first call, current",
        "says": "generated block is stale against HAND_CONTRACT; run fix-loader"
      }
    ]
  },
  "coverage": null,
  "spec": null,
  "evals": null,
  "files": [
    "AGENTS.md",
    "SKILL.md",
    "api.ts",
    "entities.json",
    "face.test.ts",
    "faces/components/github-comments.css",
    "faces/components/github-comments.tsx",
    "faces/components/github-pr-preview.tsx",
    "faces/family.tsx",
    "faces/fixtures/github-comment.json",
    "faces/fixtures/github-comments.json",
    "faces/fixtures/github-pr.json",
    "refusals.test.ts",
    "stage.test.ts"
  ],
  "total_size": 111703,
  "checksum": "sha256:846719278979e8f0398ca8d4555771c5e5537f3b83ea74729ba24236f3332fc1",
  "built_at": "2026-09-09T22:09:24.682Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-github",
      "version": "0.0.0",
      "description": "Centralized GitHub operations across all Snappy client repos via the `gh` CLI -- pull request creation, code review, merging, CI/CD monitoring, workflow run inspection, issue management, multi-repo status checks, commit history retrieval, and per-line PR comments. Single source of truth for git/PR/issue ops; enforces PR-required client repo policy, no force-push to main, no skipped hooks, no interactive flags, prefer `gh` over raw `curl https://api.github.com`. Triggers on: github, gh cli, pull request, PR, open PRs, draft PR, merge PR, squash merge, code review, PR review, review comments, line comment, request changes, approve PR, CI, ci status, workflow run, rerun failed, gh run watch, deploy status, issue, create issue, close issue, label, assign, multi-repo, jcameron12, total repo, snappy repo, git log since, commits since last monday, milestone commits, branch diff, force push, hook bypass, gh auth, repo clone."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-github/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/issues": {
        "get": {
          "operationId": "snappy_github_issues",
          "summary": "snappy-github issues",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "state",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which issues or pull requests to return",
                "enum": [
                  "open",
                  "closed",
                  "all"
                ],
                "default": "open",
                "x-snappy-position": 2
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/prs": {
        "get": {
          "operationId": "snappy_github_prs",
          "summary": "snappy-github prs",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "state",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "Which issues or pull requests to return",
                "enum": [
                  "open",
                  "closed",
                  "all"
                ],
                "default": "open",
                "x-snappy-position": 2
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/repos": {
        "get": {
          "operationId": "snappy_github_repos",
          "summary": "snappy-github repos",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "org",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "The organisation whose repositories are listed; omit for the authenticated account's own",
                "x-snappy-position": 0
              }
            },
            {
              "name": "limit",
              "in": "query",
              "required": false,
              "schema": {
                "type": "integer",
                "description": "How many repositories to return; the count is the FLAG --limit, never a positional word",
                "default": 20,
                "maximum": 100,
                "x-snappy-flag": "--limit"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/comments": {
        "get": {
          "operationId": "snappy_github_comments",
          "summary": "snappy-github comments",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "number",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "The pull request or issue number, as GitHub shows it after the #. A pull request IS an issue here: its discussion lives on the issue comments endpoint",
                "x-snappy-position": 2
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/thread": {
        "get": {
          "operationId": "snappy_github_thread",
          "summary": "snappy-github thread",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "number",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "The pull request or issue number, as GitHub shows it after the #",
                "x-snappy-position": 2
              }
            },
            {
              "name": "limit",
              "in": "query",
              "required": false,
              "schema": {
                "type": "integer",
                "description": "How many comments of that conversation to return. The count is the FLAG --limit, never a positional word; default 20, ceiling 100",
                "default": 20,
                "minimum": 1,
                "maximum": 100,
                "x-snappy-flag": "--limit"
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/comment": {
        "post": {
          "operationId": "snappy_github_comment",
          "summary": "snappy-github comment",
          "x-snappy-effect": "post",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": true,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "owner": {
                      "type": "string",
                      "description": "The repository's owner — the user or organisation half of owner/name",
                      "x-snappy-position": 0
                    },
                    "repo": {
                      "type": "string",
                      "description": "The repository's name — the second half of owner/name, without the owner",
                      "x-snappy-position": 1
                    },
                    "number": {
                      "type": "integer",
                      "description": "The pull request or issue number the comment lands on",
                      "x-snappy-position": 2
                    },
                    "text": {
                      "type": "string",
                      "description": "The comment's words, verbatim, as Markdown",
                      "x-snappy-position": 3
                    },
                    "json": {
                      "x-snappy-flag": "--json"
                    }
                  },
                  "required": [
                    "owner",
                    "repo",
                    "number",
                    "text"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/pr": {
        "get": {
          "operationId": "snappy_github_pr",
          "summary": "snappy-github pr",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "number",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "The pull request number, as GitHub shows it after the #",
                "x-snappy-position": 2
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/get": {
        "get": {
          "operationId": "snappy_github_get",
          "summary": "snappy-github get",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "parameters": [
            {
              "name": "owner",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's owner — the user or organisation half of owner/name",
                "x-snappy-position": 0
              }
            },
            {
              "name": "repo",
              "in": "query",
              "required": true,
              "schema": {
                "type": "string",
                "description": "The repository's name — the second half of owner/name, without the owner",
                "x-snappy-position": 1
              }
            },
            {
              "name": "number",
              "in": "query",
              "required": true,
              "schema": {
                "type": "integer",
                "description": "The pull request number, as GitHub shows it after the #",
                "x-snappy-position": 2
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "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": [
      "GITHUB_TOKEN"
    ]
  }
}