selan.ai Gateway Reactor

Guide · Claude Code for teams

How do you run Claude Code in GitLab CI for a team?

Add a job to .gitlab-ci.yml that installs Claude Code and runs claude -p, with the credential in a masked CI/CD variable. Anthropic documents an API key, or OIDC into Amazon Bedrock or Google Cloud with no stored key. Cap each run with --max-turns and a job timeout. Through Selan, each job carries a token of its own.

token gateway pipeline

How do you set up Claude Code in GitLab CI?

Add ANTHROPIC_API_KEY under Settings → CI/CD → Variables, and mark it masked. Then add a job that installs Claude Code and gives it a prompt. This is Anthropic's quick setup, shortened:

claude:
  stage: ai
  image: node:24-alpine3.21
  rules:
    - if: '$CI_PIPELINE_SOURCE == "web"'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  before_script:
    - apk add --no-cache git curl bash
    - curl -fsSL https://claude.ai/install.sh | bash
    - export PATH="$HOME/.local/bin:$PATH"
  script:
    - claude -p "Review this MR" --permission-mode acceptEdits --allowedTools "Bash Read Edit Write mcp__gitlab"

The integration is in beta, and GitLab maintains it. It is the Claude Code CLI in a job, not an app you install.

@claude mentions need a listener of your own. A project webhook for comments calls it, and it calls the pipeline trigger API with variables such as AI_FLOW_INPUT and AI_FLOW_CONTEXT.

Which credential should the job use?

Anthropic's GitLab and authentication documentation name four:

CredentialWhere it comes fromWho pays
ANTHROPIC_API_KEYAn API key from the Claude Console, in a masked variableThe Console organisation, per token
CLAUDE_CODE_OAUTH_TOKENclaude setup-token, valid for one year, on Pro, Max, Team or EnterpriseThe subscription of the person who ran it
Amazon BedrockThe job's GitLab OIDC token from id_tokens:, exchanged for temporary credentials of an IAM roleYour AWS account
Google Cloud's Agent PlatformThe same OIDC token, through Workload Identity Federation to a service accountYour Google Cloud project

The two OIDC routes store no long-lived key in GitLab at all. Anthropic's GitLab page advises them where possible.

A key every project's jobs share should belong to the company, not to whoever ran setup-token.

Good to know: a protected variable reaches only pipelines on protected branches and tags. A merge request pipeline gets it only when both its branches are protected, in the same project, and the project's settings allow it. Otherwise a review job on a feature branch runs with no credential.

Why can't the job comment on the merge request?

Anthropic's setup posts through the job's CI_JOB_TOKEN, or a project access token with api scope. On GitLab.com Free, neither can post a comment:

  • CI_JOB_TOKEN cannot create a note.
  • On GitLab.com Free, neither a project nor a group access token can be issued.
  • What is left is a personal token, which posts as that person and carries everything they can do.

A job can skip the API instead. A Code Quality report, declared under artifacts:reports:codequality, is read by GitLab itself, with no token. It shows in the merge request's Reports tab. The inline markers in the diff need GitLab Ultimate.

What does a run cost, and how do you cap it?

Each run uses two things:

  • Runner compute minutes, under your GitLab plan's runner billing.
  • Model tokens, which grow with the prompt, the task and the size of the codebase.

Anthropic's advice for keeping both down:

  • Set --max-turns to bound how long Claude works.
  • Set the job's timeout, for example timeout: 30m.
  • Limit how many runs go in parallel.
  • Keep CLAUDE.md short, because Claude reads it on every run.

None of these is a budget. They bound one run, not the month across every project. What a developer's Claude Code costs a day is in the cost-per-developer guide.

What should the job keep away from Claude?

GitLab hands every job variable to every line of the script. An agent that reads text a merge request wrote can be talked into printing them.

  • Start the agent from an empty environment. env -i passes only the variables it names.
  • Remove the job token from disk. On the docker executor, the runner writes CI_JOB_TOKEN into .gitlab-runner.ext.conf beside the checkout.
  • Do not run as root with permissions skipped. Claude Code refuses --dangerously-skip-permissions at uid 0, and container images run as root, so the job drops to a user.

Each of these steps, with the reason for it, is in the GitLab CI review pipeline.

How does Selan run Claude Code in GitLab CI?

The job installs selan and Claude Code, then runs an agent from the repository's .claude/agents/ with selan agent-run. It signs in with a SELAN_TOKEN variable instead of a provider key.

  • No provider key in GitLab. The company's provider accounts stay on Selan, and the job holds only its token.
  • A token per job. An owner mints each one under Settings → API tokens. It spends as itself, under an address like ci-review@tokens.selan.ai, so its runs show up as that job in Usage and Logs.
  • A limit per job. The company's per-person spend limit applies to a token as it does to a person, and a token can be given a limit of its own. How limits work is on the spend page.
  • API keys only, if you want. An owner can switch a token to API only. Selan then serves it only from the company's own API keys.
  • One revoke. Revoking a token ends that job's access without touching any other job.

How the token works is in Agents in CI. The complete GitLab pipeline, which posts its findings as a Code Quality report, is on the code review page.

When is Anthropic's GitLab setup the better choice?

When the job should change code. Anthropic's examples write a branch and open a merge request from an issue or a comment. Selan's documented GitLab pipeline runs an agent that writes a file, and the pipeline decides what to do with it.

When you want no stored secret at all. The Bedrock and Google Cloud routes exchange the job's OIDC token, while a Selan job still holds a SELAN_TOKEN.

When one project uses it, a single masked API key is simple and enough. Selan earns its place once several projects and jobs share the bill and you want each one shown and capped on its own, next to the people on the team.

Start for free

Free for up to three seats, and the Free plan needs no card. A CI token takes a seat of its own on a paid plan; the Free plan is people only.

The short version

How the integration works is as Anthropic's GitLab CI/CD and authentication documentation (code.claude.com/docs/en/gitlab-ci-cd and /authentication) and GitLab's CI/CD variables and merge request pipeline documentation stated it on 28 October 2026. It changes: check the date before relying on it. What Selan does is as its CLI, control app and docs stated it on that date.