# Cross-model tool mappings

<!-- generated by scripts/sync-codex-skill-wrappers.py from tool-mappings.yml -->

Generated from [`tool-mappings.yml`](tool-mappings.yml). Edit that file, then
run `python3 scripts/sync-codex-skill-wrappers.py` to regenerate this page and
the links in `codex-skills/`.

The canonical skills under `skills/` are written for Claude Code and name
concrete tools — mostly `gh`/`git` commands. This registry maps each canonical
operation to the equivalent GitHub MCP tool so any model can run a skill.

> [!IMPORTANT]
> **Every comment-posting operation below carries the agent-disclosure marker in
> its body**, on its own line after a blank line:
> `_Posted by <your agent> (AI agent) --- not written by a human._`
>
> Substitute your own agent's name --- this registry is read by every model, so a
> hard-coded `Claude Code` would have a Codex or Gemini session misattribute its
> own comment.
> Keep the rest of the line verbatim.
> Check the substituted name against `scripts/check-pr-fully-clean.py`'s
> `REVIEW_BODY_MARKERS` too --- `code review` is one of them, so an agent named
> for code review would reintroduce the false-clean the emoji ban prevents.
>
> This registry is the substitution point for remote/web sessions, which have no
> `gh` at all --- so a marker-free template here is a marker-free comment there, in
> exactly the population that cannot fall back to the CLI examples in the skills.
> See [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md).
> Two exemptions: a body another machine parses as a command (`@dependabot
> rebase`), and a comment posted under a genuine bot token, where the forge
> already reports `type: Bot`.

## How each model resolves an operation

- **Claude Code** — GitHub MCP tool in remote/web sessions; the CLI command locally.
- **Codex** — GitHub MCP tool if the session has it; otherwise the CLI command.
- **VS Code Copilot** — GitHub MCP tool.
- **Gemini CLI** — GitHub MCP tool if configured in MCP settings; otherwise the CLI command.
- **Generic shell / CLI** — The CLI command (fallback for any agent that just runs a shell).

## Operations

