← Public packages
@kody/github
Call GitHub REST, GraphQL, and pull requests with a GitHub OAuth App or a personal access token.
AGENTS.md
154 lines · 4.2 KB · Markdown@kody/github — agent notes
Human setup and intent live in README.md. This file is for
agents: imports, smoke/dryRun snippets, and edge cases. Secrets by name
only — never paste token values. Do not disable live webhooks or jobs.
Secrets / integrations
| Lane | Credential | Default name |
|---|---|---|
| OAuth App | Saved integration | github |
| PAT | User secret | githubAccessToken |
Pass integrationName (OAuth) or secretName (PAT). Extra OAuth identities:
github-work, etc. account aliases integrationName. Retired alias bot
throws with setup URLs.
Import paths
| Export | Import |
|---|---|
| overview | kody:@kody/github |
| accounts | kody:@kody/github/accounts |
| get-viewer | kody:@kody/github/get-viewer |
| graphql | kody:@kody/github/graphql |
| paginate | kody:@kody/github/paginate |
| request | kody:@kody/github/request |
| types | kody:@kody/github/types |
| pr/get-info | kody:@kody/github/pr/get-info |
| pr/get-checks | kody:@kody/github/pr/get-checks |
| pr/merge | kody:@kody/github/pr/merge |
| pr/set-review-status | kody:@kody/github/pr/set-review-status |
Prefer static kody:@kody/github/... imports from execute. If you must
invoke dynamically, pass bare kody id github (not @kody/github).
Smoke test (read-only)
OAuth (default integration github):
import getGithubViewer from 'kody:@kody/github/get-viewer'
export default async function main() {
return await getGithubViewer()
// or: getGithubViewer({ integrationName: 'github' })
}PAT:
import getGithubViewer from 'kody:@kody/github/get-viewer'
export default async function main() {
return await getGithubViewer({ secretName: 'githubAccessToken' })
}dryRun / confirm (mutations)
import mergePr from 'kody:@kody/github/pr/merge'
export default async function main() {
return await mergePr({
owner: 'example-org',
repo: 'example',
prNumber: 1,
mergeMethod: 'squash',
dryRun: true,
})
}import githubRequest from 'kody:@kody/github/request'
export default async function main() {
return await githubRequest({
method: 'POST',
path: '/repos/example-org/example/issues',
body: { title: 'Example', body: 'Preview only' },
dryRun: true,
})
}import setPrReviewStatus from 'kody:@kody/github/pr/set-review-status'
export default async function main() {
return await setPrReviewStatus({
owner: 'example-org',
repo: 'example',
prNumber: 1,
status: 'ready',
dryRun: true,
})
}Common reads
import githubRequest from 'kody:@kody/github/request'
export default async function main() {
const response = await githubRequest({
path: '/user/repos',
query: { per_page: 5 },
throwOnError: true,
})
return response.data
}import getPrInfo from 'kody:@kody/github/pr/get-info'
export default async function main() {
return await getPrInfo({
owner: 'example-org',
repo: 'example',
prNumber: 1,
integrationName: 'github-work',
})
}PR locators: { prUrl } or { owner, repo, prNumber } (number aliases
prNumber).
Edge cases
- On
401/403, helpers throwGitHubRequestErrornaming missing OAuth scopes (X-Accepted-OAuth-ScopesvsX-OAuth-Scopes) and the next setup step. - OAuth: reconnect at
/connect/oauth?provider=<integrationName>after adding the missing scope on the GitHub OAuth App. - PAT: grant the missing permission, then update the secret.
- Rate limit:
403withX-RateLimit-Remaining: 0— wait or batch with GraphQL. - Org-restricted OAuth App: request third-party access approval, or use a fine-grained PAT approved for that org.
redirect_urimust be exactlyhttps://kody.codes/connect/oauth.- Token exchange in Lane B still needs the client secret even with PKCE.
- Authenticated rate limit is typically 5,000 requests/hour per user.
Fork / adapt
- Fork into the caller's account (kody id stays
github). - Connect their OAuth App and/or save their PAT; approve GitHub hosts.
- Run
./get-viewerfor the selected lane before treating the copy as ready. - Keep
## Intentandcommunity-icon.svgintact for community listing; do not hard-code personal account aliases.