Skip to content

/ci-debug

Diagnose a failing CI run against an 11-pattern playbook. Classifies the failure, cites the relevant memory entry, proposes the exact fix command — but NEVER applies without explicit user approval. Use when a specific PR check or GitHub Actions run failed and you want a

shell
$ npx -y skills add yonatangross/orchestkit --skill ci-debug --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-debug
How auto-invocation works

Context preview

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

Diagnose a failing CI run against an 11-pattern playbook. Classifies the failure, cites the relevant memory entry, proposes the exact fix command — but NEVER applies without explicit user approval. Use when a specific PR check or GitHub Actions run failed and you want a

SKILL.md

ci-debug.SKILL.md
name: ci-debug
license: MIT
compatibility: "Claude Code 2.1.220+ — uses `gh` CLI for GitHub Actions log inspection. Works in interactive sessions and headless `claude -p --bare` invocations (e.g. /ork:ci-sentinel)."
description: "Diagnose a failing CI run against an 11-pattern playbook. Classifies the failure, cites the relevant memory entry, proposes the exact fix command — but NEVER applies without explicit user approval. Use when a specific PR check or GitHub Actions run failed and you want a diagnosis instead of speculation. Don't use for org-wide CI sweeps (that's /status) or for app-level test failures (the playbook is CI-infra-specific)."
argument-hint: "<PR-number | run-URL | job-URL>"
context: fork
# user-typed commands stay interactive; CC >= 2.1.218 backgrounds forks by default (#3093)
background: false
version: 0.2.0
disable-model-invocation: false
author: OrchestKit
tags: [ci, github-actions, debugging, classification, propose-dont-apply]
user-invocable: true
allowed-tools: [Bash, Read, Grep, Glob]
skills: [github-operations, memory]
complexity: medium
persuasion-type: guidance
model: sonnet
metadata:
  category: workflow-automation
  origin: "/insights audit 2026-05-11 — recurring CI-debug pattern across 12 sessions in 3 weeks"
triggers:
  keywords: ["ci failure", "build red", "actions failed", "workflow failed", "PR check failed", "CI broken"]
  examples:
    - "PR #1842 build is red, what happened?"
    - "/ci-debug 822"
    - "/ci-debug https://github.com/owner/repo/actions/runs/12345"
  anti-triggers: ["what's failing across the org", "test broke in my code"]
paths:
  - ".github/workflows/**/*.yml"

/ci-debug — classify a failing CI run

Direct response to the recurring CI-debug pattern surfaced by `/insights`: ~12 sessions in 3 weeks doing the same classification dance. This skill encodes the 11 patterns so the dance becomes a lookup.

Input

User invokes with one of:

  • **PR number**: `/ci-debug 822` (default repo from context; ask if ambiguous)
  • **Run URL**: `/ci-debug https://github.com/owner/repo/actions/runs/12345`
  • **Job URL**: `/ci-debug https://github.com/owner/repo/actions/runs/X/job/Y`

Execution

1. Resolve the failing job

# From PR number:
gh pr checks <n> --repo <owner>/<repo> --json bucket,link,name \
  --jq '.[] | select(.bucket=="fail") | "\(.name)|\(.link)"'

# From run URL:
gh api repos/<owner>/<repo>/actions/runs/<run-id>/jobs \
  --jq '.jobs[] | select(.conclusion=="failure")
                | {id, name, runner_name, started_at, completed_at,
                   steps: [.steps[] | select(.conclusion=="failure") | {name, number}]}'

If multiple jobs failed, pick the one with the **shortest duration** — root cause is usually the first failure; later jobs cascade.

**No job in the `fail` bucket but a check won't settle?** If `gh pr checks` shows zero `fail`-bucket entries yet a status sits in `pending` that never resolves (and `gh pr view --json mergeStateStatus` returns `UNSTABLE` while `mergeable=MERGEABLE`), this is a *stuck external status*, not a failure — jump straight to **Pattern #11**. There is no failing log to fetch; classify on the commit-status metadata (`gh api repos/<o>/<r>/commits/<sha>/status`).

2. Fetch the failing log

gh api repos/<owner>/<repo>/actions/jobs/<job_id>/logs 2>&1 \
  | grep -iE '(error|fail|ERR_|CONFLICT|Process completed with exit code)' \
  | head -30

Capture the **FIRST distinct error message** (later lines often echo).

3. Classify against the playbook

Walk the patterns in order. **First match wins.**

| # | Pattern | Signature in logs | Memory ref | Proposed fix | |---|---------|-------------------|------------|--------------| | 1 | **Billing block** | runner_name empty + steps[] empty + ~3s duration + annotation: "recent account payments have failed or your spending limit needs to be increased" | `billing-surface-hosted-vs-self-hosted.md` | Org admin → Settings → Billing & plans → raise limit / update card. No code change. | | 2 | **Root-lockfile drift** | `ERR_PNPM_OUTDATED_LOCKFILE` mentioning `<ROOT>/typescript/<pkg>/package.json` | `pnpm-lock-root-vs-workspace-duality.md` | `pnpm install --lockfile-only && git add pnpm-lock.yaml && git commit && git push`. | | 3 | **uv.lock drift** | `error: The lockfile at uv.lock needs to be updated` | `changeset-release-uv-lock-drift.md` | `cd python && uv lock` then commit. | | 4 | **ci-shared.yml missing permissions** | startup_failure pattern (empty runner_name + steps[]=[] + ~3s) BUT billing is resolved | `ci-shared-permissions-block-required.md` | Add `permissions: { contents: read, packages: read }` to the caller workflow. | | 5 | **YAML python embed** | YAML parse error pointing at a multi-line block scalar with `python -c` | `yaml-python-embed.md` | Rewrite `python -c` as a separate shell script invocation; never inline multi-line python in YAML. | | 6 | **actionlint shellcheck false-positive** | audit/actionlint job failing with SC2086/SC2046 on workflow YAMLs you didn't touch | `audit-actionlint-triggers-on-workflow-edit.md` | Not required check; safe to merge past if the warnings predate your change. Optional: add shellcheck disable comments. | | 7 | **macOS BSD date %3N** | `%3N` printed literally in CI output / arithmetic fails | `macos-bsd-date-no-percent-3N.md` | Replace `date +%s%3N` with `node -e 'console.log(Date.now())'` or `python3 -c 'import time; print(int(time.time()*1000))'`. | | 8 | **Runner pnpm Rosetta arch drift** | pnpm install fails with "wrong-arch native bin" / dlopen error on a self-hosted runner | `runner-pnpm-rosetta-arch-drift.md` | Restart the affected runner pool; root cause is node x64↔arm64 flips storing wrong-arch native bins in shared cache. | | 9 | **Shallow clone false divergence** | `git status` reports diverged but PR was actually merged | `shallow-clone-false-divergence.md` | `git fetch origin <branch> --unshallow` then `gh pr view --merge-commit` to verify. | | 10 | **P

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withorchestkit

The Complete AI Development Toolkit for Claude Code — 114 skills, 37 agents, 212 hooks. Production-ready patterns for full-stack development.

Get the whole plugin, auto-invoked
Stats
212
Stars
0
Views
22
Forks
Active
Maintenance
TypeScript
Language
MIT
License
29m ago
Last commit
7mo ago
Created

Repo: yonatangross/orchestkit

Other skills on orchestkit.