linear-cli-agents 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +87 -1
  2. package/dist/commands/cycles/current.d.ts +11 -0
  3. package/dist/commands/cycles/current.js +104 -0
  4. package/dist/commands/cycles/get.d.ts +12 -0
  5. package/dist/commands/cycles/get.js +86 -0
  6. package/dist/commands/cycles/list.d.ts +16 -0
  7. package/dist/commands/cycles/list.js +147 -0
  8. package/dist/commands/documents/create.d.ts +13 -0
  9. package/dist/commands/documents/create.js +68 -0
  10. package/dist/commands/documents/delete.d.ts +9 -0
  11. package/dist/commands/documents/delete.js +32 -0
  12. package/dist/commands/documents/get.d.ts +12 -0
  13. package/dist/commands/documents/get.js +79 -0
  14. package/dist/commands/documents/list.d.ts +12 -0
  15. package/dist/commands/documents/list.js +105 -0
  16. package/dist/commands/documents/update.d.ts +16 -0
  17. package/dist/commands/documents/update.js +75 -0
  18. package/dist/commands/info.js +209 -3
  19. package/dist/commands/initiatives/archive.d.ts +12 -0
  20. package/dist/commands/initiatives/archive.js +44 -0
  21. package/dist/commands/initiatives/create.d.ts +15 -0
  22. package/dist/commands/initiatives/create.js +84 -0
  23. package/dist/commands/initiatives/delete.d.ts +9 -0
  24. package/dist/commands/initiatives/delete.js +32 -0
  25. package/dist/commands/initiatives/get.d.ts +12 -0
  26. package/dist/commands/initiatives/get.js +90 -0
  27. package/dist/commands/initiatives/list.d.ts +11 -0
  28. package/dist/commands/initiatives/list.js +135 -0
  29. package/dist/commands/initiatives/update.d.ts +18 -0
  30. package/dist/commands/initiatives/update.js +90 -0
  31. package/dist/commands/issues/bulk-update.d.ts +2 -0
  32. package/dist/commands/issues/bulk-update.js +10 -0
  33. package/dist/commands/issues/create.d.ts +2 -0
  34. package/dist/commands/issues/create.js +10 -0
  35. package/dist/commands/issues/get.d.ts +1 -0
  36. package/dist/commands/issues/get.js +19 -1
  37. package/dist/commands/issues/update.d.ts +2 -0
  38. package/dist/commands/issues/update.js +12 -0
  39. package/dist/commands/upload.d.ts +13 -0
  40. package/dist/commands/upload.js +117 -0
  41. package/dist/lib/formatter.d.ts +4 -0
  42. package/dist/lib/formatter.js +15 -0
  43. package/oclif.manifest.json +1323 -405
  44. package/package.json +10 -1
