GitHub App credentials
Mjolnir can mint GitHub App installation tokens for bundle repositories. The
private key stays on the Mjolnir controller host, and the controller shares a
cached token across provisioning, resume, running-session credential sync, and
the mj github-token command.
Create and install the App
Section titled “Create and install the App”- In GitHub, create a private GitHub App under your account or organization. See GitHub’s guides for registering an App and choosing permissions.
- Grant repository Contents: Read and write and Metadata: Read-only.
Add Workflows: Read and write only if sessions must push changes to
.github/workflowsfiles. - Install the App on each organization or user account whose repositories Mjolnir should access. Limit the installation to the needed repositories.
- Create a private key for the App and copy its PEM file to the controller
host. Restrict the file to the daemon’s user, for example with
chmod 600. - Record the App ID and, optionally, each installation ID from the App’s installation settings page.
Configure Mjolnir
Section titled “Configure Mjolnir”Add this to the controller’s config.toml:
[github.app]app_id = 1234private_key_path = "/home/mj/.config/mjolnir/github-app.pem"
[github.app.installations]acme = 987654The installation map is optional. When an owner is missing, Mjolnir asks GitHub for the repository or account installation and caches the result. The key path must be readable on the controller host. Restart the daemon after changing the App configuration.
Permission subsets are optional. Each table is a complete grant for its token
type: list every permission the token should receive. Permission names use
GitHub’s permission keys and values are "read" or "write". For example,
sessions can use the listed permissions with read-only statuses, while tokens
from mj github-token receive write access to statuses:
[github.app.session_permissions]contents = "write"pull_requests = "write"issues = "write"workflows = "write"actions = "write"checks = "write"statuses = "read"metadata = "read"
[github.app.token_permissions]contents = "write"pull_requests = "write"issues = "write"workflows = "write"actions = "write"checks = "write"statuses = "write"metadata = "read"Add any other permission keys required by your GitHub App to both tables. When
a table is omitted, Mjolnir does not send a permissions field and GitHub
applies the installation’s full grant. Mjolnir checks configured levels
against the installation and refuses to mint a token if the grant is too
narrow. Repository scoping and permission subsets apply together.
Without [github.app], Mjolnir continues to use GH_TOKEN, GITHUB_TOKEN, or
gh auth token. The private key and installation tokens are not stored in the
database or session checkpoints.
Token scope and session limit
Section titled “Token scope and session limit”Each session can use repositories from one GitHub App installation. Session creation reports an error when its bundle needs more than one installation. Session tokens are limited to the repositories in that bundle; the controller keeps a separate cache entry for each installation and sorted repository set. Tokens refresh when fewer than 10 minutes of validity remain. Running remote and container sessions receive the refreshed token through credential sync. Local bare sessions are not periodically refreshed, so an App token used there expires within at most one hour.
Use the daemon’s shared cache to obtain a token for host-side CI or automation:
export GH_TOKEN="$(mj github-token --owner acme)"gh api /user--owner returns an installation-wide token. Use --repo to restrict a token
to the selected repository, or repeat it to select several repositories from
the same installation:
export GH_TOKEN="$(mj github-token --repo acme/project)"export GH_TOKEN="$(mj github-token --repo acme/project --repo acme/tools)"The command rejects repository sets that span installations.
The command requires a running daemon and a configured App. Its output is a credential: keep it out of logs and discard it when the job finishes.