@fink-andreas/pi-linear-tools 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.
package/src/cli.js CHANGED
@@ -18,6 +18,8 @@ import {
18
18
  import {
19
19
  executeIssueList,
20
20
  executeIssueView,
21
+ executeIssueImages,
22
+ executeIssueDownload,
21
23
  executeIssueActivity,
22
24
  executeIssueCreate,
23
25
  executeIssueUpdate,
@@ -164,6 +166,8 @@ Other commands:
164
166
  config Show current configuration
165
167
  config --api-key <key> Set Linear API key (legacy)
166
168
  config --default-team <key> Set default team
169
+ config --allow-overwrite-files true|false
170
+ Allow issue download overwrites when requested
167
171
 
168
172
  Auth Actions:
169
173
  login Authenticate with Linear via OAuth 2.0
@@ -173,9 +177,12 @@ Auth Actions:
173
177
  Issue Actions:
174
178
  list [--project X] [--states X,Y] [--assignee me|all] [--team X] [--limit N]
175
179
  view <issue> [--no-comments]
180
+ images <issue> [--no-comments] [--limit N] [--max-bytes N]
181
+ download <issue> --directory DIR [--attachment-id ID|--attachment-title TITLE|--attachment-url URL|--attachment-index N]
182
+ [--filename NAME] [--overwrite true|false] [--max-bytes N]
176
183
  activity <issue> [--limit N] [--include-archived true|false]
177
- create --title X [--team X] [--project X] [--description X] [--priority 0-4] [--assignee me|ID]
178
- update <issue> [--title X] [--description X] [--state X] [--priority 0-4]
184
+ create --title X [--team X] [--project X] [--description X] [--priority 0-4|name] [--assignee me|ID]
185
+ update <issue> [--title X] [--description X] [--state X] [--priority 0-4|name]
179
186
  [--assignee me|ID] [--milestone X] [--sub-issue-of X]
180
187
  comment <issue> --body X
181
188
  start <issue> [--from-ref X] [--on-branch-exists switch|suffix]
@@ -242,7 +249,7 @@ Common Flags:
242
249
  --project Project name or ID
243
250
  --team Team key (e.g., ENG)
244
251
  --assignee "me" or assignee ID
245
- --priority Priority 0-4 (0=None, 1=Urgent, 2=High, 3=Medium, 4=Low)
252
+ --priority Issue priority: 0=None, 1=Urgent, 2=High, 3=Medium, 4=Low; or none, urgent, high, medium, low
246
253
  --state State name or ID
247
254
  --limit Max results (default: 50)
248
255
 
@@ -286,11 +293,14 @@ Guidance:
286
293
  Use "update" to change the issue itself: title, description, state, assignee, milestone, or parent.
287
294
  Use "comment" to add a discussion entry.
288
295
  Use "activity" to read the Activity timeline shown in Linear.
296
+ Use "images" to fetch image attachments embedded in issue markdown/comments.
289
297
 
290
298
  Actions:
291
299
  list List issues in a project
292
300
  view View issue details
301
+ images Fetch image attachments embedded in issue markdown/comments
293
302
  activity View issue activity/history
303
+ download Download a Linear issue attachment
294
304
  create Create a new issue
295
305
  update Update an existing issue
296
306
  comment Add a comment to an issue
@@ -308,6 +318,23 @@ View Options:
308
318
  <issue> Issue key (e.g., ENG-123), ID, or issue URL
309
319
  --no-comments Exclude comments from output
310
320
 
321
+ Images Options:
322
+ <issue> Issue key (e.g., ENG-123), ID, or issue URL
323
+ --no-comments Exclude images from comments
324
+ --limit N Max images to fetch (default: 10)
325
+ --max-bytes N Max bytes per image (default/max: 10485760)
326
+
327
+ Download Options:
328
+ <issue> Issue key, ID, or issue URL
329
+ --directory DIR Relative destination directory (required)
330
+ --attachment-id ID Attachment ID selector
331
+ --attachment-title X Attachment title selector (must be unique)
332
+ --attachment-url URL Attachment URL selector
333
+ --attachment-index N 1-based attachment index selector
334
+ --filename NAME Optional output filename
335
+ --overwrite X true or false (default: false; requires config guard)
336
+ --max-bytes N Max download bytes (default/max: 52428800)
337
+
311
338
  Activity Options:
312
339
  <issue> Issue key, ID, or issue URL
313
340
  --limit N Max activity entries to fetch (default: 20)
@@ -318,7 +345,7 @@ Create Options:
318
345
  --team X Team key, e.g., ENG (required if no default team)
319
346
  --project X Project name or ID
320
347
  --description X Issue description (markdown)
321
- --priority N Priority 0-4
348
+ --priority N Issue priority: 0=None, 1=Urgent, 2=High, 3=Medium, 4=Low; or none, urgent, high, medium, low
322
349
  --assignee X "me" or assignee ID
323
350
  --parent-id X Parent issue ID for sub-issues
324
351
 
@@ -327,7 +354,7 @@ Update Options:
327
354
  --title X New title
328
355
  --description X New description
329
356
  --state X New state name or ID
330
- --priority N New priority 0-4
357
+ --priority N New issue priority: 0=None, 1=Urgent, 2=High, 3=Medium, 4=Low; or none, urgent, high, medium, low
331
358
  --assignee X "me" or assignee ID
332
359
  --milestone X Milestone name/ID, or "none" to clear
333
360
  --sub-issue-of X Parent issue key/ID, or "none" to clear
@@ -351,6 +378,7 @@ Examples:
351
378
  pi-linear-tools issue comment ENG-123 --body "Ready for review"
352
379
  pi-linear-tools issue activity ENG-123 --limit 20
353
380
  pi-linear-tools issue activity https://linear.app/workspace/issue/ENG-123/example --limit 20
381
+ pi-linear-tools issue download ENG-123 --attachment-index 1 --directory downloads
354
382
  `);
355
383
  }
356
384
 
@@ -729,6 +757,7 @@ async function handleConfig(args) {
729
757
  const defaultTeam = readFlag(args, '--default-team');
730
758
  const projectTeam = readFlag(args, '--team');
731
759
  const projectName = readFlag(args, '--project');
760
+ const allowOverwriteFiles = readFlag(args, '--allow-overwrite-files');
732
761
 
733
762
  if (apiKey) {
734
763
  const settings = await loadSettings();
@@ -748,6 +777,19 @@ async function handleConfig(args) {
748
777
  return;
749
778
  }
750
779
 
780
+ if (allowOverwriteFiles !== undefined) {
781
+ const enabled = parseBoolean(allowOverwriteFiles);
782
+ if (enabled === undefined) {
783
+ throw new Error('Invalid value for --allow-overwrite-files. Use true or false.');
784
+ }
785
+
786
+ const settings = await loadSettings();
787
+ settings.allow_overwrite_files = enabled;
788
+ await saveSettings(settings);
789
+ console.log(`File overwrite guard ${enabled ? 'allows overwrites' : 'blocks overwrites'}`);
790
+ return;
791
+ }
792
+
751
793
  if (projectTeam) {
752
794
  if (!projectName) {
753
795
  throw new Error('Missing required flag: --project when using --team');
@@ -777,12 +819,14 @@ async function handleConfig(args) {
777
819
  console.log(`Configuration:
778
820
  LINEAR_API_KEY: ${hasKey ? 'configured' : 'not set'} (source: ${keySource})
779
821
  Default team: ${settings.defaultTeam || 'not set'}
822
+ Allow overwrite files: ${settings.allow_overwrite_files ? 'enabled' : 'disabled'}
780
823
  Project team mappings: ${Object.keys(settings.projects || {}).length}
781
824
 
782
825
  Commands:
783
826
  pi-linear-tools config --api-key lin_xxx
784
827
  pi-linear-tools config --default-team ENG
785
- pi-linear-tools config --team ENG --project MyProject`);
828
+ pi-linear-tools config --team ENG --project MyProject
829
+ pi-linear-tools config --allow-overwrite-files true|false`);
786
830
  }
