<!-- Generated by `just docs` from catalog/toolkits/linear.yaml, catalog/expansions/linear.yaml, catalog/evals/scorecard.json. Edit the source, not this file. -->

# Linear

Issue tracking for software teams. Create and triage tickets, run cycles, and manage projects, labels, and comments.

| Property | Value |
| --- | --- |
| Slug | `linear` |
| Definition version | `0.1.0` |
| Base URL | `https://api.linear.app` |
| Auth schemes | `oauth2`, `api_key` |
| Action tools | 38 |
| By class | 17 read, 18 write, 3 destructive |
| Triggers | 0 |
| Provider rate limit | not declared, so outbound calls are unpaced |

## Measured routing accuracy

56 golden cases replayed through the router over the whole index: measured over corpus `ea4f12ad2948` (65 toolkits, 2283 tools indexed and 13 declared uncallable), 38 cases written by hand and 15 cases from the paraphrase pass, plus 3 context cases whose intent names no app and is decided by the session. A case counts as top-1 when its gold tool ranked first and top-8 when it reached the slate at all.

| Measure | Cases | Share |
| --- | --- | --- |
| top-1 | 28/56 | 50.0% |
| top-8 | 47/56 | 83.9% |

The sweep is offline: the reranker is a deterministic identity fake that returns candidates in the order retrieval produced them, so top-1 measures retrieval order rather than a reranked slate. `just eval-live` measures the same cases through the live reranker.

## Authentication

Connect an entity with `ConnectionsService.InitiateConnection`, naming this toolkit's slug. Credentials stay in the connections vault; callers hold connected-account ids only.

### `oauth2`

| Property | Value |
| --- | --- |
| Authorization URL | `https://linear.app/oauth/authorize` |
| Token URL | `https://api.linear.app/oauth/token` |
| Default scopes | `read`, `write` |
| Refresh tokens | yes, the refresh daemon renews ahead of expiry |

### `api_key`

| Property | Value |
| --- | --- |
| Placement | `header` |
| Name | `Authorization` |
| Rendered as | `{key}` |

Submit the key with `ConnectionsService` rather than putting it in a request; it is sealed at rest and never returned.

## Tools

38 action tools. The catalog-wide slug is `linear.<tool>`, which is what `search_tools` returns and `call_tool` takes.

### `linear.create_issue`

Create a new issue: a ticket, task, bug, or story on a team. Use when the user wants to open, file, log, or add a new item to track. Requires a team; title, description, assignee, priority, labels, state, due date, and estimate are all optional at creation.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_id` | string | no | Optional user id to assign on creation. |
| `description` | string | no | Optional issue body in markdown. |
| `due_date` | string (date) | no | Optional due date, ISO 8601 (YYYY-MM-DD). |
| `estimate` | number | no | Optional point or time estimate. |
| `label_ids` | array of string | no | Optional label ids to attach on creation. |
| `priority` | integer | no | Optional priority: 0 none, 1 urgent, 2 high, 3 medium, 4 low. |
| `project_id` | string | no | Optional project id to file the issue under. |
| `state_id` | string | no | Optional workflow state id to start in. |
| `team_id` | string | **yes** | Linear team id the issue belongs to. |
| `title` | string | **yes** | Issue title. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.id` | string |  |
| `issue.identifier` | string |  |
| `issue.title` | string |  |
| `issue.url` | string |  |
| `success` | boolean |  |

Also retrieved by: "open a ticket on a linear team", "file a bug against the team's board", "log a new task in the issue tracker", "add an item to the backlog", "start tracking a new story", "write up a new issue for the team".

### `linear.get_issue`

