One integration for GitHub and GitLab.
Forge is the platform's single point of contact with your code hosts. One contract over GitHub and self-hosted GitLab — for reading repos, issues, and PRs; for writing build, readiness, and deploy status back as native checks; and for the agent tools that open, merge, and commit. Every other service talks to your forges through it.
Stop integrating GitHub and GitLab in six places.
Every platform that touches code eventually wires the GitHub and GitLab APIs into a dozen services — each with its own tokens, its own retry logic, its own idea of a 'status'. Forge is the one seam instead.
Forge runs three planes over a single backend. Discovery reads repos, issues, and PRs across both hosts. Write-back posts build, readiness, and deploy state onto the originating commit as native GitHub Check Runs and Deployments or GitLab commit statuses and Environments. And a set of agent tools opens changes, arms auto-merge, and commits files. Discovery and the tools run as the signed-in user — a per-request token, never a shared service account — so an agent can only do what the person behind it could.
One contract in front of every code host. Discovery, status, and writes — the same call whether it lands on GitHub or your own GitLab.
Both forges, one table.
The Repos, Issues, and Pull Requests panels query GitHub and every configured GitLab host at once and render them side by side — the provider is just a column.
| repo | forge | default | open issues |
|---|---|---|---|
| fastverk/rules_cc_cross | github | main | 7 |
| fastverk/plugin-forge | github | main | 2 |
| aion/web | gitlab | main | 3 |
| aion/lean | gitlab | main | 0 |
Build, readiness, and deploy state — on the commit.
forge.v1.ForgeWrite turns platform events into native checks — a Vercel-style 'Environment · Ready · Visit' surface: a GitHub Check Run and Deployment, or a GitLab commit status and Environment — found-or-updated by (sha, name), so a transition never duplicates a check.
| commit | check | state | as |
|---|---|---|---|
| rules_cc_cross@a1b3f9 | fastverk / build | success | github Check Run |
| rules_cc_cross@a1b3f9 | readiness · 6/6 | success | github Check Run |
| rules_cc_cross@a1b3f9 | deploy · aion-dev | in_progress | github Deployment |
| aion/web@7c0e21 | fastverk / build | running | gitlab commit status |
| aion/web@7c0e21 | deploy · staging | success | gitlab Environment |
The whole change lifecycle, as tools.
Every discovery read and every mutation is an MCP tool. Reads run freely; the six writes are confirm-gated — an agent previews the action and only performs it after the user approves.
| tool | kind | does |
|---|---|---|
| list_repos | read | repos across both forges |
| list_issues | read | open issues, org-wide |
| list_pull_requests | read | open PRs / MRs |
| mr_pipeline_status | read | live CI rollup for a change |
| change_state | read | open / merged / closed |
| read_file | read | a blob at a ref |
| open_mr | write | open a change — confirm-gated |
| enable_auto_merge | write | arm auto-merge — confirm-gated |
| merge_change | write | merge when green — confirm-gated |
| commit_file | write | commit a file — confirm-gated |
| create_branch | write | branch from a ref — confirm-gated |
| open_issue | write | file an issue — confirm-gated |
Open → arm → wait → merge.
The same four steps whether it lands on GitHub or GitLab. Forge normalizes auto-merge (GitHub's GraphQL mutation, GitLab's merge-when-pipeline-succeeds) behind one contract.
open_mr
Open the change on the target forge. Idempotent — re-running returns the existing change with already_existed=true instead of a duplicate.
enable_auto_merge
Arm auto-merge. On GitHub this is the enablePullRequestAutoMerge mutation; on GitLab it's merge-when-pipeline-succeeds — one tool, either host.
mr_pipeline_status
If auto-merge couldn't arm, poll the live CI rollup — success | failed | running | pending | canceled — until the pipeline is green.
merge_change
Merge. A neutral or skipped check is treated as canceled, never a pass, so a vacuous pipeline can't wave a change through.
It acts as you — not as a bot.
There is no forge-wide credential behind user data. Every read and every user-scoped write is built from the caller's own token, forwarded per request.
How access works
- Discovery and tools build a per-request client from the signed-in user's token (X-Fastverk-Github-Token / X-Fastverk-Gitlab-Token) — an agent inherits exactly the caller's reach, nothing more.
- Status write-back uses the fastverk GitHub App: a per-org installation client is minted and cached, so checks land on repos across every org the App is installed on.
- Self-hosted GitLab is first-class — per-host and per-group service tokens (FASTVERK_TOKEN_GITLAB_<HOST>) mean gitlab.savvifi.com is treated exactly like github.com.
- GitLab MR writes route through the forge-gateway as the user; GitHub PR writes run in-process as the App — same six tools, correct actor either way.
One seam, not six.
The alternative isn't a competitor — it's every service integrating GitHub and GitLab directly, each reinventing tokens, retries, and what a 'status' means.
A neutral or skipped check maps to canceled — never a false green.
source · github.com/fastverk/plugin-forge · tools: list_repos, open_issue, open_mr, enable_auto_merge, merge_change, commit_file
Prove it's safe to merge.
forge is one of 14 plugins in the fastverk console — hosted, or in your own cloud.