@opennous/cli 0.4.0 → 0.6.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +92 -50
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opennous/cli",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Nous CLI — install Nous event tracking into your app, plus terminal access to the Context API",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -383,9 +383,20 @@ program
383
383
  if (key) {
384
384
  console.log(`Logged in\nAPI URL: ${url}\nKey: ${key.slice(0, 8)}...`);
385
385
  } else {
386
- console.log("Not logged in. Run: nous auth login --key <your-key>");
386
+ console.log("Not logged in. Run: npx @opennous/cli login");
387
387
  }
388
388
  })
389
+ )
390
+ .addCommand(
391
+ new Command("logout")
392
+ .description("Sign out — remove the saved API key")
393
+ .action(() => {
394
+ const cfg = readConfig();
395
+ if (!cfg.apiKey) { console.log("Not signed in."); return; }
396
+ delete cfg.apiKey;
397
+ writeConfig(cfg);
398
+ console.log("✓ Signed out — removed the saved API key from ~/.nous/config.json");
399
+ })
389
400
  );
390
401
 
391
402
  // ---------------------------------------------------------------------------
@@ -659,63 +670,94 @@ program
659
670
  });
660
671
 
661
672
  // ---------------------------------------------------------------------------
662
- // nous login — browser sign-in (device authorization). Opens the browser, you
663
- // approve, and a freshly minted API key is saved to ~/.nous/config.json. No
664
- // copy-paste. This is what the plugin's /nous-login command runs.
673
+ // Browser sign-in (device authorization). Opens the browser, you approve, and a
674
+ // freshly minted API key is saved to ~/.nous/config.json. No copy-paste. Shared
675
+ // by `nous login`, `nous init`, and the plugin's /nous-login command.
665
676
  // ---------------------------------------------------------------------------
677
+ async function browserLogin(url) {
678
+ const apiUrl = url || process.env.NOUS_API_URL || readConfig().apiUrl || "https://api.opennous.cloud";
679
+
680
+ let start;
681
+ try {
682
+ const r = await fetch(`${apiUrl}/api/cli/auth/start`, {
683
+ method: "POST", headers: { "Content-Type": "application/json" }, body: "{}",
684
+ });
685
+ if (!r.ok) throw new Error(`server returned ${r.status}`);
686
+ start = await r.json();
687
+ } catch (e) {
688
+ console.error(`Couldn't start sign-in: ${e.message}`);
689
+ process.exit(1);
690
+ }
691
+
692
+ console.log(`\nOpening your browser to sign in. If it doesn't open, visit:\n ${start.verification_uri_complete}\n`);
693
+ openBrowser(start.verification_uri_complete);
694
+
695
+ const interval = (start.interval || 4) * 1000;
696
+ const deadline = Date.now() + (start.expires_in || 600) * 1000;
697
+ process.stdout.write("Waiting for you to approve in the browser");
698
+
699
+ while (Date.now() < deadline) {
700
+ await sleep(interval);
701
+ process.stdout.write(".");
702
+ let j = {};
703
+ try {
704
+ const r = await fetch(`${apiUrl}/api/cli/auth/poll`, {
705
+ method: "POST", headers: { "Content-Type": "application/json" },
706
+ body: JSON.stringify({ device_code: start.device_code }),
707
+ });
708
+ j = await r.json().catch(() => ({}));
709
+ } catch { continue; }
710
+
711
+ if (j.status === "approved" && j.api_key) {
712
+ const cfg = readConfig();
713
+ cfg.apiKey = j.api_key;
714
+ cfg.apiUrl = apiUrl;
715
+ writeConfig(cfg);
716
+ console.log(`\n\n✓ Signed in. Key saved to ~/.nous/config.json`);
717
+ return true;
718
+ }
719
+ if (j.status === "denied") { console.log("\nAuthorization was denied."); process.exit(1); }
720
+ if (j.status === "expired") { console.log("\nThis sign-in expired. Run it again."); process.exit(1); }
721
+ }
722
+ console.log("\nTimed out waiting for approval. Run it again.");
723
+ process.exit(1);
724
+ }
725
+
666
726
  program
667
727
  .command("login")
