GitHub REST, GraphQL, and pull request helpers for Kody agents.
- Integrations
- github
- api
- accounts
- pr
- automation
- actions
- secrets
- License
- MIT
- Published
- August 21, 2026
- Pinned commit
4539a93- Rating
- No ratings yet
- Forks
- 2
- Stars
- 0
- Adaptation effort
- —
README
@kentcdodds/github
Intent
One GitHub helpers package for Kody agents, with two BYO OAuth identities: kody-bot (account: 'bot', integration github-bot) is the default for every call; Kent C. Dodds (account: 'kent', integration github-kent) is used only when the user explicitly asks to act as Kent. Agents must not infer Kent from private repos, org access, or “the bot might not have permission.”
When To Use
- Make GitHub REST or GraphQL calls with the correct saved credential (
request,graphql,paginate). - Verify which GitHub identity will perform an action (
get-viewer). - Fetch PR details, CI checks, merge, or change draft/ready status (
pr/*exports). - Create or update GitHub Actions secrets without returning plaintext (
actions/put-secret). - Choose
bot(default) orkent(explicit Kent C. Dodds only).
Required setup
Two user-owned GitHub OAuth connections to the same BYO GitHub OAuth app (not the Kody platform app), both with god-level scopes (gist, notifications, read:org, read:user, repo, user:email, workflow):
github-bot— kody-bot. Default account. Connect while signed into GitHub as kody-bot.github-kent— Kent C. Dodds. Explicit-only account. Connect while signed into GitHub as kentcdodds.
Reconnect: /connect/oauth?provider=github-bot or /connect/oauth?provider=github-kent.
Account guide
| Account | Integration | Default | Use when |
|---|---|---|---|
bot | github-bot | Yes | Every GitHub call unless the user explicitly asks for Kent. |
kent | github-kent | No | Only when the user explicitly asks to use Kent C. Dodds / kentcdodds. |
All PR helpers accept optional account (default 'bot'). PR locators: { prUrl } or { owner, repo, prNumber } (number aliases prNumber).
pr/merge reliability
You do not need to handle slow GitHub merges. pr/merge bounds the direct
merge attempt (default timeoutMs: 25000), and if GitHub's merge endpoint
stalls it escalates to a durable Kody workflow that finishes the merge
idempotently (deduped per owner/repo/PR/head SHA). The call itself stays under
a ~55s total budget and either returns the completed merge or
merge_dispatched with a workflowId — not a problem for the caller to retry.
timed_out_unconfirmed is reserved for the rare case where workflows are
unavailable. Fail-fast preflight still covers already-merged, closed, draft,
dirty, blocked, and not-mergeable PRs; timings includes escalationMs and
totalBudgetMs.
Exports
kody:@kentcdodds/github— package overviewkody:@kentcdodds/github/accounts— account aliases and selection guidancekody:@kentcdodds/github/get-viewer— identity smoke testkody:@kentcdodds/github/graphql— GraphQL helperkody:@kentcdodds/github/paginate— REST pagination helperkody:@kentcdodds/github/request— REST request helper (timeoutMs/signaloptional; no default timeout on reads)kody:@kentcdodds/github/types— shared TypeScript typeskody:@kentcdodds/github/pr/get-info— fetch pull request detailskody:@kentcdodds/github/pr/get-checks— fetch check-run statuskody:@kentcdodds/github/pr/merge— merge a pull request (bounded direct attempt + durable escalation)kody:@kentcdodds/github/pr/merge-durable— durable workflow entry for finishing a slow merge (used bypr/merge)kody:@kentcdodds/github/pr/workflows-probe— smoke-test thatworkflowsis reachable from this package runtimekody:@kentcdodds/github/pr/set-review-status— set draft, ready-for-review, or toggle (status: 'toggle'; mutation bounded bytimeoutMs)kody:@kentcdodds/github/actions/put-secret— create or update a repo or environment Actions secret (sealed-box encrypt; never returns the value)
Dynamic invocation
Prefer static imports (kody:@kentcdodds/github/...) — from execute they
always see the current published version, and from another package they bundle
a snapshot. Use packages.invoke only when the export name is data or you
need this package's own runtime; pass the bare kody id github (see Kody
Dynamic package invocation):
import { packages } from 'kody:runtime'
await packages.invoke({
kodyId: 'github',
exportName: './request',
params: { path: '/repos/kentcdodds/kody', throwOnError: true },
})Do not pass @kentcdodds/github as kodyId. packageId (UUID) also works.
Examples
REST request:
import githubRequest from 'kody:@kentcdodds/github/request'
const response = await githubRequest({
account: 'bot',
path: '/repos/kentcdodds/kody',
throwOnError: true,
})
return response.dataPR info with account:
import getPrInfo from 'kody:@kentcdodds/github/pr/get-info'
return await getPrInfo({
owner: 'kentcdodds',
repo: 'kentcdodds.com',
prNumber: 1,
account: 'bot',
})Merge with structured timeout recovery:
import mergePr from 'kody:@kentcdodds/github/pr/merge'
return await mergePr({
prUrl: 'https://github.com/kentcdodds/kody/pull/969',
mergeMethod: 'squash',
// timeoutMs: 25000 is the default direct-attempt budget
})
// On a slow GitHub merge you may see status: 'merge_dispatched' with workflowId.
// You do not need to retry — the durable workflow finishes the merge.Put a repo Actions secret (plaintext never returned):
import putActionsSecret from 'kody:@kentcdodds/github/actions/put-secret'
return await putActionsSecret({
owner: 'kentcdodds',
repo: 'kody',
name: 'NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN',
generateBytes: 32,
})Report this listing
Log in to report this listing.