Track Linear cycle progress, added scope and days left each morning

Every weekday: how much of the active Linear cycle is complete, how much scope was added since it started, and how many days are left.

Runs
Weekdays at 8:45
Uses
Linear
Posts
Stat tile

What lands on your board

AcmeCycle scope completed55%+20% vs previous period, bettervs last report
Completed32 of 58pts
Scope added10pts
Days left3
Cycle elapsedDay 11 of 14
An example with made-up numbers. Your agent posts your real ones.

What it does

Linear draws the cycle graph well. What it will not do, without a click, is tell you that the cycle grew by a fifth since day one and that most of what is left has not been started.

The agent reads the active cycle through the Linear API, takes completed scope against total scope, compares today's scope with the first day's, and posts the percentage with that context next to it. Product managers get the forecast; the team gets the list of large issues still untouched.

How it works

  1. 1Read the active cycle

    Query team(id: "<team id>") { activeCycle { number startsAt endsAt progress scopeHistory completedScopeHistory issues(first: 100) { nodes { identifier title estimate state { type } } } } } through https://api.linear.app/graphql, or the Linear MCP server.

  2. 2

    2Work out completion

    Completed scope is the last value of completedScopeHistory over the last value of scopeHistory (estimates, or issue counts if the team does not estimate). Linear's own progress counts a started issue as a quarter done, so show it alongside.

  3. 3Measure scope added

    Scope added is the latest scopeHistory value minus the first. To name the issues, read history on each open issue and keep entries whose toCycle is this cycle with a createdAt after startsAt.

  4. 4

    4Count days left and forecast

    Days from today to endsAt, and the share of the cycle elapsed. Forecast the spillover from the points completed per day so far, and call the cycle at risk when completion trails the elapsed share by more than 15 points.

  5. 5

    5Report

    Completion, Linear's progress figure, scope added, days left, the forecast, and the three largest open issues.

  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

  • Completed: share of the cycle's scope done, with Linear's own progress figure.
  • Scope added since the cycle started, in points and issues.
  • Days left, against where an even pace would be.
  • Still open: the largest issues not yet started.
  • A one-line forecast of how much will spill into the next cycle.

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/linear-cycle-progress/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the linear-cycle-progress skill

    Or paste the prompt instead of installing:

    promptUsing the Linear GraphQL API (or the Linear MCP server), read the active cycle of team ENG: number, startsAt, endsAt, progress, scopeHistory, completedScopeHistory, and its issues with estimate and state. Tell me the share of scope completed (last completedScopeHistory value over last scopeHistory value), Linear's own progress figure, scope added since the cycle started (last scopeHistory minus first) and which issues were added, and days left until endsAt. Compare completion with the share of the cycle elapsed and forecast how many points will spill into the next cycle. List the three largest open issues.
  3. Put it on a schedule

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

    crontab45 8 * * 1-5 claude -p "Run the linear-cycle-progress 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 stat tile. How setup works

View the SKILL.mdRaw file
SKILL.md---
name: linear-cycle-progress
description: "Every weekday: how much of the active Linear cycle is complete, how much scope was added since it started, and how many days are left. Use when the user asks for this, or when it runs on a schedule."
---

# Linear cycle progress

Every weekday: how much of the active Linear cycle is complete, how much scope was added since it started, and how many days are left.

Linear draws the cycle graph well. What it will not do, without a click, is tell you that the cycle grew by a fifth since day one and that most of what is left has not been started.

The agent reads the active cycle through the Linear API, takes completed scope against total scope, compares today's scope with the first day's, and posts the percentage with that context next to it. Product managers get the forecast; the team gets the list of large issues still untouched.

## 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

- A Linear account in the team, and the team's ID or key (such as `ENG`).
- The Linear MCP server or connector, or a personal API key in `LINEAR_API_KEY`, sent as the `Authorization` header to the GraphQL API.

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

### Steps

1. **Read the active cycle** (Linear): Query `team(id: "<team id>") { activeCycle { number startsAt endsAt progress scopeHistory completedScopeHistory issues(first: 100) { nodes { identifier title estimate state { type } } } } }` through `https://api.linear.app/graphql`, or the Linear MCP server.
2. **Work out completion**: Completed scope is the last value of `completedScopeHistory` over the last value of `scopeHistory` (estimates, or issue counts if the team does not estimate). Linear's own `progress` counts a started issue as a quarter done, so show it alongside.
3. **Measure scope added** (Linear): Scope added is the latest `scopeHistory` value minus the first. To name the issues, read `history` on each open issue and keep entries whose `toCycle` is this cycle with a `createdAt` after `startsAt`.
4. **Count days left and forecast**: Days from today to `endsAt`, and the share of the cycle elapsed. Forecast the spillover from the points completed per day so far, and call the cycle at risk when completion trails the elapsed share by more than 15 points.
5. **Report**: Completion, Linear's progress figure, scope added, days left, the forecast, and the three largest open issues.

