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 pathgroup/projectis inferred fromgit remote get-url originin 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>. - If no argument is given, 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.
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 to handle. In pipeline-id mode the script 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_idis the GitLab pipeline ID.{"type":"conflicts","sha":"..."}: MR reports merge conflicts against the target branch. MR mode only.{"type":"queued-timeout","minutes":N}: pipeline has been queued longer than the threshold.{"type":"api-error","consecutive":N}: consecutiveglabfailures crossed the threshold.{"type":"rate-limited","retry_after":"..."}: emitted only whenglabsurfaces structured rate-limit data.{"type":"pr-closed"}: MR was merged, closed, or the source branch was deleted. 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 and pr-closed are never emitted (there is no MR metadata to derive them from).
The script exits on status: success in every mode. 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 naturally:
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 queued-timeout, api-error, or rate-limited, surface the event once and keep the monitor running. Consecutive rate-limit or api-error events indicate the monitor should be stopped manually.
On pr-closed or max-time-reached, the monitor has already exited. Report and finish.
Stopping
The monitor exits on its own for status: success, pr-closed, and max-time-reached. In pipeline-id mode it also exits on status: failing. To stop earlier (for example after surfacing a failure summary to the user), call TaskStop on the monitor task.
Reference
See references/log-parsing.md for how the gitlab:logs agent narrows long job traces via ANSI section_start/section_end markers.