@withone/cli 1.43.9 → 1.44.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/README.md CHANGED
@@ -144,11 +144,21 @@ In a monorepo, the project root is the nearest ancestor with `.one/`, `.git`, or
144
144
 
145
145
  If you've already set up, `one init` shows your current status for the active scope and lets you update your key, install to more agents, or reconfigure.
146
146
 
147
+ **Agent-driven setup (no prompts).** Pass `--auth` and `one init` runs end-to-end without any terminal interaction — handy when an AI agent is onboarding you. It saves the key, auto-installs the One skill, and skips the connect step (`one add` later).
148
+
149
+ ```bash
150
+ one init --auth browser # opens a login window; you authenticate, the window closes — done
151
+ one init --auth manual --api-key sk_live_... # headless / CI, no browser
152
+ ```
153
+
147
154
  | Flag | What it does |
148
155
  |------|-------------|
149
156
  | `-y` | Skip confirmations |
150
157
  | `-g` | Non-interactive: write the One config globally (`~/.one/config.json`) |
151
158
  | `-p` | Non-interactive: write the One config for this project (`~/.one/projects/<slug>/config.json`) |
159
+ | `--auth <browser\|manual>` | Run setup with **no prompts**. `browser` opens a login window; `manual` uses `--api-key`. Scope from `-g`/`-p` (default global). |
160
+ | `--api-key <key>` | API key for `--auth manual` (`sk_live_…` / `sk_test_…`) |
161
+ | `--openai-key <key>` | Optional OpenAI key for `one mem` semantic search |
152
162
 
153
163
  ### `one add <platform>`
154
164
 
