> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ComposioHQ/agent-orchestrator/llms.txt
> Use this file to discover all available pages before exploring further.

# Linear Tracker Plugin

> Issue tracker plugin for Linear

# Linear Tracker Plugin

The Linear tracker plugin integrates with Linear's issue tracking system, allowing Agent Orchestrator to manage tasks, track progress, and update issue state as agents work.

## Overview

This plugin uses Linear's GraphQL API and supports two authentication methods:

1. **Direct API**: Using `LINEAR_API_KEY` environment variable
2. **Composio SDK**: Using `COMPOSIO_API_KEY` for integrated workflow automation

The plugin automatically detects which method is available and routes requests accordingly.

<Note>
  Linear uses alphanumeric identifiers (e.g., `INT-1234`) rather than numeric issue numbers. Branch names follow the convention `feat/INT-1234`.
</Note>

## Configuration

Configure the Linear tracker plugin in your `agent-orchestrator.yaml`:

```yaml theme={null}
plugins:
  tracker:
    name: linear

projects:
  - id: my-app
    repo: owner/repo-name
    tracker:
      type: linear
      teamId: "abc123-team-uuid"        # Required: Linear team UUID
      workspaceSlug: "my-workspace"     # Optional: for prettier URLs
```

### Configuration Options

<ParamField path="teamId" type="string" required>
  Linear team UUID. Required for creating issues and filtering by team.

  Find your team ID in Linear's URL or via the API.
</ParamField>

<ParamField path="workspaceSlug" type="string">
  Linear workspace URL slug for generating issue URLs.

  Example: If your Linear URL is `https://linear.app/my-workspace/issue/INT-123`, the slug is `my-workspace`.
</ParamField>

## Requirements

<Warning>
  Prerequisites:

  * `LINEAR_API_KEY` environment variable (for direct API access)
    OR
  * `COMPOSIO_API_KEY` environment variable (for Composio SDK)
  * Network access to `https://api.linear.app/graphql`
</Warning>

### Authentication Setup

**Option 1: Direct API Key**

```bash theme={null}
# Get your API key from Linear settings:
# https://linear.app/settings/api

export LINEAR_API_KEY="lin_api_xxxxxxxxxxxxxx"
```

**Option 2: Composio SDK**

```bash theme={null}
# Install Composio SDK
pnpm add @composio/core

# Set API keys
export COMPOSIO_API_KEY="your-composio-key"
export COMPOSIO_ENTITY_ID="default"  # Optional, defaults to "default"
```

### Finding Your Team ID

```graphql theme={null}
# Run this query in Linear's API explorer:
# https://linear.app/settings/api

query {
  teams {
    nodes {
      id
      name
      key
    }
  }
}
```

Or use the Linear CLI:

```bash theme={null}
# Linear URL contains team key (e.g., INT)
# https://linear.app/my-workspace/team/INT/active
```

## Features

### Issue Operations

**Get Issue**

Fetch a single issue by identifier:

```typescript theme={null}
const issue = await tracker.getIssue("INT-1234", project);
// Returns: { id, title, description, url, state, labels, assignee, priority }
```

**List Issues**

List issues with filters:

```typescript theme={null}
const issues = await tracker.listIssues({
  state: "open",                    // "open" | "closed" | "all"
  labels: ["bug", "frontend"],     // Filter by labels
  assignee: "John Doe",             // Filter by display name
  limit: 30                         // Max results (default: 30)
}, project);
```

<Info>
  The Linear API automatically filters by `teamId` from the project config, so you only see issues for your team.
</Info>

**Create Issue**

Create a new issue:

```typescript theme={null}
const issue = await tracker.createIssue({
  title: "Bug: App crashes on startup",
  description: "## Steps to Reproduce\n\n1. Open app\n2. Crashes",
  labels: ["bug", "high-priority"],
  assignee: "John Doe",
  priority: 1  // 0=None, 1=Urgent, 2=High, 3=Normal, 4=Low
}, project);
```

**Update Issue**

Update issue state, labels, assignee, or add comments:

```typescript theme={null}
await tracker.updateIssue("INT-1234", {
  state: "closed",                  // "open" | "in_progress" | "closed"
  labels: ["fixed"],                // Adds labels (additive)
  assignee: "Jane Smith",           // Change assignee by display name
  comment: "Fixed in PR #456"       // Add comment
}, project);
```

### Issue State Mapping

Linear State Type → Tracker State:

| Linear State | Tracker State |
| - | - |
| `triage` | `open` |
| `backlog` | `open` |
| `unstarted` | `open` |
| `started` | `in_progress` |
| `completed` | `closed` |
| `canceled` | `cancelled` |

