CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-linear-api

A comprehensive Python wrapper for the Linear API with rich Pydantic models, simplified workflows, and an object-oriented design.

Overview
Eval results
Files

issue-operations.mddocs/

Issue Operations

Comprehensive issue management including creation, updates, querying, and relationship management with support for attachments, comments, and metadata.

Capabilities

Core CRUD Operations

Basic issue management operations for creating, reading, updating, and deleting issues.

def get(self, issue_id: str) -> LinearIssue:
    """
    Fetch a Linear issue by ID with comprehensive details including attachments,
    labels, team, project, etc.

    Args:
        issue_id: The ID of the issue to fetch

    Returns:
        LinearIssue with complete details

    Raises:
        ValueError: If issue not found
    """

def create(self, issue: LinearIssueInput) -> LinearIssue:
    """
    Create a new issue in Linear with support for team assignment, parent relationships,
    and metadata attachments.

    Args:
        issue: LinearIssueInput with issue details

    Returns:
        Created LinearIssue object

    Raises:
        ValueError: If creation fails
    """

def update(self, issue_id: str, update_data: LinearIssueUpdateInput) -> LinearIssue:
    """
    Update an existing issue with support for state changes, team transfers,
    and metadata updates.

    Args:
        issue_id: The ID of the issue to update
        update_data: LinearIssueUpdateInput with fields to update

    Returns:
        Updated LinearIssue object

    Raises:
        ValueError: If update fails
    """

def delete(self, issue_id: str) -> bool:
    """
    Delete an issue by its ID.

    Args:
        issue_id: The ID of the issue to delete

    Returns:
        True if successful

    Raises:
        ValueError: If deletion fails
    """

Usage examples:

from linear_api import LinearClient, LinearIssueInput, LinearIssueUpdateInput

client = LinearClient()

# Get an issue
issue = client.issues.get("issue-id")
print(f"Issue: {issue.title} ({issue.state.name})")

# Create a new issue
new_issue = client.issues.create(LinearIssueInput(
    title="New task from API",
    teamName="Engineering",
    description="Task created via Python API",
    priority=LinearPriority.HIGH
))

# Update an issue
updated = client.issues.update("issue-id", LinearIssueUpdateInput(
    title="Updated title",
    description="Updated description"
))

# Delete an issue
success = client.issues.delete("issue-id")

Query Operations

Advanced querying capabilities for finding issues by various criteria.

def get_by_team(self, team_name: str) -> Dict[str, LinearIssue]:
    """
    Get all issues for a specific team.

    Args:
        team_name: Name of the team

    Returns:
        Dictionary mapping issue IDs to LinearIssue objects
    """

def get_by_project(self, project_id: str) -> Dict[str, LinearIssue]:
    """
    Get all issues for a specific project.

    Args:
        project_id: The ID of the project

    Returns:
        Dictionary mapping issue IDs to LinearIssue objects
    """

def get_all(self) -> Dict[str, LinearIssue]:
    """
    Get all issues from all teams in the organization.
    Processes in batches for performance.

    Returns:
        Dictionary mapping issue IDs to LinearIssue objects
    """

Usage examples:

# Get issues by team
team_issues = client.issues.get_by_team("Engineering")
print(f"Found {len(team_issues)} issues in Engineering team")

# Get issues by project
project_issues = client.issues.get_by_project("project-id")
for issue_id, issue in project_issues.items():
    print(f"{issue.title} - {issue.state.name}")

# Get all issues (use with caution for large organizations)
all_issues = client.issues.get_all()

Attachment Management

Handle issue attachments with URL validation and metadata support.

def create_attachment(self, attachment: LinearAttachmentInput) -> Dict[str, Any]:
    """
    Create an attachment for an issue with URL validation and metadata support.

    Args:
        attachment: LinearAttachmentInput with attachment details

    Returns:
        Created attachment data

    Raises:
        ValueError: If attachment creation fails
    """

def get_attachments(self, issue_id: str) -> List[Dict[str, Any]]:
    """
    Get all attachments for an issue with creator and metadata information.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of attachment dictionaries
    """

Usage examples:

from linear_api import LinearAttachmentInput

# Create an attachment
attachment = client.issues.create_attachment(LinearAttachmentInput(
    url="https://example.com/document.pdf",
    issueId="issue-id",
    title="Requirements Document",
    subtitle="Project requirements v1.0",
    metadata={"category": "documentation", "version": "1.0"}
))

# Get issue attachments
attachments = client.issues.get_attachments("issue-id")
for attach in attachments:
    print(f"Attachment: {attach['title']} - {attach['url']}")

History and Comments

Access issue change history and comment management.

def get_history(self, issue_id: str) -> List[Dict[str, Any]]:
    """
    Get the change history for an issue including state transitions and actors.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of history entries
    """

def get_comments(self, issue_id: str) -> List[Comment]:
    """
    Get all comments for an issue with automatic pagination and Comment model conversion.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of Comment objects
    """

Usage examples:

# Get issue history
history = client.issues.get_history("issue-id")
for entry in history:
    print(f"Change: {entry.get('action')} by {entry.get('actor', {}).get('name')}")

# Get issue comments
comments = client.issues.get_comments("issue-id")
for comment in comments:
    print(f"Comment by {comment.creator.name}: {comment.body[:50]}...")

Relationship Management

Manage issue relationships including parent-child hierarchies and inter-issue relations.

def get_children(self, issue_id: str) -> Dict[str, LinearIssue]:
    """
    Get child issues for a parent issue.

    Args:
        issue_id: The ID of the parent issue

    Returns:
        Dictionary mapping issue IDs to LinearIssue objects
    """

