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

team-administration.mddocs/

Team Administration

Team configuration and member management including workflow states, labels, cycles, templates, and organizational hierarchy.

Capabilities

Core Team Operations

Basic team management operations for accessing team information and configuration.

def get(self, team_id: str) -> LinearTeam:
    """
    Fetch a team by ID with comprehensive details including configuration,
    cycles, states, and memberships.

    Args:
        team_id: The ID of the team to fetch

    Returns:
        LinearTeam with complete details

    Raises:
        ValueError: If team not found
    """

def get_all(self) -> Dict[str, LinearTeam]:
    """
    Get all teams in the organization.

    Returns:
        Dictionary mapping team IDs to LinearTeam objects
    """

def get_id_by_name(self, team_name: str) -> str:
    """
    Get a team ID by its name.

    Args:
        team_name: Name of the team to find

    Returns:
        Team ID string

    Raises:
        ValueError: If team not found
    """

Usage examples:

from linear_api import LinearClient

client = LinearClient()

# Get a specific team
team = client.teams.get("team-id")
print(f"Team: {team.name} ({team.key})")

# Get all teams
all_teams = client.teams.get_all()
print(f"Organization has {len(all_teams)} teams")

# Find team by name
team_id = client.teams.get_id_by_name("Engineering")
engineering_team = client.teams.get(team_id)

Workflow State Management

Manage team workflow states that control issue progression.

def get_states(
    self,
    team_id: str,
    include_issue_ids: bool = False,
    force_refresh: bool = False
) -> List[LinearState]:
    """
    Get all workflow states for a team with optional issue ID inclusion
    and cache refresh.

    Args:
        team_id: The ID of the team
        include_issue_ids: Whether to include issue IDs using each state
        force_refresh: Whether to force cache refresh

    Returns:
        List of LinearState objects
    """

def get_state_id_by_name(self, state_name: str, team_id: str) -> str:
    """
    Get a state ID by its name within a team.

    Args:
        state_name: Name of the state to find
        team_id: The ID of the team

    Returns:
        State ID string

    Raises:
        ValueError: If state not found
    """

Usage examples:

# Get team workflow states
states = client.teams.get_states("team-id")
for state in states:
    print(f"State: {state.name} ({state.type}) - {state.color}")

# Get states with issue counts
states_with_issues = client.teams.get_states("team-id", include_issue_ids=True)

# Find specific state
todo_state_id = client.teams.get_state_id_by_name("Todo", "team-id")

Member Management

Manage team membership and access controls.

def get_members(self, team_id: str) -> List[LinearUser]:
    """
    Get members of a team with automatic pagination and LinearUser model conversion.

    Args:
        team_id: The ID of the team

    Returns:
        List of LinearUser objects
    """

def get_membership(self, team_id: str, user_id: Optional[str] = None) -> Optional[TeamMembership]:
    """
    Get the membership of a user in a team, uses current user if user_id not provided.

    Args:
        team_id: The ID of the team
        user_id: Optional user ID, uses current user if not provided

    Returns:
        TeamMembership object or None if not a member

    Raises:
        ValueError: If user not found
    """

Usage examples:

# Get team members
members = client.teams.get_members("team-id")
print(f"Team has {len(members)} members:")
for member in members:
    print(f"  - {member.name} ({member.email})")

# Check current user's membership
my_membership = client.teams.get_membership("team-id")
if my_membership:
    print(f"I am a member with owner status: {my_membership.owner}")

# Check specific user's membership
user_membership = client.teams.get_membership("team-id", "user-id")

Label Management

Manage team labels for issue categorization and organization.

def get_labels(self, team_id: str, include_issue_ids: bool = False) -> List[LinearLabel]:
    """
    Get labels for a team with optional issue ID inclusion.

    Args:
        team_id: The ID of the team
        include_issue_ids: Whether to include issue IDs using each label

    Returns:
        List of LinearLabel objects
    """

def get_label_children(self, label_id: str) -> List[LinearLabel]:
    """
    Get child labels for a parent label.

    Args:
        label_id: The ID of the parent label

    Returns:
        List of child LinearLabel objects
    """

Usage examples:

# Get team labels
labels = client.teams.get_labels("team-id")
for label in labels:
    print(f"Label: {label.name} ({label.color})")

