or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-utilities.mdclient-management.mddata-models-types.mdindex.mdissue-operations.mdproject-management.mdteam-administration.mduser-management.md

issue-operations.mddocs/

0

# Issue Operations

1

2

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

3

4

## Capabilities

5

6

### Core CRUD Operations

7

8

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

9

10

```python { .api }

11

def get(self, issue_id: str) -> LinearIssue:

12

"""

13

Fetch a Linear issue by ID with comprehensive details including attachments,

14

labels, team, project, etc.

15

16

Args:

17

issue_id: The ID of the issue to fetch

18

19

Returns:

20

LinearIssue with complete details

21

22

Raises:

23

ValueError: If issue not found

24

"""

25

26

def create(self, issue: LinearIssueInput) -> LinearIssue:

27

"""

28

Create a new issue in Linear with support for team assignment, parent relationships,

29

and metadata attachments.

30

31

Args:

32

issue: LinearIssueInput with issue details

33

34

Returns:

35

Created LinearIssue object

36

37

Raises:

38

ValueError: If creation fails

39

"""

40

41

def update(self, issue_id: str, update_data: LinearIssueUpdateInput) -> LinearIssue:

42

"""

43

Update an existing issue with support for state changes, team transfers,

44

and metadata updates.

45

46

Args:

47

issue_id: The ID of the issue to update

48

update_data: LinearIssueUpdateInput with fields to update

49

50

Returns:

51

Updated LinearIssue object

52

53

Raises:

54

ValueError: If update fails

55

"""

56

57

def delete(self, issue_id: str) -> bool:

58

"""

59

Delete an issue by its ID.

60

61

Args:

62

issue_id: The ID of the issue to delete

63

64

Returns:

65

True if successful

66

67

Raises:

68

ValueError: If deletion fails

69

"""

70

```

71

72

Usage examples:

73

74

```python

75

from linear_api import LinearClient, LinearIssueInput, LinearIssueUpdateInput

76

77

client = LinearClient()

78

79

# Get an issue

80

issue = client.issues.get("issue-id")

81

print(f"Issue: {issue.title} ({issue.state.name})")

82

83

# Create a new issue

84

new_issue = client.issues.create(LinearIssueInput(

85

title="New task from API",

86

teamName="Engineering",

87

description="Task created via Python API",

88

priority=LinearPriority.HIGH

89

))

90

91

# Update an issue

92

updated = client.issues.update("issue-id", LinearIssueUpdateInput(

93

title="Updated title",

94

description="Updated description"

95

))

96

97

# Delete an issue

98

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

99

```

100

101

### Query Operations

102

103

Advanced querying capabilities for finding issues by various criteria.

104

105

```python { .api }

106

def get_by_team(self, team_name: str) -> Dict[str, LinearIssue]:

107

"""

108

Get all issues for a specific team.

109

110

Args:

111

team_name: Name of the team

112

113

Returns:

114

Dictionary mapping issue IDs to LinearIssue objects

115

"""

116

117

def get_by_project(self, project_id: str) -> Dict[str, LinearIssue]:

118

"""

119

Get all issues for a specific project.

120

121

Args:

122

project_id: The ID of the project

123

124

Returns:

125

Dictionary mapping issue IDs to LinearIssue objects

126

"""

127

128

def get_all(self) -> Dict[str, LinearIssue]:

129

"""

130

Get all issues from all teams in the organization.

131

Processes in batches for performance.

132

133

Returns:

134

Dictionary mapping issue IDs to LinearIssue objects

135

"""

136

```

137

138

Usage examples:

139

140

```python

141

# Get issues by team

142

team_issues = client.issues.get_by_team("Engineering")

143

print(f"Found {len(team_issues)} issues in Engineering team")

144

145

# Get issues by project

146

project_issues = client.issues.get_by_project("project-id")

147

for issue_id, issue in project_issues.items():

148

print(f"{issue.title} - {issue.state.name}")

149

150

# Get all issues (use with caution for large organizations)

151

all_issues = client.issues.get_all()

152

```

153

154

### Attachment Management

155

156

Handle issue attachments with URL validation and metadata support.

157

158

```python { .api }

159

def create_attachment(self, attachment: LinearAttachmentInput) -> Dict[str, Any]:

160

"""

161

Create an attachment for an issue with URL validation and metadata support.

162

163

Args:

164

attachment: LinearAttachmentInput with attachment details

165

166

Returns:

167

Created attachment data

168

169

Raises:

170

ValueError: If attachment creation fails

171

"""

172

173

def get_attachments(self, issue_id: str) -> List[Dict[str, Any]]:

174

"""

175

Get all attachments for an issue with creator and metadata information.

176

177

Args:

178

issue_id: The ID of the issue

179

180

Returns:

181

List of attachment dictionaries

182

"""

183

```

