# Connect Linear

> Monitor Linear with its own issue filters. New matches, status changes, issues in triage, SLAs at risk, your mentions and projects going off track reach your Mac's notch.

Source: https://coisland.app/docs/connect-linear/

## What you need

- **You need:** Personal API key, Read, from Settings › Account › Security & access
- **The form asks:** Connector name, Workspace, Personal API key
- **You can watch:** Issues, Status changes, New in triage, SLA at risk, Inbox, Project health
- **Access:** GraphQL queries only, with a Read key

To connect Linear to CoIsland you need a personal API key. No admin, no OAuth app and no developer registration: CoIsland calls Linear's GraphQL API at `https://api.linear.app/graphql` straight from your Mac, with no CoIsland server or account in between, and keeps the key in your login Keychain. This page covers creating the key, the connector form, the six Linear monitor kinds with filters you can paste, and the errors you may meet.

## Create a Linear personal API key

1. In Linear, open **Settings › Account › Security & access**.
2. Under **Personal API keys**, create a new key and name it `CoIsland`.
3. For its permissions, pick **Read** only. CoIsland never writes to Linear.
4. Optionally, restrict the key to some teams. Monitors then see only those teams, and **Test connector** says how many teams the key sees, so the restriction is visible.
5. Copy the key. It is shown once.

**No Personal API keys section?** Workspace admins decide whether members may create keys, under **Settings › Administration › API › Member API keys**. If it is off, ask a workspace admin to allow Member API keys: CoIsland has no other way in, since OAuth would need an app registered by an admin. Admins can also see and revoke members' keys there.

A key belongs to one workspace. For several workspaces, add one connector per key.

## Connect Linear in CoIsland

Open **Settings › Connectors**, click **+** at the top right (or **Add Connector** when you have none yet), and choose **Linear**.

| Field | What to enter |
|---|---|
| Connector name | What monitors call it: `linear`, or your workspace once you type it. Letters, digits, `_` and `-`. |
| Workspace | Optional: what follows `linear.app/` in your Linear address, such as `acme`. A pasted issue link works too. |
| Personal API key | The key you created. |

Click **Test connector**, which saves nothing. It asks Linear who the key is, which workspace it belongs to and how many teams it sees, and reads **Connected: Ana Silva · ana@acme.com · Acme (acme) · sees 3 teams**. When you filled in **Workspace** and the key belongs to another one, Test says which: pasting the key of the wrong workspace is caught before any monitor runs.

Click **Add Connector**. The name and workspace go to `~/Library/Application Support/CoIsland/connectors.json`, the key to your login Keychain under `linear/<name>`. CoIsland sends the key as Linear documents it, in the `Authorization` header with no `Bearer` prefix, and never follows a redirect.

## Choose what to watch: the six Linear monitor kinds

Open **Monitors**, add a monitor and choose **Linear**. The issue kinds take Linear's own `IssueFilter`, the JSON its API takes, written for you by the fields in the editor (teams, states, priority, assignee, labels, age). A filter the fields cannot show, such as one with `or`, stays editable as JSON. The inbox and project health take `key:value` words.

A new-items monitor's first check records what already matches and raises nothing. **Test** runs the monitor once and shows what would alert.

### Issues

An issue alerts when it starts matching, tracked by its ID. Open issues assigned to you:

```json
{"assignee":{"isMe":{"eq":true}},"state":{"type":{"nin":["completed","canceled"]}}}
```

Urgent issues in team ENG:

```json
{"priority":{"in":[1]},"team":{"key":{"eq":"ENG"}}}
```

More filters that work as presets: due within a day `{"dueDate":{"lt":"P1D"}}`, blocked `{"hasBlockedByRelations":{"eq":true}}`, joining the active cycle `{"cycle":{"isActive":{"eq":true}}}`, with customer requests `{"customerCount":{"gt":0}}`. Priorities are numbers: 1 Urgent, 2 High, 3 Medium, 4 Low, 0 none. Relative dates are ISO 8601 durations: `-P1D` is a day ago, `P1D` a day from now.

For a cycle about to end with open work, use the filter below with **Alert when** set to a count greater than 0:

```json
{"cycle":{"endsAt":{"lt":"P1D"},"isActive":{"eq":true}},"state":{"type":{"nin":["completed","canceled"]}}}
```

### Status changes

An issue alerts each time it lands in a new workflow state, with the state it came from (`In Progress → In Review`). A state entered more than an hour before the previous check does not alert: the issue came back into your filter, it did not move.

