What it needs

Minimal on purpose. A Python runtime (or the image), a read-scoped token, and — optionally — an LLM endpoint.

Runtime

Access to your CI provider

A read-scoped API token, from an environment variable or a file:

# Env var (name is configurable via gitlab.token_env / github.token_env):
export CI_DOCTOR_GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
export CI_DOCTOR_GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"

# ...or a file (k8s/Vault secret mount), which takes precedence:
#   gitlab:
#     token_file: /run/secrets/gitlab_token

base_url defaults to the public host (gitlab.com / api.github.com); override it for self-hosted GitLab or GitHub Enterprise. Custom CA bundles, self-signed certs, and the standard HTTPS_PROXY / NO_PROXY / REQUESTS_CA_BUNDLE env vars are honoured.

Token scopes

ProviderNeeds
GitLabread_api. Add api only if you turn on MR notes.
GitHubactions: read. Add pull-requests: write only for PR comments.

Predefined CI variables it reads

ProviderVariables
GitLabCI_PIPELINE_ID, CI_PROJECT_ID, CI_MERGE_REQUEST_IID (for MR notes)
GitHubGITHUB_REPOSITORY, GITHUB_REF, GITHUB_SHA
None of these are required off a runner. When the repository variable is unset, ci-doctor resolves it from your git origin and logs a warning naming what it picked — so the same command works unchanged on your laptop.

An LLM endpoint — optional

ci-doctor produces a useful deterministic report with no model at all(llm.enabled: false, or simply leaving llm.model/llm.api_base unset). To enable the explanation step, point it at any OpenAI-compatible endpoint: Ollama, vLLM, llama.cpp server, LocalAI, or an internal gateway. An API key is optional. Other backends — litellm, Anthropic, the local claude CLI — are onConfiguration .

Network & air-gap