Talooner ships as one image — talooner-runner — that you add as a step to the
pipeline you already have. The job starts OpenTalon and the Talooner plugin inside its
own container, checks your license, reviews the merge request or pull request against
your repository's .talooner/rules.tln, posts a check run and one comment, and exits.
registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1
The image holds binaries only — no source, no compiler — on a minimal, non-root base.
What you need
- A license key — from your license page (or get a free demo license).
- A forge token so Talooner can post its review:
GitLab — a project or group access token, Developer role,
apiscope; GitHub Actions — the built-ingithub.token. - Optional: any LLM for AI review — see Any LLM. Without one, Talooner reviews with rules only.
- Optional: Jev (
JEV_URL+JEV_TOKEN) — TypeSafe's typed-decision model as a fast first pass: each changed unit gets a typed match / mismatch / unclear with a confidence score, and only what Jev can't confirm goes to the full LLM review.
Any LLM
Talooner works with any model behind an OpenAI-compatible API — hosted or on your own servers. Set three variables:
TALOONER_MODEL_BASE_URL | TALOONER_MODEL | |
|---|---|---|
| Qwen (Alibaba Cloud) | https://dashscope-intl.aliyuncs.com/compatible-mode/v1 | qwen3-coder-plus |
| DeepSeek | https://api.deepseek.com/v1 | deepseek-chat |
| OpenRouter | https://openrouter.ai/api/v1 | any model it lists |
| Ollama / vLLM on your servers | http://llm.internal:11434/v1 | e.g. qwen3-coder |
…plus TALOONER_MODEL_API_KEY (any non-empty value for a local server). Anthropic and
OpenAI have shortcuts: ANTHROPIC_API_KEY, or OPENAI_API_KEY with TALOONER_MODEL.
The snippets below use the three variables; swap in a shortcut if you prefer.
GitLab CI
Works on gitlab.com and self-managed GitLab. Add the job to .gitlab-ci.yml, then add
TALOONER_LICENSE_KEY and GITLAB_TOKEN (and optionally your LLM:
TALOONER_MODEL_BASE_URL, TALOONER_MODEL, TALOONER_MODEL_API_KEY) under
Settings → CI/CD → Variables, masked.
talooner:
image:
name: registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1
entrypoint: [""]
stage: test
needs: []
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
TALOONER_PROVIDER: gitlab
GIT_STRATEGY: none
script:
- talooner-step
Keep entrypoint: [""] — GitLab runs the job's script: through a shell.
GitHub Actions
Works on github.com and GitHub Enterprise Server. Add TALOONER_LICENSE_KEY (and
optionally your LLM's TALOONER_MODEL_API_KEY) under Settings → Secrets and
variables → Actions, and
allow GitHub Actions to create and approve pull requests under Settings → Actions →
General.
# .github/workflows/talooner.yml
name: talooner
on:
pull_request:
pull_request_review:
issue_comment:
types: [created]
permissions:
contents: read
pull-requests: write
checks: write
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: docker://registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1
env:
TALOONER_PROVIDER: github
TALOONER_LICENSE_KEY: ${{ secrets.TALOONER_LICENSE_KEY }}
TALOONER_MODEL_BASE_URL: https://dashscope-intl.aliyuncs.com/compatible-mode/v1
TALOONER_MODEL: qwen3-coder-plus
TALOONER_MODEL_API_KEY: ${{ secrets.TALOONER_MODEL_API_KEY }}
GITHUB_TOKEN: ${{ github.token }}
Any other CI
Jenkins, CircleCI, Buildkite, Drone, Woodpecker, TeamCity — anything that can run a container against a GitHub or GitLab repository:
docker run --rm \
-e TALOONER_PROVIDER=gitlab \
-e TALOONER_LICENSE_KEY \
-e TALOONER_MODEL_BASE_URL -e TALOONER_MODEL -e TALOONER_MODEL_API_KEY \
-e GITLAB_TOKEN -e GITLAB_API_URL \
-e CI_PROJECT_ID -e CI_MERGE_REQUEST_IID -e CI_PIPELINE_SOURCE \
registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1 talooner-step
The image prints a ready config for your CI:
docker run --rm <image> snippet gitlab (or github, generic).
Gitea/Forgejo, Bitbucket and Azure DevOps are coming soon.
One variable instead of five
Put everything in one YAML file and store it as a single masked variable,
TALOONER_CONFIG_B64:
# talooner.yaml
provider: gitlab
license_key: TLN1....
model:
base_url: https://dashscope-intl.aliyuncs.com/compatible-mode/v1
name: qwen3-coder-plus
api_key: sk-...
gitlab_token: glpat-...
docker run --rm -i registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1 \
encode-config - < talooner.yaml # → paste the output into TALOONER_CONFIG_B64
A variable set on its own always overrides the same setting in the file.
Settings
| Variable | In talooner.yaml | |
|---|---|---|
TALOONER_LICENSE_KEY | license_key | required |
TALOONER_PROVIDER | provider | gitlab or github — detected in GitLab CI and GitHub Actions |
GITLAB_TOKEN / GITHUB_TOKEN | gitlab_token / github_token | required for the provider |
GITLAB_API_URL | gitlab_url | self-managed GitLab outside GitLab CI |
TALOONER_MODEL_BASE_URL + TALOONER_MODEL_API_KEY + TALOONER_MODEL | model.base_url + model.api_key + model.name | AI review with any LLM behind an OpenAI-compatible API |
ANTHROPIC_API_KEY | model.anthropic_api_key | shortcut for Anthropic; model defaults to claude-sonnet-5-5 |
OPENAI_API_KEY + TALOONER_MODEL | model.openai_api_key + model.name | shortcut for OpenAI |
JEV_URL + JEV_TOKEN | jev.url + jev.token | Jev triage before the full review |
TALOONER_JEV_MIN_CONFIDENCE | jev.min_confidence | Jev threshold, default 0.9 |
TALOONER_LOG_LEVEL | log_level | debug prints OpenTalon's own log |
TALOONER_METRICS_PUSH_URL | metrics.push_url | push talooner_* metrics at the end of each job — see below |
TALOONER_METRICS_PUSH_TOKEN | metrics.push_token | the gateway's bearer token — store it masked / as a secret |
TALOONER_METRICS_PUSH_JOB | metrics.job | the job label, default talooner |
TALOONER_METRICS_LABELS | metrics.labels | optional extra labels to filter by in Grafana, e.g. team=payments when several teams share one Prometheus |
Metrics with Prometheus and Grafana
Every verdict, action, rule hit and AI review is a talooner_* Prometheus metric. A
pipeline job lives for seconds, so Prometheus can't scrape it — instead, each job
pushes its metrics once, when it finishes, to a gateway next to your Prometheus.
Push from your pipeline
The job pushes its metrics with the Prometheus Pushgateway protocol to your gateway — prom-aggregation-gateway, which adds up the counters of every job.
GitLab CI — add two variables under Settings → CI/CD → Variables (or once on the group, for every project):
| Variable | Value | |
|---|---|---|
TALOONER_METRICS_PUSH_URL | https://metrics.acme.dev:9091 | |
TALOONER_METRICS_PUSH_TOKEN | the gateway's token — only if it has one | masked, never in .gitlab-ci.yml |
The URL can also go in the job; the token always stays a masked variable:
talooner:
image:
name: registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1
entrypoint: [""]
stage: test
needs: []
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
TALOONER_PROVIDER: gitlab
GIT_STRATEGY: none
TALOONER_METRICS_PUSH_URL: https://metrics.acme.dev:9091
# TALOONER_METRICS_PUSH_TOKEN comes from the masked CI/CD variable
script:
- talooner-step
When the review is done, talooner-step pushes once and the job log shows
talooner-step: metrics: pushed 23 series to https://metrics.acme.dev:9091. The token is sent as
Authorization: Bearer <token>.
GitHub Actions — the same two settings in the step's env: the URL as a repository
variable, the token as a secret:
- uses: docker://registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1
env:
TALOONER_PROVIDER: github
TALOONER_LICENSE_KEY: ${{ secrets.TALOONER_LICENSE_KEY }}
GITHUB_TOKEN: ${{ github.token }}
TALOONER_METRICS_PUSH_URL: ${{ vars.TALOONER_METRICS_PUSH_URL }}
TALOONER_METRICS_PUSH_TOKEN: ${{ secrets.TALOONER_METRICS_PUSH_TOKEN }}
The runner must reach the gateway. The push goes out from the machine that runs the job:
- Your own runners (self-hosted GitLab runner or GitHub runner) — use the internal
address, e.g.
http://metrics.internal:9091. Nothing needs to be public. - gitlab.com shared runners or GitHub-hosted runners run on the internet, so the
gateway needs a public HTTPS address. Put it behind a reverse proxy that checks a bearer
token, and store the token as a masked variable or secret,
TALOONER_METRICS_PUSH_TOKEN.
Collect it in Prometheus
docker run -d -p 9091:80 ghcr.io/zapier/prom-aggregation-gateway:latest
# prometheus.yml
scrape_configs:
- job_name: talooner
honor_labels: true # keep the repo / provider labels Talooner sets
static_configs:
- targets: ["metrics.internal:9091"]
Import the dashboard into Grafana (Dashboards → New → Import) — download talooner-dashboard.json, or print the one that matches your image:
docker run --rm registry.gitlab.com/onlinecopyrig-rlr6226/talooner-runner:1 \
dashboard > talooner-dashboard.json
What you get
| Metric | |
|---|---|
talooner_pr_evaluations_total{repo, verdict} | reviews by verdict — approve, block, none |
talooner_pr_actions_total{verb} | what the rules did: approve, block, route, comment… |
talooner_pr_rules_fired | rules that fired per review (histogram) |
talooner_pr_evaluation_duration_seconds | how long a review took (histogram) |
talooner_llm_reviews_total{result} | AI reviews: match, mismatch, unclear, triage hits… |
talooner_pr_warnings_total{code} | ruleset health warnings |
Each series also carries repo, provider and pipeline_source, plus your own
TALOONER_METRICS_LABELS. The dashboard shows the auto-approval and needs-a-human rates,
the verdict mix over time, latency, top repositories, AI review outcomes and warnings —
watch the auto-approval rate climb as you tune the rules:
sum(rate(talooner_pr_evaluations_total{verdict="approve"}[1d]))
/ sum(rate(talooner_pr_evaluations_total[1d]))
A push that fails — gateway down, wrong URL — is logged as a warning and never fails the job.
What leaves your pipeline
- Calls to your forge's API.
- Calls to your own LLM provider — only where a rule asks for
llm_review. - Metrics to your own gateway, if you set one — counts, verdicts and repository names.
- One license check to us: the key, a nonce and the version.
Never code, repositories or PR data to us.
Each job verifies the license online before it reviews. If the license is revoked or expired, or the license server can't be reached, Talooner posts a "license inactive" check run and comment — and the job still succeeds, so it never blocks your merges.