<Note>
  Linear has rich workflow states. The plugin maps them to standardized tracker states while preserving Linear's native state information.
</Note>

### Priority Levels

Linear uses numeric priorities:

| Priority | Value | Typical Use |
| - | - | - |
| No priority | 0 | Unset |
| Urgent | 1 | Critical bugs |
| High | 2 | Important features |
| Normal | 3 | Standard work |
| Low | 4 | Nice-to-have |

### Prompt Generation

The plugin generates context-aware prompts for agents:

```typescript theme={null}
const prompt = await tracker.generatePrompt("INT-1234", project);
```

Example output:

```
You are working on Linear ticket INT-1234: Fix login redirect bug
Issue URL: https://linear.app/my-workspace/issue/INT-1234

Labels: bug, authentication
Priority: Urgent

## Description

Users are redirected to the wrong page after login...

Please implement the changes described in this ticket. When done, commit and push your changes.
```

### Branch Naming

The plugin generates branch names from issue identifiers:

```typescript theme={null}
tracker.branchName("INT-1234", project);
// Returns: "feat/INT-1234"
```

This follows Linear's recommended convention for branch names.

### Issue URLs and Labels

```typescript theme={null}
// Generate URL from issue identifier
tracker.issueUrl("INT-1234", project);
// Returns: "https://linear.app/my-workspace/issue/INT-1234"

// Extract identifier from URL
tracker.issueLabel("https://linear.app/my-workspace/issue/INT-1234", project);
// Returns: "INT-1234"
```

## Usage Example

### Start Agent on Issue

```yaml theme={null}
# agent-orchestrator.yaml
projects:
  - id: my-app
    repo: owner/my-app
    path: ~/repos/my-app
    defaultBranch: main
    tracker:
      type: linear
      teamId: "abc123-team-uuid"
      workspaceSlug: "my-workspace"
```

```bash theme={null}
# Start agent on Linear issue
ao start my-app "INT-1234"

# The agent will:
# 1. Fetch issue details from Linear
# 2. Create branch "feat/INT-1234"
# 3. Generate prompt with issue context (including priority)
# 4. Start coding to fix the issue
```

### Auto-Update on Progress

```yaml theme={null}
# Configure reactions to update Linear when work starts
reactions:
  - event: session_started
    action: run
    command: |
      # Update Linear issue to "In Progress"
      ao tracker update $ISSUE_ID --state in_progress
```

## Troubleshooting

<Accordion title="Error: LINEAR_API_KEY environment variable is required">
  The plugin couldn't find authentication credentials.

  Solution:

  ```bash theme={null}
  # Option 1: Direct API
  export LINEAR_API_KEY="lin_api_xxxxxxxxxxxxxx"

  # Option 2: Composio SDK
  pnpm add @composio/core
  export COMPOSIO_API_KEY="your-composio-key"
  ```
</Accordion>

<Accordion title="Error: Linear tracker requires 'teamId' in project tracker config">
  The `teamId` field is missing from project configuration.

  Solution:

  ```yaml theme={null}
  projects:
    - id: my-app
      tracker:
        type: linear
        teamId: "abc123-team-uuid"  # Add this
  ```

  Find your team ID in Linear's API explorer.
</Accordion>

<Accordion title="Error: Composio SDK (@composio/core) is not installed">
  You're using `COMPOSIO_API_KEY` but the SDK isn't installed.

  Solution:

  ```bash theme={null}
  pnpm add @composio/core
  ```

  Or switch to direct API with `LINEAR_API_KEY`.
</Accordion>

<Accordion title="Error: No workflow state of type 'completed' found">
  Your Linear team doesn't have a workflow state of the required type.

  Linear requires specific workflow state types:

  * `unstarted` for "open"
  * `started` for "in\_progress"
  * `completed` for "closed"

  Solution: Check your team's workflow settings in Linear and ensure you have states of each type.
</Accordion>

