Catch failed GitHub Actions runs on main, with the job and step that broke

Each weekday morning: workflow runs that failed on the default branch in the last 24 hours, the job and step that broke, the error and the commit behind it.

Runs
Weekdays at 8:00
Posts
Report card

What lands on your board

acme-webGitHub Actions failed runs on main · Claude Code

Main is red: e2e failing since yesterday evening

e2e has failed on the last 3 runs, starting at a41c9e2 (#1297). lint failed once overnight and passed on the next run.

WorkflowJob / stepErrorStatus
e2eplaywright / Run testssettings.spec.ts:42 timed out waiting for the Save buttonFailing since 18:12
linteslint / Lintno-unused-vars in app/billing/plan.tsRecovered at 02:30
Broken by
a41c9e2 Move settings to the app router (#1297)
Author
mo
Failed runs
4 in 24 hours: e2e 3, lint 1
ResolveFailed
An example with made-up numbers. Your agent posts your real ones.

What it does

Main goes red at 18:00, and the first person to notice is whoever tries to merge at 10:00 the next morning. Actions emails the person who triggered the run, which on main is whoever merged last, and only if they kept those notifications on.

The agent checks the default branch every morning, opens each failed run, finds the job and step that broke and pulls the first real error line out of the log. It also says whether the workflow is still failing or a later run already went green, and whether a failure looks flaky.

How it works

  1. 1Find the default branch

    gh repo view acme/acme-web --json defaultBranchRef --jq .defaultBranchRef.name, so the same skill works on repos that use main, master or trunk.

  2. 2List failed runs

    gh run list --repo acme/acme-web --branch main --status failure --created ">=2026-10-15" --json databaseId,workflowName,headSha,displayTitle,createdAt,url, with the date set to 24 hours ago.

  3. 3Find the failing job and step

    gh run view <id> --json jobs lists each job with its conclusion and steps; keep the first step whose conclusion is failure. Then read gh run view <id> --log-failed and take the first line that is a real error (Error, FAIL, exit code), skipping setup noise.

  4. 4Check whether it is still red

    Read the newest run of each workflow on the branch (gh run list --workflow <name> --branch main --limit 3). Mark it recovered if that run passed, failing since the first of its consecutive failures if not, and flaky if the same commit both failed and passed.

  5. 5

    5Report

    One row per workflow with job, step, error line, commit and author. Post with work_state: failed while any workflow is still red, and done once all have recovered.

  6. Post it to the board

    With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.

What you get

  • Still failing: workflows whose latest run on the default branch is red.
  • For each: job, step, the first error line, the commit that broke it and its author.
  • Recovered: workflows that failed in the window but have passed since.
  • Flaky: jobs that failed and passed on the same commit.

Install and run it

Pick your agent, where the data comes from and how to schedule it; the commands below follow.

Agent
Data
Schedule
  1. Install the skill

    One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.

    shellcurl -fsSL https://briefkin.dev/skills/github-actions-failed-runs/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the github-actions-failed-runs skill

    Or paste the prompt instead of installing:

    promptFor the GitHub repo acme/acme-web, find GitHub Actions runs that failed on the default branch in the last 24 hours (gh run list --branch <default> --status failure --created ">=DATE"). For each failed run, find the failing job and step (gh run view <id> --json jobs) and the first real error line from gh run view <id> --log-failed. Check whether the latest run of each workflow on the branch has passed since. Report one line per workflow: job, step, error, the commit and author that started the failure, and whether it is still failing, recovered, or looks flaky (failed and passed on the same commit).
  3. Put it on a schedule

    Weekdays at 8:00, from cron on any machine where Claude Code is signed in:

    crontab0 8 * * 1-5 claude -p "Run the github-actions-failed-runs skill"

    Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.

  4. Send it to your board

    Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a report card. How setup works

View the SKILL.mdRaw file
SKILL.md---
name: github-actions-failed-runs
description: "Each weekday morning: workflow runs that failed on the default branch in the last 24 hours, the job and step that broke, the error and the commit behind it. Use when the user asks for this, or when it runs on a schedule."
---

# GitHub Actions failed runs on main

Each weekday morning: workflow runs that failed on the default branch in the last 24 hours, the job and step that broke, the error and the commit behind it.

Main goes red at 18:00, and the first person to notice is whoever tries to merge at 10:00 the next morning. Actions emails the person who triggered the run, which on main is whoever merged last, and only if they kept those notifications on.

The agent checks the default branch every morning, opens each failed run, finds the job and step that broke and pulls the first real error line out of the log. It also says whether the workflow is still failing or a later run already went green, and whether a failure looks flaky.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- Read access to Actions on the repo; on a fine-grained token, the Actions read permission.
- The `gh` CLI signed in, or a GitHub MCP server or connector that can list workflow runs and read job logs.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Find the default branch** (GitHub): `gh repo view acme/acme-web --json defaultBranchRef --jq .defaultBranchRef.name`, so the same skill works on repos that use `main`, `master` or `trunk`.
2. **List failed runs** (GitHub Actions): `gh run list --repo acme/acme-web --branch main --status failure --created ">=2026-10-15" --json databaseId,workflowName,headSha,displayTitle,createdAt,url`, with the date set to 24 hours ago.
3. **Find the failing job and step** (GitHub Actions): `gh run view <id> --json jobs` lists each job with its `conclusion` and `steps`; keep the first step whose conclusion is `failure`. Then read `gh run view <id> --log-failed` and take the first line that is a real error (`Error`, `FAIL`, `exit code`), skipping setup noise.
4. **Check whether it is still red** (GitHub Actions): Read the newest run of each workflow on the branch (`gh run list --workflow <name> --branch main --limit 3`). Mark it recovered if that run passed, failing since the first of its consecutive failures if not, and flaky if the same commit both failed and passed.
5. **Report**: One row per workflow with job, step, error line, commit and author. Post with `work_state: failed` while any workflow is still red, and `done` once all have recovered.

## Route B: the browser

### What you need

- Signed in to GitHub with read access to the repository; the Actions tab must be visible to that account.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://github.com/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Open the repository's Actions tab**: Go to `github.com/<owner>/<repo>` and click **Actions**. In the filter bar set **Branch** to the default branch (`main` on most repos) and **Status** to **Failure**, or type `branch:main is:failure` into the "Filter workflow runs" box. Keep only runs whose time, shown on each row, is within the last 24 hours.
2. **Find the failing job and step**: Open each run. The left pane lists its jobs with a red mark on the failed ones; click one and the failed step opens with its log. Copy the first line that is a real error (`Error`, `FAIL`, `exit code`), skipping setup output. **Search logs** at the top helps on long jobs.
3. **Check whether it is still red**: In the Actions sidebar click the workflow's name and filter by the branch: if the newest run is green the failure has recovered; if several in a row are red, note the first failing commit and author from its row. The same commit both red and green means a flaky job.
4. **Report**: One row per workflow with job, step, error line, commit and author, and whether it is still failing, recovered or flaky.

Note: The Actions filter has no date field, so the 24-hour window is read off the run times by eye; the list is newest first, so stop at the first older row. Logs older than 90 days are gone by default, which never matters here.

## The report

- **Still failing**: workflows whose latest run on the default branch is red.
- For each: job, step, the first error line, the commit that broke it and its author.
- **Recovered**: workflows that failed in the window but have passed since.
- **Flaky**: jobs that failed and passed on the same commit.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "github-actions-failed-runs/<date of this run, e.g. 2026-10-16>",
  "item_key": "github-actions-failed-runs",
  "project": "acme-web",
  "source": "GitHub Actions failed runs on main skill",
  "kind": "update",
  "title": "Main is red: e2e failing since yesterday evening",
  "summary": "**e2e** has failed on the last 3 runs, starting at `a41c9e2` (#1297). **lint** failed once overnight and passed on the next run.",
  "work_state": "failed",
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Workflow",
          "Job / step",
          "Error",
          "Status"
        ],
        "rows": [
          [
            "e2e",
            "playwright / Run tests",
            "settings.spec.ts:42 timed out waiting for the Save button",
            "Failing since 18:12"
          ],
          [
            "lint",
            "eslint / Lint",
            "no-unused-vars in app/billing/plan.ts",
            "Recovered at 02:30"
          ]
        ]
      }
    },
    {
      "type": "KeyValue",
      "props": {
        "items": [
          {
            "key": "Broken by",
            "value": "a41c9e2 Move settings to the app router (#1297)"
          },
          {
            "key": "Author",
            "value": "mo"
          },
          {
            "key": "Failed runs",
            "value": "4 in 24 hours: e2e 3, lint 1"
          }
        ]
      }
    },
    {
      "type": "Links",
      "props": {
        "items": [
          {
            "label": "Latest e2e run",
            "url": "https://github.com/acme/acme-web/actions/runs/11873450912"
          }
        ]
      }
    }
  ]
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

