plugins/github-actions/skills/investigating-runs/SKILL.md
--- name: investigating-runs description: Use whenever the user mentions a GitHub Actions / GHA run, even casually — invoke this skill before reaching for raw `gh` commands, because the bundled `gha-snapshot` helper distills `gh run view --log-failed` (a firehose) into a readable block with per-job status, failed-step log tails, and annotations. Specific triggers (any one is enough): a `github.com/.../actions/runs/...` URL; the phrase "GitHub Actions" or "GHA"; the `gh run` CLI; a failing workfl
npx skillsauth add technicalpickles/pickled-claude-plugins plugins/github-actions/skills/investigating-runsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps you investigate failing GitHub Actions runs. It covers checking status, finding the root failure, and reading log output efficiently — not authoring workflow YAML, not driving a fix-then-rerun loop. Load it when working with an existing run (failed CI, red PR check, "why is this broken").
gha-snapshot?One command, one ref, gets you everything: run metadata, per-job status, the failed step's log tail, and annotations — in a single readable block. gh run view --log-failed is a firehose; gha-snapshot distills it.
Use in this order. Don't skip ahead unless the current tier can't answer the question.
gha-snapshot (primary)${CLAUDE_PLUGIN_ROOT}/scripts/gha-snapshot <ref>
Accepts any of:
| Input | Example |
|-------|---------|
| Full URL | gha-snapshot https://github.com/octocat/Hello-World/actions/runs/123 |
| Run ID (uses cwd's repo) | gha-snapshot 123 |
| PR number | gha-snapshot --pr 42 |
| Default (latest failed run on current branch) | gha-snapshot |
Flags: --tail N controls how many lines of failed-step log to include per failed job (default 50).
Exit 0 = snapshot rendered (even if the run failed). Exit 1 = couldn't resolve a run.
gh CLI (secondary)When the snapshot doesn't expose what you need:
gh run list --branch <branch> --status failure --limit 5
gh run view <run-id> --json jobs,conclusion,headSha,event
gh run view <run-id> --log # full log (huge)
gh run view <run-id> --log-failed # failed steps only
gh run rerun <run-id> --failed # transient infra only — see below
gh pr checks <pr-num>
gh workflow view <workflow>
See references/gh-cheatsheet.md for --json field names and jq patterns.
gh api (fallback)For things the wrappers don't cover: GraphQL queries, raw check-run annotations, paged listings.
gh api repos/{owner}/{repo}/actions/runs/{run_id}/jobs
gh api repos/{owner}/{repo}/check-runs/{check_id}/annotations
A gha-snapshot block has five sections in fixed order:
Run: <workflow> #<num> ← header: name, conclusion, duration, trigger, sha, URL
Status: <conclusion> (<dur>)
Trigger: <event> on <branch> @ <sha>
URL: <run-url>
Jobs: ← per-job status with icon (✓ success, ✗ failure, ⊘ skipped)
✓ build (2m 14s) ← passed jobs noted but not detailed
✗ test (1m 03s) — failed at step "..."
⊘ deploy (skipped, dependency failed)
Failed step output (...) ← log tail for each failed step's named step
...
FAIL ...
Annotations: ← grouped by job, `::error::` / `::warning::` / `::notice::`
test: ::error file=...,line=...::message
Links: ← run URL + per-failed-job URLs
Run: ...
test: .../job/<id>
The most valuable section is usually Failed step output. It's the part gh run view --log-failed would have buried under hundreds of unrelated lines.
A common mistake: pointing at the wrong job as "the bug."
fail-fast: true, one matrix leg's failure cancels the rest. The cancelled legs are marked failure but aren't the bug. Find the leg with the earliest failure timestamp.needs: cascade: A job with conclusion skipped because its dependency failed is not the bug. Trace upstream to the failed dependency.uses: org/repo/.github/workflows/x.yml@ref shows in the parent run, but the real log is in the called workflow's own run. The snapshot's link section will point at the parent; click through to the called workflow.See references/failure-patterns.md for more cases.
GitHub Actions emits workflow commands in logs that surface as annotations:
::error file=path,line=N::message — error tied to a file::warning::message — non-fatal::notice::message — informational::group::title / ::endgroup:: — bracket log sectionsThe snapshot's Annotations section extracts these from gh run view --log-failed. Annotations with file= and line= are usually the strongest signal for "where the bug is."
See references/annotation-format.md for the full directive reference.
Don't reflexively gh run rerun --failed. Rerun only when the failure is clearly transient infrastructure:
429 Too Many Requests pulling base images)Worker initialization timeout, host setup failures)Never rerun for:
Resource not accessible by integration — needs a real permissions: fix)If you can't tell whether it's transient, say so to the user and ask.
When a step references actions/<name>@v... and the snapshot's error looks like it might be related to the action's behavior (Error: Input ... not found, Unknown argument), don't guess from training data. Check the action's releases page:
gh release list --repo actions/<name>
gh release view <tag> --repo actions/<name>
Action APIs change between major versions. The current state of actions/checkout@v4 is not what was current at any given training cutoff.
gh subcommands, common flags, --json field names, jq patternstools
--- name: writing-for-scannability description: Use when structuring prose so readers can skim it - drafting or restructuring READMEs, docs, PR or issue bodies, design docs, RFCs, or any long-form text where a wall of prose hides the structure. Also use when explicitly asked to make something scannable or skimmable, convert prose to a list, surface a buried list, fix a wall of text, or decide whether bullets or prose fit. Strong signal: text with parallel sentence shapes, contrast markers ("that
development
Ignore actually-lsp nudges for an ecosystem in this project. Use when the user wants to silence, dismiss, or ignore the LSP setup nudges for a specific ecosystem (Rust, TypeScript, Ruby), or invokes `/actually-lsp-ignore` directly. Writes `dismissed=true` to `.claude/actually-lsp.json`. Persistent across sessions for this project only.
tools
Diagnose and fix LSP setup for the current project's detected ecosystems (Rust, TypeScript, Ruby). Use when the SessionStart hook nudged about a missing LSP plugin, when the env isn't ready (no `bundle install`, no `cargo build`, missing server binary), when LSP calls are failing, or when the user invokes `/actually-lsp-doctor` directly. Walks the per-ecosystem state machine, reports what's missing, then runs the fix.
tools
Use when querying or modifying tasks via the taskwarrior CLI - dense recipes for listing, single-field lookups, multi-task batched lookups, full-text search, and the soft description-length convention. Activates on `task list`, `task add`, `task info`, `task done`, "what's on the backlog", "find a task", or any taskwarrior interaction.