## Route B: the browser

### What you need

- Signed in to Linear as a member of the workspace and the team; cycles must be enabled for that team.

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

### Steps

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

1. **Open the current cycle**: Linear opens your workspace. In the sidebar expand the team (for example **ENG**), click **Cycles**, then **Current** at the top. The page header shows the cycle number and its start and end dates.
2. **Read the cycle graph**: Press `Cmd/Ctrl + I` to open the cycle details sidebar. The gray line is total scope, the solid blue line is completed, the yellow line is started, and the dotted blue line is the even-pace target. Read today's completed and scope values, and the scope value on the first day.
3. **Work out completion and added scope**: Completion is completed over scope today, in estimate points or issue counts. Scope added is today's scope minus the first day's. Linear's own percentage in the same sidebar counts started issues as a quarter done, so show both.
4. **Count days left and forecast**: Days from today to the end date, and the share of the cycle elapsed. Forecast the spillover from the points completed per day so far; call the cycle at risk when completion trails the elapsed share by more than 15 points.
5. **List the largest open issues**: In the cycle's issue list, use the display options to group by **Status** and sort by **Estimate**, and take the three largest issues still in Todo. To name issues added mid-cycle, open an issue's activity: it shows when it was added to the cycle.

Note: Scope read off the graph is approximate to a point or two; the API's `scopeHistory` is exact. The cycle graph only appears for teams that estimate or have at least a few issues in the cycle.

## The report

- **Completed**: share of the cycle's scope done, with Linear's own progress figure.
- **Scope added** since the cycle started, in points and issues.
- **Days left**, against where an even pace would be.
- **Still open**: the largest issues not yet started.
- A one-line forecast of how much will spill into the next cycle.

## 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": "linear-cycle-progress/<date of this run, e.g. 2026-10-16>",
  "item_key": "linear-cycle-progress",
  "project": "Acme",
  "source": "Linear cycle progress skill",
  "kind": "metric",
  "title": "Cycle 42 is 55% complete with 3 days left",
  "metric": {
    "label": "Cycle scope completed",
    "value": 55,
    "unit": "%",
    "better": "higher",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "Completed",
            "value": "32 of 58",
            "unit": "pts"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Scope added",
            "value": 10,
            "unit": "pts",
            "tone": "warn"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Days left",
            "value": 3
          }
        }
      ]
    },
    {
      "type": "Progress",
      "props": {
        "label": "Cycle elapsed",
        "value": 79,
        "text": "Day 11 of 14"
      }
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Open issue",
          "Estimate",
          "State"
        ],
        "align": [
          "left",
          "right",
          "left"
        ],
        "rows": [
          [
            "ENG-882 Usage-based billing preview",
            8,
            "Todo"
          ],
          [
            "ENG-891 Proration on plan changes",
            5,
            "In Progress"
          ],
          [
            "ENG-903 New invoice email",
            5,
            "Todo"
          ]
        ]
      }
    },
    {
      "type": "KeyValue",
      "props": {
        "items": [
          {
            "key": "Linear progress",
            "value": "60%, counting started work at partial credit"
          },
          {
            "key": "Scope at start",
            "value": "48 points"
          }
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "At 2.9 points a day, about 17 of the 26 open points spill into Cycle 43.",
        "tone": "warn"
      }
    }
  ],
  "size": "md"
}
JSON
```

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

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

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

```bash
45 8 * * 1-5 claude -p "Run the linear-cycle-progress 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/linear-cycle-progress#schedule

Source: https://briefkin.dev/skills/linear-cycle-progress

What your agent needs

  • A Linear account in the team, and the team's ID or key (such as ENG).

  • The Linear MCP server or connector, or a personal API key in LINEAR_API_KEY, sent as the Authorization header to the GraphQL API.

Connecting Linear

  1. Linear MCP server, Linear's official remote server at https://mcp.linear.app/mcp. Add Linear from Claude's connector directory, or run claude mcp add --transport http linear https://mcp.linear.app/mcp in Claude Code, and sign in with OAuth.
  2. GraphQL API with a personal API key. Create a key in Linear's settings under Security & access, store it in LINEAR_API_KEY, and send it as the Authorization header with no Bearer prefix. For a workspace bot, an OAuth app with the read scope does the same job.

When you create the key, give it Read access and only the teams in the report; it then can't create or edit issues.

Questions

Why is its percentage lower than Linear's?

Linear's progress field counts a started issue as a quarter done, so a cycle full of started work looks further along. The skill leads with completed scope only, which is what will actually close, and shows Linear's figure next to it.

Does it handle several teams?

Each team has its own active cycle, so run it once per team key with its own item_key. A workspace query, cycles(filter: { isActive: { eq: true } }), returns them all at once if you want one combined card.

Do I need Briefkin to use the Linear cycle progress 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 stat tile, 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 Linear pages themselves: the agent opens linear.app 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.

Watch cycle scope completed on your board, run after run

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.