## Run it on a schedule

Suggested: Weekdays at 8:00 (`0 8 * * 1-5`). From cron, with the agent signed in on that machine:

```bash
0 8 * * 1-5 claude -p "Run the github-actions-failed-runs skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/github-actions-failed-runs#schedule

Source: https://briefkin.dev/skills/github-actions-failed-runs

What your agent needs

  • Read access to Actions on the repo; on a fine-grained token, the Actions read permission.

  • The gh CLI signed in, or a GitHub MCP server or connector that can list workflow runs and read job logs.

Connecting GitHub Actions

  1. GitHub MCP Server with the actions toolset, hosted at https://api.githubcopilot.com/mcp/x/actions; append /readonly for read tools only. It lists runs and jobs and fetches job logs.
  2. The gh CLI. gh run list --branch main --status failure --json databaseId,workflowName,conclusion,createdAt finds red runs, and gh run view <run-id> --log-failed prints only the failing steps' output. Set GH_TOKEN for unattended runs.
  3. REST API with a fine-grained token in GITHUB_TOKEN, scoped to the repositories you watch, with Actions: Read and Metadata: Read.

Actions: Read lets the agent list runs and download logs but not rerun, cancel or trigger workflows; grant write only if you want it to retry flaky jobs.

Connecting GitHub

  1. GitHub MCP Server, GitHub's official server, hosted at https://api.githubcopilot.com/mcp/. Sign in with OAuth or a personal access token; add /readonly to the URL, or use a toolset URL such as https://api.githubcopilot.com/mcp/x/pull_requests/readonly, to expose only read tools. It also runs locally (source).
  2. The gh CLI. Run gh auth login once, or set GH_TOKEN for scheduled runs. gh pr list --search "review-requested:@me" --json number,title,url,createdAt and gh api repos/{owner}/{repo}/dependabot/alerts cover most reports.
  3. REST and GraphQL with a fine-grained token. Store it in GITHUB_TOKEN, limit it to the repositories in the report, and grant Read on Metadata, Contents, Pull requests and Issues, plus Dependabot alerts if you report on them.

With every permission on a fine-grained token set to Read, the agent can't push, merge, comment or close anything.

Questions

Does it read logs from private repos?

Yes, with a token that can read Actions on that repo. Logs are kept for 90 days by default (an org can set less), so a 24-hour window is always well inside that.

Can it rerun the failed jobs?

It can with gh run rerun <id> --failed, which needs write access to Actions. The skill leaves that off by default: rerunning a real failure only delays the fix, so it suggests a rerun only for jobs that look flaky.

Do I need Briefkin to use the GitHub Actions failed runs on main skill?

No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a report card, so you can glance at it instead of asking again.

Which agents can run it?

Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.

Can it work without an API or MCP server, from my browser?

Yes. Switch the data source to "Your browser" and the steps change to the GitHub Actions and GitHub pages themselves: the agent opens github.com in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.

Read this report on your board, not in a chat log

Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.

Free during the open beta. No card.