plugins/github-app/skills/github-app-token/SKILL.md
Manage GitHub App installation tokens in Claude Code sessions. Use when tokens expire, auth errors occur in long-running sessions, or when setting up GitHub App credentials for agent teams. <example>my github token expired</example> <example>refresh the github app token</example> <example>check token status</example> <example>set up github app authentication for this session</example>
npx skillsauth add nsheaps/ai-mktpl github-app-tokenInstall 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 managing GitHub App installation tokens in Claude Code sessions, including setup, refresh, troubleshooting, and agent team distribution.
Session Start
│
├─ SessionStart Hook (github-token-init.sh)
│ ├─ Reads GITHUB_APP_ID, GITHUB_INSTALLATION_ID, GITHUB_APP_PRIVATE_KEY
│ ├─ Materializes PEM to $CLAUDE_PLUGIN_DATA/github-app.pem
│ ├─ Generates JWT from PEM key
│ ├─ Exchanges JWT for installation token (1 hour validity)
│ ├─ Writes token to $CLAUDE_PLUGIN_DATA/github-token
│ ├─ Creates runtime env file ($CLAUDE_PLUGIN_DATA/github-app-env)
│ ├─ Sources env file via CLAUDE_ENV_FILE
│ ├─ Configures git identity (bot user)
│ └─ Prints: app name, expiry time, env var names
│
└─ PreToolUse Hook (github-token-check.sh)
├─ Debounced: checks at most every 300 seconds (5 minutes)
├─ For gh/git commands: synchronous check
│ ├─ Valid + >45min: silent allow
│ ├─ Valid + <45min: allow + background refresh
│ └─ Expired: synchronous refresh, then allow
├─ For other tools: async background check
├─ Retries up to 3x with exponential backoff
└─ 5-minute cooldown after all retries fail
$CLAUDE_PLUGIN_DATA/github-token (permissions 600)https://github.com/settings/appsSet these three env vars before the session starts:
GITHUB_APP_IDGITHUB_INSTALLATION_IDGITHUB_APP_PRIVATE_KEY (PEM content, not a file path)Recommended: Use the 1pass plugin to inject from 1Password by adding the three vars to your agent's 1pass.secrets list in plugins.settings.yaml:
1pass:
secrets:
- envVar: GITHUB_APP_ID
reference: "op://vault/github-app--repo--my-repo/GITHUB_APP_ID"
- envVar: GITHUB_INSTALLATION_ID
reference: "op://vault/github-app--repo--my-repo/GITHUB_INSTALLATION_ID"
- envVar: GITHUB_APP_PRIVATE_KEY
reference: "op://vault/github-app--repo--my-repo/GITHUB_APP_PRIVATE_KEY"
github-app:
enabled: true
autoGitConfig: true
Any other mechanism that exports these vars into the session env works (direct shell export, .env file sourced before launch, etc.).
The plugin materializes the PEM to $CLAUDE_PLUGIN_DATA/github-app.pem on every session start. No pre-existing PEM file is needed.
Run the token status script directly:
$CLAUDE_PLUGIN_ROOT/bin/token-status.sh
Or check the metadata file (length-only — never print the raw token):
jq '.expires_at' "$CLAUDE_PLUGIN_DATA/github-token.meta"
$CLAUDE_PLUGIN_ROOT/bin/token-check.sh --sync
Exit codes: 0 = valid/refreshed, 1 = failed after retries, 2 = not configured, 3 = cooldown.
Step 1 — Verify env vars (length-only, never print values)
for v in GITHUB_APP_ID GITHUB_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY; do
val="${!v:-}"
[[ -n "$val" ]] && echo "$v is set (${#val} chars)" || echo "$v is NOT set"
done
Step 2 — Run generate-token.sh
The PEM is already at $CLAUDE_PLUGIN_DATA/github-app.pem (materialized by SessionStart).
$CLAUDE_PLUGIN_ROOT/bin/generate-token.sh \
"$GITHUB_APP_ID" \
"$CLAUDE_PLUGIN_DATA/github-app.pem" \
"$GITHUB_INSTALLATION_ID" \
"$CLAUDE_PLUGIN_DATA/github-token"
Step 3 — Verify
GH_TOKEN=$(cat "$CLAUDE_PLUGIN_DATA/github-token") gh api /user --jq '.login'
# Expected: <app-slug>[bot]
| Symptom | Likely cause |
| ------------------------------------ | --------------------------------------------------------- |
| HTTP 401 during JWT exchange | PEM key mismatch or clock skew > 60s |
| HTTP 404 on /app/installations/… | Wrong GITHUB_INSTALLATION_ID |
| Failed to sign JWT | PEM content malformed or GITHUB_APP_PRIVATE_KEY missing |
| exit 2 from token-check.sh | Credential env vars missing |
| exit 3 from token-check.sh | 5-min cooldown — wait or clear .cooldown file |
The SessionStart hook configures git to use gh auth git-credential directly. The gitconfig entry written is:
[credential "https://github.com"]
helper =
helper = !gh auth git-credential
Missing env vars. Check lengths (never print values):
for v in GITHUB_APP_ID GITHUB_INSTALLATION_ID GITHUB_APP_PRIVATE_KEY; do
val="${!v:-}"; [[ -n "$val" ]] && echo "$v set (${#val} chars)" || echo "$v NOT SET"
done
Clear the cooldown:
rm "$CLAUDE_PLUGIN_DATA/github-token.cooldown"
v0.4.0 writes everything under $CLAUDE_PLUGIN_DATA/. Orphaned files at ~/.agents/<name>/.config/ can be removed:
rm -rf ~/.agents/<name>/.config/github-token* ~/.agents/<name>/.config/github-app-env \
~/.agents/<name>/.config/github-app.pem ~/.agents/<name>/.config/github-git-identity
github-auth skill covers all auth methodstools
Reference material for Claude Code internals — the on-disk layout under ~/.claude and project-scope .claude, the plugin cache, session-env propagation, and the full hook lifecycle. Auto-recall when working on Claude-Code-related tasks: writing or debugging hooks, authoring plugins, inspecting session state, troubleshooting why an env var is or isn't visible to a Bash tool call, or when paths under ~/.claude or ~/.claude/plugins/ come up.
tools
Auto-detect project formatting tools and configure edit-utils settings
tools
Use this skill when the user asks about 1Password, secrets management, retrieving credentials, using op CLI, service accounts, secret references, vault operations, or any task involving the 1Password CLI (op). Also use when needing to inject secrets into environment variables, read passwords or API keys from 1Password, or manage 1Password items from the command line.
tools
Use this skill when the user asks about op-exec, running commands with 1Password secrets injected, wrapping processes with secret injection, automating secret-aware command execution, or configuring whole-item environment injection with multiple output targets. op-exec is a wrapper around the 1Password CLI that simplifies running commands with secrets from 1Password vaults.