Get one issue's full status and details by id or identifier, one call for everything about it. Use for a specific known ticket. To find issues by keyword, use search_issues; to list many, use list_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier, e.g. "ENG-123". |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `assignee` | object |  |
| `assignee.id` | string |  |
| `assignee.name` | string |  |
| `createdAt` | string |  |
| `description` | string |  |
| `dueDate` | string |  |
| `estimate` | number |  |
| `id` | string |  |
| `identifier` | string |  |
| `labels` | object |  |
| `labels.nodes` | array of object |  |
| `labels.nodes[].id` | string |  |
| `labels.nodes[].name` | string |  |
| `priority` | integer |  |
| `project` | object |  |
| `project.id` | string |  |
| `project.name` | string |  |
| `state` | object |  |
| `state.name` | string |  |
| `state.type` | string |  |
| `team` | object |  |
| `team.id` | string |  |
| `team.key` | string |  |
| `title` | string |  |
| `updatedAt` | string |  |
| `url` | string |  |

Also retrieved by: "what's going on with this ticket", "pull up ticket details", "show me this bug's status", "look up a specific task by number".

### `linear.update_issue`

Edit an issue's title or description text. Use when the user wants to rename a ticket or rewrite its body. For a single-field change like assignee, priority, state, due date, estimate, or project, use the dedicated tool for that field instead (faster and less error-prone).

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | New body in markdown. |
| `issue_id` | string | **yes** | Linear issue id or identifier, e.g. "ENG-123". |
| `title` | string | no | New title. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.description` | string |  |
| `issue.id` | string |  |
| `issue.title` | string |  |
| `issue.updatedAt` | string |  |
| `success` | boolean |  |

Also retrieved by: "rename this ticket", "rewrite the ticket description", "edit the task's title", "change what this bug says".

### `linear.search_issues`

Keyword search across issue titles and descriptions, optionally scoped to a team. Use when the user names a topic, phrase, or word to find, not a filter. For a filtered listing (by team, state, or assignee) use list_issues; for the caller's own open work use list_my_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `query` | string | **yes** | Free-text search term. |
| `team_id` | string | no | Optional team id to restrict the search to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `results` | array of object |  |
| `results[].id` | string |  |
| `results[].identifier` | string |  |
| `results[].state` | object |  |
| `results[].state.name` | string |  |
| `results[].title` | string |  |
| `results[].url` | string |  |

Also retrieved by: "find tickets mentioning a keyword", "look for a bug about something", "search the backlog for a topic", "dig up tasks that mention this word", "dig through everything for any mention of a topic".

### `linear.list_issues`

List issues on a team's board filtered by state, assignee, or both. Use for "show open tickets", "what's on the backlog", or "issues assigned to X". For a keyword search use search_issues; for the caller's own issues use list_my_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_id` | string | no | Optional assignee user id to filter to. |
| `limit` | integer | no | Max results, default 50. |
| `state_id` | string | no | Optional workflow state id to filter to. |
| `team_id` | string | **yes** | Team id whose issues to list. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].assignee` | object |  |
| `nodes[].assignee.name` | string |  |
| `nodes[].id` | string |  |
| `nodes[].identifier` | string |  |
| `nodes[].state` | object |  |
| `nodes[].state.name` | string |  |
| `nodes[].title` | string |  |
| `nodes[].url` | string |  |

Also retrieved by: "show open tickets for a team", "what's on the backlog", "see everything assigned to someone", "browse the board", "what tasks are in this state".

### `linear.list_my_issues`

List issues assigned to the caller's own account. Use for "my tickets", "what's on my plate", or "my open tasks". For anyone else's or a team's issues use list_issues; for a keyword search across everyone's issues use search_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].id` | string |  |
| `nodes[].identifier` | string |  |
| `nodes[].state` | object |  |
| `nodes[].state.name` | string |  |
| `nodes[].title` | string |  |
| `nodes[].url` | string |  |

Also retrieved by: "what's on my plate", "show my open tickets", "my assigned tasks", "what am I working on", "my to-do list here".

### `linear.assign_issue`