@@ -0,0 +1,79 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print, printItem } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class DocumentsGet extends Command {
6
+ static description = 'Get document details';
7
+ static examples = [
8
+ '<%= config.bin %> documents get DOCUMENT_ID',
9
+ '<%= config.bin %> documents get DOCUMENT_ID --format table',
10
+ ];
11
+ static args = {
12
+ id: Args.string({
13
+ description: 'Document ID',
14
+ required: true,
15
+ }),
16
+ };
17
+ static flags = {
18
+ format: Flags.string({
19
+ char: 'F',
20
+ description: 'Output format',
21
+ options: ['json', 'table', 'plain'],
22
+ default: 'json',
23
+ }),
24
+ };
25
+ async run() {
26
+ try {
27
+ const { args, flags } = await this.parse(DocumentsGet);
28
+ const format = flags.format;
29
+ const client = getClient();
30
+ const document = await client.document(args.id);
31
+ if (!document) {
32
+ throw new CliError(ErrorCodes.NOT_FOUND, `Document ${args.id} not found`);
33
+ }
34
+ const [project, creator] = await Promise.all([document.project, document.creator]);
35
+ const data = {
36
+ id: document.id,
37
+ title: document.title,
38
+ content: document.content,
39
+ icon: document.icon ?? null,
40
+ color: document.color ?? null,
41
+ project: project
42
+ ? {
43
+ id: project.id,
44
+ name: project.name,
45
+ }
46
+ : null,
47
+ creator: creator
48
+ ? {
49
+ id: creator.id,
50
+ name: creator.name,
51
+ }
52
+ : null,
53
+ createdAt: document.createdAt,
54
+ updatedAt: document.updatedAt,
55
+ };
56
+ if (format === 'json') {
57
+ print(success(data));
58
+ }
59
+ else if (format === 'table') {
60
+ printItem({
61
+ id: data.id,
62
+ title: data.title,
63
+ project: data.project?.name ?? 'None',
64
+ creator: data.creator?.name ?? 'Unknown',
65
+ content: data.content ? `${data.content.slice(0, 100)}...` : 'Empty',
66
+ createdAt: data.createdAt,
67
+ updatedAt: data.updatedAt,
68
+ }, format);
69
+ }
70
+ else {
71
+ console.log(data.id);
72
+ }
73
+ }
74
+ catch (err) {
75
+ handleError(err);
76
+ this.exit(1);
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DocumentsList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ first: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ after: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,105 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { successList, print, printList } from '../../lib/output.js';
4
+ import { handleError } from '../../lib/errors.js';
5
+ import { colors, truncate } from '../../lib/formatter.js';
6
+ const COLUMNS = [
7
+ {
8
+ key: 'title',
9
+ header: 'TITLE',
10
+ format: (value) => colors.bold(truncate(String(value), 40)),
11
+ },
12
+ {
13
+ key: 'projectName',
14
+ header: 'PROJECT',
15
+ format: (value) => (value ? colors.cyan(truncate(String(value), 20)) : colors.gray('None')),
16
+ },
17
+ {
18
+ key: 'creatorName',
19
+ header: 'CREATOR',
20
+ format: (value) => (value ? colors.dim(String(value)) : colors.gray('Unknown')),
21
+ },
22
+ {
23
+ key: 'updatedAt',
24
+ header: 'UPDATED',
25
+ format: (value) => colors.dim(new Date(value).toISOString().split('T')[0]),
26
+ },
27
+ ];
28
+ export default class DocumentsList extends Command {
29
+ static description = 'List documents';
30
+ static examples = [
31
+ '<%= config.bin %> documents list',
32
+ '<%= config.bin %> documents list --project-id PROJECT_ID',
33
+ '<%= config.bin %> documents list --format table',
34
+ ];
35
+ static flags = {
36
+ format: Flags.string({
37
+ char: 'F',
38
+ description: 'Output format',
39
+ options: ['json', 'table', 'plain'],
40
+ default: 'json',
41
+ }),
42
+ 'project-id': Flags.string({
43
+ description: 'Filter by project ID',
44
+ }),
45
+ first: Flags.integer({
46
+ description: 'Number of documents to fetch (default: 50)',
47
+ default: 50,
48
+ }),
49
+ after: Flags.string({
50
+ description: 'Cursor for pagination',
51
+ }),
52
+ };
53
+ async run() {
54
+ try {
55
+ const { flags } = await this.parse(DocumentsList);
56
+ const format = flags.format;
57
+ const client = getClient();
58
+ const filter = {};
59
+ if (flags['project-id']) {
60
+ filter.project = { id: { eq: flags['project-id'] } };
61
+ }
62
+ const documents = await client.documents({
63
+ first: flags.first,
64
+ after: flags.after,
65
+ filter: Object.keys(filter).length > 0 ? filter : undefined,
66
+ });
67
+ const data = await Promise.all(documents.nodes.map(async (doc) => {
68
+ const [project, creator] = await Promise.all([doc.project, doc.creator]);
69
+ return {
70
+ id: doc.id,
71
+ title: doc.title,
72
+ icon: doc.icon ?? null,
73
+ color: doc.color ?? null,
74
+ projectId: project?.id ?? null,
75
+ projectName: project?.name ?? null,
76
+ creatorId: creator?.id ?? null,
77
+ creatorName: creator?.name ?? null,
78
+ createdAt: doc.createdAt,
79
+ updatedAt: doc.updatedAt,
80
+ };
81
+ }));
82
+ const pageInfo = {
83
+ hasNextPage: documents.pageInfo.hasNextPage,
84
+ hasPreviousPage: documents.pageInfo.hasPreviousPage,
85
+ startCursor: documents.pageInfo.startCursor,
86
+ endCursor: documents.pageInfo.endCursor,
87
+ };
88
+ if (format === 'json') {
89
+ print(successList(data, pageInfo));
90
+ }
91
+ else {
92
+ printList(data, format, {
93
+ columns: COLUMNS,
94
+ primaryKey: 'title',
95
+ secondaryKey: 'id',
96
+ pageInfo,
97
+ });
98
+ }
99
+ }
100
+ catch (err) {
101
+ handleError(err);
102
+ this.exit(1);
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DocumentsUpdate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ content: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ 'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ icon: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,75 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class DocumentsUpdate extends Command {
6
+ static description = 'Update a document';
7
+ static examples = [
8
+ '<%= config.bin %> documents update DOCUMENT_ID --title "New Title"',
9
+ '<%= config.bin %> documents update DOCUMENT_ID --content "Updated content"',
10
+ '<%= config.bin %> documents update DOCUMENT_ID --project-id PROJECT_ID',
11
+ ];
12
+ static args = {
13
+ id: Args.string({
14
+ description: 'Document ID',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ title: Flags.string({
20
+ char: 't',
21
+ description: 'New document title',
22
+ }),
23
+ content: Flags.string({
24
+ char: 'c',
25
+ description: 'New document content (markdown)',
26
+ }),
27
+ 'project-id': Flags.string({
28
+ description: 'New project ID (empty string to remove)',
29
+ }),
30
+ icon: Flags.string({
31
+ description: 'New document icon (emoji)',
32
+ }),
33
+ color: Flags.string({
34
+ description: 'New document color (hex)',
35
+ }),
36
+ };
37
+ async run() {
38
+ try {
39
+ const { args, flags } = await this.parse(DocumentsUpdate);
40
+ const client = getClient();
41
+ const input = {};
42
+ if (flags.title)
43
+ input.title = flags.title;
44
+ if (flags.content)
45
+ input.content = flags.content;
46
+ if (flags['project-id'] !== undefined) {
47
+ input.projectId = flags['project-id'] || null;
48
+ }
49
+ if (flags.icon)
50
+ input.icon = flags.icon;
51
+ if (flags.color)
52
+ input.color = flags.color;
53
+ if (Object.keys(input).length === 0) {
54
+ throw new CliError(ErrorCodes.INVALID_INPUT, 'No update fields provided');
55
+ }
56
+ const payload = await client.updateDocument(args.id, input);
57
+ if (!payload.success) {
58
+ throw new CliError(ErrorCodes.API_ERROR, 'Failed to update document');
59
+ }
60
+ const document = await payload.document;
61
+ if (!document) {
62
+ throw new CliError(ErrorCodes.API_ERROR, 'Document not returned');
63
+ }
64
+ print(success({
65
+ id: document.id,
66
+ title: document.title,
67
+ updatedAt: document.updatedAt,
68
+ }));
69
+ }
70
+ catch (err) {
71
+ handleError(err);
72
+ this.exit(1);
73
+ }
74
+ }
75
+ }
@@ -43,8 +43,9 @@ const COMMANDS = {
43
43
  args: { id: { description: 'Issue ID or identifier (e.g., ENG-123)', required: true } },
44
44
  flags: {
45
45
  format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' },
46
+ 'with-attachments': { type: 'boolean', description: 'Include attachments (linked PRs, commits, etc.)' },
46
47
  },
47
- examples: ['linear issues get ENG-123', 'linear issues get abc123-uuid'],
48
+ examples: ['linear issues get ENG-123', 'linear issues get ENG-123 --with-attachments'],
48
49
  },
49
50
  'issues create': {
50
51
  description: 'Create a new issue',
@@ -405,6 +406,122 @@ const COMMANDS = {
405
406
  },
406
407
  examples: ['linear templates update TEMPLATE_ID --name "New Name"'],
407
408
  },
409
+ // Documents
410
+ 'documents list': {
411
+ description: 'List documents',
412
+ flags: {
413
+ format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' },
414
+ first: { type: 'number', description: 'Number of results' },
415
+ },
416
+ examples: ['linear documents list'],
417
+ },
418
+ 'documents get': {
419
+ description: 'Get document details',
420
+ args: { id: { description: 'Document ID', required: true } },
421
+ flags: { format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' } },
422
+ examples: ['linear documents get DOCUMENT_ID'],
423
+ },
424
+ 'documents create': {
425
+ description: 'Create a new document',
426
+ flags: {
427
+ title: { type: 'string', char: 't', description: 'Document title', required: true },
428
+ content: { type: 'string', char: 'c', description: 'Document content (markdown)' },
429
+ 'project-id': { type: 'string', description: 'Project ID to associate with' },
430
+ icon: { type: 'string', description: 'Document icon (emoji)' },
431
+ color: { type: 'string', description: 'Document color (hex)' },
432
+ },
433
+ examples: [
434
+ 'linear documents create --title "My Document"',
435
+ 'linear documents create --title "Notes" --content "# Heading\\n\\nContent"',
436
+ ],
437
+ },
438
+ 'documents update': {
439
+ description: 'Update a document',
440
+ args: { id: { description: 'Document ID', required: true } },
441
+ flags: {
442
+ title: { type: 'string', char: 't', description: 'New title' },
443
+ content: { type: 'string', char: 'c', description: 'New content (markdown)' },
444
+ 'project-id': { type: 'string', description: 'New project ID (empty to remove)' },
445
+ icon: { type: 'string', description: 'New icon (emoji)' },
446
+ color: { type: 'string', description: 'New color (hex)' },
447
+ },
448
+ examples: ['linear documents update DOCUMENT_ID --title "New Title"'],
449
+ },
450
+ 'documents delete': {
451
+ description: 'Delete a document (moves to trash)',
452
+ args: { id: { description: 'Document ID', required: true } },
453
+ flags: {},
454
+ examples: ['linear documents delete DOCUMENT_ID'],
455
+ },
456
+ // Initiatives
457
+ 'initiatives list': {
458
+ description: 'List initiatives',
459
+ flags: {
460
+ format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' },
461
+ status: { type: 'string', options: ['Planned', 'Active', 'Completed'], description: 'Filter by status' },
462
+ first: { type: 'number', description: 'Number of results' },
463
+ },
464
+ examples: [
465
+ 'linear initiatives list',
466
+ 'linear initiatives list --status Active',
467
+ ],
468
+ },
469
+ 'initiatives get': {
470
+ description: 'Get initiative details',
471
+ args: { id: { description: 'Initiative ID', required: true } },
472
+ flags: { format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' } },
473
+ examples: ['linear initiatives get INITIATIVE_ID'],
474
+ },
475
+ 'initiatives create': {
476
+ description: 'Create a new initiative',
477
+ flags: {
478
+ name: { type: 'string', char: 'n', description: 'Initiative name', required: true },
479
+ description: { type: 'string', char: 'd', description: 'Initiative description' },
480
+ status: { type: 'string', options: ['Planned', 'Active', 'Completed'], description: 'Initial status' },
481
+ 'target-date': { type: 'string', description: 'Target completion date (YYYY-MM-DD)' },
482
+ 'owner-id': { type: 'string', description: 'Owner user ID' },
483
+ icon: { type: 'string', description: 'Initiative icon (emoji)' },
484
+ color: { type: 'string', description: 'Initiative color (hex)' },
485
+ },
486
+ examples: [
487
+ 'linear initiatives create --name "Q1 Goals"',
488
+ 'linear initiatives create --name "Launch" --status Active --target-date 2024-12-31',
489
+ ],
490
+ },
491
+ 'initiatives update': {
492
+ description: 'Update an initiative',
493
+ args: { id: { description: 'Initiative ID', required: true } },
494
+ flags: {
495
+ name: { type: 'string', char: 'n', description: 'New name' },
496
+ description: { type: 'string', char: 'd', description: 'New description' },
497
+ status: { type: 'string', options: ['Planned', 'Active', 'Completed'], description: 'New status' },
498
+ 'target-date': { type: 'string', description: 'New target date (YYYY-MM-DD)' },
499
+ 'owner-id': { type: 'string', description: 'New owner user ID' },
500
+ icon: { type: 'string', description: 'New icon (emoji)' },
501
+ color: { type: 'string', description: 'New color (hex)' },
502
+ },
503
+ examples: [
504
+ 'linear initiatives update INITIATIVE_ID --status Completed',
505
+ 'linear initiatives update INITIATIVE_ID --name "New Name"',
506
+ ],
507
+ },
508
+ 'initiatives delete': {
509
+ description: 'Delete an initiative (moves to trash)',
510
+ args: { id: { description: 'Initiative ID', required: true } },
511
+ flags: {},
512
+ examples: ['linear initiatives delete INITIATIVE_ID'],
513
+ },
514
+ 'initiatives archive': {
515
+ description: 'Archive or unarchive an initiative',
516
+ args: { id: { description: 'Initiative ID', required: true } },
517
+ flags: {
518
+ unarchive: { type: 'boolean', char: 'u', description: 'Unarchive instead of archive' },
519
+ },
520
+ examples: [
521
+ 'linear initiatives archive INITIATIVE_ID',
522
+ 'linear initiatives archive INITIATIVE_ID --unarchive',
523
+ ],
524
+ },
408
525
  // Config
409
526
  'config set': {
410
527
  description: 'Set a configuration value',
@@ -435,6 +552,40 @@ const COMMANDS = {
435
552
  flags: { format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' } },
436
553
  examples: ['linear me'],
437
554
  },
555
+ // Cycles
556
+ 'cycles list': {
557
+ description: 'List cycles (sprints)',
558
+ flags: {
559
+ format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' },
560
+ 'team-id': { type: 'string', description: 'Filter by team ID' },
561
+ team: { type: 'string', description: 'Filter by team key (e.g., ENG)' },
562
+ active: { type: 'boolean', description: 'Show only active cycles' },
563
+ upcoming: { type: 'boolean', description: 'Show only upcoming cycles' },
564
+ completed: { type: 'boolean', description: 'Show only completed cycles' },
565
+ first: { type: 'number', description: 'Number of results' },
566
+ },
567
+ examples: [
568
+ 'linear cycles list',
569
+ 'linear cycles list --team ENG',
570
+ 'linear cycles list --active',
571
+ ],
572
+ },
573
+ 'cycles get': {
574
+ description: 'Get cycle (sprint) details',
575
+ args: { id: { description: 'Cycle ID', required: true } },
576
+ flags: { format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' } },
577
+ examples: ['linear cycles get CYCLE_ID'],
578
+ },
579
+ 'cycles current': {
580
+ description: 'Get the current active cycle for a team',
581
+ flags: {
582
+ format: { type: 'string', options: ['json', 'table', 'plain'], default: 'json' },
583
+ 'team-id': { type: 'string', description: 'Team ID' },
584
+ team: { type: 'string', description: 'Team key (e.g., ENG)' },
585
+ },
586
+ examples: ['linear cycles current --team ENG'],
587
+ },
588
+ // Other
438
589
  search: {
439
590
  description: 'Search for issues',
440
591
  args: { query: { description: 'Search query', required: true } },
@@ -467,6 +618,19 @@ const COMMANDS = {
467
618
  },
468
619
  examples: ['linear schema', 'linear schema issues', 'linear schema --full'],
469
620
  },
621
+ upload: {
622
+ description: 'Upload a file to Linear and get the asset URL',
623
+ args: { file: { description: 'Path to the file to upload', required: true } },
624
+ flags: {
625
+ 'content-type': { type: 'string', description: 'Override the content type (MIME type)' },
626
+ markdown: { type: 'boolean', char: 'm', description: 'Output as markdown link/image' },
627
+ },
628
+ examples: [
629
+ 'linear upload ./screenshot.png',
630
+ 'linear upload ./document.pdf --content-type application/pdf',
631
+ 'linear upload ./image.png --markdown',
632
+ ],
633
+ },
470
634
  info: {
471
635
  description: 'Show comprehensive CLI documentation (this command)',
472
636
  flags: {
@@ -516,6 +680,20 @@ const ENTITY_SCHEMAS = {
516
680
  teams: 'Associated teams',
517
681
  },
518
682
  },
683
+ cycles: {
684
+ entity: 'cycles',
685
+ operations: ['list', 'get', 'current'],
686
+ description: 'Time-boxed iterations (sprints)',
687
+ fields: {
688
+ id: 'Unique identifier',
689
+ number: 'Cycle number',
690
+ name: 'Cycle name (optional)',
691
+ startsAt: 'Start date',
692
+ endsAt: 'End date',
693
+ progress: 'Completion progress (0-1)',
694
+ team: 'Associated team',
695
+ },
696
+ },
519
697
  teams: {
520
698
  entity: 'teams',
521
699
  operations: ['list'],
@@ -568,6 +746,34 @@ const ENTITY_SCHEMAS = {
568
746
  createdAt: 'Creation timestamp',
569
747
  },
570
748
  },
749
+ documents: {
750
+ entity: 'documents',
751
+ operations: ['list', 'get', 'create', 'update', 'delete'],
752
+ description: 'Rich text documents in Linear',
753
+ fields: {
754
+ id: 'Unique identifier',
755
+ title: 'Document title',
756
+ content: 'Markdown content',
757
+ icon: 'Document icon (emoji)',
758
+ color: 'Document color (hex)',
759
+ project: 'Associated project',
760
+ creator: 'User who created it',
761
+ },
762
+ },
763
+ initiatives: {
764
+ entity: 'initiatives',
765
+ operations: ['list', 'get', 'create', 'update', 'delete', 'archive'],
766
+ description: 'Strategic initiatives grouping projects',
767
+ fields: {
768
+ id: 'Unique identifier',
769
+ name: 'Initiative name',
770
+ description: 'Initiative description',
771
+ status: 'Planned/Active/Completed',
772
+ targetDate: 'Target completion date',
773
+ owner: 'Initiative owner',
774
+ projects: 'Associated projects',
775
+ },
776
+ },
571
777
  };
572
778
  const WORKFLOWS = {
573
779
  createIssue: {
@@ -644,7 +850,7 @@ export default class Info extends Command {
644
850
  return acc;
645
851
  }, {});
646
852
  print(success({
647
- version: '0.5.1',
853
+ version: '0.7.0',
648
854
  commands: compactCommands,
649
855
  configKeys: CONFIG_KEYS,
650
856
  note: 'Use "linear info" for full documentation with examples and workflows',
@@ -653,7 +859,7 @@ export default class Info extends Command {
653
859
  }
654
860
  // Full documentation
655
861
  print(success({
656
- version: '0.5.1',
862
+ version: '0.7.0',
657
863
  overview: {
658
864
  description: 'CLI for interacting with Linear, designed for LLMs and agents',
659
865
  authentication: 'Run "linear auth login" or set LINEAR_API_KEY environment variable',
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class InitiativesArchive extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ unarchive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,44 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { getClient } from '../../lib/client.js';
3
+ import { success, print } from '../../lib/output.js';
4
+ import { handleError, CliError, ErrorCodes } from '../../lib/errors.js';
5
+ export default class InitiativesArchive extends Command {
6
+ static description = 'Archive or unarchive an initiative';
7
+ static examples = [
8
+ '<%= config.bin %> initiatives archive INITIATIVE_ID',
9
+ '<%= config.bin %> initiatives archive INITIATIVE_ID --unarchive',
10
+ ];
11
+ static args = {
12
+ id: Args.string({
13
+ description: 'Initiative ID',
14
+ required: true,
15
+ }),
16
+ };
17
+ static flags = {
18
+ unarchive: Flags.boolean({
19
+ char: 'u',
20
+ description: 'Unarchive instead of archive',
21
+ default: false,
22
+ }),
23
+ };
24
+ async run() {
25
+ try {
26
+ const { args, flags } = await this.parse(InitiativesArchive);
27
+ const client = getClient();
28
+ const payload = flags.unarchive
29
+ ? await client.unarchiveInitiative(args.id)
30
+ : await client.archiveInitiative(args.id);
31
+ if (!payload.success) {
32
+ throw new CliError(ErrorCodes.API_ERROR, `Failed to ${flags.unarchive ? 'unarchive' : 'archive'} initiative`);
33
+ }
34
+ print(success({
35
+ id: args.id,
36
+ archived: !flags.unarchive,
37
+ }));
38
+ }
39
+ catch (err) {
40
+ handleError(err);
41
+ this.exit(1);
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,15 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class InitiativesCreate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ 'target-date': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'owner-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ icon: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ run(): Promise<void>;
15
+ }