```json
{"team":{"key":{"eq":"ENG"}}}
```

### New in triage

An issue alerts when it enters a team's Triage. Name the team; triage must be on for it in Linear. Accepting the issue into the backlog alerts nothing.

```json
{"team":{"key":{"eq":"ENG"}}}
```

### SLA at risk (Linear Business and Enterprise)

An issue alerts when its SLA turns high risk, and once more when it breaches. Name the team. To watch other risk levels, add `slaStatus` yourself:

```json
{"slaStatus":{"in":["MediumRisk","HighRisk","Breached"]},"team":{"key":{"eq":"ENG"}}}
```

### Inbox

Your own Linear notifications: mentions, replies, assignments and the rest, by category. Your 50 newest are read at each check; a notification older than the previous check does not alert.

```text
category:mentions,commentsAndReplies
```

`category:all` watches every category.

### Project health

A project update alerts when it is posted with a health you pick, at risk and off track unless you say otherwise. Updates of the last 14 days are read.

```text
health:atRisk,offTrack team:ENG
```

Add `project:<slug>` to watch one project; the editor lists them.

## What a Linear alert shows

In the notch, each issue's second line reads `ENG-123 · In Review · Urgent · Ana · SLA 14:30`: its reference, state, priority, owner and deadline. SLA and due times are absolute, so a card read between checks never goes stale. A click opens the alert in CoIsland; **Open in Linear** is on the alert page.

The alert page shows each issue at once as the monitor saw it, then fills in live from Linear: the current state, labels in their colours, the description and the five latest comments, rendered from Linear's Markdown with raw HTML and scripts removed. A status alert adds who moved it and the issue's state history; an inbox alert highlights the comment it is about. Images uploaded to Linear need your key, which never reaches the page, so they show as their alt text.

## Rate limits

Linear allows 2,500 requests and 3,000,000 complexity points an hour for each user, across all their keys. A monitor checked every 5 minutes uses 12 requests an hour for its first page of 50 issues, so 20 Linear monitors use about a tenth of the allowance. When Linear says the limit is reached, the check backs off and tries again later; when less than a tenth is left, the monitor warns you first.

A check reads up to 250 issues (5 pages of 50). When more match, nothing is compared and the monitor asks you to narrow the filter.

## What a Linear monitor's watch file looks like

```sql
-- name: Assigned to me
-- kind: linear.issues
-- connector: acme
-- every: 5m
-- alert: new-rows

{"assignee":{"isMe":{"eq":true}},"state":{"type":{"nin":["completed","canceled"]}}}
```

The kinds are `linear.issues`, `linear.status`, `linear.triage`, `linear.sla`, `linear.inbox` and `linear.project-updates`. Changing the filter, the kind or the connector starts a new baseline. [Watch files](https://coisland.app/docs/watch-files/) lists every header key.

## Troubleshooting Linear connector errors

- **The token was refused. Check it has not expired or been revoked.** Linear answered `AUTHENTICATION_ERROR`: the key was revoked or mistyped. Create a new key, add it as a connector and pick it under **Runs on**.
- **This key belongs to workspace X, not Y.** The key is from another workspace. Fix **Workspace**, or paste the right key.
- **Rate limited; retry after …** Linear's hourly limit for your account is used up, perhaps by another tool using your keys. Checks resume on their own.
- **Linear refused the request:** then Linear's reason, such as a filter field it does not know. Fix the JSON; the fields in the editor always write a valid filter.
- **Pick a team: triage is watched team by team.** Add a team to a New in triage or SLA at risk monitor.
- **It was deleted or is not visible to this key.** On the alert page: the issue was deleted, or the key cannot see its team.
- **No Linear connector is named acme.** A monitor's `-- connector:` line names a connector that does not exist.
- A filter on a team the key cannot see returns no issues, without an error. **Test connector** shows how many teams the key sees.
- An archived issue leaves a monitor quietly; unarchived and matching again, it alerts again.

## Common questions

### Does CoIsland need a Linear admin?

No, unless your workspace turned off Member API keys. A member creates a personal key in their own account settings.

### Can CoIsland change my Linear issues?

No. It only reads, and a **Read** key is all it needs. The key stays in your login Keychain and goes only to `api.linear.app`.

### Which filters can a Linear monitor use?

Any `IssueFilter` Linear's API accepts, as JSON. The editor writes the common ones for you and keeps anything else as text.

Next: [Getting started](https://coisland.app/docs/getting-started/), or the [Linear connector](https://coisland.app/linear/) for everything it can watch.