Assign an issue to a person. Use when the user says to hand off, route, or give a ticket to someone, or to take it themselves. Only changes the assignee; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `assignee_id` | string | **yes** | User id to assign the issue to. |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.assignee` | object |  |
| `issue.assignee.id` | string |  |
| `issue.assignee.name` | string |  |
| `issue.id` | string |  |
| `success` | boolean |  |

Also retrieved by: "hand this ticket to someone", "give this bug to a teammate", "route this task to a person", "put someone's name on this issue", "make someone responsible for a ticket".

### `linear.set_issue_priority`

Set the priority level of an issue: urgent, high, medium, low, or none. Use when the user says to bump, escalate, deprioritize, or mark a ticket's urgency. Only changes priority; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `priority` | integer | **yes** | 0 none, 1 urgent, 2 high, 3 medium, 4 low. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.id` | string |  |
| `issue.priority` | integer |  |
| `success` | boolean |  |

Also retrieved by: "bump this ticket's urgency", "mark this as high priority", "make this a low priority item", "escalate this bug", "deprioritize this task".

### `linear.move_issue_to_state`

Move an issue to a different workflow state, such as in progress, in review, done, or cancelled. Use when the user says to change a ticket's status, mark it done, start it, or reopen it. Only changes state; other fields are untouched. See list_workflow_states for the state ids a team has.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `state_id` | string | **yes** | Target workflow state id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.id` | string |  |
| `issue.state` | object |  |
| `issue.state.name` | string |  |
| `success` | boolean |  |

Also retrieved by: "mark this ticket as done", "move this to in progress", "change this bug's status", "reopen this task", "send this back to backlog".

### `linear.set_issue_due_date`

Set or clear an issue's due date. Use when the user says a ticket is due, needed by, or deadlined on a date, or to remove its deadline. Only changes the due date; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `due_date` | string (date) | no | ISO 8601 date (YYYY-MM-DD). Omit to clear the due date. |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.dueDate` | string |  |
| `issue.id` | string |  |
| `success` | boolean |  |

Also retrieved by: "when is this ticket due", "set a deadline for this task", "remind me this bug is due friday", "clear the due date".

### `linear.set_issue_estimate`

Set a Linear issue's story point or time estimate, the size the team fills a cycle with. Use when the user says to size, point, or estimate a ticket. Only changes the estimate; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `estimate` | number | **yes** | Point or time estimate value, per the team's scale. |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.estimate` | number |  |
| `issue.id` | string |  |
| `success` | boolean |  |

Also retrieved by: "size this ticket", "point this story", "how many hours is this task", "set story points".

### `linear.add_label_to_issue`

Attach an existing label to an issue. Use when the user says to tag, label, or categorize a ticket. The label must already exist; use create_label first if it does not.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `label_id` | string | **yes** | Label id to attach. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.id` | string |  |
| `issue.labels` | object |  |
| `issue.labels.nodes` | array of object |  |
| `success` | boolean |  |

Also retrieved by: "tag this ticket", "put a label on this bug", "categorize this task", "mark this as a certain kind of issue".

### `linear.remove_label_from_issue`

Remove a label from an issue. Use when the user says to untag, unlabel, or take a tag off a ticket. The issue and its other labels are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `label_id` | string | **yes** | Label id to remove. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `success` | boolean |  |

Also retrieved by: "untag this ticket", "take a label off this bug", "remove a tag from the task".

### `linear.archive_issue`

Archive an issue, taking it off active boards and searches without permanently erasing it; an archived issue can be restored by moving it back to a workflow state. Use when the user says to close out, shelve, or clean up an old ticket. To permanently erase it instead, use delete_issue.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `success` | boolean |  |

Also retrieved by: "close out this linear ticket", "shelve a linear issue without erasing it", "clean up a stale bug on the team's board", "take this off the active linear board".

### `linear.delete_issue`

Permanently delete an issue. Irreversible: the ticket, its comments, and its history are gone, unlike archive_issue which can be undone. Use only when the user is explicit about erasing or permanently removing a ticket, not just closing it out.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `success` | boolean |  |

Also retrieved by: "permanently remove this ticket", "erase this task for good", "wipe this bug entirely".

