GitLab CI/CD
Beta: Claude Code for GitLab CI/CD is currently in beta. This integration is maintained by GitLab. For issues, see the GitLab tracking issue.
Claude Code integrates with GitLab CI/CD by running as a job in your .gitlab-ci.yml. The pattern is the same as GitHub Actions, but the mechanics differ: GitLab uses masked CI/CD variables instead of secrets, $VARIABLE syntax instead of ${{ secrets.VARIABLE }}, and before_script to install Claude.
Prerequisites
-
Add
ANTHROPIC_API_KEYas a masked variable — Go to your project → Settings → CI/CD → Variables → Add variable. Set the key toANTHROPIC_API_KEY, paste your API key as the value, and check Mask variable. Optionally check Protected to restrict it to protected branches. -
A runner — Any GitLab runner (shared, group, or project-level) running Docker. The examples below use
node:24-alpine3.21which is small and fast. -
No app installation required — Unlike GitHub Actions, GitLab CI/CD does not need a separate app. The job uses
CI_JOB_TOKENfor GitLab API operations by default.
How It Works
The mcp__gitlab tool (provided by the GitLab MCP server) is what allows Claude to post MR comments, create branches, and interact with the GitLab API. Without it, Claude can still read and write files — it just cannot communicate back to GitLab’s UI.
Template 1: MR Code Review
Triggers on merge request events. Claude reviews the diff and posts findings as an MR comment.
stages: - ai
claude-mr-review: stage: ai image: node:24-alpine3.21 rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' variables: GIT_STRATEGY: fetch before_script: - apk update - apk add --no-cache git curl bash - curl -fsSL https://claude.ai/install.sh | bash script: - /bin/gitlab-mcp-server || true - > claude -p "Review this merge request for bugs, security issues, and code quality. Check the diff with git diff origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}...HEAD. Post your findings as an MR comment." --permission-mode acceptEdits --allowedTools "Bash,Read,Edit,Write,mcp__gitlab" --max-turns 5What each part does:
rules: if: '$CI_PIPELINE_SOURCE == "merge_request_event"'— only runs on MR pipelines, not every pushGIT_STRATEGY: fetch— fetches the repo so Claude can read files and rungit diffapk add --no-cache git curl bash— Alpine doesn’t include these by default; all three are neededcurl -fsSL https://claude.ai/install.sh | bash— installs the Claude CLI on the runner/bin/gitlab-mcp-server || true— starts the GitLab MCP server if available;|| trueprevents failure if it’s not present--allowedTools "Bash,Read,Edit,Write,mcp__gitlab"— allows Claude to run shell commands, read/write files, and post to GitLab
Template 2: Release Notes Generator
Triggers when a tag is pushed. Claude reads the commit log and writes a release notes file.
claude-release-notes: stage: ai image: node:24-alpine3.21 rules: - if: '$CI_COMMIT_TAG =~ /^v/' variables: GIT_STRATEGY: fetch before_script: - apk update - apk add --no-cache git curl bash - curl -fsSL https://claude.ai/install.sh | bash script: - /bin/gitlab-mcp-server || true - > claude -p "Read the git log from the previous tag to HEAD using git log and git describe. Write release notes to RELEASE_NOTES.md. Group by: Features, Bug Fixes, Breaking Changes, Internal. One sentence per item." --allowedTools "Bash,Read,Write" --max-turns 5 artifacts: paths: - RELEASE_NOTES.md expire_in: 90 days when: alwaysThe artifacts block makes RELEASE_NOTES.md available for download from the GitLab pipeline UI and for use in downstream jobs.
Template 3: Scheduled Weekly Audit
Runs on a schedule (configured in GitLab CI/CD → Schedules). Claude audits the codebase and writes a report.
claude-weekly-audit: stage: ai image: node:24-alpine3.21 rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' variables: GIT_STRATEGY: fetch before_script: - apk update - apk add --no-cache git curl bash - curl -fsSL https://claude.ai/install.sh | bash script: - > claude -p "Audit this codebase for security anti-patterns, hardcoded credentials, missing input validation, and files with unresolved TODO/FIXME comments. Write findings to audit-report.md. Rate each finding: Critical/High/Medium/Low." --permission-mode plan --allowedTools "Bash,Read,Write" --max-turns 10 artifacts: paths: - audit-report.md expire_in: 90 days when: always--permission-mode plan means Claude describes what it would do but does not execute shell commands or write files — suitable for read-only audits. Remove it if you want Claude to fix issues directly.
To create the schedule: go to your project → CI/CD → Schedules → New schedule. Set cron to 0 9 * * 1 (Mondays 9 AM UTC).
Key Differences from GitHub Actions
| GitHub Actions | GitLab CI/CD | |
|---|---|---|
| Secret syntax | ${{ secrets.ANTHROPIC_API_KEY }} | $ANTHROPIC_API_KEY (set as masked variable) |
| Trigger on MR event | on: pull_request: | if: '$CI_PIPELINE_SOURCE == "merge_request_event"' |
| Trigger on tag | on: push: tags: ['v*'] | if: '$CI_COMMIT_TAG =~ /^v/' |
| Trigger on schedule | on: schedule: - cron: '...' | Set in CI/CD → Schedules UI, then if: '$CI_PIPELINE_SOURCE == "schedule"' |
| Install Claude CLI | Handled by the Action | Manual: curl -fsSL https://claude.ai/install.sh | bash |
| Post MR comment | Action handles automatically | Requires mcp__gitlab tool + GitLab MCP server |
| Artifacts | upload-artifact action | artifacts: paths: block in job |
| Runner image | GitHub-hosted Ubuntu | Your choice; examples use node:24-alpine3.21 |
Using AI_FLOW_* Variables for Comment Triggers
GitLab does not have a native “respond to @claude in comments” feature yet. The pattern used by the GitLab integration is to set up a webhook that listens for note events and calls the pipeline trigger API with context variables:
claude-comment-handler: stage: ai image: node:24-alpine3.21 rules: - if: '$CI_PIPELINE_SOURCE == "web"' when: always variables: GIT_STRATEGY: fetch before_script: - apk update - apk add --no-cache git curl bash - curl -fsSL https://claude.ai/install.sh | bash script: - /bin/gitlab-mcp-server || true - > claude -p "${AI_FLOW_INPUT:-Review this MR and post your findings}" --permission-mode acceptEdits --allowedTools "Bash,Read,Edit,Write,mcp__gitlab" --max-turns 10When triggered via the pipeline API with AI_FLOW_INPUT set to the comment text, Claude receives the user’s request as its prompt. The ${AI_FLOW_INPUT:-fallback} pattern uses the variable if set, or falls back to the default string.
Cost Management
Set job timeouts to prevent runaway pipeline minutes:
claude-mr-review: timeout: 10 minutesLimit turns to control API token usage:
--max-turns 5Restrict to specific branches to avoid running on every commit:
rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'Use interruptible: true so newer pipeline runs cancel stale ones:
claude-mr-review: interruptible: trueEnterprise: AWS Bedrock and Google Vertex AI
For air-gapped or data-residency environments, swap the API key for cloud provider credentials. The Claude CLI picks up provider configuration from environment variables.
AWS Bedrock — uses OIDC to assume a role; no static keys stored:
claude-bedrock: stage: ai image: node:24-alpine3.21 before_script: - apk add --no-cache bash curl jq git python3 py3-pip - pip install --no-cache-dir awscli - curl -fsSL https://claude.ai/install.sh | bash - > aws sts assume-role-with-web-identity --role-arn "$AWS_ROLE_TO_ASSUME" --role-session-name "gitlab-claude-$(date +%s)" --web-identity-token "$(cat $CI_JOB_JWT_FILE)" --duration-seconds 3600 > /tmp/aws_creds.json - export AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId /tmp/aws_creds.json)" - export AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey /tmp/aws_creds.json)" - export AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken /tmp/aws_creds.json)" script: - claude -p "Your task here" --allowedTools "Bash,Read,Write" variables: AWS_REGION: "us-west-2"Required CI/CD variables: AWS_ROLE_TO_ASSUME, AWS_REGION.
Related
- GitHub Actions — Equivalent setup for GitHub pipelines
- Headless Mode — Understanding
claude -pdirectly - Official GitLab tracking issue — Current beta status and updates