§ Guides

GitLab integration.

Push the spec document and BMAD pack to gitlab.com or your own self-hosted GitLab — connect, link a repository, push only what changed.

SpecGraph can push a project's spec document (spec.md) and its BMAD pack straight into a GitLab repository, so engineers and coding tools find them next to the code. It works with gitlab.com and with your own self-hosted GitLab, including private instances behind a firewall.

Pushing is one-way and manual. You open Push to GitLab, see which files changed, and push them in one commit. Files that haven't changed are left alone, and when nothing changed there's nothing to push. Nothing is read back into SpecGraph, and nothing is pushed on its own.

What goes into the repository #

PathContents
docs/spec.mdThe spec document (path is configurable)
bmad/CLAUDE.mdInstructions for coding agents
bmad/planning-artifacts/Product brief, PRD, architecture, UX design, epics, QA test plan, project context
bmad/implementation-artifacts/sprint-status.yaml and one file per story

The pack folder (bmad) is configurable, and the pack can be switched off to push only spec.md.

Setup at a glance #

  1. An owner or admin connects GitLab once, in Settings → Git.
  2. For a private GitLab, your GitLab admin allows SpecGraph's IP through the firewall.
  3. In each project, an editor links a repository, branch and file path.
  4. Anyone with edit rights opens Push to GitLab (git icon at the bottom of the project's right-hand bar, shown once the project is linked) whenever the spec or pack should go out.

Connect GitLab (owners and admins) #

Create an access token in GitLab #

SpecGraph signs in to GitLab with an access token. Create one of these:

TokenWhere in GitLabGood for
Service account token (recommended)Group → Settings → Service accountsEvery repository in a group. Commits show as a bot, not a person, and keep working when people leave
Project access tokenRepository → Settings → Access tokensOne repository. The narrowest option
Group access tokenGroup → Settings → Access tokensEvery repository in a group
Personal access tokenYour avatar → Edit profile → Access tokensWorks everywhere, but commits show as you and stop working if you leave

Give the token:

  • Scope api. read_repository and write_repository alone are not enough.
  • Role Developer or higher. To push to a protected branch such as main, the role must be allowed to push there (often Maintainer). Or push to a separate branch, for example specgraph/spec.
  • An expiry date you'll remember. When the token expires, pushes stop until you paste a new one.

On gitlab.com, service accounts and project and group access tokens depend on your GitLab plan. A personal access token always works.

A service account is a non-human GitLab user that belongs to your group. Commits from SpecGraph show as that bot, and the connection doesn't depend on any one person's account.

  1. In GitLab, open your group, then Settings → Service accounts, and add a service account. Give it a clear name, such as specgraph-sync.
  2. On the service account's row, open the ⋮ menu and choose Manage access tokens. Create a token with scope api and an expiry date. Copy it; GitLab shows it only once.
  3. Open the group's Manage → Members page, choose Invite members, and add the service account (search for its @service_account_… username) with the role Maintainer. Maintainer lets it push to protected branches such as main.
  4. In SpecGraph, add the connection as described below and paste the token. Test connection shows the service account's @service_account_… username.

The token only needs the api scope. What it can reach is set by the service account's group membership: it sees every repository in the group, and none outside it.

Add the connection #

  1. Open Settings → Git and choose Add GitLab.
  2. Name: something your team recognises, like "Acme GitLab".
  3. GitLab URL: the address you open GitLab at, such as https://gitlab.com or https://git.acme.com. Custom ports and sub-paths (https://acme.com/gitlab) work too. It must start with https://.
  4. Access token: paste it. It's stored encrypted; afterwards SpecGraph only shows its last four characters and the GitLab user it belongs to.
  5. Certificate: leave off unless your GitLab uses a self-signed or company-internal certificate (see below).
  6. Choose Test connection. You'll see who the token signs in as, or the exact reason it failed.
  7. Save. SpecGraph checks the connection again before saving.

You can add more than one connection, for example gitlab.com and an on-premise GitLab.

Keep it healthy #

Each connection shows Connected or Failing, the last error, and when it was last checked. Use Test to check again.

  • Replace a token: choose the pencil icon, paste the new token, save. Leave the token field empty to keep the current one while changing other fields.
  • Remove a connection: choose the trash icon. Projects linked through it are unlinked and the stored token is deleted. Files already pushed stay in GitLab.

Private and self-hosted GitLab #

SpecGraph talks to the standard GitLab API at whatever address you give it, so self-hosted GitLab (Community or Enterprise Edition) works the same as gitlab.com.

All traffic to GitLab comes from one fixed SpecGraph IP address, shown in the Allowlist this IP card in Settings → Git. If your GitLab only accepts known addresses, ask your GitLab or network admin to allow inbound HTTPS from that IP.

For a private GitLab to work:

Needs to be trueIf it isn't
GitLab is served over HTTPSNot supported. Ask your admin to enable HTTPS
Its address resolves on the public internet (DNS)"Host not found". An internal-only name or a private IP needs a VPN or private link set up by SpecGraph support
The firewall allows SpecGraph's IPRequests time out. Add the IP from Settings → Git to the allowlist
The certificate is from a public certificate authorityTurn on Accept self-signed certificate on the connection

About self-signed certificates: turning the switch on makes SpecGraph accept the certificate without verifying it, for that connection only. Use it only when your company issues its own certificates and you trust the network path. Client-certificate (mutual TLS) setups aren't supported yet.

  1. Open the project and its Settings panel (gear icon in the right-hand bar). Find the GitLab section.
  2. Repository: start typing to search. You'll only see repositories the token can write to. Type group/name to search by full path.
  3. Branch: defaults to the repository's default branch.
  4. File path: where spec.md goes. Defaults to docs/spec.md. Folders that don't exist are created.
  5. Include the BMAD pack: on by default. Pack folder defaults to bmad.
  6. Choose Link repository.

Change points the project at another repository, branch, path or folder. Unlink stops pushing; nothing is deleted in GitLab. Viewers see where the project is pushed but can't push or change the link.

Push changes #

  1. Choose the git icon at the bottom of the project's right-hand bar (it appears once the project is linked), or Push to GitLab in the settings panel's GitLab section.
  2. SpecGraph checks GitLab and lists only the files that would change: New, Changed, Removed or Edited in GitLab. Unchanged files are counted but not pushed.
  3. If everything matches, you'll see Everything is up to date and there's nothing to push.
  4. Optionally type a commit message, then choose Push N files. Everything goes in one commit.

After a push you'll get a notification with View commit, and the settings panel shows when the project was last pushed.

What a push does #

SituationResult
A file's content hasn't changedNot pushed. A different generation date alone doesn't count as a change
Nothing changed at allNo commit. You'll see "Everything is up to date"
A file doesn't exist yetCreated
SpecGraph pushed the file last time and it changed in SpecGraphUpdated
A story was removed from the projectIts story file is removed from the repository
Someone edited a file in GitLab since the last pushMarked Edited in GitLab. Nothing is pushed until you tick Overwrite the changes made in GitLab
A file exists but wasn't created by SpecGraphMarked Already in GitLab, same confirmation
A removed story's file was edited in GitLabLeft in place, not removed
The branch doesn't existIt's created from the repository's default branch
The repository has no commits at allMake a first commit in GitLab, then push again
A teammate is pushing the same project right nowWait a moment and try again

The commit message is yours, or a default like docs(spec): update spec and BMAD pack from Specgraph. Every commit also notes how many files were added, updated or removed, the project name and who pushed. In GitLab, the commit author is the token's user.

Linking, unlinking and every push are recorded in the project's Audit log.

Check GitLab and pull changes back #

Edits can also happen in GitLab, for example a reviewer fixing a requirement in spec.md. GitLab sync shows them and lets you bring them into SpecGraph, carefully and one change at a time.

  1. Open GitLab sync (git icon in the right-hand bar) and choose Check GitLab at any time to see the current status.
  2. Every file that differs is listed. Choose a file to see its diff:
    • Changed in GitLab: what changed in GitLab since SpecGraph's last push. This is the "git status" view.
    • Push would change: what pushing from SpecGraph would write. Generation dates are ignored, so only real edits show.
  3. If spec.md was changed in GitLab, a notice offers View changes and Review and pull.
  4. Review and pull lists each edit as a spec change, grouped by phase: a changed field, an added or removed feature, an edited endpoint, and so on. Pick the ones to apply and choose Apply.

What a pull does and doesn't do:

  • Only the changes you select are applied. Nothing else in the spec changes, and other sections aren't rewritten.
  • A feature renamed in GitLab (same F- number) is renamed in place, not deleted and re-added, so its story keeps its key and status.
  • For list items like features or endpoints, only the fields edited in GitLab are updated. The item keeps its identity and everything spec.md doesn't show, such as personas, FR IDs and Given/When/Then.
  • Edits you made in SpecGraph and haven't pushed yet are kept.
  • Locked phases can't change. Their changes are listed but can't be selected; unlock the phase to apply them.
  • Applied changes show as uncommitted changes in each phase, so you can review, commit or discard them there.
  • Only spec.md can be pulled. The BMAD pack is generated from the spec, so edit the spec, not the pack files. Pack files edited in GitLab are flagged and overwritten only if you confirm.
  • Free text added to spec.md outside its structure (new headings or paragraphs) can't be matched to a spec field. It shows in the diff but isn't pulled.

After pulling, check again: spec.md matches GitLab and the pack files show as changed, so push them to bring GitLab fully up to date.

Synced commit, history and restore #

When a project is linked, the top bar shows a git indicator with the branch and the commit the spec was last synced with, for example main @9639220a. "Synced" means the latest push, a pull that applied every change from GitLab, or a restore.

Click it to see:

  • The repository, the synced commit and when it was synced (pushed, pulled or restored).
  • Open GitLab sync, the same dialog as the git icon in the right-hand bar.
  • Spec and pack history: commits on the branch that changed spec.md or the BMAD pack, newest first. The synced commit is always listed and marked Synced.

Restore on an older commit brings the spec in SpecGraph back to how spec.md was at that commit. It works like a pull:

  1. Every difference between the spec now and the spec at that commit is listed as a change, grouped by phase.
  2. Pick the changes to restore and choose Apply. Nothing else in the spec changes.
  3. Locked phases can't be selected; unlock them first.
  4. Restored changes show as uncommitted changes in each phase, so you can still discard them.

Restoring doesn't change GitLab or rewrite its history. To record the restored spec in the repository, push afterwards; it becomes a new commit. Like a pull, a restore only covers what spec.md contains.

Viewers see the indicator and the synced commit; editors also see the history and can restore.

Keeping spec, repository and code in step #

Three directions, each with its own safe path:

What changedHow it reaches the specWho decides
The spec, in SpecGraphPush writes spec.md and the BMAD pack to GitLabWhoever pushes
spec.md, edited in GitLabPull in GitLab sync applies the selected edits to the specWhoever pulls; locked phases need unlocking
The code, changed by hand or in an emergency/sg-sync in Claude Code proposes amendments with file evidenceThe team, in the Amendments panel

See Connecting coding agents for /sg-sync.

Troubleshooting #

MessageWhat to do
GitLab rejected the access token (401)The token is wrong, expired or revoked. Create a new one and replace it in Settings → Git
The access token isn't allowed to… (403)Give the token the api scope and at least the Developer role, or push to an unprotected branch
GitLab couldn't find… (404)The repository was deleted or moved, or the token lost access. Link the project again
Host not foundThe GitLab address doesn't resolve publicly. Check the URL, or contact SpecGraph support about private networks
Timed out, "is the relay's IP allowlisted?"Ask your GitLab admin to allow the IP shown in Settings → Git
TLS certificate not trustedTurn on Accept self-signed certificate for that connection
Resolves to a private or reserved addressYour GitLab is on a private network. Contact SpecGraph support
GitLab redirected the requestUse the exact address GitLab opens at, as shown in your browser's address bar
No repositories matchThe token needs at least the Developer role on the repository
A push for this project is already runningSomeone just pushed. Try again in a moment

What's coming #

  • Pushing automatically when a phase is locked
  • Pulling changes to the BMAD pack's story statuses
  • Opening a merge request instead of committing straight to a branch
  • GitHub

Related: Spec preview & export · Connecting coding agents (MCP) · Roles & permissions