Skip to content
Development
Command

/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

From plugin
orchestkit
21535 skills37 agents35 commands
Install
$ npx -y skills add yonatangross/orchestkit --agent claude-code

How it fires

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

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/ci-debug

Context preview

What this command does when you run it.

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

Command definition

ci-debug.md
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>"
disable-model-invocation: false
model: sonnet
context: fork
user-invocable: true
name: ci-debug
background: false
allowed-tools: [Bash, Read, Grep, Glob]

Auto-generated from skills/ci-debug/SKILL.md

Source: https://github.com/yonatangross/orchestkit

/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 | **Publish run cancelled** | Publish-tag workflow run shows `conclusion=cancelled`; artifact never lands | `publish-runs-cancelled-need-redrive.md` | Re-fire via `gh workflow run publish-python.yml -f tag=<tag>` (adjust for your publish workflow). | | 11 | **Vercel status orphaned (path-skip)** | No job in the `fail` bucket, but `Vercel` appears as a *commit status* (not a check-run) stuck `state=pending` with `created_at == updated_at` and no terminal update; all GitHub Actions checks green; `mergeStateStatus=UNSTABLE` + `mergeable=MERGEABLE` on an unprotected base branch | `vercel-pending-orphaned-on-path-skip.md` | Not a failure — cosmetic. Vercel posted a `pending` status then **skipped** the build (project-root path filter, e.g. a docs-only change that never touches `apps/web`), orphaning the status. Safe to merge: `gh pr merge <n> --repo <owner>/<repo> --squash`. Permanent fix: the Verc

Read more
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
215
Stars
0
Views
20
Forks
Active
Maintenance
TypeScript
Language
MIT
License
6m ago
Last commit
7mo ago
Created

Repo: yonatangross/orchestkit

Other commands on orchestkit.