Interact with GitHub via the `gh` CLI. Use for issues (read, comment, file), pull requests (view, comment, check CI status), workflow runs, and `gh api` for queries the subcommands don't cover. Authentication is via the bot's GITHUB_TOKEN (already wired through `gh auth setup-git` at container start).
Scanned 9/1/2026
Install to Claude Code
npx -y skills add jasoncarreira/mimir --skill github --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Github?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jasoncarreira-github)More formats (shields.io, HTML) on the badges page.
---
name: github
description: Interact with GitHub via the `gh` CLI. Use for issues (read, comment, file), pull requests (view, comment, check CI status), workflow runs, and `gh api` for queries the subcommands don't cover. Authentication is via the bot's GITHUB_TOKEN (already wired through `gh auth setup-git` at container start).
success_criteria:
# The skill exists to wrap gh CLI invocations. Loading the SKILL.md
# and not running any gh command means we read the policy but
# didn't actually act on it.
any_of:
- tool_call:
name: Bash
args:
command_glob: "gh *"
- tool_call:
name: Bash
args:
command_glob: "* gh *"
---
<!-- desc: Interact with GitHub via the gh CLI — issues, pull requests, CI status, workflow runs, and gh api for uncovered queries. -->
# GitHub
The `gh` CLI is installed in the container and authenticated via `GITHUB_TOKEN`
from the env. Commits the agent makes through `git push` go through the same
credential helper, so `gh pr create` and `git push` both work.
## Contract
**Trigger**: Any interaction with GitHub that goes beyond local git — reading issues
or PRs, filing comments, checking CI, querying the API. If the task requires GitHub
state (not just local repo state), invoke this skill.
**Requires**: `GITHUB_TOKEN` in environment (verified by `gh auth status`). The PAT's
scope determines which repos are reachable — operations on out-of-scope repos return
403; check what the operator configured if you hit one.
**Guarantees**:
- GitHub interactions happen via `gh` CLI (authenticated, auditable), not via
WebFetch on raw GitHub URLs.
- PAT scope is checked mentally before any cross-repo operation — a 403 from an
out-of-scope repo is expected behavior, not a bug.
**Does not**: Push code (that's `git push`, separate from `gh`); manage GitHub Actions
billing; access repos outside the PAT scope; file issues on external repos without
operator approval.
When `cwd` is inside a git checkout of the target repo, you don't need `--repo`
— gh resolves the upstream remote from the local `origin`. When working from
elsewhere or operating on a different repo, pass `--repo owner/repo` (or use a
URL).
## Pre-merge CHANGES_REQUESTED gate (chainlink #214, rule via #217)
**Before invoking `gh pr merge` on any PR, ALWAYS check the current review
state.** A reviewer can flip to CHANGES_REQUESTED after the first approval —
calling `gh pr merge` without a fresh check can merge a PR that has outstanding
blocking feedback.
```bash
# Returns the login list of blocking reviewers (empty array [] if none)
BLOCKING=$(gh pr view <PR> --json reviews --jq '
[.reviews | group_by(.author.login)[] | sort_by(.submittedAt)[-1]
| select(.state == "CHANGES_REQUESTED") | .author.login]')
# Refuse if non-empty
if [ "$BLOCKING" != "[]" ]; then
# blocked — do not merge; see steps below
echo "Merge blocked by CHANGES_REQUESTED from: $BLOCKING"
fi
```
If `$BLOCKING` is non-empty (one or more reviewers in CHANGES_REQUESTED state):
1. **Refuse the merge** — do not call `gh pr merge`.
2. Post a `gh pr comment` explaining why the merge was blocked and listing the
blocking reviewers from `$BLOCKING` who need to re-approve.
This is a non-negotiable hard gate — not a heuristic. "Operator approved once"
is not sufficient if a subsequent CHANGES_REQUESTED arrived, even seconds later.
(Structured event emission for blocked merges is tracked in chainlink #218.)
## Pre-push staleness gate (chainlink #219)
**Before pushing a PR branch for re-review, ALWAYS check that the branch is
current against `origin/main`.** Between the last rebase and the next push,
other PRs may have merged to `main`; a stale base makes the PR diff include
complete reverts of unrelated landed work. A squash-merge would silently drop
those commits from `main`.
Exception: Worklink slice branches named `issue/<digits>-a<digits>` are based
on their epic integration branch, and `epic/*` integration branches merge to
main only through the single epic draft PR. Do not rebase those machinery
branches directly onto `origin/main` for this gate.
```bash
# Step 1: fetch and check staleness
git fetch origin main
MERGE_BASE=$(git merge-base HEAD origin/main)
MAIN_TIP=$(git rev-parse origin/main)
if [ "$MERGE_BASE" != "$MAIN_TIP" ]; then
echo "Branch is stale — rebasing onto current origin/main"
git rebase origin/main
fi
# Step 2: inspect paths in the diff after rebase
git diff origin/main..HEAD --name-only
```
**If the rebase fails with conflicts** (i.e. `git rebase origin/main` returned
non-zero), abort with `git rebase --abort` and stop — **do not push**. A failed
rebase leaves the branch in an intermediate state where the subsequent diff and
push are both unsafe. Resolve the conflicts manually (or request operator
guidance) before re-running the gate from step 1.
After fetching (and rebasing if stale), inspect the path list:
- If every path is **within the PR's declared scope** (the chainlink ID, PR
title, or known feature area), the push is safe — proceed.
- If any path is **outside scope** (a revert of unrelated work, or an
accidentally-staged file), stop — do not push. Investigate whether a further
rebase is needed or whether a stale commit slipped onto the branch.
**Non-negotiable rule**: do not push to a PR branch for re-review without this
check. The cost of missing a stale base is silently reverting landed work when
the PR is squash-merged. Pairs with the pre-merge gate above — both gates exist
because the window between "last rebase" and "reviewer sees diff" is enough for
main to advance.
Four concrete instances from 2026-05-27 that this gate would have caught:
#393 (would have wiped #391/#388/#389/#392), #394 round 1 (stacked on stale
#393), #396 (would have reverted #395 ~520 lines), #394 round 2 (stale base
after #395 merged).
## Pull requests
Budget rule: perform required GitHub side effects before optional long
validation or repeated polling consumes the turn. Once a PR comment,
review, or status update is the next required durable action, do it first
and then run extra checks if budget remains. When the tool-call count is
visibly high, reserve roughly 10-15 calls for the side effect,
verification (`gh pr view` / `gh pr checks`), and wrap-up.
```bash
gh pr list --state open # open PRs on the current repo
gh pr view 42 # view a PR
gh pr view 42 --json title,state,reviews # structured fields
gh pr checks 42 # CI status
gh pr create --title "..." --body "..." # open a PR (uses HEREDOC for body)
gh pr comment 42 --body "looking now"
gh pr diff 42 # the PR's diff
```
For PRs the bot opens, the convention (see mimirbot/README.md) is feature
branch + PR; do not push to `main` directly.
## Issues
```bash
gh issue list --state open
gh issue view 7
gh issue comment 7 --body "ack — picking this up"
gh issue create --title "..." --body "..." # only when explicitly asked
```
## Workflow runs / CI
```bash
gh run list --limit 10
gh run view <run-id> # which steps passed/failed
gh run view <run-id> --log-failed # logs for failed steps only
gh run watch <run-id> # block until done
```
## `gh api` for advanced queries
When the subcommands don't cover what you need, drop to the API:
```bash
gh api repos/jasoncarreira/mimir/pulls/42 --jq '.title, .state, .user.login'
gh api repos/jasoncarreira/mimir/pulls/42/comments
gh api 'repos/jasoncarreira/mimir/issues?state=open&labels=bug' --jq '.[] | "\(.number): \(.title)"'
```
`--jq` filters work like inline jq queries; chain with shell tools when needed.
> **`--jq` is not available on poller or scheduled turns.** The trusted-service
> shell profiles do not admit it: `gh` evaluates the filter in-process and jq's
> `env` builtin reads the process environment, so the option is a credential
> read rather than an output formatter. Use `--json <fields>` and filter the
> returned JSON yourself. Piped and bracketed filters were already refused on
> those turns anyway, because `|`, `[` and `]` are shell metacharacters.
## When NOT to use this
- Don't push to `main` even when you can — feature branch + PR is the
convention. Operator merges.
- Don't open issues without being asked; reading and commenting is the
default mode.
- Don't use `gh repo delete` or `gh release delete` ever (no destructive ops).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!