# Get labels with usage stats
labels_with_usage = client.teams.get_labels("team-id", include_issue_ids=True)
for label in labels_with_usage:
    issue_count = len(label.issue_ids) if hasattr(label, 'issue_ids') else 0
    print(f"Label: {label.name} - used on {issue_count} issues")

# Get label hierarchy
parent_label = labels[0]  # Assuming first label has children
children = client.teams.get_label_children(parent_label.id)

Cycle Management

Manage team development cycles and sprint planning.

def get_active_cycle(self, team_id: str) -> Optional[Dict[str, Any]]:
    """
    Get the active cycle for a team, returns None if no active cycle.

    Args:
        team_id: The ID of the team

    Returns:
        Active cycle dictionary or None
    """

def get_cycles(self, team_id: str) -> List[Dict[str, Any]]:
    """
    Get all cycles for a team with pagination support.

    Args:
        team_id: The ID of the team

    Returns:
        List of cycle dictionaries
    """

Usage examples:

# Get current cycle
active_cycle = client.teams.get_active_cycle("team-id")
if active_cycle:
    print(f"Active cycle: {active_cycle['name']} (ends {active_cycle['endsAt']})")
else:
    print("No active cycle")

# Get all cycles
cycles = client.teams.get_cycles("team-id")
print(f"Team has {len(cycles)} cycles")
for cycle in cycles[-3:]:  # Last 3 cycles
    print(f"Cycle: {cycle['name']} - {cycle['startsAt']} to {cycle['endsAt']}")

Template Management

Access team templates for consistent issue and project creation.

def get_templates(self, team_id: str) -> List[Dict[str, Any]]:
    """
    Get templates for a team with error handling.

    Args:
        team_id: The ID of the team

    Returns:
        List of template dictionaries
    """

Usage examples:

# Get team templates
templates = client.teams.get_templates("team-id")
for template in templates:
    print(f"Template: {template.get('name')}")

Organizational Hierarchy

Navigate team hierarchies and organizational structure.

def get_children(self, team_id: str) -> List[LinearTeam]:
    """
    Get child teams for a parent team.

    Args:
        team_id: The ID of the parent team

    Returns:
        List of child LinearTeam objects
    """

def get_parent(self, team_id: str) -> Optional[LinearTeam]:
    """
    Get the parent team of a team, returns None if no parent.

    Args:
        team_id: The ID of the team

    Returns:
        Parent LinearTeam object or None
    """

Usage examples:

# Navigate team hierarchy
parent_team = client.teams.get_parent("team-id")
if parent_team:
    print(f"Parent team: {parent_team.name}")

child_teams = client.teams.get_children("team-id")
print(f"Has {len(child_teams)} child teams:")
for child in child_teams:
    print(f"  - {child.name}")

Team Content Access

Access issues, projects, and other content associated with teams.

def get_issues(self, team_id: str) -> List[Dict[str, Any]]:
    """
    Get issues for a team with basic issue information.

    Args:
        team_id: The ID of the team

    Returns:
        List of issue dictionaries
    """

def get_projects(self, team_id: str) -> Dict[str, Any]:
    """
    Get projects for a team (delegates to ProjectManager).

    Args:
        team_id: The ID of the team

    Returns:
        Dictionary of project data
    """

Usage examples:

# Get team issues
issues = client.teams.get_issues("team-id")
print(f"Team has {len(issues)} issues")

# Get team projects
projects = client.teams.get_projects("team-id")
print(f"Team has projects: {list(projects.keys())}")

Integration Management

Manage team integrations and webhooks.

def get_webhooks(self, team_id: str) -> List[Dict[str, Any]]:
    """
    Get webhooks for a team.

    Args:
        team_id: The ID of the team

    Returns:
        List of webhook dictionaries
    """

Usage examples:

# Get team webhooks
webhooks = client.teams.get_webhooks("team-id")
for webhook in webhooks:
    print(f"Webhook: {webhook.get('url')}")

Triage Management

Access team triage responsibility and configuration.

def get_triage_responsibility(self, team_id: str) -> TriageResponsibility:
    """
    Get triage responsibility data for a team.

    Args:
        team_id: The ID of the team

    Returns:
        TriageResponsibility object
    """

Usage examples:

# Get triage configuration
triage = client.teams.get_triage_responsibility("team-id")
print(f"Triage action: {triage.action}")

Cache Management

Control caching for team-related data.

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

Usage examples:

