Documentation
¶
Overview ¶
Package linear provides a Go client for the Linear API with comprehensive GraphQL support, automatic rate limiting, and robust error handling.
The client supports all major Linear operations including issue management, comments, notifications, team operations, and custom metadata storage using a description-based approach.
Authentication ¶
The client requires a Linear API token for authentication. You can provide the token directly or load it from a file:
// Direct token
client := linear.NewClient("your-api-token")
// Token from file with fallback to environment variable
client := linear.NewClientWithTokenPath("/path/to/token")
Basic Usage ¶
Get an issue:
issue, err := client.GetIssue("issue-id")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Issue: %s - %s\n", issue.Identifier, issue.Title)
Create an issue:
issue, err := client.CreateIssue("team-id", "Bug Report", "Description here")
if err != nil {
log.Fatal(err)
}
Update issue state:
err := client.UpdateIssueState("issue-id", "state-id")
if err != nil {
log.Fatal(err)
}
Metadata Management ¶
This client supports storing custom metadata in Linear issue and project descriptions using a collapsible markdown format. Metadata is automatically extracted when fetching issues/projects and preserved when updating descriptions.
Update metadata for an issue:
err := client.UpdateIssueMetadataKey("issue-id", "priority", "high")
if err != nil {
log.Fatal(err)
}
Remove metadata:
err := client.RemoveIssueMetadataKey("issue-id", "priority")
if err != nil {
log.Fatal(err)
}
Error Handling ¶
The package defines custom error types for better error handling:
err := client.UpdateIssueState("issue-id", "invalid-state")
if linear.IsValidationError(err) {
// Handle validation error
}
if linear.IsRateLimitError(err) {
// Handle rate limit with retry
retryAfter := linear.GetRetryAfter(err)
}
Rate Limiting ¶
The client automatically handles rate limiting with exponential backoff and respects Linear's rate limit headers. When rate limits are exceeded, a RateLimitError is returned with retry information.
Network Resilience ¶
The client includes automatic retry logic for transient network errors with exponential backoff. Connection failures, timeouts, and temporary DNS issues are automatically retried.
Index ¶
- type Client
- func (c *Client) AddReaction(targetID, emoji string) error
- func (c *Client) ArchiveCycle(cycleID string) error
- func (c *Client) AssignIssue(identifierOrID, assigneeNameOrEmail string) error
- func (c *Client) CommentClient() *comments.Client
- func (c *Client) CreateComment(issueID, body string) (*core.Comment, error)
- func (c *Client) CreateCommentReply(issueID, parentID, body string) (*core.Comment, error)
- func (c *Client) CreateCycle(input *core.CreateCycleInput) (*core.Cycle, error)
- func (c *Client) CreateIssue(input *core.IssueCreateInput) (*core.Issue, error)
- func (c *Client) CreateProject(name, description, teamKeyOrName string) (*core.Project, error)
- func (c *Client) CreateRelation(issueID, relatedIssueID string, relationType core.IssueRelationType) error
- func (c *Client) CycleClient() *cycles.Client
- func (c *Client) GetAPIToken() string
- func (c *Client) GetActiveCycle(teamKeyOrName string) (*core.Cycle, error)
- func (c *Client) GetAppUserID() (string, error)
- func (c *Client) GetAuthMode() string
- func (c *Client) GetBase() *core.BaseClient
- func (c *Client) GetCommentWithReplies(commentID string) (*core.CommentWithReplies, error)
- func (c *Client) GetCycle(cycleID string) (*core.Cycle, error)
- func (c *Client) GetCycleIssues(cycleID string, limit int) ([]core.Issue, error)
- func (c *Client) GetHTTPClient() *http.Client
- func (c *Client) GetIssue(identifierOrID string) (*core.Issue, error)
- func (c *Client) GetIssueBasic(issueID string) (*core.Issue, error)
- func (c *Client) GetIssueSimplified(issueID string) (*core.Issue, error)
- func (c *Client) GetIssueWithParentContext(issueID string) (*core.Issue, error)
- func (c *Client) GetIssueWithProjectContext(issueID string) (*core.Issue, error)
- func (c *Client) GetIssueWithRelations(identifier string) (*core.IssueWithRelations, error)
- func (c *Client) GetNotifications(includeRead bool, limit int) ([]core.Notification, error)
- func (c *Client) GetProject(projectID string) (*core.Project, error)
- func (c *Client) GetSubIssues(parentIssueID string) ([]core.SubIssue, error)
- func (c *Client) GetTeam(keyOrName string) (*core.Team, error)
- func (c *Client) GetTeamEstimateScale(keyOrName string) (*core.EstimateScale, error)
- func (c *Client) GetTeams() ([]core.Team, error)
- func (c *Client) GetUser(idOrEmail string) (*core.User, error)
- func (c *Client) GetViewer() (*core.User, error)
- func (c *Client) GetWorkflowStateByName(teamID, stateName string) (*core.WorkflowState, error)
- func (c *Client) GetWorkflowStates(teamID string) ([]core.WorkflowState, error)
- func (c *Client) IsAgentMode() bool
- func (c *Client) IssueClient() *issues.Client
- func (c *Client) ListAllIssues(filter *core.IssueFilter) (*core.ListAllIssuesResult, error)
- func (c *Client) ListAllProjects(limit int) ([]core.Project, error)
- func (c *Client) ListAssignedIssues(limit int) ([]core.Issue, error)
- func (c *Client) ListByTeam(teamID string, limit int) ([]core.Project, error)
- func (c *Client) ListCycles(filter *core.CycleFilter) (*core.CycleSearchResult, error)
- func (c *Client) ListUserProjects(userID string, limit int) ([]core.Project, error)
- func (c *Client) ListUsers(filter *core.UserFilter) ([]core.User, error)
- func (c *Client) ListUsersWithPagination(filter *core.UserFilter) (*core.ListUsersResult, error)
- func (c *Client) MarkNotificationAsRead(notificationID string) error
- func (c *Client) ProjectClient() *projects.Client
- func (c *Client) RemoveIssueMetadataKey(issueID, key string) error
- func (c *Client) RemoveProjectMetadataKey(projectID, key string) error
- func (c *Client) ResolveCycleIdentifier(numberOrNameOrID string, teamID string) (string, error)
- func (c *Client) ResolveIssueIdentifier(identifier string) (string, error)
- func (c *Client) ResolveLabelIdentifier(labelName string, teamID string) (string, error)
- func (c *Client) ResolveProjectIdentifier(nameOrID string, teamID string) (string, error)
- func (c *Client) ResolveTeamIdentifier(keyOrName string) (string, error)
- func (c *Client) ResolveUserIdentifier(nameOrEmail string) (*ResolvedUser, error)
- func (c *Client) SearchIssues(filters *core.IssueSearchFilters) (*core.IssueSearchResult, error)
- func (c *Client) SetBase(base *core.BaseClient)
- func (c *Client) TeamClient() *teams.Client
- func (c *Client) TestConnection() error
- func (c *Client) UpdateCycle(cycleID string, input *core.UpdateCycleInput) (*core.Cycle, error)
- func (c *Client) UpdateIssue(identifierOrID string, input core.UpdateIssueInput) (*core.Issue, error)
- func (c *Client) UpdateIssueDescription(issueID, newDescription string) error
- func (c *Client) UpdateIssueMetadataKey(issueID, key string, value interface{}) error
- func (c *Client) UpdateIssueState(identifierOrID, stateID string) error
- func (c *Client) UpdateProject(projectID string, input interface{}) (*core.Project, error)
- func (c *Client) UpdateProjectDescription(projectID, newDescription string) error
- func (c *Client) UpdateProjectMetadataKey(projectID, key string, value interface{}) error
- func (c *Client) UpdateProjectState(projectID, state string) error
- func (c *Client) WorkflowClient() *workflows.Client
- type ResolvedUser
- type Resolver
- func (r *Resolver) ResolveCycle(numberOrNameOrID string, teamID string) (string, error)
- func (r *Resolver) ResolveIssue(identifier string) (string, error)
- func (r *Resolver) ResolveLabel(labelName string, teamID string) (string, error)
- func (r *Resolver) ResolveProject(nameOrID string, teamID string) (string, error)
- func (r *Resolver) ResolveTeam(keyOrName string) (string, error)
- func (r *Resolver) ResolveUser(nameOrEmail string) (*ResolvedUser, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// Sub-clients for different domains
Issues *issues.Client
Projects *projects.Client
Comments *comments.Client
Teams *teams.Client
Notifications *users.NotificationClient
Workflows *workflows.Client
Attachments *attachments.Client
Cycles *cycles.Client
// contains filtered or unexported fields
}
Client represents the main Linear API client that orchestrates all sub-clients. It provides a single entry point for all Linear API operations while delegating to specialized sub-clients for specific functionality.
func NewClientWithAuthMode ¶ added in v1.4.5
NewClientWithAuthMode creates a new Linear API client with explicit auth mode. authMode should be "user" or "agent". Empty string defaults to email suffix detection for backward compatibility with existing tokens.
func NewClientWithTokenPath ¶
NewClientWithTokenPath creates a new Linear API client with token loading. It intelligently selects between static and refreshing token providers based on: - Whether a refresh token is available - Whether OAuth credentials are configured
func NewDefaultClient ¶
func NewDefaultClient() *Client
NewDefaultClient creates a new Linear API client using default token path
func (*Client) AddReaction ¶
func (*Client) ArchiveCycle ¶
func (*Client) AssignIssue ¶
func (*Client) CommentClient ¶ added in v1.3.0
func (*Client) CreateComment ¶
Comment operations
func (*Client) CreateCommentReply ¶
func (*Client) CreateCycle ¶
func (*Client) CreateIssue ¶
Issue operations
func (*Client) CreateProject ¶
Project operations
func (*Client) CreateRelation ¶ added in v1.5.0
func (c *Client) CreateRelation(issueID, relatedIssueID string, relationType core.IssueRelationType) error
func (*Client) CycleClient ¶ added in v1.3.0
func (*Client) GetAPIToken ¶
GetAPIToken returns the current API token Why: Some operations may need direct access to the token, such as checking authentication status.
func (*Client) GetActiveCycle ¶
func (*Client) GetAppUserID ¶
func (*Client) GetAuthMode ¶ added in v1.4.5
GetAuthMode returns the authentication mode: "user", "agent", or "" (legacy token) Empty string indicates a legacy token without explicit auth mode
func (*Client) GetBase ¶
func (c *Client) GetBase() *core.BaseClient
GetBase returns the base client (for testing purposes)
func (*Client) GetCommentWithReplies ¶
func (c *Client) GetCommentWithReplies(commentID string) (*core.CommentWithReplies, error)
func (*Client) GetCycleIssues ¶
func (*Client) GetHTTPClient ¶
GetHTTPClient returns the underlying HTTP client for testing purposes
func (*Client) GetIssue ¶
GetIssue retrieves an issue with the best context automatically determined This is the preferred method for getting issues as it intelligently chooses whether to include parent or project context based on the issue's relationships.
func (*Client) GetIssueBasic ¶
GetIssueBasic retrieves basic issue information without additional context Use this when you only need basic issue data without parent/project details.
func (*Client) GetIssueSimplified ¶
GetIssueSimplified retrieves basic issue information using a simplified query Use this as a fallback when the full context queries fail due to server issues.
func (*Client) GetIssueWithParentContext ¶
DEPRECATED: Use GetIssue() instead, which automatically determines the best context
func (*Client) GetIssueWithProjectContext ¶
DEPRECATED: Use GetIssue() instead, which automatically determines the best context
func (*Client) GetIssueWithRelations ¶ added in v1.3.0
func (c *Client) GetIssueWithRelations(identifier string) (*core.IssueWithRelations, error)
func (*Client) GetNotifications ¶
Notification operations
func (*Client) GetSubIssues ¶
func (*Client) GetTeamEstimateScale ¶
func (c *Client) GetTeamEstimateScale(keyOrName string) (*core.EstimateScale, error)
func (*Client) GetWorkflowStateByName ¶
func (c *Client) GetWorkflowStateByName(teamID, stateName string) (*core.WorkflowState, error)
func (*Client) GetWorkflowStates ¶
func (c *Client) GetWorkflowStates(teamID string) ([]core.WorkflowState, error)
Workflow operations
func (*Client) IsAgentMode ¶ added in v1.4.5
IsAgentMode returns whether the client is authenticated as an OAuth application When true, "me" resolution will use delegateId instead of assigneeId
func (*Client) IssueClient ¶ added in v1.3.0
func (*Client) ListAllIssues ¶
func (c *Client) ListAllIssues(filter *core.IssueFilter) (*core.ListAllIssuesResult, error)
func (*Client) ListAllProjects ¶
func (*Client) ListAssignedIssues ¶
func (*Client) ListByTeam ¶ added in v1.3.0
func (*Client) ListCycles ¶
func (c *Client) ListCycles(filter *core.CycleFilter) (*core.CycleSearchResult, error)
func (*Client) ListUserProjects ¶
func (*Client) ListUsersWithPagination ¶
func (c *Client) ListUsersWithPagination(filter *core.UserFilter) (*core.ListUsersResult, error)
func (*Client) MarkNotificationAsRead ¶
func (*Client) ProjectClient ¶ added in v1.3.0
func (*Client) RemoveIssueMetadataKey ¶
func (*Client) RemoveProjectMetadataKey ¶
func (*Client) ResolveCycleIdentifier ¶
func (*Client) ResolveIssueIdentifier ¶
func (*Client) ResolveLabelIdentifier ¶ added in v1.4.0
func (*Client) ResolveProjectIdentifier ¶ added in v1.4.7
func (*Client) ResolveTeamIdentifier ¶
Resolver operations (expose resolver functionality)
func (*Client) ResolveUserIdentifier ¶
func (c *Client) ResolveUserIdentifier(nameOrEmail string) (*ResolvedUser, error)
func (*Client) SearchIssues ¶
func (c *Client) SearchIssues(filters *core.IssueSearchFilters) (*core.IssueSearchResult, error)
Issue search operations
func (*Client) SetBase ¶
func (c *Client) SetBase(base *core.BaseClient)
SetBase sets the base client (for testing purposes)
func (*Client) TeamClient ¶ added in v1.3.0
func (*Client) TestConnection ¶
TestConnection tests if the client can connect to Linear API Why: Users need to verify their authentication and network connectivity before attempting other operations.
func (*Client) UpdateCycle ¶
func (*Client) UpdateIssue ¶
func (*Client) UpdateIssueDescription ¶
func (*Client) UpdateIssueMetadataKey ¶
func (*Client) UpdateIssueState ¶
func (*Client) UpdateProject ¶ added in v1.3.0
func (*Client) UpdateProjectDescription ¶
func (*Client) UpdateProjectMetadataKey ¶
func (*Client) UpdateProjectState ¶
func (*Client) WorkflowClient ¶ added in v1.3.0
type ResolvedUser ¶ added in v1.4.3
ResolvedUser contains the resolved user ID and whether it's an OAuth application
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver handles intelligent resolution of human-readable identifiers to UUIDs It manages caching and provides smart matching with ambiguity detection
Why: The MCP server should accept human-readable inputs (emails, names, CEN-123) instead of forcing clients to look up UUIDs. The resolver handles this translation.
func NewResolver ¶
NewResolver creates a new resolver with the default cache TTL
func (*Resolver) ResolveCycle ¶
ResolveCycle resolves a cycle identifier (number or name) to a cycle UUID Supports: - Cycle numbers: "62" (fastest lookup) - Cycle names: "Cycle 67" or "Sprint Planning"
Returns error with suggestions if multiple cycles match
func (*Resolver) ResolveIssue ¶
ResolveIssue resolves an issue identifier (CEN-123) to an issue UUID Only accepts Linear identifiers in format TEAM-NUMBER
Returns error if identifier invalid or issue not found
func (*Resolver) ResolveLabel ¶ added in v1.4.0
ResolveLabel resolves a label name to a label UUID within a specific team Labels are team-scoped, so teamID is required
Returns error if label not found
func (*Resolver) ResolveProject ¶ added in v1.4.7
ResolveProject resolves a project identifier (name or UUID) to a project UUID Supports: - UUIDs - returned as-is - Project names: "My Project" (case-insensitive match)
When teamID is provided, only projects for that team are searched. When teamID is empty, all workspace projects are searched.
Returns error with suggestions if multiple projects match
func (*Resolver) ResolveTeam ¶
ResolveTeam resolves a team identifier (name or key) to a team UUID Supports: - Team keys: "ENG", "PRODUCT" - Team names: "Engineering", "Product Team"
Returns error if team not found
func (*Resolver) ResolveUser ¶
func (r *Resolver) ResolveUser(nameOrEmail string) (*ResolvedUser, error)
ResolveUser resolves a user identifier (email or name) to a ResolvedUser containing the UUID and whether it's an OAuth application. Supports: - "me" - resolves to the authenticated user - UUIDs - returned as-is (already resolved, IsApplication=false) - Email addresses: "[email protected]" - Display names: "John Doe" - First names: "John" (errors if ambiguous)
Returns error with suggestions if multiple users match
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package guidance provides AI agent-friendly error messages with actionable guidance.
|
Package guidance provides AI agent-friendly error messages with actionable guidance. |
|
Package identifiers provides format detection and parsing for Linear identifiers.
|
Package identifiers provides format detection and parsing for Linear identifiers. |
|
Package metadata provides HTML-based metadata storage for Linear issues and projects.
|
Package metadata provides HTML-based metadata storage for Linear issues and projects. |
|
Package pagination provides utilities for offset-based pagination in Linear API queries.
|
Package pagination provides utilities for offset-based pagination in Linear API queries. |
|
Package schema contains the Linear GraphQL schema for reference and validation.
|
Package schema contains the Linear GraphQL schema for reference and validation. |
|
Package testutil provides testing utilities for Linear client tests.
|
Package testutil provides testing utilities for Linear client tests. |
|
Package validation provides input validation utilities for Linear API operations.
|
Package validation provides input validation utilities for Linear API operations. |