@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/CHANGELOG.md +38 -0
- package/README.md +44 -16
- package/extensions/pi-linear-tools.js +210 -27
- package/package.json +2 -2
- package/settings.json.example +6 -2
- package/src/cli.js +101 -8
- package/src/handlers.js +405 -18
- package/src/linear-client.js +120 -14
- package/src/linear.js +319 -26
- package/src/settings.js +22 -0
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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':
|