/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.
$ npx -y skills add bendrucker/claude --skill ci-monitor --agent claude-codeHow 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.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/ci-monitor
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.mdname: 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]"
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 monitor exits on i
Read more
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]" 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 monitor exits on i
My personal plugin marketplace for Claude Code, Anthropic's AI coding assistant.
Repo: bendrucker/claude
Other skills on bendrucker-claude.
cleye
Type-safe CLI argument parsing with cleye, the standard parser for this repo's Bun scripts. Use when writing or editing any script that takes arguments (flags,…
activity
Report real device usage from ActivityWatch. Covers per-app time, window titles, and active vs idle spans. Use when asked "what apps did I use", "how long was…
history
Report shell history from atuin's local capture. Covers what commands ran, when, where, and how they exited. Use when asked "what commands did I run", "what…
bun
Bun runtime patterns. Use when running bun commands, working with package.json/bun.lock, writing TypeScript scripts under Bun, or developing Claude Code…
agent-team
Orchestrating Claude Code agent teams. Use when creating teams, spawning teammates, assigning tasks, configuring teammate modes, or setting up team quality…

