@withone/cli 1.16.0 → 1.17.2

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/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  loadFlow,
12
12
  resolveFlowPath,
13
13
  saveFlow
14
- } from "./chunk-SX2Y4HDW.js";
14
+ } from "./chunk-QW4MBV4F.js";
15
15
 
16
16
  // src/index.ts
17
17
  import { createRequire as createRequire2 } from "module";
@@ -19,9 +19,10 @@ import { Command } from "commander";
19
19
 
20
20
  // src/commands/init.ts
21
21
  import * as p3 from "@clack/prompts";
22
- import pc3 from "picocolors";
22
+ import pc2 from "picocolors";
23
+ import fs3 from "fs";
23
24
  import path3 from "path";
24
- import { spawn } from "child_process";
25
+ import os3 from "os";
25
26
  import { fileURLToPath } from "url";
26
27
 
27
28
  // src/lib/config.ts
@@ -222,12 +223,6 @@ var AGENTS = [
222
223
  projectConfigPath: ".kiro/settings/mcp.json"
223
224
  }
224
225
  ];
225
- function getAllAgents() {
226
- return AGENTS;
227
- }
228
- function supportsProjectScope(agent) {
229
- return agent.projectConfigPath !== void 0;
230
- }
231
226
  function getAgentConfigPath(agent, scope = "global") {
232
227
  if (scope === "project" && agent.projectConfigPath) {
233
228
  return path2.join(process.cwd(), agent.projectConfigPath);
@@ -530,117 +525,59 @@ function formatList(list) {
530
525
 
531
526
  // src/commands/init.ts
532
527
  import open2 from "open";
533
-
534
- // src/lib/table.ts
535
- import pc2 from "picocolors";
536
- function printTable(columns, rows) {
537
- if (rows.length === 0) return;
538
- const gap = " ";
539
- const indent = " ";
540
- const widths = columns.map((col) => {
541
- const headerLen = col.label.length;
542
- const maxValueLen = Math.max(...rows.map((row) => stripAnsi(row[col.key] || "").length));
543
- return Math.max(headerLen, maxValueLen);
544
- });
545
- const header = columns.map((col, i) => {
546
- const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
547
- return pc2.dim(padded);
548
- }).join(gap);
549
- console.log(`${indent}${header}`);
550
- const separator = columns.map((_, i) => pc2.dim("\u2500".repeat(widths[i]))).join(gap);
551
- console.log(`${indent}${separator}`);
552
- for (const row of rows) {
553
- const line = columns.map((col, i) => {
554
- const raw = row[col.key] || "";
555
- const rawLen = stripAnsi(raw).length;
556
- const padding = widths[i] - rawLen;
557
- const colored = col.color ? col.color(raw) : raw;
558
- if (col.align === "right") {
559
- return " ".repeat(Math.max(0, padding)) + colored;
560
- }
561
- return colored + " ".repeat(Math.max(0, padding));
562
- }).join(gap);
563
- console.log(`${indent}${line}`);
564
- }
565
- }
566
- function stripAnsi(str) {
567
- return str.replace(/\x1b\[[0-9;]*m/g, "");
568
- }
569
-
570
- // src/commands/init.ts
571
528
  async function initCommand(options) {
572
529
  if (isAgentMode()) {
573
530
  error("This command requires interactive input. Run without --agent.");
574
531
  }
575
532
  const existingConfig = readConfig();
533
+ printBanner();
576
534
  if (existingConfig) {
577
- p3.intro(pc3.bgCyan(pc3.black(" One ")));
578
535
  await handleExistingConfig(existingConfig.apiKey, options);
579
536
  return;
580
537
  }
581
- printBanner();
582
538
  await freshSetup(options);
583
539
  }
584
540
  async function handleExistingConfig(apiKey, options) {
585
541
  const statuses = getAgentStatuses();
586
542
  const masked = maskApiKey(apiKey);
543
+ const skillInstalled = isSkillInstalled();
587
544
  console.log();
588
- console.log(` ${pc3.bold("Current Setup")}`);
589
- console.log(` ${pc3.dim("\u2500".repeat(42))}`);
590
- console.log(` ${pc3.dim("API Key:")} ${masked}`);
591
- console.log(` ${pc3.dim("Config:")} ${getConfigPath()}`);
592
- console.log();
593
- printTable(
594
- [
595
- { key: "agent", label: "Agent" },
596
- { key: "global", label: "Global" },
597
- { key: "project", label: "Project" }
598
- ],
599
- statuses.map((s) => ({
600
- agent: s.agent.name,
601
- global: !s.detected ? pc3.dim("-") : s.globalMcp ? pc3.green("\u25CF yes") : pc3.yellow("\u25CB no"),
602
- project: s.projectMcp === null ? pc3.dim("-") : s.projectMcp ? pc3.green("\u25CF yes") : pc3.yellow("\u25CB no")
603
- }))
604
- );
605
- const notDetected = statuses.filter((s) => !s.detected);
606
- if (notDetected.length > 0) {
607
- console.log(` ${pc3.dim("- = not detected on this machine")}`);
608
- }
545
+ console.log(` ${pc2.bold("Current Setup")}`);
546
+ console.log(` ${pc2.dim("\u2500".repeat(42))}`);
547
+ console.log(` ${pc2.dim("API Key:")} ${masked}`);
548
+ console.log(` ${pc2.dim("Skill:")} ${skillInstalled ? pc2.green("installed") : pc2.yellow("not installed")}`);
549
+ console.log(` ${pc2.dim("Config:")} ${getConfigPath()}`);
609
550
  const ac = getAccessControl();
610
551
  if (Object.keys(ac).length > 0) {
611
- console.log(` ${pc3.bold("Access Control")}`);
612
- console.log(` ${pc3.dim("\u2500".repeat(42))}`);
613
- if (ac.permissions) console.log(` ${pc3.dim("Permissions:")} ${ac.permissions}`);
614
- if (ac.connectionKeys) console.log(` ${pc3.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
615
- if (ac.actionIds) console.log(` ${pc3.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
616
- if (ac.knowledgeAgent) console.log(` ${pc3.dim("Knowledge only:")} yes`);
617
552
  console.log();
553
+ console.log(` ${pc2.bold("Access Control")}`);
554
+ console.log(` ${pc2.dim("\u2500".repeat(42))}`);
555
+ if (ac.permissions) console.log(` ${pc2.dim("Permissions:")} ${ac.permissions}`);
556
+ if (ac.connectionKeys) console.log(` ${pc2.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
557
+ if (ac.actionIds) console.log(` ${pc2.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
558
+ if (ac.knowledgeAgent) console.log(` ${pc2.dim("Knowledge only:")} yes`);
618
559
  }
560
+ console.log();
619
561
  const actionOptions = [];
620
562
  actionOptions.push({
621
- value: "update-key",
622
- label: "Update API key"
563
+ value: "install-skills",
564
+ label: skillInstalled ? "Update skill" : "Install skill",
565
+ hint: skillInstalled ? "reinstall latest version" : "recommended"
623
566
  });
624
567
  actionOptions.push({
625
- value: "install-skills",
626
- label: "Install/update skills"
568
+ value: "show-prompt",
569
+ label: "Show agent onboarding prompt",
570
+ hint: "copy-paste to your AI agent"
571
+ });
572
+ actionOptions.push({
573
+ value: "add-connection",
574
+ label: "Connect a platform",
575
+ hint: "add Gmail, Slack, Shopify, etc."
576
+ });
577
+ actionOptions.push({
578
+ value: "update-key",
579
+ label: "Update API key"
627
580
  });
628
- const agentsMissingGlobal = statuses.filter((s) => s.detected && !s.globalMcp);
629
- if (agentsMissingGlobal.length > 0) {
630
- actionOptions.push({
631
- value: "install-more",
632
- label: "Install MCP to more agents",
633
- hint: `${agentsMissingGlobal.map((s) => s.agent.name).join(", ")} (not recommended)`
634
- });
635
- }
636
- const agentsMissingProject = statuses.filter((s) => s.projectMcp === false);
637
- if (agentsMissingProject.length > 0) {
638
- actionOptions.push({
639
- value: "install-project",
640
- label: "Install MCP for this project",
641
- hint: `${agentsMissingProject.map((s) => s.agent.name).join(", ")} (not recommended)`
642
- });
643
- }
644
581
  actionOptions.push({
645
582
  value: "access-control",
646
583
  label: "Configure access control",
@@ -659,26 +596,26 @@ async function handleExistingConfig(apiKey, options) {
659
596
  return;
660
597
  }
661
598
  switch (action) {
662
- case "update-key":
663
- await handleUpdateKey(statuses);
664
- break;
665
599
  case "install-skills": {
666
- const success = await runSkillsInstall();
600
+ const success = await promptSkillInstall();
667
601
  if (success) {
668
- p3.outro("Skills installed successfully.");
602
+ printOnboardingPrompt();
603
+ p3.outro("Skill installed. Paste the prompt above to your AI agent.");
669
604
  } else {
670
- const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
671
- const skillsDir = path3.resolve(__dirname2, "..", "skills");
672
- p3.log.warn(`Skills installation failed. You can try manually: ${pc3.cyan(`npx skills add ${skillsDir}`)}`);
673
605
  p3.outro("Done.");
674
606
  }
675
607
  break;
676
608
  }
677
- case "install-more":
678
- await handleInstallMore(apiKey, agentsMissingGlobal);
609
+ case "show-prompt":
610
+ printOnboardingPrompt();
611
+ p3.outro("Paste the prompt above to your AI agent.");
679
612
  break;
680
- case "install-project":
681
- await handleInstallProject(apiKey, agentsMissingProject);
613
+ case "add-connection":
614
+ await promptConnectIntegrations(apiKey);
615
+ p3.outro("Done.");
616
+ break;
617
+ case "update-key":
618
+ await handleUpdateKey(statuses);
682
619
  break;
683
620
  case "access-control":
684
621
  await configCommand();
@@ -690,7 +627,7 @@ async function handleExistingConfig(apiKey, options) {
690
627
  }
691
628
  async function handleUpdateKey(statuses) {
692
629
  p3.note(`Get your API key at:
693
- ${pc3.cyan(getApiKeyUrl())}`, "API Key");
630
+ ${pc2.cyan(getApiKeyUrl())}`, "API Key");
694
631
  const openBrowser = await p3.confirm({
695
632
  message: "Open browser to get API key?",
696
633
  initialValue: true
@@ -751,208 +688,165 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
751
688
  }
752
689
  p3.outro("API key updated.");
753
690
  }
754
- async function handleInstallMore(apiKey, missing) {
755
- const ac = getAccessControl();
756
- if (missing.length === 1) {
757
- const agent = missing[0].agent;
758
- const confirm3 = await p3.confirm({
759
- message: `Install One MCP to ${agent.name}?`,
760
- initialValue: true
761
- });
762
- if (p3.isCancel(confirm3) || !confirm3) {
763
- p3.outro("No changes made.");
764
- return;
691
+ var SKILL_AGENTS = [
692
+ { id: "claude-code", name: "Claude Code", skillDir: ".claude/skills", primary: true },
693
+ { id: "claude-desktop", name: "Claude Desktop", skillDir: ".claude/skills", primary: true },
694
+ { id: "codex", name: "Codex", skillDir: ".codex/skills", primary: true },
695
+ { id: "cursor", name: "Cursor", skillDir: ".cursor/skills" },
696
+ { id: "windsurf", name: "Windsurf", skillDir: ".codeium/windsurf/skills" },
697
+ { id: "kiro", name: "Kiro", skillDir: ".kiro/skills" },
698
+ { id: "goose", name: "Goose", skillDir: ".config/goose/skills" },
699
+ { id: "amp", name: "Amp", skillDir: ".amp/skills" },
700
+ { id: "opencode", name: "OpenCode", skillDir: ".opencode/skills" },
701
+ { id: "roo", name: "Roo", skillDir: ".roo/skills" }
702
+ ];
703
+ var CANONICAL_SKILL_DIR = ".agents/skills";
704
+ function getSkillSourceDir() {
705
+ const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
706
+ return path3.resolve(__dirname2, "..", "skills", "one");
707
+ }
708
+ function getCanonicalSkillPath() {
709
+ return path3.join(os3.homedir(), CANONICAL_SKILL_DIR, "one");
710
+ }
711
+ function getAgentSkillPath(agent) {
712
+ return path3.join(os3.homedir(), agent.skillDir, "one");
713
+ }
714
+ function isSkillInstalled() {
715
+ return fs3.existsSync(path3.join(getCanonicalSkillPath(), "SKILL.md"));
716
+ }
717
+ function isSkillInstalledForAgent(agent) {
718
+ return fs3.existsSync(path3.join(getAgentSkillPath(agent), "SKILL.md"));
719
+ }
720
+ function copyDirSync(src, dest) {
721
+ fs3.mkdirSync(dest, { recursive: true });
722
+ for (const entry of fs3.readdirSync(src, { withFileTypes: true })) {
723
+ const srcPath = path3.join(src, entry.name);
724
+ const destPath = path3.join(dest, entry.name);
725
+ if (entry.isDirectory()) {
726
+ copyDirSync(srcPath, destPath);
727
+ } else {
728
+ fs3.copyFileSync(srcPath, destPath);
765
729
  }
766
- installMcpConfig(agent, apiKey, "global", ac);
767
- updateConfigAgents(agent.id);
768
- p3.log.success(`${agent.name}: MCP installed`);
769
- p3.outro("Done.");
770
- return;
771
730
  }
772
- const selected = await p3.multiselect({
773
- message: "Select agents to install MCP:",
774
- options: missing.map((s) => ({
775
- value: s.agent.id,
776
- label: s.agent.name
777
- }))
778
- });
779
- if (p3.isCancel(selected)) {
780
- p3.outro("No changes made.");
781
- return;
782
- }
783
- const agents = missing.filter((s) => selected.includes(s.agent.id));
784
- for (const s of agents) {
785
- installMcpConfig(s.agent, apiKey, "global", ac);
786
- updateConfigAgents(s.agent.id);
787
- p3.log.success(`${s.agent.name}: MCP installed`);
788
- }
789
- p3.outro("Done.");
790
731
  }
791
- async function handleInstallProject(apiKey, missing) {
792
- const ac = getAccessControl();
793
- if (missing.length === 1) {
794
- const agent = missing[0].agent;
795
- const confirm3 = await p3.confirm({
796
- message: `Install project-level MCP for ${agent.name}?`,
797
- initialValue: true
798
- });
799
- if (p3.isCancel(confirm3) || !confirm3) {
800
- p3.outro("No changes made.");
801
- return;
802
- }
803
- installMcpConfig(agent, apiKey, "project", ac);
804
- const configPath = getAgentConfigPath(agent, "project");
805
- p3.log.success(`${agent.name}: ${configPath} created`);
806
- p3.note(
807
- pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
808
- "Tip"
809
- );
810
- p3.outro("Done.");
811
- return;
732
+ function installSkillForAgents(agentIds) {
733
+ const source = getSkillSourceDir();
734
+ const canonical = getCanonicalSkillPath();
735
+ const installed = [];
736
+ const failed = [];
737
+ if (!fs3.existsSync(path3.join(source, "SKILL.md"))) {
738
+ return { installed: [], failed: ["skill source not found"] };
812
739
  }
813
- const selected = await p3.multiselect({
814
- message: "Select agents for project-level MCP:",
815
- options: missing.map((s) => ({
816
- value: s.agent.id,
817
- label: s.agent.name
818
- }))
819
- });
820
- if (p3.isCancel(selected)) {
821
- p3.outro("No changes made.");
822
- return;
740
+ try {
741
+ if (fs3.existsSync(canonical)) {
742
+ fs3.rmSync(canonical, { recursive: true });
743
+ }
744
+ copyDirSync(source, canonical);
745
+ } catch {
746
+ return { installed: [], failed: ["canonical copy"] };
823
747
  }
824
- const agents = missing.filter((s) => selected.includes(s.agent.id));
825
- for (const s of agents) {
826
- installMcpConfig(s.agent, apiKey, "project", ac);
827
- const configPath = getAgentConfigPath(s.agent, "project");
828
- p3.log.success(`${s.agent.name}: ${configPath} created`);
748
+ const seen = /* @__PURE__ */ new Map();
749
+ for (const id of agentIds) {
750
+ const agent = SKILL_AGENTS.find((a) => a.id === id);
751
+ if (!agent) continue;
752
+ const agentPath = getAgentSkillPath(agent);
753
+ if (seen.has(agentPath)) {
754
+ (seen.get(agentPath) ? installed : failed).push(agent.name);
755
+ continue;
756
+ }
757
+ try {
758
+ const agentSkillsDir = path3.dirname(agentPath);
759
+ fs3.mkdirSync(agentSkillsDir, { recursive: true });
760
+ try {
761
+ fs3.lstatSync(agentPath);
762
+ fs3.rmSync(agentPath, { recursive: true });
763
+ } catch {
764
+ }
765
+ const relative = path3.relative(agentSkillsDir, canonical);
766
+ fs3.symlinkSync(relative, agentPath);
767
+ installed.push(agent.name);
768
+ seen.set(agentPath, true);
769
+ } catch {
770
+ failed.push(agent.name);
771
+ seen.set(agentPath, false);
772
+ }
829
773
  }
830
- p3.note(
831
- pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
832
- "Tip"
833
- );
834
- p3.outro("Done.");
774
+ return { installed, failed };
835
775
  }
836
- async function runSkillsInstall() {
837
- const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
838
- const skillsDir = path3.resolve(__dirname2, "..", "skills");
839
- return new Promise((resolve) => {
840
- const handler = () => {
841
- };
842
- process.on("SIGINT", handler);
843
- const child = spawn("npx", ["skills", "add", skillsDir], {
844
- stdio: "inherit",
845
- shell: true
846
- });
847
- child.on("close", (code) => {
848
- process.removeListener("SIGINT", handler);
849
- resolve(code === 0);
850
- });
851
- child.on("error", () => {
852
- process.removeListener("SIGINT", handler);
853
- resolve(false);
854
- });
776
+ async function promptSkillInstall() {
777
+ const primaryAgents = SKILL_AGENTS.filter((a) => a.primary);
778
+ const otherAgents = SKILL_AGENTS.filter((a) => !a.primary);
779
+ const options = [
780
+ ...primaryAgents.map((a) => ({
781
+ value: a.id,
782
+ label: a.name,
783
+ hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
784
+ })),
785
+ {
786
+ value: "_other",
787
+ label: "Other agents",
788
+ hint: otherAgents.map((a) => a.name).join(", ")
789
+ }
790
+ ];
791
+ const choice = await p3.multiselect({
792
+ message: "Install the One skill to:",
793
+ options,
794
+ initialValues: primaryAgents.map((a) => a.id)
855
795
  });
856
- }
857
- async function promptAndInstallMcp(apiKey, options) {
858
- const allAgents = getAllAgents();
859
- const agentChoice = await p3.select({
860
- message: "Where do you want to install the MCP?",
861
- options: [
862
- {
863
- value: "all",
864
- label: "All agents",
865
- hint: allAgents.map((a) => a.name).join(", ")
866
- },
867
- ...allAgents.map((agent) => ({
868
- value: agent.id,
869
- label: agent.name
796
+ if (p3.isCancel(choice)) {
797
+ return false;
798
+ }
799
+ let selectedIds = choice;
800
+ if (selectedIds.includes("_other")) {
801
+ selectedIds = selectedIds.filter((id) => id !== "_other");
802
+ const otherChoice = await p3.multiselect({
803
+ message: "Select additional agents:",
804
+ options: otherAgents.map((a) => ({
805
+ value: a.id,
806
+ label: a.name,
807
+ hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
870
808
  }))
871
- ]
872
- });
873
- if (p3.isCancel(agentChoice)) {
874
- p3.log.info("Skipped MCP installation.");
875
- return;
876
- }
877
- const selectedAgents = agentChoice === "all" ? allAgents : allAgents.filter((a) => a.id === agentChoice);
878
- let scope = "global";
879
- const hasProjectScopeAgent = selectedAgents.some((a) => supportsProjectScope(a));
880
- if (options.global) {
881
- scope = "global";
882
- } else if (options.project) {
883
- scope = "project";
884
- } else if (hasProjectScopeAgent) {
885
- const scopeChoice = await p3.select({
886
- message: "How do you want to install it?",
887
- options: [
888
- {
889
- value: "global",
890
- label: "Global (Recommended)",
891
- hint: "Available in all your projects"
892
- },
893
- {
894
- value: "project",
895
- label: "Project only",
896
- hint: "Creates config files in current directory"
897
- }
898
- ]
899
809
  });
900
- if (p3.isCancel(scopeChoice)) {
901
- p3.log.info("Skipped MCP installation.");
902
- return;
903
- }
904
- scope = scopeChoice;
905
- }
906
- if (scope === "project") {
907
- const projectAgents = selectedAgents.filter((a) => supportsProjectScope(a));
908
- const nonProjectAgents = selectedAgents.filter((a) => !supportsProjectScope(a));
909
- if (projectAgents.length === 0) {
910
- const supported = allAgents.filter((a) => supportsProjectScope(a)).map((a) => a.name).join(", ");
911
- p3.note(
912
- `${selectedAgents.map((a) => a.name).join(", ")} does not support project-level MCP.
913
- Project scope is supported by: ${supported}`,
914
- "Not Supported"
915
- );
916
- p3.log.warn("Run again and choose global scope or a different agent.");
917
- return;
918
- }
919
- for (const agent of projectAgents) {
920
- const wasInstalled = isMcpInstalled(agent, "project");
921
- installMcpConfig(agent, apiKey, "project");
922
- const configPath = getAgentConfigPath(agent, "project");
923
- const status = wasInstalled ? "updated" : "created";
924
- p3.log.success(`${agent.name}: ${configPath} ${status}`);
925
- }
926
- if (nonProjectAgents.length > 0) {
927
- p3.log.info(`Installing globally for agents without project scope support:`);
928
- for (const agent of nonProjectAgents) {
929
- const wasInstalled = isMcpInstalled(agent, "global");
930
- installMcpConfig(agent, apiKey, "global");
931
- const status = wasInstalled ? "updated" : "installed";
932
- p3.log.success(`${agent.name}: MCP ${status} (global)`);
933
- }
810
+ if (!p3.isCancel(otherChoice)) {
811
+ selectedIds.push(...otherChoice);
934
812
  }
935
- const allInstalled = [...projectAgents, ...nonProjectAgents];
936
- updateConfigAgentsList(allInstalled.map((a) => a.id));
937
- p3.note(
938
- pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
939
- "Tip"
940
- );
941
- return;
942
813
  }
943
- const installedAgentIds = [];
944
- for (const agent of selectedAgents) {
945
- const wasInstalled = isMcpInstalled(agent, "global");
946
- installMcpConfig(agent, apiKey, "global");
947
- installedAgentIds.push(agent.id);
948
- const status = wasInstalled ? "updated" : "installed";
949
- p3.log.success(`${agent.name}: MCP ${status}`);
814
+ if (selectedIds.length === 0) {
815
+ p3.log.info("No agents selected.");
816
+ return false;
817
+ }
818
+ const spinner5 = p3.spinner();
819
+ spinner5.start("Installing skill...");
820
+ const { installed, failed } = installSkillForAgents(selectedIds);
821
+ spinner5.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
822
+ for (const name of installed) {
823
+ p3.log.success(`${name}: ${pc2.green("\u2713")} skill installed`);
824
+ }
825
+ for (const name of failed) {
826
+ p3.log.warn(`${name}: failed to install`);
950
827
  }
951
- updateConfigAgentsList(installedAgentIds);
828
+ return installed.length > 0;
829
+ }
830
+ function printOnboardingPrompt() {
831
+ console.log();
832
+ console.log(pc2.bold(" Copy-paste this to your AI agent:"));
833
+ console.log();
834
+ console.log(pc2.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
835
+ console.log(pc2.cyan(" \u2502"));
836
+ console.log(pc2.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
837
+ console.log(pc2.cyan(" \u2502 lets you interact with 250+ third-party platforms (Gmail,"));
838
+ console.log(pc2.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
839
+ console.log(pc2.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
840
+ console.log(pc2.cyan(" \u2502 third-party platform or external service, use the `one`"));
841
+ console.log(pc2.cyan(" \u2502 skill. Please save this to your project instructions or"));
842
+ console.log(pc2.cyan(" \u2502 memory so you remember it in future conversations."));
843
+ console.log(pc2.cyan(" \u2502"));
844
+ console.log(pc2.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
845
+ console.log();
952
846
  }
953
847
  async function freshSetup(options) {
954
848
  p3.note(`Get your API key at:
955
- ${pc3.cyan(getApiKeyUrl())}`, "API Key");
849
+ ${pc2.cyan(getApiKeyUrl())}`, "API Key");
956
850
  const openBrowser = await p3.confirm({
957
851
  message: "Open browser to get API key?",
958
852
  initialValue: true
@@ -994,52 +888,29 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
994
888
  installedAgents: [],
995
889
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
996
890
  });
997
- const installSkills = await p3.confirm({
998
- message: "Install One skills to your AI agents? (recommended)",
999
- initialValue: true
1000
- });
1001
- if (!p3.isCancel(installSkills) && installSkills) {
1002
- const success = await runSkillsInstall();
1003
- if (success) {
1004
- p3.log.success("Skills installed successfully.");
1005
- } else {
1006
- const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
1007
- const skillsDir = path3.resolve(__dirname2, "..", "skills");
1008
- p3.log.warn(`Skills installation failed. You can try manually: ${pc3.cyan(`npx skills add ${skillsDir}`)}`);
1009
- }
1010
- }
891
+ await promptSkillInstall();
1011
892
  await promptConnectIntegrations(apiKey);
1012
- const installMcp = await p3.confirm({
1013
- message: "Install One MCP server to your AI agents? (not recommended)",
1014
- initialValue: false
1015
- });
1016
- if (!p3.isCancel(installMcp) && installMcp) {
1017
- await promptAndInstallMcp(apiKey, options);
1018
- }
1019
893
  p3.note(
1020
- `Config saved to: ${pc3.dim(getConfigPath())}`,
894
+ `Config saved to: ${pc2.dim(getConfigPath())}`,
1021
895
  "Setup Complete"
1022
896
  );
1023
- p3.note(
1024
- `Tell your agent to run ${pc3.cyan("one onboard")} to learn what it can do.`,
1025
- "Next Step"
1026
- );
1027
- p3.outro("Your AI agents now have access to One integrations!");
897
+ printOnboardingPrompt();
898
+ p3.outro("Done! Paste the prompt above to your AI agent.");
1028
899
  }
1029
900
  function printBanner() {
1030
901
  console.log();
1031
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
1032
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
1033
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
1034
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
1035
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
1036
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
1037
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
1038
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
1039
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
1040
- console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
902
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
903
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
904
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
905
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
906
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
907
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
908
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
909
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
910
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
911
+ console.log(pc2.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
1041
912
  console.log();
1042
- console.log(pc3.dim(" U N I V E R S A L I N T E G R A T I O N S F O R A I"));
913
+ console.log(pc2.dim(" I N F R A S T R U C T U R E F O R A G E N T S"));
1043
914
  console.log();
1044
915
  }
1045
916
  var TOP_INTEGRATIONS = [
@@ -1084,13 +955,13 @@ async function promptConnectIntegrations(apiKey) {
1084
955
  } catch {
1085
956
  p3.note("https://app.withone.ai/connections", "Open in browser");
1086
957
  }
1087
- p3.log.info(`Connect from the dashboard, or use ${pc3.cyan("one add <platform>")}`);
958
+ p3.log.info(`Connect from the dashboard, or use ${pc2.cyan("one add <platform>")}`);
1088
959
  break;
1089
960
  }
1090
961
  const platform = choice;
1091
962
  const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
1092
963
  const label = integration?.label ?? platform;
1093
- p3.log.info(`Opening browser to connect ${pc3.cyan(label)}...`);
964
+ p3.log.info(`Opening browser to connect ${pc2.cyan(label)}...`);
1094
965
  try {
1095
966
  await openConnectionPage(platform);
1096
967
  } catch {
@@ -1103,13 +974,13 @@ async function promptConnectIntegrations(apiKey) {
1103
974
  try {
1104
975
  await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
1105
976
  spinner5.stop(`${label} connected!`);
1106
- p3.log.success(`${pc3.green("\u2713")} ${label} is now available to your AI agents`);
977
+ p3.log.success(`${pc2.green("\u2713")} ${label} is now available to your AI agents`);
1107
978
  connected.push(platform);
1108
979
  first = false;
1109
980
  } catch (error2) {
1110
981
  spinner5.stop("Connection timed out");
1111
982
  if (error2 instanceof TimeoutError) {
1112
- p3.log.warn(`No worries. Connect later with: ${pc3.cyan(`one add ${platform}`)}`);
983
+ p3.log.warn(`No worries. Connect later with: ${pc2.cyan(`one add ${platform}`)}`);
1113
984
  }
1114
985
  first = false;
1115
986
  }
@@ -1123,24 +994,6 @@ function maskApiKey(key) {
1123
994
  if (key.length <= 12) return key.slice(0, 8) + "...";
1124
995
  return key.slice(0, 8) + "..." + key.slice(-4);
1125
996
  }
1126
- function updateConfigAgents(agentId) {
1127
- const config = readConfig();
1128
- if (!config) return;
1129
- if (!config.installedAgents.includes(agentId)) {
1130
- config.installedAgents.push(agentId);
1131
- writeConfig(config);
1132
- }
1133
- }
1134
- function updateConfigAgentsList(agentIds) {
1135
- const config = readConfig();
1136
- if (!config) return;
1137
- for (const id of agentIds) {
1138
- if (!config.installedAgents.includes(id)) {
1139
- config.installedAgents.push(id);
1140
- }
1141
- }
1142
- writeConfig(config);
1143
- }
1144
997
 
1145
998
  // src/commands/connection.ts
1146
999
  import * as p4 from "@clack/prompts";
@@ -1181,6 +1034,42 @@ function countMatchingChars(a, b) {
1181
1034
  return count;
1182
1035
  }
1183
1036
 
1037
+ // src/lib/table.ts
1038
+ import pc3 from "picocolors";
1039
+ function printTable(columns, rows) {
1040
+ if (rows.length === 0) return;
1041
+ const gap = " ";
1042
+ const indent = " ";
1043
+ const widths = columns.map((col) => {
1044
+ const headerLen = col.label.length;
1045
+ const maxValueLen = Math.max(...rows.map((row) => stripAnsi(row[col.key] || "").length));
1046
+ return Math.max(headerLen, maxValueLen);
1047
+ });
1048
+ const header = columns.map((col, i) => {
1049
+ const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
1050
+ return pc3.dim(padded);
1051
+ }).join(gap);
1052
+ console.log(`${indent}${header}`);
1053
+ const separator = columns.map((_, i) => pc3.dim("\u2500".repeat(widths[i]))).join(gap);
1054
+ console.log(`${indent}${separator}`);
1055
+ for (const row of rows) {
1056
+ const line = columns.map((col, i) => {
1057
+ const raw = row[col.key] || "";
1058
+ const rawLen = stripAnsi(raw).length;
1059
+ const padding = widths[i] - rawLen;
1060
+ const colored = col.color ? col.color(raw) : raw;
1061
+ if (col.align === "right") {
1062
+ return " ".repeat(Math.max(0, padding)) + colored;
1063
+ }
1064
+ return colored + " ".repeat(Math.max(0, padding));
1065
+ }).join(gap);
1066
+ console.log(`${indent}${line}`);
1067
+ }
1068
+ }
1069
+ function stripAnsi(str) {
1070
+ return str.replace(/\x1b\[[0-9;]*m/g, "");
1071
+ }
1072
+
1184
1073
  // src/commands/connection.ts
1185
1074
  async function connectionAddCommand(platformArg) {
1186
1075
  if (isAgentMode()) {
@@ -2513,7 +2402,7 @@ function validateFlow(flow2) {
2513
2402
  }
2514
2403
 
2515
2404
  // src/commands/flow.ts
2516
- import fs3 from "fs";
2405
+ import fs4 from "fs";
2517
2406
  function getConfig2() {
2518
2407
  const apiKey = getApiKey();
2519
2408
  if (!apiKey) {
@@ -2571,7 +2460,7 @@ async function flowCreateCommand(key, options) {
2571
2460
  if (raw.startsWith("@")) {
2572
2461
  const filePath = raw.slice(1);
2573
2462
  try {
2574
- raw = fs3.readFileSync(filePath, "utf-8");
2463
+ raw = fs4.readFileSync(filePath, "utf-8");
2575
2464
  } catch (err) {
2576
2465
  error(`Cannot read file "${filePath}": ${err.message}`);
2577
2466
  }
@@ -2754,7 +2643,7 @@ async function flowValidateCommand(keyOrPath) {
2754
2643
  let flowData;
2755
2644
  try {
2756
2645
  const flowPath = resolveFlowPath(keyOrPath);
2757
- const content = fs3.readFileSync(flowPath, "utf-8");
2646
+ const content = fs4.readFileSync(flowPath, "utf-8");
2758
2647
  flowData = JSON.parse(content);
2759
2648
  } catch (err) {
2760
2649
  spinner5.stop("Validation failed");
@@ -3451,7 +3340,7 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
3451
3340
 
3452
3341
  ## Features
3453
3342
 
3454
- ### 1. Actions \u2014 Execute API calls on 200+ platforms
3343
+ ### 1. Actions \u2014 Execute API calls on 250+ platforms
3455
3344
  Search for actions, read their docs, and execute them. This is the core workflow.
3456
3345
 
3457
3346
  **Quick start:**
@@ -3812,7 +3701,7 @@ function buildStep1() {
3812
3701
  nextCommand: "one onboard --step 2",
3813
3702
  message: `# One CLI \u2014 Agent Onboarding
3814
3703
 
3815
- You now have access to the One CLI. It connects you to 200+ platforms
3704
+ You now have access to the One CLI. It connects you to 250+ platforms
3816
3705
  (Gmail, Slack, Stripe, Notion, etc.) \u2014 you'll learn the details shortly.
3817
3706
 
3818
3707
  IMPORTANT: Your only task right now is to send the message below to the
@@ -3822,7 +3711,7 @@ Do not offer demos yet. Just send this message and wait for their reply:
3822
3711
  ---
3823
3712
 
3824
3713
  I just got access to the One CLI \u2014 it connects me to your platforms like
3825
- Gmail, Slack, Stripe, and 200+ others so I can work with them directly.
3714
+ Gmail, Slack, Stripe, and 250+ others so I can work with them directly.
3826
3715
  I'll show you what I can do in a moment.
3827
3716
 
3828
3717
  First, one quick setup step: right now only this conversation knows about
@@ -3851,7 +3740,7 @@ If they declined, skip this section.
3851
3740
  ## One CLI \u2014 Platform Integrations
3852
3741
 
3853
3742
  The One CLI (\`one\`) is installed and configured on this machine. It is a
3854
- command-line tool that gives AI agents the ability to interact with 200+
3743
+ command-line tool that gives AI agents the ability to interact with 250+
3855
3744
  third-party platforms (Gmail, Slack, Shopify, HubSpot, Stripe, GitHub,
3856
3745
  Notion, Salesforce, etc.) through a single, unified interface.
3857
3746
 
@@ -3946,7 +3835,7 @@ function buildStep3(connections) {
3946
3835
  The user can connect any of these popular platforms:
3947
3836
  Gmail, Google Calendar, Slack, Notion, Shopify, Stripe, HubSpot, GitHub,
3948
3837
  Salesforce, QuickBooks, Asana, Jira, Linear, Intercom, Zendesk, Twilio,
3949
- and 200+ more. Run \`one platforms\` for the full list.`);
3838
+ and 250+ more. Run \`one platforms\` for the full list.`);
3950
3839
  sections.push("## Onboarding complete!\n\nYou're all set. Use `one --agent guide` any time you need the full reference.");
3951
3840
  return {
3952
3841
  step: 3,
@@ -3977,7 +3866,7 @@ platform before you can start using actions. Suggest they run:
3977
3866
  one add slack
3978
3867
  one add <any-platform>
3979
3868
 
3980
- Run \`one platforms\` to see all 200+ available platforms.`;
3869
+ Run \`one platforms\` to see all 250+ available platforms.`;
3981
3870
  }
3982
3871
  const header = `## Current State
3983
3872
 
@@ -4037,20 +3926,23 @@ function buildWorkflowIdeas(connections) {
4037
3926
 
4038
3927
  // src/commands/update.ts
4039
3928
  import { createRequire } from "module";
4040
- import { spawn as spawn2 } from "child_process";
3929
+ import { spawn } from "child_process";
4041
3930
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
4042
3931
  import { homedir } from "os";
4043
3932
  import { join } from "path";
4044
3933
  var require2 = createRequire(import.meta.url);
4045
3934
  var { version: currentVersion } = require2("../package.json");
4046
3935
  var CACHE_PATH = join(homedir(), ".one", "update-check.json");
4047
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
4048
- async function fetchLatestVersion() {
3936
+ var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
3937
+ var AGE_GATE_MS = 30 * 60 * 1e3;
3938
+ async function fetchLatestVersionInfo() {
4049
3939
  try {
4050
- const res = await fetch("https://registry.npmjs.org/@withone/cli/latest");
3940
+ const res = await fetch("https://registry.npmjs.org/@withone/cli");
4051
3941
  if (!res.ok) return null;
4052
3942
  const data = await res.json();
4053
- return data.version;
3943
+ const latest = data["dist-tags"]?.latest;
3944
+ if (!latest) return null;
3945
+ return { version: latest, publishedAt: data.time?.[latest] ?? null };
4054
3946
  } catch {
4055
3947
  return null;
4056
3948
  }
@@ -4062,24 +3954,26 @@ function readCache() {
4062
3954
  return null;
4063
3955
  }
4064
3956
  }
4065
- function writeCache(latestVersion) {
3957
+ function writeCache(latestVersion, publishedAt) {
4066
3958
  try {
4067
3959
  mkdirSync(join(homedir(), ".one"), { recursive: true });
4068
- writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion }));
3960
+ writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion, publishedAt }));
4069
3961
  } catch {
4070
3962
  }
4071
3963
  }
4072
3964
  async function checkLatestVersion() {
4073
- const version2 = await fetchLatestVersion();
4074
- if (version2) writeCache(version2);
4075
- return version2;
3965
+ const info = await fetchLatestVersionInfo();
3966
+ if (info) writeCache(info.version, info.publishedAt);
3967
+ return info?.version ?? null;
4076
3968
  }
4077
3969
  async function checkLatestVersionCached() {
4078
3970
  const cache = readCache();
4079
3971
  if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
4080
- return cache.latestVersion;
3972
+ return { version: cache.latestVersion, publishedAt: cache.publishedAt ?? null };
4081
3973
  }
4082
- return checkLatestVersion();
3974
+ const info = await fetchLatestVersionInfo();
3975
+ if (info) writeCache(info.version, info.publishedAt);
3976
+ return info;
4083
3977
  }
4084
3978
  function getCurrentVersion() {
4085
3979
  return currentVersion;
@@ -4104,7 +3998,7 @@ async function updateCommand() {
4104
3998
  s.stop(`Update available: v${currentVersion} \u2192 v${latestVersion}`);
4105
3999
  console.log(`Updating @withone/cli: v${currentVersion} \u2192 v${latestVersion}...`);
4106
4000
  const code = await new Promise((resolve) => {
4107
- const child = spawn2("npm", ["install", "-g", "@withone/cli@latest", "--force"], {
4001
+ const child = spawn("npm", ["install", "-g", "@withone/cli@latest", "--force"], {
4108
4002
  stdio: isAgentMode() ? "pipe" : "inherit",
4109
4003
  shell: true
4110
4004
  });
@@ -4121,12 +4015,24 @@ async function updateCommand() {
4121
4015
  error("Update failed \u2014 try running: npm install -g @withone/cli@latest");
4122
4016
  }
4123
4017
  }
4018
+ function autoUpdate(targetVersion, publishedAt) {
4019
+ if (publishedAt) {
4020
+ const age = Date.now() - new Date(publishedAt).getTime();
4021
+ if (age < AGE_GATE_MS) return;
4022
+ }
4023
+ const child = spawn("npm", ["install", "-g", `@withone/cli@${targetVersion}`], {
4024
+ detached: true,
4025
+ stdio: "ignore",
4026
+ shell: true
4027
+ });
4028
+ child.unref();
4029
+ }
4124
4030
 
4125
4031
  // src/index.ts
4126
4032
  var require3 = createRequire2(import.meta.url);
4127
4033
  var { version } = require3("../package.json");
4128
4034
  var program = new Command();
4129
- program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 200+ platforms through one interface.
4035
+ program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 250+ platforms through one interface.
4130
4036
 
4131
4037
  Setup:
4132
4038
  one init Set up API key and install MCP server
@@ -4170,7 +4076,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
4170
4076
  -d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
4171
4077
 
4172
4078
  Platform names are always kebab-case (e.g. hub-spot, ship-station, google-calendar).
4173
- Run 'one platforms' to browse all 200+ available platforms.`).version(version);
4079
+ Run 'one platforms' to browse all 250+ available platforms.`).version(version);
4174
4080
  var updateCheckPromise;
4175
4081
  program.hook("preAction", (thisCommand) => {
4176
4082
  const opts = program.opts();
@@ -4184,18 +4090,11 @@ program.hook("preAction", (thisCommand) => {
4184
4090
  });
4185
4091
  program.hook("postAction", async () => {
4186
4092
  if (!updateCheckPromise) return;
4187
- const latestVersion = await updateCheckPromise;
4188
- if (!latestVersion) return;
4093
+ const info = await updateCheckPromise;
4094
+ if (!info) return;
4189
4095
  const current = getCurrentVersion();
4190
- if (current === latestVersion) return;
4191
- if (isAgentMode()) {
4192
- process.stderr.write(`
4193
- Update available: v${current} \u2192 v${latestVersion}. Run "one update" to upgrade.
4194
- `);
4195
- } else {
4196
- console.log(`
4197
- \x1B[33mUpdate available: v${current} \u2192 v${latestVersion}. Run \x1B[1mone update\x1B[22m to upgrade.\x1B[0m`);
4198
- }
4096
+ if (current === info.version) return;
4097
+ autoUpdate(info.version, info.publishedAt);
4199
4098
  });
4200
4099
  program.command("init").description("Set up One and install MCP to your AI agents").option("-y, --yes", "Skip confirmations").option("-g, --global", "Install MCP globally (available in all projects)").option("-p, --project", "Install MCP for this project only (creates .mcp.json)").action(async (options) => {
4201
4100
  await initCommand(options);