GitHub App Configuration Guide
Cloud Harness MCP uses a GitHub App integration to clone private repositories and execute origin-only pushes (git_push) without storing long-lived personal access tokens or SSH private keys inside container environments.
A GitHub App is optional. Without one, GitHub operations resolve an operator-supplied fallback credential instead: GH_TOKEN then GITHUB_TOKEN from the runner environment (owner-bearer mode only), or a global runtime secret named GH_TOKEN/GITHUB_TOKEN held by the requesting principal. See GitHub credential fallback below.
GitHub credential fallback
Use this when you want GitHub operations without registering a GitHub App.
Resolution order for github_action and private Git operations (clone, fetch, pull, push):
- A GitHub App repository-scoped token, when an App is configured and authorized.
GH_TOKEN, thenGITHUB_TOKEN, from the runner process environment (each also accepting a_FILEform). This source is honored only inowner-bearermode.- An active global runtime secret named
GH_TOKEN, thenGITHUB_TOKEN, held by the requesting principal.
In cloudflare-access mode step 2 is refused entirely: a single operator-wide credential must never stand in for a different principal's App grant. Use step 3 there.
Setting the runner environment credential:
# In the runner's environment file (e.g. .env). Read GH_TOKEN first, then GITHUB_TOKEN.
GH_TOKEN=github_pat_...Or create it in the dashboard under Secrets, which requires no restart and is scoped per principal.
Behavior notes:
- A value that cannot be a GitHub credential (shorter than 20 characters, or containing whitespace) is ignored rather than sent to GitHub.
- Resolved credentials are passed over
stdinto ephemeral helpers and are registered with the ingest-time redactor. They are never written to results, logs, audit payloads, or the Git remote. workspace_capabilitiesreports GitHub read/write capability when either an App or a fallback credential is available.- A personal access token is not repository-scoped and cannot be limited by an installation grant. Prefer a GitHub App, or the narrowest fine-grained token.
- The environment credential authenticates harness-side operations only; it is never placed in an executor environment. To authenticate the workspace's own
ghCLI, create a global runtime secret namedGH_TOKEN/GITHUB_TOKEN(see Secrets & Credentials).
How It Works
[ AI Agent in Executor Container ]
│
│ 1. Calls git_push / workspace_open
▼
[ Trusted Runner Daemon ]
│ 2. Exchanges App Private Key for a 10-minute repository token
▼
[ GitHub App Broker ] ──(token over STDIN)──► [ Ephemeral Git Helper ]
│
│ 3. Pushes to github.com
▼
[ GitHub Private Repo ]- Ephemeral Access: The token is valid for only 10 minutes and strictly scoped to the repository being operated on.
- Never Saved to Disk: The token is streamed over
stdindirectly into Git's credential helper and is never written to.git/configor workspace files. - Executor Confinement: The container running your agent code has zero access to the GitHub App private key or control-plane credentials.
Step 1: Decide Required Permissions
Before creating the App in GitHub, choose the minimum required permission level:
| Goal | Required Permission |
|---|---|
| Clone, fetch, and pull private repos | Contents: Read-only |
| Push ordinary code & branch commits | Contents: Read and write |
Push CI/CD workflows (.github/workflows/) | Contents: Read and write + Workflows: Read and write |
Read issues and pull requests through github_read/github_action | Issues: Read-only + Pull requests: Read-only + Contents: Read-only |
Create or update issues and pull requests through github_action | Issues: Read and write + Pull requests: Read and write + Contents: Read-only |
List/compare commits, releases, and tags through github_read/github_action | Contents: Read-only |
Principle of Least Privilege
Leave every other repository, organization, and user permission set to No access.
github_action always carries Contents: Read-only on its token, because gh resolves repository metadata over the GraphQL API; an App that grants only the issue and pull-request permissions cannot mint an action-scoped token.
Step 2: Register the GitHub App
- Open your GitHub account:
- For a personal account: Go to github.com/settings/apps.
- For an organization: Go to
https://github.com/organizations/<YOUR_ORG>/settings/apps.
- Click New GitHub App.
- Fill in the basic details:
- GitHub App name:
Cloud-Harness-<YourName>(must be globally unique across GitHub). - Homepage URL:
https://harness.agentkit.best(or your repository URL). - Callback URL: Leave empty (unless using Access SSO OAuth redirect).
- Setup URL: Leave empty.
- GitHub App name:
- Webhook:
- Uncheck Active under the Webhook section (Cloud Harness does not require webhooks).
- Repository permissions:
- Set Contents to Read and write (or Read-only).
- (Optional) Set Workflows to Read and write if your agents need to edit GitHub Actions.
- Where can this GitHub App be installed?:
- Select Only on this account.
- Click Create GitHub App.
Step 3: Download Private Key & Note IDs
After creating the App:
- App ID: Copy the numeric App ID displayed at the top of the General settings page (e.g.
123456). - App Slug / Name: Note the URL slug of your app (e.g.
cloud-harness-operator). - Generate Private Key:
- Scroll down to the Private keys section.
- Click Generate a private key.
- A
.pemfile will automatically download to your machine. Keep this file secure; GitHub does not store it.
Step 4: Install App on Selected Repositories
In your GitHub App settings, click Install App in the left sidebar.
Click Install next to your account or organization.
Choose Only select repositories.
Select the private repositories you want Cloud Harness agents to access.
Click Install.
After installation, GitHub redirects to a settings page URL such as:
texthttps://github.com/settings/installations/78901234The trailing number (
78901234) is your Installation ID.
Step 5: Configure the Server Environment
On your Cloud Harness production server or VPS:
1. Secure the Private Key File
Place the downloaded .pem file on the host filesystem with strict root permissions:
sudo install -d -m 700 -o root -g root /etc/cloud-harness-mcp
sudo install -m 600 -o root -g root /path/to/downloaded-key.pem /etc/cloud-harness-mcp/github-app-private-key.pem2. Update Environment Variables (.env)
In your server's .env or /etc/cloud-harness-mcp/runtime.env:
# Your numeric GitHub App ID
GITHUB_APP_ID=123456
# In owner-bearer mode: provide the numeric installation ID
GITHUB_APP_INSTALLATION_ID=78901234
# In cloudflare-access mode: provide the app slug for dashboard linking
GITHUB_APP_SLUG=cloud-harness-operator
# Container mount path to the private key (inside the runner)
GITHUB_APP_PRIVATE_KEY_FILE=/run/cloud-harness-secrets/github-app-private-key.pem3. Restart the Runner
Restart containers so the runner picks up the new configuration:
docker compose down && docker compose up -dStep 6: Link in Operator Dashboard
- Open the Operator Dashboard at
https://harness.zuey.me/dashboard. - Navigate to GitHub in the left navigation rail.
- If not already bound, click Install / Link GitHub App.
- Authorize the application. The dashboard will display your active installation ID and bound repositories.
Step 7: Verify Private Repository Access
Test opening a private repository through your AI client (Cursor, Claude Code, etc.):
// Tool: workspace_open
{
"repositoryUrl": "https://github.com/my-org/private-repo.git",
"idempotencyKey": "test-github-app-01"
}Confirm
workspace_statusreturnsstatus: "ready".Test committing and pushing on a disposable branch:
json// Tool: git_push { "workspaceId": "ws_...", "refspec": "HEAD:refs/heads/feature/test-branch" }
Troubleshooting
| Issue | Cause | Resolution |
|---|---|---|
Repository clone failed: unauthorized (404/401) | Repository not selected in GitHub App installation. | Go to github.com/settings/installations, click Configure on your App, and add the repository to Repository access. |
Push failed: 403 Forbidden | App has Read-only permissions for Contents. | In App settings → Permissions, change Contents to Read and write. Then accept the permission update under your installation settings. |
Push touching workflows failed: 403 | Missing Workflows permission when editing .github/workflows/*. | Add Workflows: Read and write to Repository Permissions in GitHub App settings. |
Token minting: UNAVAILABLE | App ID or Private Key mismatch. | Verify GITHUB_APP_ID matches GitHub App ID, and that the .pem file corresponds to that exact App. |
| Key rotation | Need to rotate an existing key. | Generate a second key in GitHub first, update the .pem file on host, restart runner, then delete the old key in GitHub. |
Where this page lives now
GitHub authorization lives on the Integrations page. The rail links to Integrations, which is also served at /dashboard/integrations/github; /dashboard/github still works and redirects there, so existing bookmarks and documentation links keep resolving. MCP server connections have their own rail entry, MCP Servers.