plugins/github-app/skills/github-auth/SKILL.md
Guide Claude through GitHub authentication methods including device code flow, personal access tokens, fine-grained tokens, and GitHub App authorization. Use when the user needs to authenticate with GitHub for CLI operations, API access, cross-repo work, or automated workflows. <example>authenticate with github</example> <example>I need to create a PR in another repo</example> <example>gh auth login</example> <example>set up a personal access token</example> <example>configure github app authentication</example>
npx skillsauth add nsheaps/ai-mktpl github-authInstall 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.
This skill covers all GitHub authentication methods relevant to Claude Code sessions. It enables Claude to guide users through the appropriate auth flow for their use case.
| Method | Best For | Expires | Scope Control | | ------------------------------- | ------------------------ | --------------------------- | ------------------ | | Device Code Flow | Interactive CLI sessions | Session-based | Per-login | | Personal Access Token (classic) | Simple automation, CI | Configurable / never | Broad scopes | | Fine-Grained PAT | Targeted repo access | Configurable (max 1yr) | Per-repo, granular | | GitHub App (as app) | Automated systems, bots | 1 hour (installation token) | Per-installation | | GitHub App (as user) | User-to-server, OAuth | Session-based | Per-authorization |
Best for: Claude Code sessions where the user is present and can authorize in a browser.
BROWSER=false gh auth login
This outputs:
ABCD-1234)https://github.com/login/deviceThe user visits the URL, enters the code, and authorizes access.
# GitHub.com with HTTPS
BROWSER=false gh auth login --hostname github.com --git-protocol https
# With specific scopes
BROWSER=false gh auth login --scopes "repo,read:org,write:packages"
# GitHub Enterprise
BROWSER=false gh auth login --hostname github.mycompany.com
| Scope | Description |
| ------------------ | -------------------------------------- |
| repo | Full control of private repositories |
| read:org | Read organization membership |
| write:org | Read and write organization membership |
| read:packages | Download packages from GitHub Packages |
| write:packages | Upload packages to GitHub Packages |
| admin:public_key | Manage public keys |
| gist | Create gists |
| workflow | Update GitHub Action workflows |
# Check current status
gh auth status
# Refresh expired token
BROWSER=false gh auth refresh
# Switch accounts
gh auth switch --user username
# Logout
gh auth logout
Best for: Simple automation, CI pipelines, or when device code flow isn't available.
https://github.com/settings/tokens# Authenticate with token
echo "$GH_TOKEN" | gh auth login --with-token
# Or set as environment variable
export GH_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export GITHUB_TOKEN="$GH_TOKEN" # Also recognized by git and many tools
# Via credential helper
git config --global credential.helper store
# Then use token as password when prompted
# Or via URL
git clone https://x-access-token:${GH_TOKEN}@github.com/owner/repo.git
repo grants access to ALL repos)Best for: Targeted access to specific repositories with minimal permissions.
https://github.com/settings/personal-access-tokens/newSame as classic PATs — set GH_TOKEN or GITHUB_TOKEN environment variable.
Best for: Automated systems, bot identities, long-running agent sessions.
GitHub Apps authenticate using a two-step process:
# Step 1: Generate JWT
NOW=$(date +%s)
IAT=$((NOW - 60))
EXP=$((NOW + 540))
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')
PAYLOAD=$(echo -n "{\"iss\":\"${GITHUB_APP_ID}\",\"iat\":${IAT},\"exp\":${EXP}}" | base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')
SIGNATURE=$(echo -n "${HEADER}.${PAYLOAD}" | openssl dgst -sha256 -sign "$GITHUB_APP_PRIVATE_KEY_PATH" | base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n')
JWT="${HEADER}.${PAYLOAD}.${SIGNATURE}"
# Step 2: Exchange for installation token
curl -s -X POST \
-H "Authorization: Bearer ${JWT}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/app/installations/${GITHUB_INSTALLATION_ID}/access_tokens"
| Variable | Description |
| ----------------------------- | ------------------------------------------ |
| GITHUB_APP_ID | The GitHub App's numeric ID |
| GITHUB_APP_PRIVATE_KEY_PATH | Path to PEM private key file |
| GITHUB_INSTALLATION_ID | Installation ID for the target account/org |
# With gh CLI
export GH_TOKEN="ghs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# With git
git config credential.https://github.com.helper \
'!f() { echo "protocol=https"; echo "host=github.com"; echo "username=x-access-token"; echo "password=${GH_TOKEN}"; }; f'
GitHub Apps can also act on behalf of a user via OAuth:
https://github.com/login/oauth/authorize?client_id=APP_CLIENT_IDThis is useful when the app needs to act as a specific user rather than as itself.
Is a user present and interactive?
Do you need access to specific repos only?
Is this for a long-running automated system?
Do you need a bot identity (not a user)?
chmod 600https://github.com/settings/applications| Error | Cause | Solution |
| ------------------------ | -------------------------------- | --------------------------------------- |
| HTTP 401 | Token expired or invalid | Re-authenticate or generate new token |
| HTTP 403 | Insufficient permissions | Check scopes; re-authenticate with more |
| HTTP 404 | Private repo, not authenticated | Authenticate to access private repos |
| SSO Required | Organization requires SSO | Authorize SSO in browser settings |
| Bad credentials | Token revoked or malformed | Re-authenticate from scratch |
| JWT expired | GitHub App JWT older than 10 min | Regenerate JWT and retry |
| Installation suspended | App installation was suspended | Contact org admin |
| Method | Storage Location |
| ---------------------- | ------------------------------------------- |
| gh auth login | ~/.config/gh/hosts.yml |
| GH_TOKEN env var | Process environment |
| GITHUB_TOKEN env var | Process environment |
| GitHub App token file | ~/.config/agent/github-token (convention) |
| Git credential helper | OS keychain or ~/.git-credentials |
For organizations requiring SAML SSO:
https://github.com/settings/applicationstools
Manually reproduce what the github-app plugin's SessionStart hook does to make a GitHub App installation token usable in the current session — materialize the PEM, generate the token, isolate GH_CONFIG_DIR, write the runtime env file, and wire CLAUDE_ENV_FILE so every Bash call sees GH_TOKEN/GITHUB_TOKEN. Use when the hook did not run, the token is missing from the environment, or a shell/teammate needs the token wired up by hand. <example>GH_TOKEN isn't set even though github-app is configured</example> <example>the github-app SessionStart hook didn't run, set up the token manually</example> <example>wire the github app token into CLAUDE_ENV_FILE</example> <example>gh keeps falling back to the wrong account, isolate GH_CONFIG_DIR</example>
tools
Manually configure the GitHub App bot git identity the way the github-app plugin's SessionStart hook does — resolve the app slug and bot user ID, build the <slug>[bot] name and noreply email, set GIT_AUTHOR_*/GIT_COMMITTER_* env vars, and write an isolated GIT_CONFIG_GLOBAL with the gh auth git-credential helper. Use when commits are attributed to the wrong account, "Author identity unknown" appears, or git identity must be set up by hand. <example>my commits are showing up as the handler, not the bot</example> <example>git says Author identity unknown after the github-app hook ran</example> <example>configure the github app bot git identity manually</example> <example>set up the gh credential helper for git push</example>
tools
Manages spec files for requirements capture and validation
tools
# Bash Chaining Alternatives This skill teaches you how to work around the bash command chaining restriction enforced by this plugin. ## Why Chaining is Blocked The `bash-command-rejection` plugin blocks these operators: | Operator | Name | Why Blocked | | -------- | ---------- | ----------------------------------------------------------------------------------- | | `&&` | AND chain | Runs cmd2 only if cmd1 su