# Clear team caches
client.teams.invalidate_cache()

Team Configuration

Teams in Linear have extensive configuration options that control their workflow and behavior:

Automation Settings

# Teams have various automation settings
team = client.teams.get("team-id")

print(f"Auto archive period: {team.autoArchivePeriod}")
print(f"Auto close child issues: {team.autoCloseChildIssues}")
print(f"Auto close parent issues: {team.autoCloseParentIssues}")

Cycle Configuration

# Check cycle settings
print(f"Cycles enabled: {team.cyclesEnabled}")
print(f"Cycle duration: {team.cycleDuration}")
print(f"Cycle start day: {team.cycleStartDay}")

Estimation Settings

# Check estimation configuration
print(f"Default issue estimate: {team.defaultIssueEstimate}")
print(f"Issue estimation type: {team.issueEstimationType}")

Advanced Team Workflows

Team Metrics and Analytics

def analyze_team_performance(team_id: str):
    team = client.teams.get(team_id)
    issues = client.teams.get_issues(team_id)
    states = client.teams.get_states(team_id)
    members = client.teams.get_members(team_id)

    # Calculate state distribution
    state_counts = {}
    for issue in issues:
        state_name = issue.get('state', {}).get('name', 'Unknown')
        state_counts[state_name] = state_counts.get(state_name, 0) + 1

    print(f"Team: {team.name}")
    print(f"Members: {len(members)}")
    print(f"Total issues: {len(issues)}")
    print(f"Workflow states: {len(states)}")
    print("\nIssue distribution by state:")
    for state, count in state_counts.items():
        print(f"  {state}: {count} issues")

    return {
        "team": team,
        "member_count": len(members),
        "issue_count": len(issues),
        "state_distribution": state_counts
    }

# Analyze team performance
analytics = analyze_team_performance("team-id")

Multi-Team Coordination

def get_organization_structure():
    all_teams = client.teams.get_all()

    # Build hierarchy
    root_teams = []
    team_children = {}

    for team_id, team in all_teams.items():
        if not team.parentId:
            root_teams.append(team)
        else:
            if team.parentId not in team_children:
                team_children[team.parentId] = []
            team_children[team.parentId].append(team)

    def print_hierarchy(team, indent=0):
        print("  " * indent + f"- {team.name} ({team.key})")
        children = team_children.get(team.id, [])
        for child in children:
            print_hierarchy(child, indent + 1)

    print("Organization Structure:")
    for root in root_teams:
        print_hierarchy(root)

# Print organization structure
get_organization_structure()

Label Management Workflows

def organize_team_labels(team_id: str):
    labels = client.teams.get_labels(team_id, include_issue_ids=True)

    # Group by color
    by_color = {}
    for label in labels:
        color = label.color
        if color not in by_color:
            by_color[color] = []
        by_color[color].append(label)

    # Sort by usage (if issue_ids available)
    for color, color_labels in by_color.items():
        color_labels.sort(key=lambda l: len(getattr(l, 'issue_ids', [])), reverse=True)

    print(f"Team labels organized by color:")
    for color, color_labels in by_color.items():
        print(f"\n{color}:")
        for label in color_labels:
            usage = len(getattr(label, 'issue_ids', []))
            print(f"  - {label.name} ({usage} issues)")

# Organize labels
organize_team_labels("team-id")

Cycle Planning

def plan_next_cycle(team_id: str):
    active_cycle = client.teams.get_active_cycle(team_id)
    team_issues = client.teams.get_issues(team_id)

    if active_cycle:
        print(f"Current cycle: {active_cycle['name']}")
        print(f"Ends: {active_cycle['endsAt']}")

    # Get backlog issues (not in active cycle)
    backlog = [issue for issue in team_issues
              if not issue.get('cycle')]

    print(f"\nBacklog items for next cycle: {len(backlog)}")

    # Prioritize by priority and estimate
    prioritized = sorted(backlog,
                        key=lambda i: (i.get('priority', 4), i.get('estimate', 0)))

    for issue in prioritized[:10]:  # Top 10 candidates
        title = issue.get('title', 'Untitled')
        priority = issue.get('priority', 'None')
        estimate = issue.get('estimate', 'Unestimated')
        print(f"  - {title} (Priority: {priority}, Estimate: {estimate})")

# Plan next cycle
plan_next_cycle("team-id")

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