gh-cli
Reliably drive the GitHub gh CLI for issue, PR, and label operations in automation and subagent environments, with pre-flight verification so you never fabricate a success or a fake issue URL.
What this skill does
# GitHub `gh` CLI
Reliable patterns for using the GitHub `gh` CLI for issue, PR, and label operations — built for automation and subagent environments where silent auth failures are common and fabricating a result is the worst outcome.
**When to Use**: Any time you create, list, view, edit, or close GitHub issues / PRs / labels through `gh`, particularly inside a sandboxed shell or a delegated subagent.
---
## The One Rule: Never Fabricate
When an operation cannot be verified as succeeded, **report the failure with the exact error**. Never invent an issue number, a URL, or a "created successfully" message. A loud, accurate failure is always better than a fake success — downstream agents and humans act on what gets reported.
---
## 1. Pre-flight Verification (run BEFORE any operation)
Always confirm authentication and repo access first. These are cheap, read-only, and catch the overwhelming majority of failures before you mutate anything.
```bash
# 1. Confirm you are authenticated and see which account/scopes are active
gh auth status
# 2. Confirm you can actually reach the target repo (proves token + SSO + network)
gh repo view <org>/<repo> --json name,url
```
- If `gh auth status` reports **"not logged into any GitHub hosts"** or any error, **STOP**. Do not run create/edit/close. Diagnose using the sections below, then report the exact error verbatim.
- If `gh repo view` fails (404, SAML, Bad credentials), **STOP**. The token may be valid but lack access to this org/repo. Report the exact error.
- Only proceed to mutating operations once both commands succeed.
> In a subagent: treat a failed pre-flight as a hard stop. Returning "I created issue #42" when auth failed is the failure mode this skill exists to prevent.
---
## 2. Gotcha: Sandbox / OS keychain access
`gh`'s OAuth (keyring) tokens are stored in the OS keychain (macOS Keychain, Linux Secret Service). A **sandboxed shell cannot read the keychain**, so `gh` falls back to "no credentials found" and reports **"not logged into any GitHub hosts"** — even though valid credentials exist.
**Symptom**: `gh auth status` says not logged in, but the same command works in a normal terminal.
**Fix**: Run `gh` with the sandbox disabled so it can reach the keychain.
- In Claude Code, set `dangerouslyDisableSandbox: true` on the Bash tool call that runs `gh`.
- Re-run the pre-flight (`gh auth status`) with the sandbox disabled to confirm before proceeding.
---
## 3. Gotcha: stale `GH_CONFIG_DIR`
`gh` reads its config (including which `hosts.yml` holds credentials) from `GH_CONFIG_DIR` if that env var is set, otherwise from `~/.config/gh`. A **stale or wrong `GH_CONFIG_DIR` pointing at a nonexistent directory** makes `gh` report "not logged in" even when valid keyring credentials exist elsewhere.
**Diagnose**:
```bash
echo "$GH_CONFIG_DIR" # Is it set? To what?
ls "$GH_CONFIG_DIR" # Does the directory exist? Has hosts.yml?
```
**Find the config dir that actually has credentials**:
```bash
find ~ -maxdepth 5 -name hosts.yml -path '*gh*'
```
**Fix** — point `GH_CONFIG_DIR` at the real config dir, or unset it to fall back to the default:
```bash
# Option A: point at the working config explicitly
GH_CONFIG_DIR=/path/to/real/gh-config gh auth status
# Option B: unset to use ~/.config/gh
unset GH_CONFIG_DIR && gh auth status
```
---
## 4. Multiple accounts
`gh auth status` may list **several accounts**, with one marked active. `gh` uses the active account. If the active one lacks access to your target org/repo, switch:
```bash
gh auth status # see all accounts; note which is "Active account: true"
gh auth switch -u <username> # make the correct account active
gh repo view <org>/<repo> --json name,url # re-verify after switching
```
---
## 5. Gotcha: Org SAML SSO rejects PATs
Personal Access Tokens pulled from `.env` files are frequently rejected by orgs that enforce SAML SSO:
```
HTTP 403: Resource protected by organization SAML enforcement.
You must grant your Personal Access token access to this organization.
```
**Why**: Even a valid PAT must be **SSO-authorized for that specific org** via a browser grant. Tokens injected from `.env` in a headless environment usually have never been through that grant.
**Preferred fix**: Use a **keyring OAuth token** (`gh auth login`) that has already been SSO-authorized for the org — OAuth logins prompt for the SSO grant interactively. To authorize an existing PAT, complete the org's SSO browser grant in GitHub settings (Developer settings → PATs → Configure SSO).
**Rule of thumb**: For SSO-enforced orgs, prefer keyring OAuth over `.env` PATs.
---
## 6. Server-side fallback for CI / bulk operations
When local auth is unavailable, unreliable, or you need robust bulk operations, run `gh` from a **server that holds a GitHub App installation token**. App installation tokens are **SSO-exempt** and scoped to the installation, making them the most reliable path for automation.
A common pattern is to dispatch the command to a server via AWS SSM:
```bash
aws ssm send-command \
--instance-ids <instance-id> --region <region> \
--document-name "AWS-RunShellScript" \
--parameters '{"commands":["gh issue create --repo <org>/<repo> --title \"...\" --body \"...\""]}'
```
Treat this as the **robust path for automation / CI** when keychain-backed local auth cannot be guaranteed.
---
## 7. Common commands cheat-sheet
Use `--json <fields> --jq <filter>` to get machine-parseable output and to **confirm** results rather than trusting exit codes alone.
### Issues
```bash
# Create — capture the returned URL; do not invent it
gh issue create --repo <org>/<repo> --title "Title" --body "Body" --label bug
# List (parseable)
gh issue list --repo <org>/<repo> --state open --json number,title,url --jq '.[]'
# View a specific issue
gh issue view <number> --repo <org>/<repo> --json number,title,state,url
# Close
gh issue close <number> --repo <org>/<repo> --comment "Resolved"
# Edit (also the basis of upsert-by-title — see below)
gh issue edit <number> --repo <org>/<repo> --add-label triaged --body "Updated body"
```
### Upsert-by-title pattern (idempotent issue creation)
Avoid duplicate issues by checking for an existing open issue with the same title before creating:
```bash
existing=$(gh issue list --repo <org>/<repo> --state open \
--search "in:title \"My exact title\"" \
--json number,title --jq '.[] | select(.title=="My exact title") | .number' | head -n1)
if [ -n "$existing" ]; then
gh issue edit "$existing" --repo <org>/<repo> --body "Refreshed body"
else
gh issue create --repo <org>/<repo> --title "My exact title" --body "..."
fi
```
### Pull requests
```bash
gh pr view <number> --repo <org>/<repo> --json number,title,state,url,mergeable
gh pr list --repo <org>/<repo> --state open --json number,title,headRefName --jq '.[]'
```
### Labels
```bash
gh label create "code-intelligence" --repo <org>/<repo> --color BFD4F2 --description "..."
gh label list --repo <org>/<repo> --json name,color --jq '.[].name'
```
---
## Troubleshooting / Environment-specific notes
This section documents a concrete, worked example of the failure modes above — diagnosed while ticketing subagents could not create issues in `duettoresearch/code-intelligence`. The generic instructions above are what you apply; this is the case study showing how they combine in practice.
### Symptom
Ticketing subagents reported **"not logged into any GitHub hosts"** and **"Bad credentials"** and could not create issues in `duettoresearch/code-intelligence`. Some runs would otherwise have been tempted to report a fabricated issue URL — do not.
### Root causes found (multiple, compounding)
1. **Stale `GH_CONFIG_DIR`** — subagents inherited `GH_CONFIG_DIR=/Users/masa/.config/gh-duetto`, a directory that **does not exist**, so `gh` saw no credentials. (See §3.)
2. **Sandbox blocked keychain** — the Bash sandbox prevented reading the Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.