<Accordion title="Timeout errors">
  Linear API requests have a 30-second timeout.

  Solutions:

  * Check network connectivity
  * Verify Linear API status: [https://status.linear.app/](https://status.linear.app/)
  * Check API rate limits (direct API has limits)
  * Use Composio SDK for better rate limit handling
</Accordion>

<Accordion title="User not found when setting assignee">
  The plugin looks up users by `displayName` (not email or ID).

  Solution:

  ```typescript theme={null}
  // Use the exact display name from Linear
  await tracker.updateIssue("INT-1234", {
    assignee: "John Smith"  // Must match Linear display name exactly
  }, project);
  ```

  Find display names in Linear's user settings.
</Accordion>

<Accordion title="Labels not found when creating issue">
  The plugin looks up labels by name for your team.

  Solution:

  * Create labels in Linear first (Settings → Labels)
  * Use exact label names (case-sensitive)
  * Labels are best-effort: if not found, issue is still created without them
</Accordion>

## API Reference

### Tracker Interface Methods

**getIssue(identifier, project)**

* Fetches issue details by Linear identifier
* Returns: `Issue` object with all fields including priority

**isCompleted(identifier, project)**

* Checks if issue is in completed or canceled state
* Returns: `boolean`

**issueUrl(identifier, project)**

* Generates Linear issue URL
* Returns: `string`

**issueLabel(url, project)**

* Extracts issue identifier from URL
* Returns: `string` (e.g., `"INT-1234"`)

**branchName(identifier, project)**

* Generates branch name from identifier
* Returns: `string` (e.g., `"feat/INT-1234"`)

**generatePrompt(identifier, project)**

* Creates context prompt for agent
* Returns: `string` (formatted prompt with priority)

**listIssues(filters, project)**

* Lists issues with optional filters
* Automatically filters by teamId
* Returns: `Issue[]`

**updateIssue(identifier, update, project)**

* Updates issue state/labels/assignee/comments
* Handles workflow state transitions
* Returns: `void`

**createIssue(input, project)**

* Creates a new issue
* Returns: `Issue` (created issue)

## Advanced Usage

### GraphQL Transport

The plugin uses a transport abstraction that supports two backends:

```typescript theme={null}
// Direct Linear API
const transport = createDirectTransport();

// Composio SDK
const transport = createComposioTransport(apiKey, entityId);

// Both implement the same interface
const data = await transport<{ issue: LinearIssue }>(query, variables);
```

### Custom Workflow States

When updating issue state, the plugin:

1. Queries your team's workflow states
2. Finds the appropriate state by type
3. Updates the issue to that state

```typescript theme={null}
// This finds your team's "started" state and uses it
await tracker.updateIssue("INT-1234", {
  state: "in_progress"
}, project);
```

### Label Management

<Info>
  Labels are additive: using `updateIssue` with labels merges them with existing labels, it doesn't replace them.
</Info>

```typescript theme={null}
// Add labels to an issue
await tracker.updateIssue("INT-1234", {
  labels: ["in-progress", "needs-review"]
}, project);

// Existing labels are preserved
```

### Priority Workflow

```typescript theme={null}
// Create high-priority issue
const issue = await tracker.createIssue({
  title: "Critical bug",
  description: "Production is down",
  priority: 1,  // Urgent
  labels: ["bug", "production"]
}, project);

// Priority is included in generated prompts
const prompt = await tracker.generatePrompt(issue.id, project);
// Contains: "Priority: Urgent"
```

### Comment Workflow

```typescript theme={null}
// Post status update
await tracker.updateIssue("INT-1234", {
  comment: "🚀 Started working on this issue"
}, project);

// Post completion comment
await tracker.updateIssue("INT-1234", {
  state: "closed",
  comment: "✅ Fixed in PR #456\n\nAll tests passing."
}, project);
```

## Integration with Other Plugins

### With SCM Plugin

The tracker and SCM plugins work together for full issue-to-PR workflow:

1. **Tracker** generates prompt from Linear issue (with priority context)
2. **Agent** writes code
3. **SCM** creates PR with Linear issue link
4. **Reactions** auto-close issue when PR merges

```yaml theme={null}
reactions:
  - event: pr_merged
    action: run
    command: |
      # Linear's smart PR integration automatically closes issues
      # when PR title contains issue identifier (e.g., "INT-1234: Fix bug")
```

### With Workspace Plugin

The tracker provides the branch name for workspace creation:

```typescript theme={null}
const branchName = tracker.branchName("INT-1234", project);
// Used by workspace plugin to create branch "feat/INT-1234"
```

### With Composio

When using Composio SDK, you get additional benefits:

* Centralized credential management
* Workflow automation triggers
* Multi-tool integrations
* Better rate limit handling

## Performance Considerations

### GraphQL Queries

The plugin uses optimized GraphQL queries:

* Fetches only required fields
* Uses variables to prevent injection
* Batches related operations when possible

### Caching

The Composio SDK client is cached:

```typescript theme={null}
// Client is created once and reused
const client = new Composio({ apiKey });
```

### Timeouts

All requests have a 30-second timeout to prevent hanging:

* Direct API: native timeout in `node:https`
* Composio SDK: `Promise.race` with timeout

## Security Considerations

<Warning>
  * API keys are read from environment variables (never hardcoded)
  * GraphQL queries use variables (no string interpolation)
  * User input is validated before API calls
  * Team ID is required (prevents cross-team data access)
  * All requests are HTTPS-only
</Warning>

## Source Code

Source: `packages/plugins/tracker-linear/src/index.ts`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.