### `linear.comment_on_issue`

Post a comment on an issue. Use when the user wants to reply, note, or leave a message on a ticket. To read existing comments instead, use list_issue_comments.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `body` | string | **yes** | Comment text in markdown. |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `comment` | object |  |
| `comment.body` | string |  |
| `comment.createdAt` | string |  |
| `comment.id` | string |  |
| `comment.url` | string |  |
| `success` | boolean |  |

Also retrieved by: "leave a note on this ticket", "reply on this bug", "post a message on this task", "let them know something on the issue".

### `linear.list_issue_comments`

List the comments already posted on an issue. Use when the user asks what's been said or discussed on a ticket. To add a new one, use comment_on_issue.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `limit` | integer | no | Max results, default 50. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].body` | string |  |
| `nodes[].createdAt` | string |  |
| `nodes[].id` | string |  |
| `nodes[].user` | object |  |
| `nodes[].user.name` | string |  |

Also retrieved by: "what's been said on this ticket", "show the discussion on this bug", "read the notes on this task".

### `linear.create_issue_relation`

Link two issues as blocking, blocked-by, related, or duplicate. Use when the user says one ticket blocks, depends on, relates to, or is a duplicate of another.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | The issue the relation is created from. |
| `related_issue_id` | string | **yes** | The other issue in the relation. |
| `relation_type` | string, one of blocks, related, duplicate | **yes** | Relation kind. "blocks" means issue_id blocks related_issue_id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issueRelation` | object |  |
| `issueRelation.id` | string |  |
| `issueRelation.type` | string |  |
| `success` | boolean |  |

Also retrieved by: "this ticket blocks that one", "link two bugs together", "mark this task as a duplicate of another", "this depends on that ticket".

### `linear.attach_link_to_issue`

Attach an external URL to an issue as a reference link, such as a design file, pull request, or doc. Use when the user says to link, attach, or reference an outside URL on a ticket.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `title` | string | no | Optional display title for the link. |
| `url` | string | **yes** | The URL to attach. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `attachment` | object |  |
| `attachment.id` | string |  |
| `attachment.title` | string |  |
| `attachment.url` | string |  |
| `success` | boolean |  |

Also retrieved by: "attach a pull request to this ticket", "link a design file to this bug", "reference an outside doc on this task".

### `linear.create_project`

Create a new project to group related issues under a shared goal and timeline. Use when the user wants to start a new initiative, epic, or workstream, distinct from a single ticket (create_issue) or a team's cycle.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | Optional project summary. |
| `name` | string | **yes** | Project name. |
| `team_ids` | array of string | **yes** | Team ids the project belongs to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `project` | object |  |
| `project.id` | string |  |
| `project.name` | string |  |
| `project.url` | string |  |
| `success` | boolean |  |

Also retrieved by: "start a new initiative", "kick off a new epic", "begin a workstream", "set up a project for this effort".

### `linear.get_project`

Get one project's details by id: name, description, state, target date, progress, and its teams. Use for a specific known project. To browse many, use list_projects.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Linear project id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `description` | string |  |
| `id` | string |  |
| `name` | string |  |
| `progress` | number |  |
| `state` | string |  |
| `targetDate` | string |  |
| `teams` | object |  |
| `teams.nodes` | array of object |  |
| `teams.nodes[].id` | string |  |
| `teams.nodes[].key` | string |  |
| `url` | string |  |

Also retrieved by: "what's the status of this project", "show project details", "pull up this initiative's info".

### `linear.update_project`

Edit a project's name, description, or state (planned, started, paused, completed, cancelled). Use when the user wants to rename, redescribe, or move a project between those phases.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `description` | string | no | New description. |
| `name` | string | no | New name. |
| `project_id` | string | **yes** | Linear project id. |
| `state` | string, one of planned, started, paused, completed, canceled | no | New project state. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `project` | object |  |
| `project.id` | string |  |
| `project.name` | string |  |
| `project.state` | string |  |
| `project.updatedAt` | string |  |
| `success` | boolean |  |

Also retrieved by: "rename this project", "mark the project as paused", "change the project's phase", "redescribe this initiative".

### `linear.list_projects`

Browse projects across the workspace, optionally scoped to a team. Use when the user asks what initiatives, epics, or workstreams exist. For one specific project's detail, use get_project.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `team_id` | string | no | Optional team id to restrict the listing to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |
| `nodes[].state` | string |  |
| `nodes[].url` | string |  |

Also retrieved by: "what initiatives exist", "browse all the epics", "show workstreams for a team".

### `linear.archive_project`

Archive a project, taking it off active lists without permanently erasing it. Use when the user says a project wrapped up, is done, or should be shelved. Its issues are untouched and stay searchable.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `project_id` | string | **yes** | Linear project id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `success` | boolean |  |

Also retrieved by: "wrap up this project", "shelve this initiative", "mark this epic as done".

### `linear.add_issue_to_project`

Put an existing issue into a project, or move it from one project to another. Use when the user says to file, bucket, or move a ticket under a project. Only changes the project link; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `issue_id` | string | **yes** | Linear issue id or identifier. |
| `project_id` | string | **yes** | Project id to file the issue under. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.id` | string |  |
| `issue.project` | object |  |
| `issue.project.id` | string |  |
| `issue.project.name` | string |  |
| `success` | boolean |  |