package/dist/index.js CHANGED
@@ -1046,8 +1046,12 @@ async function loginCommand() {
1046
1046
 
1047
1047
  // src/commands/init.ts
1048
1048
  async function initCommand(options) {
1049
+ if (options.auth) {
1050
+ await nonInteractiveInit(options);
1051
+ return;
1052
+ }
1049
1053
  if (isAgentMode()) {
1050
- error("This command requires interactive input. Run without --agent.");
1054
+ error("This command is interactive. Run without --agent, or pass --auth <browser|manual> for a non-interactive setup.");
1051
1055
  }
1052
1056
  printBanner();
1053
1057
  const scope = await chooseConfigScope(options);
@@ -1062,6 +1066,101 @@ async function initCommand(options) {
1062
1066
  }
1063
1067
  await freshSetup(scope, options);
1064
1068
  }
1069
+ async function nonInteractiveInit(options) {
1070
+ const auth = options.auth;
1071
+ if (auth !== "browser" && auth !== "manual") {
1072
+ error(`Invalid --auth value '${auth}'. Use 'browser' or 'manual'.`);
1073
+ }
1074
+ const scope = options.global ? "global" : options.project ? "project" : "global";
1075
+ let apiKey;
1076
+ let whoami;
1077
+ if (auth === "browser") {
1078
+ const result = await browserLogin();
1079
+ if (!result) {
1080
+ error("Browser login did not complete. Try again: one init --auth browser");
1081
+ }
1082
+ apiKey = result.apiKey;
1083
+ whoami = result.whoami;
1084
+ } else {
1085
+ const key = options.apiKey?.trim();
1086
+ if (!key) {
1087
+ error("--auth manual requires --api-key <sk_live_\u2026 | sk_test_\u2026>.");
1088
+ }
1089
+ if (!key.startsWith("sk_live_") && !key.startsWith("sk_test_")) {
1090
+ error("API key should start with sk_live_ or sk_test_.");
1091
+ }
1092
+ const api = new OneApi(key, getApiBase());
1093
+ let validated;
1094
+ try {
1095
+ validated = await api.validateApiKey();
1096
+ } catch (err) {
1097
+ const msg = err instanceof Error ? err.message : String(err);
1098
+ error(`Could not validate API key: ${msg}`);
1099
+ }
1100
+ if (!validated) {
1101
+ error(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
1102
+ }
1103
+ apiKey = key;
1104
+ whoami = validated;
1105
+ }
1106
+ const existing = scope === "project" ? readProjectConfig() : readGlobalConfig();
1107
+ writeConfig(
1108
+ {
1109
+ apiKey,
1110
+ installedAgents: existing?.installedAgents ?? [],
1111
+ createdAt: existing?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1112
+ accessControl: existing?.accessControl,
1113
+ apiBase: existing?.apiBase,
1114
+ cacheTtl: existing?.cacheTtl,
1115
+ whoami
1116
+ },
1117
+ scope
1118
+ );
1119
+ if (options.openaiKey?.trim()) {
1120
+ try {
1121
+ setOpenAiApiKey(options.openaiKey.trim());
1122
+ } catch {
1123
+ }
1124
+ }
1125
+ const primaryIds = SKILL_AGENTS.filter((a) => a.primary).map((a) => a.id);
1126
+ const { installed, failed } = installSkillForAgents(primaryIds);
1127
+ const configPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
1128
+ if (isAgentMode()) {
1129
+ json({
1130
+ success: true,
1131
+ scope,
1132
+ configPath,
1133
+ auth,
1134
+ account: {
1135
+ user: whoami.user,
1136
+ organization: whoami.organization,
1137
+ project: whoami.project,
1138
+ env: getEnvFromApiKey(apiKey)
1139
+ },
1140
+ skillInstalled: installed,
1141
+ skillFailed: failed
1142
+ });
1143
+ return;
1144
+ }
1145
+ const env = getEnvFromApiKey(apiKey);
1146
+ const contextParts = [];
1147
+ if (whoami.organization) contextParts.push(whoami.organization.name);
1148
+ if (whoami.project) contextParts.push(whoami.project.name);
1149
+ const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
1150
+ const envLabel = env === "test" ? pc2.yellow("test") : pc2.green("live");
1151
+ console.log();
1152
+ console.log(` ${pc2.bold("Setup complete")} ${scopeLabel(scope)}`);
1153
+ console.log(` ${pc2.dim("\u2500".repeat(42))}`);
1154
+ console.log(` ${pc2.dim("Account:")} ${scopeDisplay} ${pc2.dim("\xB7")} ${envLabel}`);
1155
+ console.log(` ${pc2.dim("User:")} ${whoami.user.name} ${pc2.dim(`(${whoami.user.email})`)}`);
1156
+ console.log(` ${pc2.dim("Config:")} ${tildify(configPath)}`);
1157
+ if (installed.length > 0) {
1158
+ console.log(` ${pc2.dim("Skill:")} ${pc2.green("installed")} ${pc2.dim("\xB7 " + installed.join(", "))}`);
1159
+ }
1160
+ console.log();
1161
+ console.log(` ${pc2.dim("Connect a platform later with")} ${pc2.cyan("one add <platform>")}`);
1162
+ printOnboardingPrompt();
1163
+ }
1065
1164
  async function chooseConfigScope(options) {
1066
1165
  if (options.global) return "global";
1067
1166
  if (options.project) return "project";
@@ -9236,6 +9335,17 @@ var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
9236
9335
 
9237
9336
  You can also use \`one login\` / \`one logout\` to manage authentication separately (global or per-directory).
9238
9337
 
9338
+ ### Agent-driven setup (no prompts)
9339
+ To onboard a user without any terminal interaction, pass \`--auth\` to \`one init\`. This disables every prompt, auto-installs the One skill, and skips the connect-a-platform step (run \`one add <platform>\` afterwards).
9340
+
9341
+ \`\`\`bash
9342
+ one init --auth browser # opens a login window; the user authenticates, the CLI saves the key
9343
+ one init --auth browser --project # same, but scoped to this folder (default scope is global)
9344
+ one init --auth manual --api-key sk_live_... # headless / CI \u2014 no browser
9345
+ \`\`\`
9346
+
9347
+ With \`--auth browser\` the user sees a browser window, picks how to authenticate, and the window closes when done \u2014 the agent never blocks on stdin. Add \`--openai-key sk-...\` to enable semantic search in \`one mem\` during setup.
9348
+
9239
9349
  ## The --agent Flag
9240
9350
 
9241
9351
  Always use \`--agent\` for machine-readable JSON output. It disables colors, spinners, and interactive prompts.
@@ -10640,7 +10750,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
10640
10750
  Setup:
10641
10751
  one login Authenticate via browser (opens app.withone.ai)
10642
10752
  one logout Clear local credentials
10643
- one init Set up API key and install MCP server
10753
+ one init Set up API key + skill (add --auth browser for no-prompt agent setup)
10644
10754
  one add <platform> Connect a platform via OAuth (e.g. gmail, slack, shopify)
10645
10755
  one connection delete <key> Remove a connection (alias: one connection rm)
10646
10756
  one config Configure access control (permissions, scoping)
@@ -10734,7 +10844,7 @@ program.hook("postAction", async () => {
10734
10844
  if (!isNewerVersion(info.version, current)) return;
10735
10845
  autoUpdate(info.version, info.publishedAt);
10736
10846
  });
10737
- program.command("init").description("Set up One and install MCP to your AI agents (interactive: picks global or project scope)").option("-y, --yes", "Skip confirmations").option("-g, --global", "Write the One config globally (~/.one/config.json) \u2014 skips the scope picker").option("-p, --project", "Write the One config for this project only (~/.one/projects/<slug>/) \u2014 skips the scope picker").action(async (options) => {
10847
+ program.command("init").description("Set up One and install the skill to your AI agents (interactive; pass --auth for a no-prompt setup)").option("-y, --yes", "Skip confirmations").option("-g, --global", "Write the One config globally (~/.one/config.json) \u2014 skips the scope picker").option("-p, --project", "Write the One config for this project only (~/.one/projects/<slug>/) \u2014 skips the scope picker").option("--auth <method>", 'Non-interactive setup (no prompts): "browser" opens a login window, "manual" uses --api-key').option("--api-key <key>", "API key for --auth manual (sk_live_\u2026 or sk_test_\u2026)").option("--openai-key <key>", "Optional OpenAI key for `one mem` semantic search (non-interactive setup)").action(async (options) => {
10738
10848
  await initCommand(options);
10739
10849
  });
10740
10850
  program.command("login").description("Authenticate with One via browser").action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.43.9",
3
+ "version": "1.44.0",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -31,7 +31,9 @@ one login # Browser-based login (opens app.withone.ai)
31
31
  one logout # Clear local credentials
32
32
  ```
33
33
 
34
- `one login` opens the browser for OAuth authentication and automatically creates and stores an API key. If already logged in, the user can choose to log in globally or for the current directory. `one logout` shows current session info and confirms before clearing credentials. For CI/CD or headless environments, use `one init` to paste a key manually.
34
+ `one login` opens the browser for OAuth authentication and automatically creates and stores an API key. If already logged in, the user can choose to log in globally or for the current directory. `one logout` shows current session info and confirms before clearing credentials.
35
+
36
+ **Onboarding a user with no prompts:** run `one init --auth browser` — it opens a login window (the user authenticates there), saves the key, and auto-installs this skill, all without blocking on stdin. Add `-g`/`-p` for scope (default global). For CI/CD or headless environments, use `one init --auth manual --api-key sk_live_...`.
35
37
 
36
38
  ## Core Workflow: search -> knowledge -> execute
37
39