668
728
  .description("Sign in with your browser and save an API key (no copy-paste)")
669
729
  .option("--url <url>", "API base URL (default: https://api.opennous.cloud)")
670
730
  .action(async ({ url }) => {
671
- const apiUrl = url || process.env.NOUS_API_URL || readConfig().apiUrl || "https://api.opennous.cloud";
731
+ await browserLogin(url);
732
+ console.log("Your Nous tools are ready — try `get_workspace_status` in your agent.");
733
+ });
672
734
 
673
- let start;
674
- try {
675
- const r = await fetch(`${apiUrl}/api/cli/auth/start`, {
676
- method: "POST", headers: { "Content-Type": "application/json" }, body: "{}",
677
- });
678
- if (!r.ok) throw new Error(`server returned ${r.status}`);
679
- start = await r.json();
680
- } catch (e) {
681
- console.error(`Couldn't start sign-in: ${e.message}`);
682
- process.exit(1);
683
- }
735
+ // nous init — the one-line "get started": sign in, then connect to your agent.
736
+ // This is the command the marketing site points to (`npx @opennous/cli init`).
737
+ program
738
+ .command("init")
739
+ .description("Get started — sign in, then connect Nous to your agent")
740
+ .option("--url <url>", "API base URL (default: https://api.opennous.cloud)")
741
+ .action(async ({ url }) => {
742
+ await browserLogin(url);
743
+ console.log("\nNow add Nous to Claude Code:\n");
744
+ console.log(" /plugin marketplace add NousC/nous");
745
+ console.log(" /plugin install nous@nous-plugins\n");
746
+ console.log('Then tell your agent: "set me up" — it onboards your workspace and builds your playbook.');
747
+ console.log("\nDocs: https://docs.opennous.cloud/mcp/introduction");
748
+ });
684
749
 
685
- console.log(`\nOpening your browser to authorize. If it doesn't open, visit:\n ${start.verification_uri_complete}\n`);
686
- openBrowser(start.verification_uri_complete);
687
-
688
- const interval = (start.interval || 4) * 1000;
689
- const deadline = Date.now() + (start.expires_in || 600) * 1000;
690
- process.stdout.write("Waiting for you to approve in the browser");
691
-
692
- while (Date.now() < deadline) {
693
- await sleep(interval);
694
- process.stdout.write(".");
695
- let j = {};
696
- try {
697
- const r = await fetch(`${apiUrl}/api/cli/auth/poll`, {
698
- method: "POST", headers: { "Content-Type": "application/json" },
699
- body: JSON.stringify({ device_code: start.device_code }),
700
- });
701
- j = await r.json().catch(() => ({}));
702
- } catch { continue; }
703
-
704
- if (j.status === "approved" && j.api_key) {
705
- const cfg = readConfig();
706
- cfg.apiKey = j.api_key;
707
- cfg.apiUrl = apiUrl;
708
- writeConfig(cfg);
709
- console.log(`\n\n✓ Signed in. Key saved to ~/.nous/config.json`);
710
- console.log("Your Nous tools are ready — try `get_workspace_status` in your agent.");
711
- return;
712
- }
713
- if (j.status === "denied") { console.log("\nAuthorization was denied."); process.exit(1); }
714
- if (j.status === "expired") { console.log("\nThis sign-in expired. Run `nous login` again."); process.exit(1); }
715
- }
716
- console.log("\nTimed out waiting for approval. Run `nous login` again.");
717
- process.exit(1);
750
+ // nous logout — top-level alias of `auth logout`. Removes the saved API key.
751
+ program
752
+ .command("logout")
753
+ .description("Sign out — remove the saved API key")
754
+ .action(() => {
755
+ const cfg = readConfig();
756
+ if (!cfg.apiKey) { console.log("Not signed in."); return; }
757
+ delete cfg.apiKey;
758
+ writeConfig(cfg);
759
+ console.log("✓ Signed out — removed the saved API key from ~/.nous/config.json");
718
760
  });
719
761
 
720
762
  // ---------------------------------------------------------------------------
721
- program.name("nous").version("0.4.0").parse();
763
+ program.name("nous").version("0.6.0").parse();