GitHub Plugin
Use the GitHub plugin when Junior should work in repositories through a GitHub App: issues, pull requests, reviews, branch pushes, workflow dispatches, reruns, and cancellations, deployment and release lookups, and resource subscriptions.
Junior uses the App installation for bot-owned work. Human OAuth is only for operations that must run as the requesting user, such as user-attachment uploads.
1. Install
Section titled “1. Install”pnpm add @sentry/junior @sentry/junior-github2. Register the plugin
Section titled “2. Register the plugin”import { defineJuniorPlugins } from "@sentry/junior";import { githubPlugin } from "@sentry/junior-github";
export const plugins = defineJuniorPlugins([ githubPlugin({ botNameEnv: "GITHUB_APP_BOT_NAME", botEmailEnv: "GITHUB_APP_BOT_EMAIL", }),]);The factory registers the GitHub manifest, bundled skills, and Git commit attribution hooks. Do not register this plugin as a bare package-name string.
Optional: declare appPermissions to match the App permissions approved in
GitHub. Junior uses that declaration when downscoping read tokens; it does not
narrow write tokens.
3. Create the GitHub App
Section titled “3. Create the GitHub App”- Create a GitHub App and generate a private key.
- Grant repository permissions:
- Actions: Read and write
- Checks: Read
- Contents: Read and write
- Deployments: Read
- Issues: Read and write
- Metadata: Read
- Pull requests: Read and write
- Workflows: Write
- Install the App on the organization or repositories Junior should reach.
- Copy the App ID, OAuth client ID and secret, installation ID, bot name, and bot noreply email into your deployment environment.
If Junior should receive resource events or report PR/issue outcomes, also:
- Set the webhook URL to
https://<your-domain>/api/webhooks/github. - Set the webhook secret to the same value as
GITHUB_WEBHOOK_SECRET. - Subscribe the App to: Check suite, Deployment, Deployment status, Issues, Issue comment, Pull request, Pull request review, Pull request review comment, and Release.
Keep the App writable if Junior should create issues, push branches, or open pull requests. Junior scopes write tokens to the target repository and still denies unsupported writes through the egress allowlist.
Install the App only on repositories where Junior may push. Protect important
branches in GitHub. Across many repositories, users should include owner/repo
when the target is not obvious, and those repositories must share the same
installation ID.
Config
Section titled “Config”Set conversation config with jr-rpc config set, or define the same keys for every conversation with createApp({ configDefaults }). Pass factory options to githubPlugin({ ... }) in plugins.ts. Set the named deployment variables, then redeploy. Explicit repositories in requests always win over defaults.
Conversation defaults
Section titled “Conversation defaults”github.org
Default GitHub organization or owner when a request does not name one.
- Define:
jr-rpc config set github.org <owner> - Install-wide default:
configDefaults["github.org"] - Required: No
- Environment override: None
github.repo
Default repository in owner/repo form when a request does not name one.
- Define:
jr-rpc config set github.repo <owner/repo> - Install-wide default:
configDefaults["github.repo"] - Required: No
- Environment override: None
Plugin options
Section titled “Plugin options”appPermissions
GitHub App permissions Junior may downscope to read for installation read tokens. Write tokens retain the App installation’s full permission envelope.
- Define:
githubPlugin({ appPermissions: { contents: "write", issues: "write" } })inplugins.ts - Required: No
- Environment override: None
additionalUserScopes
Extra OAuth scopes requested for operations that must run as the user.
- Define:
githubPlugin({ additionalUserScopes: ["scope"] })inplugins.ts - Required: No
- Environment override: None
pullRequestEvents
App-configured pull request event behavior. Use this only when the app should always watch certain events after Junior creates a pull request, or should add short guidance when those events arrive.
export const plugins = defineJuniorPlugins([ githubPlugin({ pullRequestEvents: { subscribeAfterCreate: { events: [ "pull_request.checks.failed", "pull_request.review.changes_requested", "pull_request.merged", ], intent: "Report failed checks and requested changes. Report when the pull request merges. Stay silent otherwise.", }, guidance: { "pull_request.checks.failed": "Inspect the failed checks. Fix failures caused by this change when safe.", "pull_request.review.changes_requested": "Summarize actionable feedback before deciding whether to edit code.", }, }, }),]);- Define:
githubPlugin({ pullRequestEvents: { ... } })inplugins.ts - Default: Off. Junior only watches a new pull request when asked, or when a tool result includes a subscribable resource and the model chooses to watch it.
- Required: No
- Environment override: None
subscribeAfterCreate creates a temporary resource subscription after a successful github_createPullRequest call. It only runs in Slack conversations that can host resource subscriptions, and only when GitHub webhooks are enabled. Forced events are removed from the tool result’s suggested events so the model does not re-watch them. The subscription still expires like any other watch.
guidance adds short app guidance when a matching pull request event reaches the agent. It applies within the subscription or event task instruction. It cannot replace or expand that instruction, grant credentials, or bypass action review. Keep each value short.
appIdEnv
Names the deployment variable containing the GitHub App ID.
- Define:
githubPlugin({ appIdEnv: "GITHUB_APP_ID" })inplugins.ts - Default:
GITHUB_APP_ID - Required: Yes
- Environment variable: The variable named by this option
clientIdEnv
Names the deployment variable containing the GitHub App OAuth client ID.
- Define:
githubPlugin({ clientIdEnv: "GITHUB_APP_CLIENT_ID" })inplugins.ts - Default:
GITHUB_APP_CLIENT_ID - Required: Yes
- Environment variable: The variable named by this option
clientSecretEnv
Names the deployment variable containing the GitHub App OAuth client secret.
- Define:
githubPlugin({ clientSecretEnv: "GITHUB_APP_CLIENT_SECRET" })inplugins.ts - Default:
GITHUB_APP_CLIENT_SECRET - Required: Yes
- Environment variable: The variable named by this option
privateKeyEnv
Names the deployment variable containing the GitHub App private key.
- Define:
githubPlugin({ privateKeyEnv: "GITHUB_APP_PRIVATE_KEY" })inplugins.ts - Default:
GITHUB_APP_PRIVATE_KEY - Required: Yes
- Environment variable: The variable named by this option
installationIdEnv
Names the deployment variable containing the GitHub App installation ID.
- Define:
githubPlugin({ installationIdEnv: "GITHUB_INSTALLATION_ID" })inplugins.ts - Default:
GITHUB_INSTALLATION_ID - Required: Yes
- Environment variable: The variable named by this option
botNameEnv
Names the deployment variable containing Junior’s Git author and committer name.
- Define:
githubPlugin({ botNameEnv: "GITHUB_APP_BOT_NAME" })inplugins.ts - Default:
GITHUB_APP_BOT_NAME - Required: Yes
- Environment variable: The variable named by this option
botEmailEnv
Names the deployment variable containing Junior’s Git author and committer email.
- Define:
githubPlugin({ botEmailEnv: "GITHUB_APP_BOT_EMAIL" })inplugins.ts - Default:
GITHUB_APP_BOT_EMAIL - Required: Yes
- Environment variable: The variable named by this option
Use <bot-user-id>+<app-slug>[bot]@users.noreply.github.com. Get the bot user ID from https://api.github.com/users/<app-slug>%5Bbot%5D.
Environment variables
Section titled “Environment variables”GITHUB_WEBHOOK_SECRET
Webhook signing secret for resource events and PR or issue outcome reporting.
- Define: Set
GITHUB_WEBHOOK_SECRETin the deployment environment - Required: Yes for resource events and outcome reporting; otherwise no
- Environment override:
GITHUB_WEBHOOK_SECRET
Run migrations
Section titled “Run migrations”pnpm exec junior upgradeThis creates the junior_github_pull_requests and junior_github_issues
projections used by webhook ingestion and outcome tracking. Opened pull
requests also publish native code-change records for the dashboard Code page
and person profiles.
Capabilities
Section titled “Capabilities”Once configured, Junior can:
- Create, update, and comment on issues and pull requests
- Review pull requests and leave inline review comments as the App bot
- Push branches and open draft pull requests
- Dispatch workflows, rerun workflow runs or jobs, and cancel workflow runs
- Look up deployments and releases
- Watch or automate matching resource events when webhooks are enabled
Bot-owned writes use installation credentials. Personal operations still use private user authorization when required. Merge remains outside the write allowlist.
Resource subscriptions
Section titled “Resource subscriptions”Set GITHUB_WEBHOOK_SECRET to enable resource events. See
Resource Subscriptions for temporary
resource subscriptions versus durable event tasks.
Issue and pull request events can target one item with owner/repo#number, or
every item of that kind in a repository with owner/repo.
To always watch selected events after Junior creates a pull request in this
app, set pullRequestEvents.subscribeAfterCreate in plugins.ts. To add short
app guidance for one pull request event type, set
pullRequestEvents.guidance. The guidance applies within each subscription or
event task instruction. It does not replace or expand that instruction.
deployment_source
Section titled “deployment_source”One commit, optionally limited to an environment. Identifier:
deployment-source:owner/repo[:environment]:<full-commit-sha>.
deployment.created
A deployment was created.
deployment.queued
The deployment entered the queue.
deployment.pending
The deployment is waiting to start.
deployment.in_progress
The deployment started.
deployment.succeeded
The deployment completed successfully.
deployment.failed
The deployment failed.
deployment.error
The deployment reported an error.
One issue: owner/repo#number.
issue.comment.created
A comment was added.
issue.opened
The issue was opened.
issue.closed
The issue was closed.
issue.reopened
The issue was reopened.
pull_request
Section titled “pull_request”One pull request: owner/repo#number.
pull_request.checks.failed
A check suite finished with failure or timeout. Trusted data includes the full head SHA, suite id/url, optional headBranch, the PR number when one is attached, and failed check-run ids/urls when Junior can load them. Failed check names are untrusted provider content. Suites with no pull request publish only to the repository. When a watch or event task uses isDraft, authorUsername, or authorEmail, Junior loads those pull request fields for same-repo pull requests only. headBranch comes from the webhook and does not need that load.
pull_request.checks.recovered
A check suite finished successfully after a failure. Trusted data includes the full head SHA, suite id/url, optional headBranch, and the PR number when one is attached. This is for one suite only. It does not mean the whole PR or branch is green. Suites with no pull request publish only to the repository. When a watch or event task uses isDraft, authorUsername, or authorEmail, Junior loads those pull request fields for same-repo pull requests only. headBranch comes from the webhook and does not need that load.
pull_request.comment.created
A conversation comment was added.
pull_request.opened
The pull request was opened.
pull_request.ready_for_review
The pull request became ready for review.
pull_request.review.approved
A reviewer approved the pull request.
pull_request.review.changes_requested
A reviewer requested changes.
pull_request.review.commented
A reviewer submitted a comment-only review.
pull_request.review_comment.created
An inline review comment was added.
pull_request.merged
The pull request was merged.
pull_request.closed_unmerged
The pull request closed without merging.
release_source
Section titled “release_source”One repository, optionally limited to a tag. Identifier:
release-source:owner/repo[:tag].
release.published
A release was published.
repository
Section titled “repository”Every issue and pull request in owner/repo. Supports the same issue and
pull_request events listed above. Check suites with no pull request also
publish here, so you can match branch builds with headBranch.
Verify
Section titled “Verify”Create a GitHub issue in owner/repo titled "Junior GitHub plugin check" with body "Verification run"Confirm:
- The issue lands in the expected repository.
- The author is the App bot, and the body includes
Requested byattribution. - A follow-up can update or comment on the same issue without manual tokens.
- A pushed branch can become a draft PR with
github_createPullRequest. - If webhooks are enabled, ask Junior to watch a PR or deployment and confirm a
matching GitHub delivery to
/api/webhooks/githubproduces the expected Slack follow-up.
A local git commit does not call GitHub. The write happens on push. Grant
Workflows: write when Junior may change files under .github/workflows.
Failure modes
Section titled “Failure modes”Access denied: install the App on the target repository or organization.Bad credentialsor signing errors:GITHUB_APP_PRIVATE_KEYdoes not matchGITHUB_APP_ID.- Junior never offers to watch a PR, release, or deployment:
GITHUB_WEBHOOK_SECRETis missing, or the App webhook is not subscribed to the needed event. Set the secret, fix the subscription, redeploy, and retry. github_getDeploymentreturns403: grantDeployments: read, approve the permission on the installation, and retry.- Webhook delivery returns
401: the App webhook secret does not matchGITHUB_WEBHOOK_SECRET, orX-Hub-Signature-256is missing. - Webhook delivery returns
202 Ignored: wrong installation, or an unsupported event mapping. ConfirmGITHUB_INSTALLATION_IDand the event type. - Delivery succeeds but nothing appears in Slack: create a resource subscription or event task first. A webhook alone does not create either one.
- Missing repository context: include
owner/repo, or set a thread default repository. - A
403that namesgithub_createIssue,github_updateIssue,github_createPullRequest, orgithub_updatePullRequestis a Junior routing denial. Retry with the named tool. - Private OAuth prompt for a personal operation: complete the private authorization prompt. Do not paste personal access tokens into chat.
- Permission failures on issue or PR workflows: update App permissions or the install target, then retry.
Next step
Section titled “Next step”Read Plugin Auth & Context for the public auth and target-context model.