Also retrieved by: "file this ticket under a project", "move this bug into an initiative", "bucket this task under an epic".

### `linear.create_project_update`

Post a project status update: a written check-in on progress, on track, at risk, or off track. Use when the user wants to share progress or health on a project, distinct from commenting on a single issue.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `body` | string | **yes** | Update text in markdown. |
| `health` | string, one of onTrack, atRisk, offTrack | no | Optional project health at the time of this update. |
| `project_id` | string | **yes** | Linear project id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `projectUpdate` | object |  |
| `projectUpdate.body` | string |  |
| `projectUpdate.createdAt` | string |  |
| `projectUpdate.health` | string |  |
| `projectUpdate.id` | string |  |
| `success` | boolean |  |

Also retrieved by: "post a status update", "share progress on this project", "write a check-in for this initiative", "mark this project as at risk".

### `linear.list_project_updates`

List the status updates already posted on a project, in order. Use when the user asks for a project's history, progress log, or past check-ins. To post a new one, use create_project_update.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `project_id` | string | **yes** | Linear project id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].body` | string |  |
| `nodes[].createdAt` | string |  |
| `nodes[].health` | string |  |
| `nodes[].id` | string |  |
| `nodes[].user` | object |  |
| `nodes[].user.name` | string |  |

Also retrieved by: "show the project's history", "what were the past check-ins", "read the progress log".

### `linear.list_cycles`

List a team's cycles (sprints), past and upcoming, with their number, name, and date range. Use when the user asks what sprints exist or ran. For only the one running now, use get_active_cycle.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `team_id` | string | **yes** | Team id whose cycles to list. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].endsAt` | string |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |
| `nodes[].number` | integer |  |
| `nodes[].startsAt` | string |  |

Also retrieved by: "what sprints have run", "show past sprints for a team", "list upcoming cycles".

### `linear.get_active_cycle`

Get the sprint currently running for a team: its number, dates, and progress. Use for "what sprint are we in" or "current cycle progress". For past or upcoming cycles, use list_cycles.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `team_id` | string | **yes** | Team id whose active cycle to get. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `endsAt` | string |  |
| `id` | string |  |
| `name` | string |  |
| `number` | integer |  |
| `progress` | number |  |
| `startsAt` | string |  |

Also retrieved by: "what sprint are we in", "current cycle progress", "which sprint is running now".

### `linear.add_issue_to_cycle`

