shepherd-onboard 0.1.6 → 0.1.8

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/README.md CHANGED
@@ -25,10 +25,9 @@ The command:
25
25
  - asks for name, organization, and an optional local Messages handle
26
26
  - creates or reuses the Shepherd customer account from the WorkOS-authenticated email
27
27
  - creates or reuses the organization, including case-insensitive and close-name matches
28
- - opens Google authorization for Gmail, Docs, and Calendar consent
28
+ - opens Google Workspace authorization for Gmail, Drive, Docs, and Calendar consent
29
29
  - opens Slack authorization
30
- - opens the Granola desktop app with `open -b com.granola.app`
31
- - directs the coding agent/user to Granola Settings -> Connectors -> API keys
30
+ - opens the Granola desktop app to Settings -> Connectors -> API keys
32
31
  - collects the Granola API key after opening the Granola screen when Granola is enabled
33
32
  - sets up local macOS Messages raw sync with a background LaunchAgent
34
33
  - starts raw polling/backfill for connected sources
@@ -45,10 +44,18 @@ The command does not expose Railway, database, Redis, or internal service detail
45
44
  --granola-api-key <key> Granola API key
46
45
  --messages-handle <value> Messages phone number or Apple ID email
47
46
  --messages-backfill-days Local Messages backfill window, default 30
48
- --no-google Skip Google/Gmail/Docs/Calendar
47
+ --no-google Skip Google Workspace (Gmail/Drive/Docs/Calendar)
49
48
  --no-slack Skip Slack
50
49
  --no-granola Skip Granola
51
50
  --no-open-granola Do not open the Granola API key screen
52
51
  --no-messages Skip local Messages
53
52
  --no-open Print auth URLs instead of opening the browser
