Skip to content

/ci-monitor

Watch GitLab CI and investigate pipeline failures. Use when a pipeline or job is failing or red, when watching MR CI, branch builds, or a specific pipeline, when waiting for CI to go green, or when authoring or validating .gitlab-ci.yml.

shell
$ npx -y skills add bendrucker/claude --skill ci-monitor --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/ci-monitor
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Watch GitLab CI and investigate pipeline failures. Use when a pipeline or job is failing or red, when watching MR CI, branch builds, or a specific pipeline, when waiting for CI to go green, or when authoring or validating .gitlab-ci.yml.

SKILL.md

ci-monitor.SKILL.md
name: gitlab:ci-monitor
description: Watch GitLab CI and investigate pipeline failures. Use when a pipeline or job is failing or red, when watching MR CI, branch builds, or a specific pipeline, when waiting for CI to go green, or when authoring or validating .gitlab-ci.yml.
argument-hint: "[mr-url | branch | pipeline-id] [--max-minutes N] [--project group/project]"
effort: low
allowed-tools:
  - Monitor
  - TaskStop
  - Agent
  - Bash(bun:*)
  - Bash(glab ci:*)
  - Bash(glab api:*)
  - Bash(glab mr view:*)
  - Bash(git remote:*)
  - Bash(jq:*)

CI Monitor

Watch a GitLab pipeline (for an MR, a branch, or a specific pipeline ID), reacting to failures by dispatching the `gitlab:logs` agent for diagnostics. Exits cleanly when the pipeline is green, the MR is closed, a pipeline-id target reaches a terminal status, or the wall-clock cap is hit.

Target

$ARGUMENTS

Accepts an MR URL, a branch name, a pipeline ID, or derives one from the current branch:

  • MR mode: pass a URL like `https://gitlab.com/group/project/-/merge_requests/123`.
  • Branch mode: pass a branch name (e.g. `main`, a release branch). Project path `group/project` is inferred from `git remote get-url origin` in the current directory; pass `--project <group/project>` to override.
  • Pipeline-id mode: pass a pipeline ID (e.g. from a manually-triggered pipeline or a re-run). Project is inferred from the git remote; override with `--project <group/project>`.
  • No argument: derive an MR URL from the current branch: `glab mr view --output json | jq -r '.web_url'`.

Workflow

Start the monitor

Launch the watch script via the `Monitor` tool with `persistent: true`:

  • MR mode: `bun ${CLAUDE_SKILL_DIR}/scripts/watch.ts --mr <mr-url>`
  • Branch mode: `bun ${CLAUDE_SKILL_DIR}/scripts/watch.ts --branch <name> [--project <group/project>]`
  • Pipeline-id mode: `bun ${CLAUDE_SKILL_DIR}/scripts/watch.ts --pipeline-id <id> [--project <group/project>]`
  • Optional flags: `--interval <seconds>`, `--max-minutes <N>`, `--queued-timeout <minutes>`, `--api-error-threshold <N>`.

Exactly one of `--mr`, `--branch`, or `--pipeline-id` is required. In branch and pipeline-id modes, `--project` is inferred from the current git remote when omitted. Pipeline-id mode queries `glab api projects/:id/pipelines/:pid` directly; if the pipeline does not exist the watcher exits non-zero on the first call.

MR mode resolves the pipeline from `projects/:id/merge_requests/:iid/pipelines` and branch mode from `projects/:id/pipelines?ref=<branch>`. Both ignore `external` pipelines (commit statuses posted by other tools, which carry no CI jobs) and `parent_pipeline` pipelines (children the parent already aggregates), and each prefers its own kind: `merge_request_event` in MR mode, branch pipelines in branch mode.

The script emits one JSON object per line on stdout. When the first probe is already green, it emits a single `status: success` event and exits, so there is no separate initial-green path. In pipeline-id mode it also exits after emitting `status: failing`, because a specific pipeline has a finite lifetime and will not restart on its own.

Event schema

Each line is one of:

  • `{"type":"status","state":"running|failing|success","sha":"...","run_id":"..."}`: `run_id` is the GitLab pipeline ID. A `success` is confirmed against the pipeline's jobs before it is emitted, so a pipeline reporting `success` while a required job failed is reported as `failing`.
  • `{"type":"conflicts","sha":"..."}`: MR reports merge conflicts against the target branch. MR mode only.
  • `{"type":"mergeable-unknown","sha":"..."}`: GitLab could not settle merge status after bounded re-polling. MR mode only.
  • `{"type":"queued-timeout","minutes":N}`: pipeline has been queued longer than the threshold.
  • `{"type":"api-error","consecutive":N}`: consecutive `glab` failures crossed the threshold.
  • `{"type":"rate-limited","retry_after":"..."}`: emitted only when `glab` surfaces structured rate-limit data.
  • `{"type":"pr-closed"}`: MR closed without merging, or the source branch was deleted. MR mode only. The script exits after emitting.
  • `{"type":"merged"}`: MR merged. MR mode only. The script exits after emitting.
  • `{"type":"max-time-reached","minutes":60}`: wall-clock cap hit. The script exits after emitting.

In branch and pipeline-id modes, `conflicts`, `mergeable-unknown`, `pr-closed`, and `merged` are never emitted (there is no MR metadata to derive them from). `merged` and `pr-closed` are distinct terminal events: `merged` means the MR landed, `pr-closed` means it closed without merging.

The script exits on `status: success` in every mode, but only once that success survives the job-level confirmation above. A pipeline whose jobs cannot be read keeps the watcher polling rather than exiting green, surfacing as `api-error` if it persists. In pipeline-id mode it also exits on `status: failing` (the pipeline is terminal).

React to events

On `status: failing`, invoke the `gitlab:logs` agent via the `Agent` tool with the pipeline ID from `run_id`. This applies to all three modes; the logs agent accepts a pipeline ID, so pipeline-id mode fits:

Agent(
  subagent_type="gitlab:logs",
  model="haiku",
  prompt="Fetch failing-job logs for pipeline <run_id>. Return the JSON summary described in the logs agent definition."
)

Surface the summary to the parent conversation. Do not attempt fixes; `pull-request:babysit` owns that decision.

On `conflicts`, report the SHA with conflicts and stop watching; conflict resolution belongs to the caller.

On `mergeable-unknown`, report the SHA; the caller decides whether to run an authoritative local check.

On `queued-timeout`, `api-error`, or `rate-limited`, surface the event once and keep the monitor running. Consecutive rate-limit or api-error events mean the monitor should be stopped manually.

On `merged`, `pr-closed`, or `max-time-reached`, the monitor has already exited. Report and finish.

Stopping

The monito

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withbendrucker-claude

My personal plugin marketplace for Claude Code, Anthropic's AI coding assistant.

Get the whole plugin, auto-invoked
Stats
15
Stars
0
Views
1
Forks
Active
Maintenance
TypeScript
Language
MIT
License
14h ago
Last commit
1y ago
Created

Repo: bendrucker/claude