Pull an issue into a cycle (sprint), or take it out of the current one. Use when the user says to schedule a ticket into a sprint, plan it in, or pull it from the current cycle. Only changes the cycle link; other fields are untouched.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `cycle_id` | string | **yes** | Cycle id to schedule the issue into. |
| `issue_id` | string | **yes** | Linear issue id or identifier. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issue` | object |  |
| `issue.cycle` | object |  |
| `issue.cycle.id` | string |  |
| `issue.cycle.number` | integer |  |
| `issue.id` | string |  |
| `success` | boolean |  |

Also retrieved by: "schedule this ticket into the sprint", "pull this task into the current cycle", "plan this bug into next sprint".

### `linear.list_teams`

List every team in the workspace with its key and name. Use when the user asks what teams exist. For one team's own detail, use get_team.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].id` | string |  |
| `nodes[].key` | string |  |
| `nodes[].name` | string |  |

Also retrieved by: "what teams exist", "show all the teams in the workspace", "list every team".

### `linear.get_team`

Get one team's details by id: key, name, description, and whether it's private. Use for a specific known team. To see who's on it, use list_team_members; for its board's issues, use list_issues.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `team_id` | string | **yes** | Linear team id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `description` | string |  |
| `id` | string |  |
| `key` | string |  |
| `name` | string |  |
| `private` | boolean |  |

Also retrieved by: "tell me about this team", "show team details", "what's this team's key".

### `linear.list_team_members`

List the people who belong to a team, with name and email. Use for "who's on the team" or to find an assignee id by name. For the workspace's full user directory instead, use list_users.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `team_id` | string | **yes** | Linear team id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].email` | string |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |

Also retrieved by: "who's on this team", "show the team roster", "who works on this team".

### `linear.list_workflow_states`

List a team's workflow states (statuses), such as backlog, todo, in progress, in review, done, and cancelled, with their ids. Use to look up a state id before calling move_issue_to_state, or when the user asks what statuses a board has.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `team_id` | string | **yes** | Linear team id. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |
| `nodes[].position` | number |  |
| `nodes[].type` | string |  |

Also retrieved by: "what statuses does this board have", "show the workflow stages", "list the states for this team".

### `linear.list_labels`

List labels available to tag issues with, optionally scoped to a team. Use to look up a label id before calling add_label_to_issue, or when the user asks what labels or tags exist.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |
| `team_id` | string | no | Optional team id to restrict the listing to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].color` | string |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |

Also retrieved by: "what tags exist", "show available labels", "list the categories for this team".

### `linear.create_label`

Create a new label (tag) on a team, with a name and optional color. Use when the user wants a new category or tag that does not exist yet, before tagging issues with it via add_label_to_issue.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `color` | string | no | Optional hex color, e.g. "#4ea7fc". |
| `name` | string | **yes** | Label name. |
| `team_id` | string | **yes** | Team id the label belongs to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `issueLabel` | object |  |
| `issueLabel.color` | string |  |
| `issueLabel.id` | string |  |
| `issueLabel.name` | string |  |
| `success` | boolean |  |

Also retrieved by: "make a new tag", "add a label to this team", "create a new category".

### `linear.get_me`

Get the caller's own account: id, name, and email. Use for "who am I logged in as" or to get the caller's own user id for another call. For someone else's account, use get_user or list_users.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `email` | string |  |
| `id` | string |  |
| `name` | string |  |

Also retrieved by: "who am I logged in as", "what's my account here", "my own user info".

### `linear.list_users`

List every user in the workspace, with name and email. Use for a full directory search, "who works here", or to look up someone by name across all teams. For one team's roster only, use list_team_members.

Class `read` (reads only). No scopes beyond the connection's defaults. Calls `POST /graphql`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `limit` | integer | no | Max results, default 50. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nodes` | array of object |  |
| `nodes[].active` | boolean |  |
| `nodes[].email` | string |  |
| `nodes[].id` | string |  |
| `nodes[].name` | string |  |

Also retrieved by: "who works here", "show everyone in the workspace", "full directory of people", "find someone by name across teams".