def get_relations(self, issue_id: str) -> List[IssueRelation]:
    """
    Get relations for an issue (blocks, duplicates, etc.)

    Args:
        issue_id: The ID of the issue

    Returns:
        List of IssueRelation objects
    """

def get_inverse_relations(self, issue_id: str) -> List[IssueRelation]:
    """
    Get inverse relations for an issue (blocked by, duplicate of, etc.)

    Args:
        issue_id: The ID of the issue

    Returns:
        List of IssueRelation objects
    """

Usage examples:

# Get child issues
children = client.issues.get_children("parent-issue-id")
print(f"Parent has {len(children)} child issues")

# Get issue relations
relations = client.issues.get_relations("issue-id")
for relation in relations:
    print(f"Relation: {relation.type} to issue {relation.relatedIssue['id']}")

# Get inverse relations
inverse_relations = client.issues.get_inverse_relations("issue-id")

Social Features

Access reactions, subscribers, and social interactions on issues.

def get_reactions(self, issue_id: str) -> List[Reaction]:
    """
    Get reactions to an issue with user information and emoji data.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of Reaction objects
    """

def get_subscribers(self, issue_id: str) -> List[LinearUser]:
    """
    Get subscribers of an issue with automatic pagination and LinearUser model conversion.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of LinearUser objects
    """

Usage examples:

# Get issue reactions
reactions = client.issues.get_reactions("issue-id")
for reaction in reactions:
    print(f"{reaction.user.name} reacted with {reaction.emoji}")

# Get issue subscribers
subscribers = client.issues.get_subscribers("issue-id")
print(f"Issue has {len(subscribers)} subscribers")

Customer Needs Integration

Access customer needs associated with issues for product management workflows.

def get_needs(self, issue_id: str) -> List[CustomerNeedResponse]:
    """
    Get customer needs associated with an issue.

    Args:
        issue_id: The ID of the issue

    Returns:
        List of CustomerNeedResponse objects
    """

Usage examples:

# Get customer needs for an issue
needs = client.issues.get_needs("issue-id")
for need in needs:
    print(f"Customer need: {need.priority} priority")

Cache Management

Control caching for issue-related data to optimize performance.

def invalidate_cache(self) -> None:
    """
    Invalidate all issue-related caches.
    """

Usage examples:

# Clear issue caches after bulk operations
client.issues.invalidate_cache()

# Or clear all caches
client.clear_cache()

Input Models

LinearIssueInput

For creating new issues with comprehensive field support.

class LinearIssueInput(LinearModel):
    title: str              # Required: Issue title
    teamName: str           # Required: Team name for issue
    description: Optional[str] = None
    priority: Optional[LinearPriority] = None
    assigneeId: Optional[str] = None
    projectId: Optional[str] = None
    stateId: Optional[str] = None
    parentId: Optional[str] = None
    labelIds: Optional[List[str]] = None
    estimate: Optional[int] = None
    dueDate: Optional[datetime] = None
    metadata: Optional[Dict[str, Any]] = None  # Auto-converted to attachment

LinearIssueUpdateInput

For updating existing issues with all optional fields.

class LinearIssueUpdateInput(LinearModel):
    title: Optional[str] = None
    description: Optional[str] = None
    priority: Optional[LinearPriority] = None
    assigneeId: Optional[str] = None
    projectId: Optional[str] = None
    stateId: Optional[str] = None
    teamId: Optional[str] = None
    labelIds: Optional[List[str]] = None
    estimate: Optional[int] = None
    dueDate: Optional[datetime] = None
    metadata: Optional[Dict[str, Any]] = None  # Auto-converted to attachment

LinearAttachmentInput

For creating issue attachments with metadata support.

class LinearAttachmentInput(LinearModel):
    url: str                # Required: Attachment URL
    issueId: str           # Required: Issue ID
    title: Optional[str] = None
    subtitle: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None

Advanced Usage Patterns

Bulk Operations

# Create multiple issues efficiently
issues_to_create = [
    LinearIssueInput(title=f"Task {i}", teamName="Engineering")
    for i in range(1, 11)
]

created_issues = []
for issue_input in issues_to_create:
    created = client.issues.create(issue_input)
    created_issues.append(created)

Metadata Workflow

# Use metadata for custom fields
issue_with_metadata = client.issues.create(LinearIssueInput(
    title="Feature Request",
    teamName="Engineering",
    description="New feature from customer feedback",
    metadata={
        "customer_id": "cust_123",
        "feature_type": "enhancement",
        "business_value": "high",
        "complexity": "medium"
    }
))

# Metadata is automatically converted to an attachment
attachments = client.issues.get_attachments(issue_with_metadata.id)
metadata_attachment = next((a for a in attachments if a.get('title') == 'Metadata'), None)
print(metadata_attachment['metadata'])

Parent-Child Issue Hierarchies

# Create parent issue
parent = client.issues.create(LinearIssueInput(
    title="Epic: User Authentication System",
    teamName="Engineering",
    description="Complete user authentication overhaul"
))

# Create child issues
child1 = client.issues.create(LinearIssueInput(
    title="Implement JWT tokens",
    teamName="Engineering",
    parentId=parent.id
))

child2 = client.issues.create(LinearIssueInput(
    title="Add OAuth integration",
    teamName="Engineering",
    parentId=parent.id
))

# Get all children
children = client.issues.get_children(parent.id)
print(f"Epic has {len(children)} child issues")

Install with Tessl CLI

npx tessl i tessl/pypi-linear-api

docs

cache-utilities.md

client-management.md

data-models-types.md

index.md

issue-operations.md

project-management.md

team-administration.md

user-management.md

tile.json