@kyoji2/intercom-cli 0.1.0 → 0.1.6

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/index.ts CHANGED
@@ -1,60 +1,28 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
+ import { readFileSync } from "node:fs";
3
4
  import { Command } from "commander";
5
+ import { registerCommands } from "./cli/registry.ts";
4
6
  import { handleIntercomError } from "./client.ts";
5
- import {
6
- cmdAdminGet,
7
- cmdAdminList,
8
- cmdArticleCreate,
9
- cmdArticleDelete,
10
- cmdArticleGet,
11
- cmdArticleList,
12
- cmdArticleSearch,
13
- cmdArticleUpdate,
14
- cmdCompanyCreate,
15
- cmdCompanyGet,
16
- cmdCompanyList,
17
- cmdCompanyUpdate,
18
- cmdContactAttachCompany,
19
- cmdContactCreate,
20
- cmdContactDelete,
21
- cmdContactGet,
22
- cmdContactList,
23
- cmdContactNote,
24
- cmdContactNotes,
25
- cmdContactSearch,
26
- cmdContactTag,
27
- cmdContactUntag,
28
- cmdContactUpdate,
29
- cmdContext,
30
- cmdConversationAssign,
31
- cmdConversationClose,
32
- cmdConversationGet,
33
- cmdConversationList,
34
- cmdConversationOpen,
35
- cmdConversationReply,
36
- cmdConversationSearch,
37
- cmdConversationSnooze,
38
- cmdEventList,
39
- cmdEventTrack,
40
- cmdLogin,
41
- cmdLogout,
42
- cmdSchema,
43
- cmdTagCreate,
44
- cmdTagDelete,
45
- cmdTagGet,
46
- cmdTagList,
47
- cmdWhoami,
48
- } from "./commands/index.ts";
49
- import { CLIError, type GlobalOptions, type OutputFormat } from "./utils/index.ts";
50
-
51
- const VERSION = "0.1.0";
7
+ import { CLIError, DEFAULT_CONFIG_DIR, type GlobalOptions, type OutputFormat } from "./utils/index.ts";
8
+
9
+ function readVersion(): string {
10
+ try {
11
+ const packageUrl = new URL("../package.json", import.meta.url);
12
+ const data = JSON.parse(readFileSync(packageUrl, "utf-8")) as { version?: string };
13
+ if (typeof data.version === "string" && data.version.trim().length > 0) {
14
+ return data.version;
15
+ }
16
+ } catch {}
17
+ return "0.0.0";
18
+ }
52
19
 
53
20
  function getGlobalOptions(cmd: Command): GlobalOptions {
54
21
  const opts = cmd.optsWithGlobals();
55
22
  return {
56
23
  dryRun: opts.dryRun ?? false,
57
24
  format: (opts.format as OutputFormat) ?? "toon",
25
+ configDir: (opts.configDir as string) ?? DEFAULT_CONFIG_DIR,
58
26
  };
59
27
  }
60
28
 
@@ -108,582 +76,10 @@ const program = new Command();
108
76
  program
109
77
  .name("intercom")
110
78
  .description("AI-native CLI for Intercom - manage customer conversations, contacts, messages, and support")
111
- .version(VERSION, "-v, --version")
79
+ .version(readVersion(), "-v, --version")
112
80
  .option("--dry-run", "Log actions instead of making real API requests", false)
