GitHub integration
Link pull requests to Multica issues and watch development progress from the issue.
Once GitHub is connected, Multica automatically links pull requests based on issue identifiers. Issue detail shows PR state, change size, CI results, and merge conflicts in place.
The GitHub integration only reads the repositories authorized at install time; it never pushes commits, comments, or status checks.
Self-hosted Multica can also connect self-hosted Forgejo, Gitea, or GitLab instances in parallel, with the same PR auto-linking, merge-driven status changes, and CI display. The entry point is Settings → Code; see Self-hosted Git hosting. Multica Cloud does not offer this entry point.
Connect GitHub
A workspace owner or admin can complete the connection:
- Open Settings → Code.
- In the GitHub row, click Connect GitHub.
- In GitHub, pick the account or organization and authorize all repositories or a chosen subset.
- Return to Multica after the installation completes.
The connection status shows on the same page. Regular members can view the status but can't connect, disconnect, or change the switches.
The GitHub connection decides which repositories Multica receives PR events from; the code repositories setting decides which repositories agents can pick when starting runs. They serve different purposes and are configured separately.
Feature switches
The Pull requests & issues section of Settings → Code has these settings. Pause GitHub features in the GitHub row's ⋯ menu stops the three switches below without disconnecting the GitHub App.
| Switch | Effect |
|---|---|
| PR sidebar | Shows linked pull requests in issue detail. |
| Co-authored-by | Adds Co-authored-by: multica-agent <github@multica.ai> to commits created by agents. |
| Auto-link PRs | Links a PR to the issue whose identifier is in its branch name or title, or follows a closing keyword in its body. |
| After PRs merge, move the issue to | What merging every PR linked to an issue does: move it to a status (Done by default) or leave it alone. See When merged PRs move an issue. |
| PR card → CI & mergeability | For each linked PR, Multica fetches an authenticated GitHub API snapshot and mirrors its CI status and mergeability onto the card (see What the PR card shows below). |
After PRs merge, move the issue to applies to every code host, including self-hosted Git hosting.
Link a PR to an issue
The simplest approach is to put the issue identifier in the branch name or PR title. For example, for issue MUL-123:
mul-123-fix-login-redirectMUL-123 Fix the redirect after loginMultica ignores case and only matches the current workspace's issue prefix. One PR can link to multiple issues.
If the identifier appears only in the PR body, put it right after a closing keyword:
Closes MUL-123
Fixes MUL-123
Resolves MUL-123A bare mention in the body, such as Related to MUL-123, doesn't link the PR at all. Commit messages and PR comments don't trigger linking either.
You can also link a PR by hand: in the issue's Pull requests block, click + and paste the PR URL. To take a PR off an issue, open the ⋯ menu on its row and choose Remove from issue; Multica won't link it again from its title or branch.
View PRs on an issue
Once linked, PRs appear in the Pull requests block of issue detail. Each entry shows:
- repository, number, title, and author;
Open,Draft,Merged, orClosedstate;- added and deleted lines and the number of changed files;
- CI status: all passed (with a count), some failed (naming the failing checks), or some in progress; PRs with no checks configured don't show this item — "no checks" is never treated as passing;
- mergeability: mergeable (only when GitHub reports a clean merge state), conflicting, blocked, or behind.
CI status and mergeability come from snapshots Multica pulls from the GitHub API, and the two are independent; merged or closed PRs no longer show either. When GitHub is temporarily unavailable, the card keeps the last snapshot and marks it stale instead of going blank.
Under the list, one line says what happens next — for example Moves to Done when #19 merges, or which PR closed without merging. There's no line when the workspace leaves status alone or the issue already has the target status.
Click an entry to open the PR on GitHub. Turning off the PR sidebar only hides this block; it doesn't disconnect anything.
When merged PRs move an issue
A merged PR doesn't necessarily mean the issue is finished, so the workspace decides what a merge does: Settings → Code → After PRs merge, move the issue to. Pick Done (the default for new workspaces), another started or done status — a custom one such as Awaiting regression works too — or Don't change. Workspaces that existed before this setting keep their behavior: if merging didn't always complete their issues, they start on Don't change.
An issue moves to the chosen status when all of the following hold:
- every linked PR is
Merged— anOpenorDraftPR keeps the issue waiting, and so does a PR closed without merging until you remove it from the issue; - the issue isn't
doneorcancelled, isn't in Triage, doesn't already have the target status, and hasn't been switched off for this issue (Pull requests → ⋯ → Keep status when PRs merge).
How a PR was linked doesn't matter: the title, the branch name and a Closes MUL-123 in the body all link it, and none of them changes what the merge does. When a PR delivers only part of the issue, or a release or a check has to follow the merge, keep that issue's status from its Pull requests menu.
The check runs when a PR event touches the issue: a linked PR merges, a PR is linked, or a link is removed. Reopening an issue doesn't move it back — the next linked PR that merges does. Changing the setting doesn't move issues whose PRs merged earlier.
The status change is written to the timeline as a system action naming the PRs, and members subscribed to the issue are notified.
Multiple workspaces
The same GitHub App installation can be connected to multiple Multica workspaces. GitHub events flow into each workspace separately and are matched against each workspace's own issue prefix.
For example, a PR that references both MUL-1 and ENG-2 can link in two workspaces with different prefixes. Workspaces never see each other's issues.
If one identifier matches an issue in more than one of the connected workspaces (possible when they share a prefix), Multica doesn't link it automatically in any of them, so merging the PR can't complete an unrelated issue. Link the PR by hand in the right workspace.
Disconnect
Choosing Disconnect from the GitHub row's ⋯ menu on Settings → Code only removes the relationship between the current Multica workspace and the installation; it does not uninstall the App from GitHub for you. Existing PR records are kept, and new events stop flowing into that workspace.
To revoke repository authorization on the GitHub side, uninstall the App or adjust its repository scope from your personal or organization GitHub App installations page. After uninstalling, every Multica workspace linked to that installation stops receiving events.
Self-hosting setup
Multica Cloud doesn't need this section. Self-hosting requires creating your own GitHub App first.
1. Create a GitHub App
Create the App under GitHub's Developer settings → GitHub Apps and fill in:
| Field | Value |
|---|---|
| Homepage URL | Your Multica frontend address, e.g. https://multica.example.com |
| Callback URL | Leave blank |
| Setup URL | https://<api-host>/api/github/setup, with Redirect on update enabled |
| Webhook URL | https://<api-host>/api/webhooks/github |
| Webhook secret | A random string you keep long-term |
Repository permissions:
| Permission | Level |
|---|---|
| Metadata | Read-only |
| Contents | Read-only; required by the PR snapshot query, which reads the head commit together with mergeability and the CI rollup |
| Pull requests | Read-only |
| Checks | Read-only; used to show CI status |
| Commit statuses | Read-only; used to aggregate legacy-status CI |
Subscribe to these events:
- Pull request;
- Check suite, Check run, and Status, which trigger CI and mergeability refreshes.
If you don't need CI shown in Multica, you can skip the Checks and Commit statuses permissions and their events. Contents is still required — without it the snapshot query fails outright and the PR card also loses merge state.
This is the Webhook secret, not the OAuth Client secret. If the two sides have different webhook secrets, GitHub deliveries return 401 invalid signature.
2. Set environment variables
Take the slug from the App's public URL. For example, the slug of https://github.com/apps/multica-acme is multica-acme.
GITHUB_APP_SLUG=multica-acme
GITHUB_WEBHOOK_SECRET=<the webhook secret you entered when creating the App>
FRONTEND_ORIGIN=https://multica.example.comIf either GITHUB_APP_SLUG or GITHUB_WEBHOOK_SECRET is missing, the connect button is disabled and the webhook endpoint refuses to process events.
The next two variables are required for the PR card to show CI status and mergeability — Multica uses them to authenticate as the App and pull snapshots:
GITHUB_APP_ID=<the GitHub App's numeric ID>
GITHUB_APP_PRIVATE_KEY=<full PEM private key, keeping the BEGIN/END lines and newlines>Generate the private key under the GitHub App's Private keys → Generate a private key. Without them the integration degrades gracefully: PRs still mirror, issues still auto-link and move on merge — the PR card just shows no CI or merge state.
3. Update the database and connect
When upgrading an existing deployment, run the regular database migrations first:
make migrate-upRestart the API server, then complete the connection in Settings → Code.
Troubleshooting
- Connect button disabled: check that
GITHUB_APP_SLUGandGITHUB_WEBHOOK_SECRETreached the API process. - Webhook returns 401: confirm the GitHub App and the API use the same webhook secret, then redeliver from GitHub's Recent Deliveries.
- PR not linked: check that the repository is in the App's authorized scope, auto-linking is on, the identifier belongs to the current workspace, and nobody removed the PR from the issue.
- Identifier in the body but not linked: put it right after a closing keyword (
Closes MUL-123), or in the branch name or PR title, or link the PR by hand. - No CI status: confirm
GITHUB_APP_IDandGITHUB_APP_PRIVATE_KEYare configured, and that the App has read-only Contents, Checks, and Commit statuses permissions with the matching events subscribed. Without Contents the whole snapshot fails, so the PR card shows neither CI nor merge state. After adding permissions to an installed App, each installation's owner must also approve them on GitHub before they take effect. - Issue didn't move after the PR merged: read the line under the issue's Pull requests list. It names any PR still open or closed without merging, or says the issue keeps its status when PRs merge. No line means the workspace setting is Don't change, or the issue already has the target status.
Next steps
- Issues — how status transitions relate to merged PRs.
- Project resources — which repositories agents use when running.
- Environment variables — the full self-hosted GitHub App configuration.