787
831
 
788
832
  // ===== ISSUE HANDLERS =====
@@ -819,6 +863,25 @@ async function handleIssueView(args) {
819
863
  console.log(result.content[0].text);
820
864
  }
821
865
 
866
+ async function handleIssueImages(args) {
867
+ const client = await createAuthenticatedClient();
868
+
869
+ const positional = args.filter((a) => !a.startsWith('-'));
870
+ if (positional.length === 0) {
871
+ throw new Error('Missing required argument: issue key or ID');
872
+ }
873
+
874
+ const params = {
875
+ issue: positional[0],
876
+ includeComments: !hasFlag(args, '--no-comments'),
877
+ limit: parseNumber(readFlag(args, '--limit')),
878
+ maxBytes: parseNumber(readFlag(args, '--max-bytes')),
879
+ };
880
+
881
+ const result = await executeIssueImages(client, params);
882
+ console.log(result.content[0].text);
883
+ }
884
+
822
885
  async function handleIssueActivity(args) {
823
886
  const client = await createAuthenticatedClient();
824
887
 
@@ -837,6 +900,32 @@ async function handleIssueActivity(args) {
837
900
  console.log(result.content[0].text);
838
901
  }
839
902
 
903
+ async function handleIssueDownload(args) {
904
+ const client = await createAuthenticatedClient();
905
+ const settings = await loadSettings();
906
+
907
+ const positional = args.filter((a) => !a.startsWith('-'));
908
+ if (positional.length === 0) {
909
+ throw new Error('Missing required argument: issue key or ID');
910
+ }
911
+
912
+ const overwrite = parseBoolean(readFlag(args, '--overwrite'));
913
+ const params = {
914
+ issue: positional[0],
915
+ attachmentId: readFlag(args, '--attachment-id'),
916
+ attachmentTitle: readFlag(args, '--attachment-title'),
917
+ attachmentUrl: readFlag(args, '--attachment-url'),
918
+ attachmentIndex: parseNumber(readFlag(args, '--attachment-index')),
919
+ directory: readFlag(args, '--directory'),
920
+ filename: readFlag(args, '--filename'),
921
+ overwrite: overwrite === undefined ? undefined : overwrite,
922
+ maxBytes: parseNumber(readFlag(args, '--max-bytes')),
923
+ };
924
+
925
+ const result = await executeIssueDownload(client, params, { settings });
926
+ console.log(result.content[0].text);
927
+ }
928
+
840
929
  async function handleIssueCreate(args) {
841
930
  const client = await createAuthenticatedClient();
842
931
 
@@ -845,7 +934,7 @@ async function handleIssueCreate(args) {
845
934
  team: readFlag(args, '--team'),
846
935
  project: readFlag(args, '--project'),
847
936
  description: readFlag(args, '--description'),
848
- priority: parseNumber(readFlag(args, '--priority')),
937
+ priority: readFlag(args, '--priority'),
849
938
  assignee: readFlag(args, '--assignee'),
850
939
  parentId: readFlag(args, '--parent-id'),
851
940
  state: readFlag(args, '--state'),
@@ -872,7 +961,7 @@ async function handleIssueUpdate(args) {
872
961
  title: readFlag(args, '--title'),
873
962
  description: readFlag(args, '--description'),
874
963
  state: readFlag(args, '--state'),
875
- priority: parseNumber(readFlag(args, '--priority')),
964
+ priority: readFlag(args, '--priority'),
876
965
  assignee: readFlag(args, '--assignee'),
877
966
  milestone: readFlag(args, '--milestone'),
878
967
  subIssueOf: readFlag(args, '--sub-issue-of'),
@@ -950,6 +1039,10 @@ async function handleIssue(args) {
950
1039
  return handleIssueList(rest);
951
1040
  case 'view':
952
1041
  return handleIssueView(rest);
1042
+ case 'images':
1043
+ return handleIssueImages(rest);
1044
+ case 'download':
1045
+ return handleIssueDownload(rest);
953
1046
  case 'activity':
954
1047
  return handleIssueActivity(rest);
955
1048
  case 'create':