184

185

Usage examples:

186

187

```python

188

from linear_api import LinearAttachmentInput

189

190

# Create an attachment

191

attachment = client.issues.create_attachment(LinearAttachmentInput(

192

url="https://example.com/document.pdf",

193

issueId="issue-id",

194

title="Requirements Document",

195

subtitle="Project requirements v1.0",

196

metadata={"category": "documentation", "version": "1.0"}

197

))

198

199

# Get issue attachments

200

attachments = client.issues.get_attachments("issue-id")

201

for attach in attachments:

202

print(f"Attachment: {attach['title']} - {attach['url']}")

203

```

204

205

### History and Comments

206

207

Access issue change history and comment management.

208

209

```python { .api }

210

def get_history(self, issue_id: str) -> List[Dict[str, Any]]:

211

"""

212

Get the change history for an issue including state transitions and actors.

213

214

Args:

215

issue_id: The ID of the issue

216

217

Returns:

218

List of history entries

219

"""

220

221

def get_comments(self, issue_id: str) -> List[Comment]:

222

"""

223

Get all comments for an issue with automatic pagination and Comment model conversion.

224

225

Args:

226

issue_id: The ID of the issue

227

228

Returns:

229

List of Comment objects

230

"""

231

```

232

233

Usage examples:

234

235

```python

236

# Get issue history

237

history = client.issues.get_history("issue-id")

238

for entry in history:

239

print(f"Change: {entry.get('action')} by {entry.get('actor', {}).get('name')}")

240

241

# Get issue comments

242

comments = client.issues.get_comments("issue-id")

243

for comment in comments:

244

print(f"Comment by {comment.creator.name}: {comment.body[:50]}...")

245

```

246

247

### Relationship Management

248

249

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

250

251

```python { .api }

252

def get_children(self, issue_id: str) -> Dict[str, LinearIssue]:

253

"""

254

Get child issues for a parent issue.

255

256

Args:

257

issue_id: The ID of the parent issue

258

259

Returns:

260

Dictionary mapping issue IDs to LinearIssue objects

261

"""

262

263

def get_relations(self, issue_id: str) -> List[IssueRelation]:

264

"""

265

Get relations for an issue (blocks, duplicates, etc.)

266

267

Args:

268

issue_id: The ID of the issue

269

270

Returns:

271

List of IssueRelation objects

272

"""

273

274

def get_inverse_relations(self, issue_id: str) -> List[IssueRelation]:

275

"""

276

Get inverse relations for an issue (blocked by, duplicate of, etc.)

277

278

Args:

279

issue_id: The ID of the issue

280

281

Returns:

282

List of IssueRelation objects

283

"""

284

```

285

286

Usage examples:

287

288

```python

289

# Get child issues

290

children = client.issues.get_children("parent-issue-id")

291

print(f"Parent has {len(children)} child issues")

292

293

# Get issue relations

294

relations = client.issues.get_relations("issue-id")

295

for relation in relations:

296

print(f"Relation: {relation.type} to issue {relation.relatedIssue['id']}")

297

298

# Get inverse relations

299

inverse_relations = client.issues.get_inverse_relations("issue-id")

300

```

301

302

### Social Features

303

304

Access reactions, subscribers, and social interactions on issues.

305

306

```python { .api }

307

def get_reactions(self, issue_id: str) -> List[Reaction]:

308

"""

309

Get reactions to an issue with user information and emoji data.

310

311

Args:

312

issue_id: The ID of the issue

313

314

Returns:

315

List of Reaction objects

316

"""

317

318

def get_subscribers(self, issue_id: str) -> List[LinearUser]:

319

"""

320

Get subscribers of an issue with automatic pagination and LinearUser model conversion.

321

322

Args:

323

issue_id: The ID of the issue

324

325

Returns:

326

List of LinearUser objects

327

"""

328

```

329

330

Usage examples:

331

332

```python

333

# Get issue reactions

334

reactions = client.issues.get_reactions("issue-id")

335

for reaction in reactions:

336

print(f"{reaction.user.name} reacted with {reaction.emoji}")

337

338

# Get issue subscribers

339

subscribers = client.issues.get_subscribers("issue-id")

340

print(f"Issue has {len(subscribers)} subscribers")

341

```

342

343

### Customer Needs Integration

344

345

Access customer needs associated with issues for product management workflows.

346

347

