.agents/skills/pr-comments/SKILL.md
Submit a PR review as inline GitHub comments on specific files and lines using the gh CLI.
npx skillsauth add daltoniam/switchboard pr-commentsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Post review findings as inline comments on specific diff lines via the GitHub Pull Request Reviews API and gh CLI.
pr-review produces findings and user wants them posted to the PRBefore doing anything else, check the pr-review output:
APPROVE review with a short body like "Clean PR — builds, tests pass, lint clean. LGTM." and no inline comments. Then stop.Never post test/placeholder comments. Every comment submitted to the PR must contain real, substantive feedback.
gh api repos/<owner>/<repo>/pulls/<number> --jq '.head.sha'gh pr diff <number> --repo <owner>/<repo>gh api repos/<owner>/<repo>/pulls/<number>/comments — don't duplicateThe API only accepts lines that appear in the diff. For each finding, confirm the target line is in a + or context line. If not, use the nearest line in the same hunk.
Always use a Python script to build the JSON — avoids shell escaping nightmares with Markdown and code fences:
import json
comments = [
{
"path": "pkg/foo.go",
"line": 42,
"side": "RIGHT",
"body": "`format` is user-provided and goes straight into the SQL string via Sprintf — something like `text) DROP TABLE users; --` would work. Should validate against an allow-list.\n\n```go\nvar validFormats = map[string]bool{\"text\": true, \"json\": true, \"xml\": true, \"yaml\": true}\n\nif !validFormats[strings.ToLower(format)] {\n return errResult(fmt.Errorf(\"invalid format: %s\", format))\n}\n```"
},
]
payload = {
"commit_id": "<sha>",
"event": "COMMENT",
"body": "Looks good overall, nice job on X. Few things inline.",
"comments": comments,
}
with open("/tmp/review_payload.json", "w") as f:
json.dump(payload, f)
Then submit:
gh api repos/<owner>/<repo>/pulls/<number>/reviews \
--method POST \
--input /tmp/review_payload.json \
--jq '.html_url'
gh pr comment <number> --repo <owner>/<repo> --body "..."Write comments like a peer reviewer who's read the code carefully and is being helpful, not like an automated tool generating a report. Match the user's communication style from conversation history.
Key rules:
format goes straight into the SQL string here — a value like text); DROP TABLE ... would work."Good example:
`format` is user-provided and goes straight into the SQL string here — something like `text) DROP TABLE users; --` would work. Worth validating against an allow-list and wrapping in a read-only tx like `queryTool` does.
\```go
var validFormats = map[string]bool{"text": true, "json": true, "xml": true, "yaml": true}
\```
Bad example:
**Must Fix — SQL injection via unsanitized `format` parameter**
The `format` argument is user-provided and interpolated directly into SQL via `fmt.Sprintf`. A malicious value like `text) DROP TABLE users; --` would produce valid destructive SQL.
**Suggestion:** Validate `format` against an allow-list:
The bad example reads like a security scanner output. The good example reads like a human who noticed something.
Overall review body: Keep the body field (the top-level review summary) to 1-2 natural sentences. Lead with something positive if warranted, mention roughly how many things to look at. Don't list categories or use bullet points.
Event type: Choose the event based on the review findings from pr-review:
"APPROVE" — if there are no "Must Fix (Blocking)" items in the review. Non-blocking suggestions and nits are fine alongside an approval."REQUEST_CHANGES" — if the user explicitly asks to block the PR."COMMENT" — if there are blocking items but the user hasn't explicitly asked to block. Blocking items warrant inline comments but not a hard gate unless requested.tools
Cross-model search quality benchmark for Switchboard's tool discovery. Dispatches identical search scenarios to opus, sonnet, and haiku in parallel, compiles a comparison table, and identifies optimization opportunities. Use when: "benchmark search", "test search quality", "run search benchmark", after changing scoring logic, synonyms, stop words, IDF, or tool descriptions, after adding new integrations, or when evaluating Phase 2 tag impact. Also use when the user mentions "search hit rate", "search recall", or "did search get better/worse". Not for full MCP smoke tests (use mcp-benchmark) or unit testing (use make test).
tools
Review a GitHub pull request for the Switchboard Go MCP server project. Enforces idiomatic Go, project conventions (hexagonal architecture, dispatch maps, port interfaces), test coverage, build/lint verification, and production readiness.
tools
Improve an existing Switchboard integration adapter's LLM usability — tool description enrichment, field compaction refinement, and response tuning. Use when: "optimize integration", "improve tool descriptions", "extend compaction", "make integration better for LLMs", after user story mapping, or when an LLM is making wrong tool choices or passing wrong IDs. Not for adding new integrations (use add-integration) or fixing bugs.
tools
Live benchmark protocol for Switchboard's MCP server. Runs real tool-calling sequences against enabled integrations, tracks failure metrics, and identifies impediments to successful LLM tool usage. Use when: "benchmark", "test the MCP", "run user stories", "smoke test integrations", after adding/changing integrations or tools, after changing compaction specs or search logic, before releases. Not for unit testing (use make test) or load testing.