fabro/docs/integrations/github.mdx
Bryan Helmkamp 7f9f4e964e docs: update CLI reference and GitHub integration for recent changes
Add fabro uninstall, pr create --force, secret list metadata, and
install owner selection to CLI reference. Add GitHub App owner
selection step to integration setup flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:07:28 -04:00

225 lines
10 KiB
Text

---
title: "GitHub"
description: "Integrate Fabro with GitHub for repository access and OAuth login"
---
Fabro supports two GitHub integration strategies:
- `gh_cli` — the default for local and individual use. Fabro captures `gh auth token` during `fabro install`, stores it as `GITHUB_CLI_TOKEN`, and uses that token directly for repo access, pull requests, and sandbox `GITHUB_TOKEN` injection.
- `app` — the team-oriented option. Fabro registers a [GitHub App](https://docs.github.com/en/apps/overview), uses installation tokens for repo access, and enables browser OAuth and webhooks.
`gh_cli` changes GitHub integration auth only. It does not provide browser sign-in, so the embedded web UI is disabled when `strategy = "gh_cli"`.
## Strategy matrix
| Capability | `gh_cli` | `app` |
|---|---|---|
| CLI pull requests | Yes | Yes |
| Private repo cloning | Yes | Yes |
| Sandbox `GITHUB_TOKEN` | Direct CLI token | Scoped installation token |
| Browser sign-in | No | Yes |
| Web UI routes | Disabled | Enabled |
| Webhooks | No | Yes |
## GitHub App mode
The rest of this page describes the `app` strategy, which is required for browser auth and webhooks.
| Feature | How it's used |
|---|---|
| **OAuth login** | Users sign in to the web UI with their GitHub account |
| **Private repo cloning** | Daytona and Docker sandboxes clone private repositories using short-lived Installation Access Tokens |
| **Checkpoint pushing** | After each workflow stage, Fabro pushes the run branch and metadata branch back to origin from inside the sandbox |
| **Auto-PR** | When `[run.pull_request] enabled = true` in the [run config](/execution/run-configuration#runpull_request), Fabro opens a PR from the agent's working branch after a successful run |
| **Auto-merge** | When `[run.pull_request] auto_merge = true`, Fabro enables GitHub's auto-merge on created PRs so they merge automatically once required checks pass |
| **Sandbox GITHUB_TOKEN** | When `[server.integrations.github.permissions]` are declared in the server config, Fabro mints a scoped Installation Access Token and injects it as `GITHUB_TOKEN` in the sandbox |
## Setup
### Prerequisites
- A GitHub account (personal or organization)
- The Fabro web app running (`cd apps/fabro-web && bun run dev`)
### Register the GitHub App
1. Navigate to the web app (default `http://localhost:3000`). If no GitHub App is configured, you'll be redirected to the setup page automatically.
2. Choose where to register the app. If you have the `gh` CLI installed, Fabro detects your GitHub username and any organizations you administer and lets you pick. For organization-owned apps, the app is registered under that org's settings. If `gh` is not available, the app is registered under your personal account.
3. Click **Register GitHub App**. This takes you to GitHub with a pre-filled [App Manifest](https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest) containing:
| Permission | Level | Purpose |
|---|---|---|
| Contents | Write | Clone repos, push run branches and checkpoints |
| Metadata | Read | Look up repository installation status |
| Pull requests | Write | Create and update PRs from workflows |
| Checks | Write | Report workflow status on commits |
| Issues | Write | Create issues from workflows |
| Emails | Read | Read verified email for OAuth login |
4. Review the permissions on GitHub and click **Create GitHub App**.
5. GitHub redirects back to Fabro, which automatically:
- Exchanges the temporary code for permanent app credentials
- Writes `app_id`, `client_id`, and `slug` to `~/.fabro/settings.toml`
- Stores `GITHUB_APP_CLIENT_SECRET`, `GITHUB_APP_WEBHOOK_SECRET`, and `GITHUB_APP_PRIVATE_KEY` in `<data_dir>/server.env`
- Marks the change as restart-bound so the server must be restarted before login
6. **Install the app** on your GitHub account or organization. Go to `https://github.com/settings/apps/<your-app-slug>/installations` and install it on the repositories Fabro should access.
### Verify the configuration
Run the doctor command to check that all GitHub App credentials are in place:
```bash
fabro doctor
```
The GitHub App check verifies five fields:
| Field | Source |
|---|---|
| `server.integrations.github.app_id` | `~/.fabro/settings.toml` |
| `server.integrations.github.client_id` | `~/.fabro/settings.toml` |
| `GITHUB_APP_CLIENT_SECRET` | `<data_dir>/server.env` |
| `GITHUB_APP_WEBHOOK_SECRET` | `<data_dir>/server.env` |
| `GITHUB_APP_PRIVATE_KEY` | `<data_dir>/server.env` |
If all five are set, the check passes. If none are set, it warns (GitHub integration is optional). If some are set but others are missing, it errors with the specific missing fields.
## Configuration
The GitHub App configuration lives in two places:
### `~/.fabro/settings.toml`
```toml title="settings.toml"
[server.integrations.github]
app_id = "123456"
client_id = "Iv1.abc123def"
slug = "fabro-a3f2"
```
| Field | Description |
|---|---|
| `app_id` | Numeric GitHub App ID |
| `client_id` | OAuth Client ID for the app |
| `slug` | App slug, used for linking to the GitHub App settings page |
### `server.env`
Fabro stores the GitHub App secrets in `<data_dir>/server.env` under these keys:
- `GITHUB_APP_CLIENT_SECRET`
- `GITHUB_APP_WEBHOOK_SECRET`
- `GITHUB_APP_PRIVATE_KEY`
The private key is stored as base64-encoded PEM. Fabro also accepts raw PEM format (starting with `-----BEGIN`).
## `gh_cli` mode
Choose **GitHub CLI** in `fabro install` to use the default local-user flow. The installer:
1. Runs `gh auth token`
2. Stores the token as `GITHUB_CLI_TOKEN`
3. Writes `strategy = "gh_cli"` under `[server.integrations.github]`
In this mode, Fabro disables the embedded web UI and browser auth routes. Machine API routes and `/health` continue to work.
## How it works
### OAuth login
The web app uses the GitHub App's OAuth credentials to authenticate users:
1. User clicks **Sign in with GitHub** on the login page
2. Fabro redirects to GitHub's OAuth authorization endpoint with scopes `read:user` and `user:email`
3. User authorizes the app on GitHub
4. GitHub redirects back with an authorization code
5. Fabro exchanges the code for an access token and fetches the user's profile and verified email
6. Fabro checks the username against the `allowed_usernames` list in `settings.toml`
Configure allowed users in `settings.toml`:
```toml title="settings.toml"
[web.auth]
provider = "github"
allowed_usernames = ["alice", "bob"]
```
An empty `allowed_usernames` list rejects all users.
### Repository cloning in sandboxes
When a workflow runs in a remote sandbox (Daytona or Docker), Fabro clones the current repository into the sandbox using the GitHub App:
1. Fabro detects the local repository's `origin` remote URL and current branch
2. SSH URLs (e.g. `git@github.com:owner/repo.git`) are converted to HTTPS
3. Fabro signs a short-lived JWT using the App ID and private key (RS256, 10-minute validity)
4. Using the JWT, Fabro looks up the GitHub App installation for the repository (`GET /repos/\{owner\}/\{repo\}/installation`)
5. Fabro requests a scoped Installation Access Token with `contents: write` permission on the specific repository
6. The sandbox clones via HTTPS using `x-access-token` as the username and the token as the password
For public repositories, the clone works without credentials. The token is still generated because it's needed for pushing checkpoints.
### GITHUB_TOKEN injection
When a run config declares `[github] permissions`, Fabro mints a scoped Installation Access Token at startup and injects it into the sandbox as the `GITHUB_TOKEN` environment variable. Agents running inside the sandbox can use this token for GitHub API calls, cloning additional private repos, or pushing to branches.
```toml title="run.toml"
[github]
permissions = { contents = "write", pull_requests = "write" }
```
Only the listed permissions are requested — the token is scoped to the minimum access needed. If the GitHub App isn't configured or the repository lacks an installation, the run logs a warning and continues without the token.
This also works in `.fabro/project.toml` as a project-level default, so all workflows in the project automatically get a `GITHUB_TOKEN` without repeating the config in each run TOML.
### Checkpoint pushing
After each workflow stage, Fabro [checkpoints](/execution/checkpoints) by pushing the run branch and metadata branch to origin. Inside remote sandboxes, the git remote URL is configured with the Installation Access Token for authenticated pushing.
For long-running workflows, Fabro refreshes the token before each push since Installation Access Tokens are short-lived (typically 1 hour).
## Troubleshooting
### "GitHub App is not installed for \{owner\}"
The GitHub App exists but hasn't been installed on the organization or user account that owns the repository. Install it at:
```
https://github.com/organizations/{owner}/settings/installations
```
Or for personal accounts:
```
https://github.com/settings/installations
```
### "GitHub App is private but this repo belongs to a different owner"
GitHub Apps are **private by default**, meaning they can only be installed on repositories owned by the same account or organization that owns the app. If you need to install the app on a repository owned by a different user or organization, you must make the app public:
1. Go to **GitHub → Settings → Developer settings → GitHub Apps → \{your app\}**
2. Scroll to the bottom under **Danger zone**
3. Click **Make public**
Once the app is public, anyone with the installation link can install it on their repositories. This does not grant the app any additional permissions — repository owners still choose which repositories the app can access during installation.
### "GitHub App installation is suspended"
The installation was disabled in GitHub's settings. Re-enable it in the organization's GitHub App settings.
### "GitHub App does not have access to repository \{repo\}"
The app is installed but doesn't have access to this specific repository. Update the installation's repository permissions to include it (the app may be configured for "Only select repositories").
### "GitHub App authentication failed"
The `app_id` in `settings.toml` or the `GITHUB_APP_PRIVATE_KEY` environment variable is incorrect. Re-run the setup flow or verify the values match your GitHub App.
### Clone fails for private repositories
If you see `Git clone failed ... If this is a private repository, configure a GitHub App`, the GitHub App credentials are not configured. Run the setup flow through the web UI or verify with `fabro doctor`.