113
- .option("-f, --format <format>", "Output format: toon (default) or json", "toon");
114
-
115
- program
116
- .command("login")
117
- .description("Login with your Intercom Access Token")
118
- .argument("[token]", "Access token (will prompt if not provided)")
119
- .action(
120
- withErrorHandler(async (token: string | undefined, _options, cmd: Command) => {
121
- const globalOpts = getGlobalOptions(cmd);
122
- await cmdLogin({ ...globalOpts, token });
123
- }),
124
- );
125
-
126
- program
127
- .command("logout")
128
- .description("Remove stored credentials")
129
- .action(
130
- withErrorHandler(async (_options, cmd: Command) => {
131
- const globalOpts = getGlobalOptions(cmd);
132
- await cmdLogout(globalOpts);
133
- }),
134
- );
135
-
136
- program
137
- .command("whoami")
138
- .description("Show current admin and workspace info")
139
- .action(
140
- withErrorHandler(async (_options, cmd: Command) => {
141
- const globalOpts = getGlobalOptions(cmd);
142
- await cmdWhoami(globalOpts);
143
- }),
144
- );
145
-
146
- program
147
- .command("context")
148
- .description("Show account context (admins, workspace)")
149
- .action(
150
- withErrorHandler(async (_options, cmd: Command) => {
151
- const globalOpts = getGlobalOptions(cmd);
152
- await cmdContext(globalOpts);
153
- }),
154
- );
155
-
156
- program
157
- .command("schema")
158
- .description("Dump API schemas and usage examples (for AI context)")
159
- .action(() => {
160
- cmdSchema();
161
- });
162
-
163
- const adminCmd = program.command("admin").description("Manage admins");
164
-
165
- adminCmd
166
- .command("list")
167
- .description("List all admins in workspace")
168
- .action(
169
- withErrorHandler(async (_options, cmd: Command) => {
170
- const globalOpts = getGlobalOptions(cmd);
171
- await cmdAdminList(globalOpts);
172
- }),
173
- );
174
-
175
- adminCmd
176
- .command("get")
177
- .description("Get admin details")
178
- .argument("<id>", "Admin ID")
179
- .action(
180
- withErrorHandler(async (id: string, _options, cmd: Command) => {
181
- const globalOpts = getGlobalOptions(cmd);
182
- await cmdAdminGet({ ...globalOpts, id });
183
- }),
184
- );
185
-
186
- const contactCmd = program.command("contact").description("Manage contacts");
187
-
188
- contactCmd
189
- .command("create")
190
- .description("Create a new contact")
191
- .option("--email <email>", "Contact email")
192
- .option("--name <name>", "Contact name")
193
- .option("--phone <phone>", "Contact phone")
194
- .option("--user-id <id>", "External user ID")
195
- .option("--json <json>", "Full contact data as JSON")
196
- .action(
197
- withErrorHandler(async (options, cmd: Command) => {
198
- const globalOpts = getGlobalOptions(cmd);
199
- await cmdContactCreate({
200
- ...globalOpts,
201
- email: options.email,
202
- name: options.name,
203
- phone: options.phone,
204
- userId: options.userId,
205
- json: options.json,
206
- });
207
- }),
208
- );
209
-
210
- contactCmd
211
- .command("get")
212
- .description("Get contact details")
213
- .argument("<id>", "Contact ID")
214
- .action(
215
- withErrorHandler(async (id: string, _options, cmd: Command) => {
216
- const globalOpts = getGlobalOptions(cmd);
217
- await cmdContactGet({ ...globalOpts, id });
218
- }),
219
- );
220
-
221
- contactCmd
222
- .command("update")
223
- .description("Update a contact")
224
- .argument("<id>", "Contact ID")
225
- .option("--name <name>", "New name")
226
- .option("--email <email>", "New email")
227
- .option("--phone <phone>", "New phone")
228
- .option("--json <json>", "Update data as JSON")
229
- .action(
230
- withErrorHandler(async (id: string, options, cmd: Command) => {
231
- const globalOpts = getGlobalOptions(cmd);
232
- await cmdContactUpdate({
233
- ...globalOpts,
234
- id,
235
- name: options.name,
236
- email: options.email,
237
- phone: options.phone,
238
- json: options.json,
239
- });
240
- }),
241
- );
242
-
243
- contactCmd
244
- .command("delete")
245
- .description("Delete a contact")
246
- .argument("<id>", "Contact ID")
247
- .action(
248
- withErrorHandler(async (id: string, _options, cmd: Command) => {
249
- const globalOpts = getGlobalOptions(cmd);
250
- await cmdContactDelete({ ...globalOpts, id });
251
- }),
252
- );
253
-
254
- contactCmd
255
- .command("search")
256
- .description("Search contacts")
257
- .option("--email <email>", "Search by email")
258
- .option("--json <json>", "Search query as JSON")
259
- .option("-l, --limit <limit>", "Maximum results", "25")
260
- .action(
261
- withErrorHandler(async (options, cmd: Command) => {
262
- const globalOpts = getGlobalOptions(cmd);
263
- await cmdContactSearch({
264
- ...globalOpts,
265
- email: options.email,
266
- json: options.json,
267
- limit: options.limit,
268
- });
269
- }),
270
- );
271
-
272
- contactCmd
273
- .command("list")
274
- .description("List contacts")
275
- .option("-l, --limit <limit>", "Maximum results", "25")
276
- .action(
277
- withErrorHandler(async (options, cmd: Command) => {
278
- const globalOpts = getGlobalOptions(cmd);
279
- await cmdContactList({ ...globalOpts, limit: options.limit });
280
- }),
281
- );
282
-
283
- contactCmd
284
- .command("note")
285
- .description("Add a note to contact")
286
- .argument("<id>", "Contact ID")
287
- .argument("<body>", "Note body")
288
- .action(
289
- withErrorHandler(async (id: string, body: string, _options, cmd: Command) => {
290
- const globalOpts = getGlobalOptions(cmd);
291
- await cmdContactNote({ ...globalOpts, id, body });
292
- }),
293
- );
294
-
295
- contactCmd
296
- .command("notes")
297
- .description("List contact notes")
298
- .argument("<id>", "Contact ID")
299
- .action(
300
- withErrorHandler(async (id: string, _options, cmd: Command) => {
301
- const globalOpts = getGlobalOptions(cmd);
302
- await cmdContactNotes({ ...globalOpts, id });
303
- }),
304
- );
305
-
306
- contactCmd
307
- .command("tag")
308
- .description("Add tag to contact")
309
- .argument("<contact-id>", "Contact ID")
310
- .argument("<tag-id>", "Tag ID")
311
- .action(
312
- withErrorHandler(async (contactId: string, tagId: string, _options, cmd: Command) => {
313
- const globalOpts = getGlobalOptions(cmd);
314
- await cmdContactTag({ ...globalOpts, contactId, tagId });
315
- }),
316
- );
317
-
318
- contactCmd
319
- .command("untag")
320
- .description("Remove tag from contact")
321
- .argument("<contact-id>", "Contact ID")
322
- .argument("<tag-id>", "Tag ID")
323
- .action(
324
- withErrorHandler(async (contactId: string, tagId: string, _options, cmd: Command) => {
325
- const globalOpts = getGlobalOptions(cmd);
326
- await cmdContactUntag({ ...globalOpts, contactId, tagId });
327
- }),
328
- );
329
-
330
- contactCmd
331
- .command("attach-company")
332
- .description("Attach contact to company")
333
- .argument("<contact-id>", "Contact ID")
334
- .argument("<company-id>", "Company ID")
335
- .action(
336
- withErrorHandler(async (contactId: string, companyId: string, _options, cmd: Command) => {
337
- const globalOpts = getGlobalOptions(cmd);
338
- await cmdContactAttachCompany({ ...globalOpts, contactId, companyId });
339
- }),
340
- );
341
-
342
- const conversationCmd = program.command("conversation").description("Manage conversations");
343
-
344
- conversationCmd
345
- .command("list")
346
- .description("List conversations")
347
- .option("-l, --limit <limit>", "Maximum results", "25")
348
- .action(
349
- withErrorHandler(async (options, cmd: Command) => {
350
- const globalOpts = getGlobalOptions(cmd);
351
- await cmdConversationList({ ...globalOpts, limit: options.limit });
352
- }),
353
- );
354
-
355
- conversationCmd
356
- .command("get")
357
- .description("Get conversation details")
358
- .argument("<id>", "Conversation ID")
359
- .action(
360
- withErrorHandler(async (id: string, _options, cmd: Command) => {
361
- const globalOpts = getGlobalOptions(cmd);
362
- await cmdConversationGet({ ...globalOpts, id });
363
- }),
364
- );
365
-
366
- conversationCmd
367
- .command("search")
368
- .description("Search conversations")
369
- .option("--state <state>", "Filter by state (open, closed, snoozed)")
370
- .option("--assignee <id>", "Filter by assignee admin ID")
371
- .option("--json <json>", "Search query as JSON")
372
- .option("-l, --limit <limit>", "Maximum results", "25")
373
- .action(
374
- withErrorHandler(async (options, cmd: Command) => {
375
- const globalOpts = getGlobalOptions(cmd);
376
- await cmdConversationSearch({
377
- ...globalOpts,
378
- state: options.state,
379
- assignee: options.assignee,
380
- json: options.json,
381
- limit: options.limit,
382
- });
383
- }),
384
- );
385
-
386
- conversationCmd
387
- .command("reply")
388
- .description("Reply to a conversation")
389
- .argument("<id>", "Conversation ID")
390
- .requiredOption("--admin <id>", "Admin ID sending the reply")
391
- .requiredOption("--body <body>", "Reply message body")
392
- .option("--json <json>", "Additional reply data as JSON")
393
- .action(
394
- withErrorHandler(async (id: string, options, cmd: Command) => {
395
- const globalOpts = getGlobalOptions(cmd);
396
- await cmdConversationReply({
397
- ...globalOpts,
398
- id,
399
- adminId: options.admin,
400
- body: options.body,
401
- json: options.json,
402
- });
403
- }),
404
- );
405
-
406
- conversationCmd
407
- .command("assign")
408
- .description("Assign conversation to admin/team")
409
- .argument("<id>", "Conversation ID")
410
- .requiredOption("--admin <id>", "Admin ID performing assignment")
411
- .requiredOption("--assignee <id>", "Assignee ID (admin or team)")
412
- .action(
413
- withErrorHandler(async (id: string, options, cmd: Command) => {
414
- const globalOpts = getGlobalOptions(cmd);
415
- await cmdConversationAssign({
416
- ...globalOpts,
417
- id,
418
- adminId: options.admin,
419
- assigneeId: options.assignee,
420
- });
421
- }),
422
- );
423
-
424
- conversationCmd
425
- .command("close")
426
- .description("Close a conversation")
427
- .argument("<id>", "Conversation ID")
428
- .requiredOption("--admin <id>", "Admin ID closing the conversation")
429
- .action(
430
- withErrorHandler(async (id: string, options, cmd: Command) => {
431
- const globalOpts = getGlobalOptions(cmd);
432
- await cmdConversationClose({ ...globalOpts, id, adminId: options.admin });
433
- }),
434
- );
435
-
436
- conversationCmd
437
- .command("open")
438
- .description("Reopen a conversation")
439
- .argument("<id>", "Conversation ID")
440
- .requiredOption("--admin <id>", "Admin ID opening the conversation")
441
- .action(
442
- withErrorHandler(async (id: string, options, cmd: Command) => {
443
- const globalOpts = getGlobalOptions(cmd);
444
- await cmdConversationOpen({ ...globalOpts, id, adminId: options.admin });
445
- }),
446
- );
447
-
448
- conversationCmd
449
- .command("snooze")
450
- .description("Snooze a conversation")
451
- .argument("<id>", "Conversation ID")
452
- .requiredOption("--admin <id>", "Admin ID snoozing the conversation")
453
- .requiredOption("--until <timestamp>", "Unix timestamp to snooze until")
454
- .action(
455
- withErrorHandler(async (id: string, options, cmd: Command) => {
456
- const globalOpts = getGlobalOptions(cmd);
457
- await cmdConversationSnooze({
458
- ...globalOpts,
459
- id,
460
- adminId: options.admin,
461
- until: options.until,
462
- });
463
- }),
464
- );
465
-
466
- const companyCmd = program.command("company").description("Manage companies");
467
-
468
- companyCmd
469
- .command("create")
470
- .description("Create a company")
471
- .requiredOption("--company-id <id>", "Unique company identifier")
472
- .requiredOption("--name <name>", "Company name")
473
- .option("--plan <plan>", "Company plan")
474
- .option("--size <size>", "Company size")
475
- .option("--website <url>", "Company website")
476
- .option("--json <json>", "Additional company data as JSON")
477
- .action(
478
- withErrorHandler(async (options, cmd: Command) => {
479
- const globalOpts = getGlobalOptions(cmd);
480
- await cmdCompanyCreate({
481
- ...globalOpts,
482
- companyId: options.companyId,
483
- name: options.name,
484
- plan: options.plan,
485
- size: options.size,
486
- website: options.website,
487
- json: options.json,
488
- });
489
- }),
490
- );
491
-
492
- companyCmd
493
- .command("get")
494
- .description("Get company details")
495
- .argument("<id>", "Company ID")
496
- .action(
497
- withErrorHandler(async (id: string, _options, cmd: Command) => {
498
- const globalOpts = getGlobalOptions(cmd);
499
- await cmdCompanyGet({ ...globalOpts, id });
500
- }),
501
- );
502
-
503
- companyCmd
504
- .command("list")
505
- .description("List companies")
506
- .option("-l, --limit <limit>", "Maximum results", "25")
507
- .action(
508
- withErrorHandler(async (options, cmd: Command) => {
509
- const globalOpts = getGlobalOptions(cmd);
510
- await cmdCompanyList({ ...globalOpts, limit: options.limit });
511
- }),
512
- );
513
-
514
- companyCmd
515
- .command("update")
516
- .description("Update a company")
517
- .argument("<id>", "Company ID")
518
- .requiredOption("--json <json>", "Update data as JSON")
519
- .action(
520
- withErrorHandler(async (id: string, options, cmd: Command) => {
521
- const globalOpts = getGlobalOptions(cmd);
522
- await cmdCompanyUpdate({ ...globalOpts, id, json: options.json });
523
- }),
524
- );
525
-
526
- const tagCmd = program.command("tag").description("Manage tags");
527
-
528
- tagCmd
529
- .command("list")
530
- .description("List all tags")
531
- .action(
532
- withErrorHandler(async (_options, cmd: Command) => {
533
- const globalOpts = getGlobalOptions(cmd);
534
- await cmdTagList(globalOpts);
535
- }),
536
- );
537
-
538
- tagCmd
539
- .command("create")
540
- .description("Create a tag")
541
- .argument("<name>", "Tag name")
542
- .action(
543
- withErrorHandler(async (name: string, _options, cmd: Command) => {
544
- const globalOpts = getGlobalOptions(cmd);
545
- await cmdTagCreate({ ...globalOpts, name });
546
- }),
547
- );
548
-
549
- tagCmd
550
- .command("get")
551
- .description("Get tag details")
552
- .argument("<id>", "Tag ID")
553
- .action(
554
- withErrorHandler(async (id: string, _options, cmd: Command) => {
555
- const globalOpts = getGlobalOptions(cmd);
556
- await cmdTagGet({ ...globalOpts, id });
557
- }),
558
- );
559
-
560
- tagCmd
561
- .command("delete")
562
- .description("Delete a tag")
563
- .argument("<id>", "Tag ID")
564
- .action(
565
- withErrorHandler(async (id: string, _options, cmd: Command) => {
566
- const globalOpts = getGlobalOptions(cmd);
567
- await cmdTagDelete({ ...globalOpts, id });
568
- }),
569
- );
570
-
571
- const articleCmd = program.command("article").description("Manage help center articles");
572
-
573
- articleCmd
574
- .command("list")
575
- .description("List articles")
576
- .option("-l, --limit <limit>", "Maximum results", "25")
577
- .action(
578
- withErrorHandler(async (options, cmd: Command) => {
579
- const globalOpts = getGlobalOptions(cmd);
580
- await cmdArticleList({ ...globalOpts, limit: options.limit });
581
- }),
582
- );
583
-
584
- articleCmd
585
- .command("get")
586
- .description("Get article details")
587
- .argument("<id>", "Article ID")
588
- .action(
589
- withErrorHandler(async (id: string, _options, cmd: Command) => {
590
- const globalOpts = getGlobalOptions(cmd);
591
- await cmdArticleGet({ ...globalOpts, id });
592
- }),
593
- );
594
-
595
- articleCmd
596
- .command("search")
597
- .description("Search articles")
598
- .argument("<query>", "Search query")
599
- .option("-l, --limit <limit>", "Maximum results", "25")
600
- .action(
601
- withErrorHandler(async (query: string, options, cmd: Command) => {
602
- const globalOpts = getGlobalOptions(cmd);
603
- await cmdArticleSearch({ ...globalOpts, query, limit: options.limit });
604
- }),
605
- );
606
-
607
- articleCmd
608
- .command("create")
609
- .description("Create an article")
610
- .requiredOption("--title <title>", "Article title")
611
- .requiredOption("--author-id <id>", "Author admin ID")
612
- .option("--body <body>", "Article body (HTML)")
613
- .option("--description <desc>", "Article description")
614
- .option("--state <state>", "Article state (draft, published)")
615
- .option("--parent-id <id>", "Parent collection/section ID")
616
- .option("--parent-type <type>", "Parent type (collection, section)")
617
- .action(
618
- withErrorHandler(async (options, cmd: Command) => {
619
- const globalOpts = getGlobalOptions(cmd);
620
- await cmdArticleCreate({
621
- ...globalOpts,
622
- title: options.title,
623
- authorId: options.authorId,
624
- body: options.body,
625
- description: options.description,
626
- state: options.state,
627
- parentId: options.parentId,
628
- parentType: options.parentType,
629
- });
630
- }),
631
- );
632
-
633
- articleCmd
634
- .command("update")
635
- .description("Update an article")
636
- .argument("<id>", "Article ID")
637
- .requiredOption("--json <json>", "Update data as JSON")
638
- .action(
639
- withErrorHandler(async (id: string, options, cmd: Command) => {
640
- const globalOpts = getGlobalOptions(cmd);
641
- await cmdArticleUpdate({ ...globalOpts, id, json: options.json });
642
- }),
643
- );
644
-
645
- articleCmd
646
- .command("delete")
647
- .description("Delete an article")
648
- .argument("<id>", "Article ID")
649
- .action(
650
- withErrorHandler(async (id: string, _options, cmd: Command) => {
651
- const globalOpts = getGlobalOptions(cmd);
652
- await cmdArticleDelete({ ...globalOpts, id });
653
- }),
654
- );
655
-
656
- const eventCmd = program.command("event").description("Track and list events");
657
-
658
- eventCmd
659
- .command("track")
660
- .description("Track a custom event")
661
- .requiredOption("--name <name>", "Event name")
662
- .option("--user-id <id>", "User ID")
663
- .option("--email <email>", "User email")
664
- .option("--metadata <json>", "Event metadata as JSON")
665
- .action(
666
- withErrorHandler(async (options, cmd: Command) => {
667
- const globalOpts = getGlobalOptions(cmd);
668
- await cmdEventTrack({
669
- ...globalOpts,
670
- name: options.name,
671
- userId: options.userId,
672
- email: options.email,
673
- metadata: options.metadata,
674
- });
675
- }),
676
- );
677
-
678
- eventCmd
679
- .command("list")
680
- .description("List events for a user")
681
- .requiredOption("--user-id <id>", "User ID")
682
- .action(
683
- withErrorHandler(async (options, cmd: Command) => {
684
- const globalOpts = getGlobalOptions(cmd);
685
- await cmdEventList({ ...globalOpts, userId: options.userId });
686
- }),
687
- );
81
+ .option("-f, --format <format>", "Output format: toon (default) or json", "toon")
82
+ .option("--config-dir <path>", "Config directory", DEFAULT_CONFIG_DIR);
83
+ registerCommands(program, { getGlobalOptions, withErrorHandler });
688
84
 
689
85
  program.parse();