This guide walks through a full garth GitHub App setup:
- create the GitHub App with the right permissions
- install it on the repos or owners you need
- store credentials in 1Password
- configure
config.toml(repo root) - validate by minting a token
opinstalled and signed in (op whoamisucceeds)- admin access to create/install a GitHub App for your target repos
garthinstalled (garth setupshould complete)
Open:
https://github.com/settings/apps
Recommended app metadata:
- App name:
<org-or-user>-garth(example:acme-garth) - Description:
GitHub App for garth agent workspaces and short-lived installation tokens
- Homepage URL:
- your repo URL (for example,
https://github.com/ealt/garth)
- your repo URL (for example,
Create a new app with at least:
- Repository permissions:
Contents: Read and writePull requests: Read and writeIssues: Read and writeChecks: Read and writeMetadata: Read-only (default)
- User authorization:
Expire user authorization tokens: keep enabled (checked by default in GitHub UI)
- Webhooks:
- disable unless you explicitly need webhook events
No account or organization permissions are required for basic garth token
minting.
For garth, choose based on where your target repositories live:
- Personal repos only:
Only this accountis fine.
- Personal + organization repos (or multiple orgs):
- choose
Any account.
- choose
If a personal-account-owned app is set to Only this account, it cannot be
installed on organization accounts.
Security note for Any account:
Any accountdoes not grant automatic repo access.- Access still requires explicit installation and approval by the target account or organization owner.
- The main risk increase is blast radius if your app private key is compromised, because more installations could be affected.
Mitigations:
- keep permissions minimal
- keep
Expire user authorization tokensenabled - store app secrets in 1Password and rotate private keys regularly
- install only on accounts/repos you actually need
After creating the app:
- Generate a private key and download the
.pem. - Record the numeric App ID from the app settings page.
- Optional but recommended: also record the Client ID.
You do not need to hand-roll JWTs when using garth; it generates app JWTs and
installation tokens internally.
For troubleshooting and security review, garth follows GitHub's JWT guidance:
alg:RS256iat: set slightly in the past to handle clock driftexp: set to no more than 10 minutes in the futureAuthorizationheader usesBearerfor JWT requestsisscan be App ID or Client ID- current
garthconfig key isapp_id_ref - GitHub recommends using Client ID, but App ID is also supported
- current
Official GitHub reference:
Install the app on the owner/repositories that garth will access.
If you use installation_strategy = "by_owner" (the default), you usually do
not need to configure installation IDs manually.
If you use single or static_map, record the installation ID too.
You can read it from the installation URL, for example:
https://github.com/settings/installations/<INSTALLATION_ID>https://github.com/organizations/<ORG>/settings/installations/<INSTALLATION_ID>
Recommended item type:
Secure Notewith custom fields
garth reads refs with op read op://<vault>/<item>/<field>, so a simple
single item with predictable field labels is the most reliable setup.
Create one item (for example, GitHub App) in your chosen vault.
Recommended field labels:
app-id(text)- numeric GitHub App ID
client-id(text, optional)- optional for future migration;
garthcurrently usesapp_id_ref
- optional for future migration;
private-key(concealed text or text)- paste the PEM content directly in this field
installation-id(text/number, optional forby_owner)- required for
installation_strategy = "single"
- required for
Recommended refs:
op://<VAULT>/GitHub App/app-idop://<VAULT>/GitHub App/private-keyop://<VAULT>/GitHub App/installation-id
If you use field labels with spaces/special characters, prefer field IDs instead of labels.
Useful discovery commands:
op vault list
op item list --vault "<VAULT>"
op item get "GitHub App" --vault "<VAULT>" --format json \
| jq -r '.fields[] | [.label, .id, .type] | @tsv'Edit config.toml in the repo root (this file is gitignored).
[github_app]
app_id_ref = "op://<VAULT>/GitHub App/app-id"
private_key_ref = "op://<VAULT>/GitHub App/private-key"
installation_strategy = "by_owner"
installation_id_ref = ""
installation_id_map = {}Use this when all repos should use one known installation.
[github_app]
app_id_ref = "op://<VAULT>/GitHub App/app-id"
private_key_ref = "op://<VAULT>/GitHub App/private-key"
installation_strategy = "single"
installation_id_ref = "op://<VAULT>/GitHub App/installation-id"
installation_id_map = {}Use this when different owners require different installation IDs.
[github_app]
app_id_ref = "op://<VAULT>/GitHub App/app-id"
private_key_ref = "op://<VAULT>/GitHub App/private-key"
installation_strategy = "static_map"
installation_id_ref = ""
installation_id_map = { "my-org" = "12345678", "my-user" = "87654321" }Also set real API key refs under [agents.*] in the same config file.
From a repo that has a GitHub origin remote:
op whoami
garth token .If token minting succeeds, your GitHub App and 1Password wiring is correct.
"isn't a vault in this account":- The vault name in
op://...does not exist in your account.
- The vault name in
Cannot read app_id_ref/private_key_ref/...during setup:- Vault, item, or field names in refs are wrong.
GitHub API request failed ... 404for/repos/<owner>/<repo>/installation:- App is not installed for that repo/owner.
GitHub API request failed ... 403:- App permissions are too narrow, or installation scope is wrong.
- Token minting fails after private key changes:
- Generate a new private key in GitHub App settings and update
private_key_ref.
- Generate a new private key in GitHub App settings and update