From ci-babysitter
Debug and fix Buildkite CI failures by pulling ALL failure logs before attempting fixes. Use when CI is failing, build is red, tests are broken in Buildkite, or the user says "fix CI", "CI keeps failing", "debug build", or mentions Buildkite failures. Requires the Buildkite MCP server (user-buildkite-read-only-toolsets).
How this skill is triggered — by the user, by Claude, or both
Slash command
/ci-babysitter:buildkite-ci-debuggerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Systematically debug CI failures using Buildkite MCP tools. **The cardinal rule: gather ALL failure context before writing a single line of fix code.**
Systematically debug CI failures using Buildkite MCP tools. The cardinal rule: gather ALL failure context before writing a single line of fix code.
user-buildkite-read-only-toolsetsCallMcpTool with server: "user-buildkite-read-only-toolsets"org_slug (string), pipeline_slug (string), build_number (string), job_id (string)Before touching logs, find the failing build.
# Get the PR number
gh pr list --repo <owner>/<repo> --head <branch-name> --json number --jq '.[0].number'
# Check CI status
gh pr checks <PR_NUMBER> --repo <owner>/<repo>
Use list_builds to find recent builds for the pipeline:
CallMcpTool: user-buildkite-read-only-toolsets / list_builds
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "branch": "<BRANCH>", "per_page": 5 }
Extract org, pipeline, and build number from the URL:
https://buildkite.com/<ORG>/<PIPELINE>/builds/<BUILD_NUMBER>
Fetch the build to see all jobs and their statuses:
CallMcpTool: user-buildkite-read-only-toolsets / get_build
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "build_number": "<BUILD>" }
From the response, extract:
state: "failed"CallMcpTool: user-buildkite-read-only-toolsets / list_annotations
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "build_number": "<BUILD>" }
Annotations often contain pre-formatted failure summaries with test names and error messages. Parse them first — they may give you all the failure info you need without reading raw logs.
DO NOT skip this step. DO NOT fix after reading only one job's logs.
For each failed job, pull failure context in parallel when possible:
CallMcpTool: user-buildkite-read-only-toolsets / search_logs
{
"org_slug": "<ORG>",
"pipeline_slug": "<PIPELINE>",
"build_number": "<BUILD>",
"job_id": "<JOB_ID>",
"pattern": "<PATTERN>",
"context": 5,
"limit": 30
}
Search patterns by failure type:
| Category | Pattern |
|---|---|
| Test failures | `"\) \[.*\]\ |
| Type errors | `"error TS\ |
| Lint errors | `"eslint\ |
| Build errors | `"build failed\ |
| Permission | `"403\ |
| Infrastructure | `"ENOMEM\ |
| General | `"Error:\ |
CallMcpTool: user-buildkite-read-only-toolsets / tail_logs
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "build_number": "<BUILD>", "job_id": "<JOB_ID>", "tail": 80 }
When search results point to an interesting row number, read the surrounding context:
CallMcpTool: user-buildkite-read-only-toolsets / read_logs
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "build_number": "<BUILD>", "job_id": "<JOB_ID>", "seek": <ROW - 20>, "limit": 60 }
Log entries contain ANSI escape codes. Strip them for analysis:
import re
clean = re.sub(r'\x1b\[[0-9;]*m', '', content).strip().replace('\r', '')
When logs are returned as large JSON, use Shell + python3 to parse and extract the relevant lines efficiently. Filter for lines containing proc [playwright], Error, Timeout, Locator, etc.
After collecting ALL logs, create a root-cause analysis table:
| RC# | Root Cause | Error Pattern | Tests Affected | Fix Strategy |
|-----|-----------|---------------|----------------|--------------|
| 1 | ... | ... | ~N tests | ... |
| 2 | ... | ... | ~N tests | ... |
Group failures by root cause, not by job. Many jobs may fail for the same reason.
Priority order:
Fix ALL identified root causes in a single commit when possible. Do not fix one, push, wait for CI, then fix the next — that wastes CI cycles.
gh pr comment <PR> --repo <owner>/<repo> --body "/ci")Use wait_for_build or poll with get_build to check the new build status:
CallMcpTool: user-buildkite-read-only-toolsets / get_build
{ "org_slug": "<ORG>", "pipeline_slug": "<PIPELINE>", "build_number": "<NEW_BUILD>" }
If the build fails again, go back to Phase 2 with the new build number.
/ci retrigger.For elastic/kibana and kibana-pull-request pipeline:
elastic, Pipeline: kibana-pull-request/ci comment to trigger builds/ci retriggerproc [playwright] in logsproc [ftr] in logsBUILDKITE_PARALLEL_JOB suffix — pull logs from ALL failing shardsProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub patrykkopycinski/patryks-treadmill-claude-plugins --plugin ci-babysitter