54
53
  ```
54
+
55
+ ## Granola API Keys
56
+
57
+ If Granola does not land on the API keys page, run:
58
+
59
+ ```sh
60
+ npx -y shepherd-onboard@latest granola-api-keys
61
+ ```
@@ -32,6 +32,8 @@ async function dispatch() {
32
32
  await runOnboarding();
33
33
  } else if (command === "agent") {
34
34
  await runAgentOnboarding();
35
+ } else if (command === "granola-api-keys") {
36
+ await openGranolaApiKeys({ noOpen: Boolean(args["no-open"]) });
35
37
  } else if (command === "messages-agent") {
36
38
  await runMessagesAgent();
37
39
  } else {
@@ -80,9 +82,9 @@ async function runOnboarding() {
80
82
  }
81
83
 
82
84
  if (session.authUrls?.google) {
83
- console.log("\nGoogle, Gmail, Docs, and Calendar authorization");
85
+ console.log("\nGoogle Workspace authorization");
84
86
  await openOrPrint(session.authUrls.google, { noOpen });
85
- await waitForEnter("Complete Google authorization in the browser, then press Enter.");
87
+ await waitForEnter("Complete Google Workspace authorization in the browser, then press Enter.");
86
88
  }
87
89
 
88
90
  if (session.authUrls?.slack) {
@@ -489,6 +491,7 @@ Usage:
489
491
  npx -y ${PACKAGE_NAME}@latest agent --name <name> --org <organization>
490
492
  npx -y ${PACKAGE_NAME}@latest agent --continue --granola-api-key <key> --messages-handle <value>
491
493
  npx -y ${PACKAGE_NAME}@latest agent --status
494
+ npx -y ${PACKAGE_NAME}@latest granola-api-keys
492
495
 
493
496
  Agent mode is non-interactive. It prints the user prompt and exact commands a coding agent should run.
494
497
  Always run --login first. WorkOS login/signup creates or relinks the Shepherd account before source setup.
@@ -516,6 +519,7 @@ Options:
516
519
  Usage:
517
520
  npx -y ${PACKAGE_NAME}@latest
518
521
  npx -y ${PACKAGE_NAME}@latest agent
522
+ npx -y ${PACKAGE_NAME}@latest granola-api-keys
519
523
 
520
524
  Options:
521
525
  --email <email> Advanced: must match the WorkOS-authenticated email.
@@ -525,7 +529,7 @@ Options:
525
529
  --messages-handle <value> Messages phone number or Apple ID email.
526
530
  --messages-backfill-days <days>
527
531
  Local Messages backfill window. Defaults to 30.
528
- --no-google Skip Google/Gmail/Docs/Calendar.
532
+ --no-google Skip Google Workspace (Gmail/Drive/Docs/Calendar).
529
533
  --no-slack Skip Slack.
530
534
  --no-granola Skip Granola.
531
535
  --no-open-granola Do not open the Granola API key screen.
@@ -561,7 +565,7 @@ function printAgentContract() {
561
565
  {
562
566
  label: "Sources",
563
567
  prompt: "Which sources should Shepherd connect for raw sync?",
564
- options: ["Google/Gmail/Docs/Calendar", "Slack", "Granola", "Messages"],
568
+ options: ["Google Workspace (Gmail/Drive/Docs/Calendar)", "Slack", "Granola", "Messages"],
565
569
  multiSelect: true,
566
570
  },
567
571
  {
@@ -576,7 +580,7 @@ function printAgentContract() {
576
580
  "Messages phone number or Apple ID email, if they want local Messages connected",
577
581
  ],
578
582
  afterStartCommand: [
579
- "Complete the opened Google authorization for Gmail, Docs, and Calendar.",
583
+ "Complete the opened Google Workspace authorization for Gmail, Drive, Docs, and Calendar.",
580
584
  "Complete the opened Slack authorization.",
581
585
  "Create/copy the Granola API key from the opened Granola Mac app API key screen, if they want Granola connected.",
582
586
  ],
@@ -597,7 +601,7 @@ function printAgentContract() {
597
601
  ],
598
602
  statusCommand: `${command} agent --status`,
599
603
  expectedResult: "Cloud sources start raw polling/backfill in the customer-facing Shepherd environment. Local Messages starts via a macOS LaunchAgent when run on macOS. Downstream wiki, memory, and summary compilers remain outside this onboarding flow.",
600
- granolaApiKeyCommand: "open -b com.granola.app",
604
+ granolaApiKeyCommand: `${command} granola-api-keys`,
601
605
  granolaApiKeyPath: "Granola desktop app -> Settings -> Connectors -> API keys",
602
606
  };
603
607
 
@@ -616,7 +620,7 @@ Ask with short interactive prompts, not as one pasted checklist.
616
620
 
617
621
  Start with selection questions to determine intent:
618
622
  1. Organization: Join existing org, or Create new org.
619
- 2. Sources: Google/Gmail/Docs/Calendar, Slack, Granola, Messages. Allow multi-select if your interface supports it.
623
+ 2. Sources: Google Workspace (Gmail/Drive/Docs/Calendar), Slack, Granola, Messages. Allow multi-select if your interface supports it.
620
624
  3. Messages, if selected: Skip Messages, or Provide handle.
621
625
 
622
626
  Before source setup, always run:
@@ -642,16 +646,18 @@ Add skip flags for sources the user did not select:
642
646
  - --no-granola
643
647
  - --no-messages
644
648
 
645
- That command creates/reuses the customer user and org, opens Google/Slack browser auth, and saves local state.
646
- If Granola is selected, it also opens the Granola desktop app. Use local computer control to navigate Granola to:
649
+ That command creates/reuses the customer user and org, opens Google Workspace/Slack browser auth, and saves local state.
650
+ If your browser automation can complete those auth screens, do it. If it cannot click through OAuth screens, leave the opened browser tabs for the user and ask them to complete Google Workspace and Slack auth.
651
+
652
+ If Granola is selected, it also opens the Granola desktop app. If your local app automation can navigate it, go to:
647
653
  Settings -> Connectors -> API keys
648
654
  Then have the user create/copy the API key.
649
655
 
650
656
  If Granola did not come forward, run:
651
657
  ${payload.granolaApiKeyCommand}
652
- Then navigate the visible Granola app to Settings -> Connectors -> API keys.
658
+ That command opens Granola and tries to navigate to Settings -> Connectors -> API keys. If your tool cannot click inside Granola, leave Granola open and ask the user to go to that screen.
653
659
 
654
- After Google/Gmail/Docs/Calendar and Slack browser auth is complete, and after the user has copied a Granola API key from the opened Granola screen if they want Granola, run:
660
+ After Google Workspace and Slack browser auth is complete, and after the user has copied a Granola API key from the opened Granola screen if they want Granola, run:
655
661
  ${payload.continueCommand} --messages-handle "<phone_or_apple_id>" --granola-api-key "<granola_key>"
656
662
 
657
663
  Omit either optional flag if that source is not being connected.
@@ -728,7 +734,7 @@ function authenticatedName(authenticated) {
728
734
 
729
735
  function agentNeedsUserAction(sources, opened) {
730
736
  const actions = [];
731
- if (sources.google && opened.includes("google")) actions.push("Complete Google browser authorization for Gmail, Docs, and Calendar consent.");
737
+ if (sources.google && opened.includes("google")) actions.push("Complete Google Workspace browser authorization for Gmail, Drive, Docs, and Calendar consent.");
732
738
  if (sources.slack && opened.includes("slack")) actions.push("Complete Slack browser authorization.");
733
739
  if (sources.granola) actions.push("Create/copy a Granola API key from the Granola Mac app.");
734
740
  if (sources.messages) actions.push("Pass the Messages phone number or Apple ID email collected before starting onboarding.");
@@ -843,7 +849,7 @@ async function openOrPrint(url, opts) {
843
849
  }
844
850
 
845
851
  async function openGranolaApiKeys(opts = {}) {
846
- const deepLink = "granola://settings/connectors/api-keys";
852
+ const deepLink = "granola://settings/integrations";
847
853
  if (opts.noOpen) {
848
854
  console.log("Granola API keys: open the Granola desktop app -> Settings -> Connectors -> API keys");
849
855
  return { opened: false, target: "Granola Settings -> Connectors -> API keys" };
@@ -868,15 +874,44 @@ async function openGranolaApiKeys(opts = {}) {
868
874
  if (bundleResult.error && activateByBundleResult.error && activateByNameResult.error) {
869
875
  await execFileQuiet("open", ["-a", "Granola"], { ignoreError: true });
870
876
  }
877
+ await navigateGranolaApiKeysWithAppleScript();
871
878
 
872
879
  return {
873
880
  opened: true,
874
881
  target: "Granola Settings -> Connectors -> API keys",
875
882
  attemptedDeepLink: deepLink,
876
- fallback: "Use local computer control to navigate Granola to Settings -> Connectors -> API keys.",
883
+ fallback: "If local app automation cannot click inside Granola, ask the user to open Settings -> Connectors -> API keys.",
877
884
  };
878
885
  }
879
886
 
887
+ async function navigateGranolaApiKeysWithAppleScript() {
888
+ const script = `
889
+ tell application id "com.granola.app" to activate
890
+ delay 0.7
891
+ tell application "System Events"
892
+ if not (exists process "Granola") then return
893
+ tell process "Granola"
894
+ set frontmost to true
895
+ try
896
+ set {x, y} to position of window 1
897
+ set {w, h} to size of window 1
898
+ click at {x + w - 55, y + 810}
899
+ return
900
+ end try
901
+ try
902
+ keystroke "," using command down
903
+ delay 0.5
904
+ set {x, y} to position of window 1
905
+ set {w, h} to size of window 1
906
+ click at {x + w - 55, y + 810}
907
+ return
908
+ end try
909
+ end tell
910
+ end tell
911
+ `;
912
+ await execFileQuiet("osascript", ["-e", script], { ignoreError: true });
913
+ }
914
+
880
915
  async function postJson(url, body, opts = {}) {
881
916
  const res = await fetch(url, {
882
917
  method: "POST",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shepherd-onboard",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Customer-facing Shepherd raw sync onboarding CLI",
5
5
  "type": "module",
6
6
  "bin": {