con un clic
github-tools
Mint GitHub App installation tokens and call GitHub REST API
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Mint GitHub App installation tokens and call GitHub REST API
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
| name | github-tools |
| description | Mint GitHub App installation tokens and call GitHub REST API |
| version | 1.0.0 |
| user-invocable | false |
| metadata | {"openclaw":{"requires":{"env":["GITHUB_APP_ID","GITHUB_APP_PRIVATE_KEY_FILE","GITHUB_INSTALLATION_ID"],"primaryEnv":"GITHUB_APP_PRIVATE_KEY_FILE"}}} |
Provides authenticated access to the GitHub REST API using a GitHub App installation token. Use this skill for ALL GitHub API calls. Never hardcode tokens.
Mint a fresh installation token at the start of each agent run. Tokens expire after 1 hour.
iat = now - 60 seconds (clock skew buffer)
exp = now + 10 minutes
iss = GITHUB_APP_ID
algorithm = RS256
key = contents of GITHUB_APP_PRIVATE_KEY_FILE (PEM file path from env)
POST https://api.github.com/app/installations/{GITHUB_INSTALLATION_ID}/access_tokens
Headers:
Authorization: Bearer {jwt}
Accept: application/vnd.github+json
X-GitHub-Api-Version: 2022-11-28
Save the returned token field. Use it as Bearer {installation_token} for all subsequent calls.
A Python helper script is available at scripts/mint-token.py in this skill directory.
Run it with: python3 <skill_dir>/scripts/mint-token.py
It reads env vars, signs the JWT via openssl (subprocess, PEM path passed — contents stay on disk), exchanges it for an installation token via urllib.request with a 10-second timeout, and prints the token to stdout. Errors go to stderr, non-zero exit on any failure (including a null token in the response body).
Stdlib only — no pip install step. Replaces a previous Node helper that hung indefinitely on https.request() on AL2023 ARM64 hosts; Python's urllib works fine on the same host class.
Always include these headers:
Authorization: Bearer {installation_token}
Accept: application/vnd.github+json
X-GitHub-Api-Version: 2022-11-28
429: read Retry-After header, wait that many seconds, retry403 with X-RateLimit-Remaining: 0: wait until X-RateLimit-Reset (unix timestamp)GET /repos/{owner}/{repo}/pulls?state=closed&sort=updated&direction=desc&per_page=100
Filter client-side: merged_at >= {since}
GET /repos/{owner}/{repo}/pulls/{pull_number}/files
Returns: array of {filename, status, additions, deletions, patch}
GET /repos/{owner}/{repo}/pulls/{pull_number}
Returns: title, body, merged_at, merge_commit_sha, user, labels
GET /repos/{owner}/{repo}/contents/{path}?ref={branch}
Returns: array of {name, path, type, sha, download_url}
GET /repos/{owner}/{repo}/contents/{path}?ref={branch}
Returns: {content} as base64. Decode before use.
First get the SHA of the base branch HEAD:
GET /repos/{owner}/{repo}/git/ref/heads/{base_branch}
→ object.sha
Then create the branch:
POST /repos/{owner}/{repo}/git/refs
Body: {"ref": "refs/heads/{new_branch}", "sha": "{base_sha}"}
First get the file's current SHA (if it exists):
GET /repos/{owner}/{repo}/contents/{path}?ref={branch}
→ sha
Then create/update:
PUT /repos/{owner}/{repo}/contents/{path}
Body: {
"message": "{commit message}",
"content": "{base64 encoded content}",
"branch": "{branch_name}",
"sha": "{existing_file_sha}" ← omit if creating new file
}
POST /repos/{owner}/{repo}/pulls
Body: {
"title": "{title}",
"body": "{markdown body}",
"head": "{branch_name}",
"base": "main",
"draft": false
}
| Repo | Owner | Access |
|---|---|---|
| HumberAgent | trnt-ai | Read (PRs, files) |
| threat-dashboard | trnt-ai | Read (PRs, files) |
| sdks | trnt-ai | Read + Write (docs/ only) |
Never write to HumberAgent or threat-dashboard. Never write outside docs/ in sdks.