```python { .api }

348

def get_needs(self, issue_id: str) -> List[CustomerNeedResponse]:

349

"""

350

Get customer needs associated with an issue.

351

352

Args:

353

issue_id: The ID of the issue

354

355

Returns:

356

List of CustomerNeedResponse objects

357

"""

358

```

359

360

Usage examples:

361

362

```python

363

# Get customer needs for an issue

364

needs = client.issues.get_needs("issue-id")

365

for need in needs:

366

print(f"Customer need: {need.priority} priority")

367

```

368

369

### Cache Management

370

371

Control caching for issue-related data to optimize performance.

372

373

```python { .api }

374

def invalidate_cache(self) -> None:

375

"""

376

Invalidate all issue-related caches.

377

"""

378

```

379

380

Usage examples:

381

382

```python

383

# Clear issue caches after bulk operations

384

client.issues.invalidate_cache()

385

386

# Or clear all caches

387

client.clear_cache()

388

```

389

390

## Input Models

391

392

### LinearIssueInput

393

394

For creating new issues with comprehensive field support.

395

396

```python { .api }

397

class LinearIssueInput(LinearModel):

398

title: str # Required: Issue title

399

teamName: str # Required: Team name for issue

400

description: Optional[str] = None

401

priority: Optional[LinearPriority] = None

402

assigneeId: Optional[str] = None

403

projectId: Optional[str] = None

404

stateId: Optional[str] = None

405

parentId: Optional[str] = None

406

labelIds: Optional[List[str]] = None

407

estimate: Optional[int] = None

408

dueDate: Optional[datetime] = None

409

metadata: Optional[Dict[str, Any]] = None # Auto-converted to attachment

410

```

411

412

### LinearIssueUpdateInput

413

414

For updating existing issues with all optional fields.

415

416

```python { .api }

417

class LinearIssueUpdateInput(LinearModel):

418

title: Optional[str] = None

419

description: Optional[str] = None

420

priority: Optional[LinearPriority] = None

421

assigneeId: Optional[str] = None

422

projectId: Optional[str] = None

423

stateId: Optional[str] = None

424

teamId: Optional[str] = None

425

labelIds: Optional[List[str]] = None

426

estimate: Optional[int] = None

427

dueDate: Optional[datetime] = None

428

metadata: Optional[Dict[str, Any]] = None # Auto-converted to attachment

429

```

430

431

### LinearAttachmentInput

432

433

For creating issue attachments with metadata support.

434

435

```python { .api }

436

class LinearAttachmentInput(LinearModel):

437

url: str # Required: Attachment URL

438

issueId: str # Required: Issue ID

439

title: Optional[str] = None

440

subtitle: Optional[str] = None

441

metadata: Optional[Dict[str, Any]] = None

442

```

443

444

## Advanced Usage Patterns

445

446

### Bulk Operations

447

448

```python

449

# Create multiple issues efficiently

450

issues_to_create = [

451

LinearIssueInput(title=f"Task {i}", teamName="Engineering")

452

for i in range(1, 11)

453

]

454

455

created_issues = []

456

for issue_input in issues_to_create:

457

created = client.issues.create(issue_input)

458

created_issues.append(created)

459

```

460

461

### Metadata Workflow

462

463

```python

464

# Use metadata for custom fields

465

issue_with_metadata = client.issues.create(LinearIssueInput(

466

title="Feature Request",

467

teamName="Engineering",

468

description="New feature from customer feedback",

469

metadata={

470

"customer_id": "cust_123",

471

"feature_type": "enhancement",

472

"business_value": "high",

473

"complexity": "medium"

474

}

475

))

476

477

# Metadata is automatically converted to an attachment

478

attachments = client.issues.get_attachments(issue_with_metadata.id)

479

metadata_attachment = next((a for a in attachments if a.get('title') == 'Metadata'), None)

480

print(metadata_attachment['metadata'])

481

```

482

483

### Parent-Child Issue Hierarchies

484

485

```python

486

# Create parent issue

487

parent = client.issues.create(LinearIssueInput(

488

title="Epic: User Authentication System",

489

teamName="Engineering",

490

description="Complete user authentication overhaul"

491

))

492

493

# Create child issues

494

child1 = client.issues.create(LinearIssueInput(

495

title="Implement JWT tokens",

496

teamName="Engineering",

497

parentId=parent.id

498

))

499

500

child2 = client.issues.create(LinearIssueInput(

501

title="Add OAuth integration",

502

teamName="Engineering",

503

parentId=parent.id

504

))

505

506

# Get all children

507

children = client.issues.get_children(parent.id)

508

print(f"Epic has {len(children)} child issues")

509

```