| Operation | Does | CLI (`gh`/`git`) | GitHub MCP tool |
| --- | --- | --- | --- |
| `VIEW_PR` | Read a pull request's details and metadata. | `gh pr view "<N>"` | `mcp__github__pull_request_read (method=get)` |
| `LIST_PRS` | List pull requests. | `gh pr list` | `mcp__github__list_pull_requests` |
| `SEARCH_PRS` | Search pull requests by keyword / query string. | `gh pr list --search "<query>"` | `mcp__github__search_pull_requests` |
| `DIFF_PR` | Read a pull request's diff. | `gh pr diff "<N>"` | `mcp__github__pull_request_read (method=get_diff)` |
| `PR_CHECKS` | Read a pull request's CI check / status results. | `gh pr checks "<N>"` | `mcp__github__pull_request_read (method=get_check_runs)` |
| `READ_PR_COMMENTS` | Read a pull request's top-level (conversation) comments. | `gh pr view "<N>" --comments` | `mcp__github__pull_request_read (method=get_comments)` |
| `READ_PR_REVIEW_COMMENTS` | Read a pull request's inline review threads. The MCP tool returns thread objects under a `review_threads` key, each with `id` (a `PRRT_` thread node ID for `resolve_thread`), `is_resolved`, `is_outdated`, `is_collapsed`, and a nested `comments` array (wrapping GraphQL `reviewThreads`' camelCase `isResolved`/`isOutdated`). The CLI fallback (`gh api "repos/<owner>/<repo>/pulls/<N>/comments"`) returns flat comment objects without resolution state; inspecting thread resolution via CLI requires a GraphQL `reviewThreads` query. | `gh api "repos/<owner>/<repo>/pulls/<N>/comments"` | `mcp__github__pull_request_read (method=get_review_comments)` |
| `READ_PR_REVIEWS` | Read a pull request's formal reviews (state per reviewer, e.g. APPROVED / CHANGES_REQUESTED / COMMENTED). | `gh pr view "<N>" --json reviews` | `mcp__github__pull_request_read (method=get_reviews)` |
| `REQUEST_COPILOT_REVIEW` | Request a GitHub Copilot code review on a pull request. | `gh api "repos/<owner>/<repo>/pulls/<N>/requested_reviewers" -X POST -f "reviewers[]=copilot-pull-request-reviewer[bot]"` | `mcp__github__request_copilot_review` |
| `CREATE_PR` | Open a new pull request. | `gh pr create` | `mcp__github__create_pull_request` |
| `EDIT_PR` | Edit a pull request (reviewers, labels, base, etc.). | `gh pr edit "<N>"` | `mcp__github__update_pull_request` |
| `MERGE_PR` | Merge a pull request. | `gh pr merge "<N>"` | `mcp__github__merge_pull_request` |
| `MARK_PR_READY` | Flip a draft pull request to ready for review. | `gh pr ready "<N>"` | `mcp__github__update_pull_request (draft=false)` |
| `REOPEN_PR` | Reopen a closed pull request. | `gh pr reopen "<N>"` | `mcp__github__update_pull_request (state=open)` |
| `COMMENT_PR` | Post a top-level comment on a pull request. **The body ends with the agent-disclosure marker** --- see [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md). | `gh pr comment "<N>" --body "..."` | `mcp__github__add_issue_comment` |
| `REPLY_REVIEW_COMMENT` | Reply to an inline pull-request review comment. The path carries the PR number; the id-only route (`PATCH .../pulls/comments/<id>`) EDITS that comment instead. **The body ends with the agent-disclosure marker** --- see [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md). | `gh api -X POST "repos/<owner>/<repo>/pulls/<N>/comments/<id>/replies" -F "body=@<file>"` | `mcp__github__add_reply_to_pull_request_comment` |
| `RESOLVE_REVIEW_THREAD` | Mark an inline pull-request review thread as resolved. | `gh api graphql -f query='mutation { resolveReviewThread(input:{threadId:"<thread_node_id>"}) { thread { isResolved } } }'` | `mcp__github__resolve_review_thread` |
| `WATCH_PR` | Subscribe to / unsubscribe from a pull request's activity. | (no CLI equivalent) | `mcp__github__subscribe_pr_activity / mcp__github__unsubscribe_pr_activity` |
| `VIEW_ISSUE` | Read an issue's details. | `gh issue view "<N>"` | `mcp__github__issue_read` |
| `LIST_ISSUES` | List issues. | `gh issue list` | `mcp__github__list_issues` |
| `SEARCH_ISSUES` | Search issues by keyword / query string. | `gh issue list --search "<query>"` | `mcp__github__search_issues` |
| `READ_ISSUE_COMMENTS` | Read an issue's comments. | `gh issue view "<N>" --comments` | `mcp__github__issue_read (method=get_comments)` |
| `ISSUE_LINKED_PRS` | List the pull requests cross-referenced from an issue's timeline (i.e. PRs that link or close it). | `gh api --paginate "repos/<owner>/<repo>/issues/<N>/timeline"` | (no GitHub MCP tool; approximate with SEARCH_PRS) |
| `CREATE_ISSUE` | Open a new issue. | `gh issue create` | `mcp__github__issue_write (method=create)` |
| `COMMENT_ISSUE` | Post a comment on an issue. **The body ends with the agent-disclosure marker** --- see [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md). | `gh issue comment "<N>" --body "..."` | `mcp__github__add_issue_comment` |
| `CLOSE_ISSUE` | Close an issue with a reason. | `gh issue close "<N>" --reason "..."` | `mcp__github__issue_write (method=update, state=closed, state_reason=...)` |
| `REOPEN_ISSUE` | Reopen a closed issue. **The body ends with the agent-disclosure marker** --- see [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md). | `gh issue reopen "<N>" --comment "..."` | `mcp__github__issue_write (method=update, state=open)` |
| `LABEL_ISSUE` | Set an issue's labels. The two behave differently and are not interchangeable: `--add-label` ADDS to the existing set, while the MCP path REPLACES the whole set, so pass the union of existing and new labels there. The MCP path also silently creates an unknown label name instead of rejecting it. | `gh issue edit "<N>" --add-label "..."` | `mcp__github__issue_write (method=update, labels=[...])` |
| `GET_LABEL` | Read a single label's name, color, and description. There is no MCP tool to create or update a label; use gh label create/edit, or gh api from a workflow. | `gh api "repos/<owner>/<repo>/labels/<name>"` | `mcp__github__get_label` |
| `LIST_DISCUSSIONS` | List a repository's discussions. Readable over REST; writes are GraphQL-only. | `gh api repos/{owner}/{repo}/discussions` | `mcp__github__list_discussions` |
| `VIEW_DISCUSSION` | Read a discussion topic and its comment thread. Readable over REST. | `gh api repos/{owner}/{repo}/discussions/{number}[/comments]` | `mcp__github__get_discussion / mcp__github__get_discussion_comments` |
| `COMMENT_DISCUSSION` | Post a reply on a discussion (top-level or threaded). **The body ends with the agent-disclosure marker** --- see [`disclose-agent-authorship`](shared/workflow/disclose-agent-authorship.md). | `gh api graphql (addDiscussionComment)` | `mcp__github__discussion_comment_write (method=add\|reply)` |
| `ANSWER_DISCUSSION` | Mark a comment as the accepted answer on a Q&A discussion. | `gh api graphql (markDiscussionCommentAsAnswer)` | `mcp__github__discussion_comment_write (method=mark_answer)` |
| `CREATE_DISCUSSION` | Open a new discussion in a category. | `gh api graphql (createDiscussion)` | (no GitHub MCP tool; use gh api graphql) |
| `CLOSE_DISCUSSION` | Close a discussion with a reason (RESOLVED, OUTDATED, DUPLICATE). | `gh api graphql (closeDiscussion)` | (no GitHub MCP tool; use gh api graphql) |
| `PUSH` | Push commits to a branch. | `git push -u origin "<branch>"` | (use git; no GitHub MCP equivalent) |
| `COMMIT` | Record staged changes as a commit. | `git commit -m "..."` | (use git; mcp__github__create_or_update_file commits a single file) |
| `FETCH` | Fetch refs from the remote. | `git fetch origin "<branch>"` | (use git; no GitHub MCP equivalent) |
| `MERGE_BRANCH` | Merge a branch into the current one. | `git merge "origin/<branch>"` | (use git; no GitHub MCP equivalent) |
| `CREATE_BRANCH` | Create a new branch (e.g. off the default branch). | `git switch -c "<branch>" "origin/<base>"` | `mcp__github__create_branch` |
| `DELETE_REF` | Delete a remote branch or tag ref. | `git push origin --delete "<branch>" (or git push origin ":refs/tags/<tag>")` | (no GitHub MCP tool; use gh api -X DELETE "repos/<owner>/<repo>/git/refs/heads/<branch>") |
| `READ_FILE` | Read a file's contents from the repo. | `gh api "repos/<owner>/<repo>/contents/<path>"` | `mcp__github__get_file_contents` |
| `LIST_COMMITS` | List a branch's commits (pass the branch or ref as sha, e.g. sha=gh-pages to see which build a Pages branch currently serves). | `git log "<branch>" (or gh api "repos/<owner>/<repo>/commits" -f "sha=<branch>")` | `mcp__github__list_commits` |
| `WRITE_FILE` | Create or update file(s) on a branch in a single commit. | `git add "<path>" && git commit -m "..." && git push` | `mcp__github__create_or_update_file (one file) / mcp__github__push_files (multiple)` |
| `LIST_SECRETS` | List a repo's Actions secrets. The value is never readable, so this can confirm a secret exists and when it last changed, never what it is or whether it works. Use the REST endpoint when created_at is needed: `gh secret list --json` offers name, numSelectedRepos, selectedReposURL, updatedAt, and visibility (gh 2.96.0), so updatedAt is available from the CLI but created_at is not. `--paginate` needs the `--jq '.secrets[]'` projection: the endpoint returns an object rather than an array, so a bare `--paginate` concatenates one object per page and the result is not valid JSON. | `gh api "repos/<owner>/<repo>/actions/secrets" --paginate --jq '.secrets[]'` | (no GitHub MCP tool; use gh api) |
| `SET_SECRET` | Set an Actions secret. Omit --body so the value is read from stdin, keeping it out of argv (visible in ps) and shell history. Exiting 0 means the value was stored, not that it is valid. | `gh secret set "<name>" --repo "<owner>/<repo>"` | (no GitHub MCP tool; use gh) |
| `RUN_WORKFLOW` | Dispatch a workflow_dispatch workflow run on a ref. Pass --ref explicitly; omitting it dispatches against the default branch, which is rarely what a PR-scoped dispatch wants. The MCP tool's `ref` is required for the same reason. | `gh workflow run "<workflow>.yml" --repo "<owner>/<repo>" --ref "<branch>" --field "<key>=<value>"` | `mcp__github__actions_run_trigger (method=run_workflow)` |
| `LIST_WORKFLOW_RUNS` | List a workflow's recent runs, with conclusion and timestamps. | `gh run list --workflow "<workflow>.yml" --repo "<owner>/<repo>"` | `mcp__github__actions_list (method=list_workflow_runs)` |
