This guide is for a self-hosted Open Mission installation that needs unattended GitHub access.
The ownership split is:
- browser OAuth login is user-scoped and interactive
- GitHub App credentials are system-scoped for one Open Mission installation
- GitHub App installation binding is Repository-scoped authorization for unattended operations
See ADR 0004.05 for the governing rule.
What You Need
- a GitHub organization or user account that will own the GitHub App
- admin access to create and install that GitHub App
- a self-hosted Open Mission installation
- Node 24 and the
open-missionCLI installed locally
1. Create A GitHub App
In GitHub:
- Open organization or user settings.
- Go to
Developer settings. - Choose
GitHub Apps. - Select
New GitHub App.
Recommended initial settings:
- App name: a deployment-specific name such as
open-mission-acme-local - Homepage URL: the local or internal URL used to access your Open Mission web host
- Callback URL: the Open Mission GitHub OAuth callback URL if you also want browser login through this app
- Webhook: optional for the first unattended-access wave
Recommended initial repository permissions for unattended Repository delivery:
- Contents:
Read and write - Pull requests:
Read and write - Issues:
Read and writeif Open Mission will create or update issues - Metadata:
Read-only
Add only the minimum permissions your installation needs.
2. Collect The App Credentials
From the GitHub App settings page, collect:
- App ID
- Client ID
- Client secret
Then generate and download a private key from the GitHub App settings page.
Important split:
GITHUB_APP_PRIVATE_KEYis used by the daemon to mint installation access tokensGITHUB_APP_CLIENT_SECRETis used for user OAuth login through the web host
They are different credentials and are not interchangeable.
3. Install The GitHub App On Repositories Or Organizations
Install the GitHub App on the organization or repositories Open Mission should manage.
This installation step is what gives GitHub an installation id and grants repository access. Open Mission should later bind that installation to specific Repository records for unattended actions.
4. Configure Environment Variables For Open Mission
Provide these variables in the shell, container environment, or service manager that launches Open Mission.
Required for unattended GitHub App installation auth:
export GITHUB_APP_ID="1234567"
export GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"
Optional but recommended when the same GitHub App also handles browser login:
export GITHUB_APP_CLIENT_ID="Iv1.abcdef1234567890"
export GITHUB_APP_CLIENT_SECRET="your-client-secret"
Optional for webhook verification later:
export GITHUB_APP_WEBHOOK_SECRET="your-webhook-secret"
If you store the private key in a single-line env value, newline escapes are supported:
export GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
The daemon-side installation token provider in packages/core/src/platforms/GitHubAppTokenProvider.ts reads GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY, generates a GitHub App JWT, exchanges it for an installation access token, and caches that installation token until it is close to expiry.
5. Bind Each Repository To Its GitHub App Installation
After Open Mission is running with the GitHub App environment variables set:
- Sign in to Open Mission through GitHub in the browser.
- Open or add the Repository you want to authorize for unattended GitHub work.
- Invoke the Repository
bindGitHubAppInstallationmutation.
Current behavior:
- the binding discovery uses the signed-in user’s GitHub OAuth token
- Open Mission discovers which installed GitHub App installation can access that Repository
- the Repository stores the resulting installation binding as Repository-owned authorization state
This binding is distinct from deployment credentials. The Repository stores only the installation id and related authorization facts, not the GitHub App private key.
At the current implementation stage, this binding step exists at the Repository entity boundary. open-mission install does not perform it for you.
6. Run Open Mission Installation
open-mission install configures local non-secret Open Mission settings such as repository and mission roots.
Run:
open-mission install
or for one-shot startup:
open-mission
What open-mission install does today:
- ensures Open Mission config exists
- prompts for repository and mission roots when needed
- records non-secret config in the Open Mission config file
What it does not do today:
- create a GitHub App for you
- upload or persist GitHub App secrets into Open Mission config
- complete Repository installation binding automatically
7. Verify The Running Installation
Start Open Mission in the same environment where the GitHub App variables are set.
open-mission
For local development with this repository, .env.example shows the supported GitHub App variables in /.env.example.
Current State Of The Implementation
Implemented now:
- browser login can use
GITHUB_APP_CLIENT_IDandGITHUB_APP_CLIENT_SECRET - daemon-side GitHub App installation token minting uses
GITHUB_APP_IDandGITHUB_APP_PRIVATE_KEY - Repository-owned installation binding storage and configuration exist
- Repository
bindGitHubAppInstallationcan discover and persist the binding from a signed-in GitHub user session - unattended Repository reads, writes, and setup pull request automation can run through the stored Repository binding
Not fully implemented yet:
- a polished operator-facing UI flow for binding and re-binding installations
- any fully automatic installation-binding step inside
open-mission install
So the core Repository authorization flow now exists, but the surrounding operator ergonomics are still a follow-up.