@primitivedotdev/cli 0.31.2 → 0.31.3

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
@@ -18,8 +18,7 @@ This package wraps the [@primitivedotdev/sdk](https://www.npmjs.com/package/@pri
18
18
  ## Quickstart
19
19
 
20
20
  ```bash
21
- export PRIMITIVE_API_KEY=prim_...
22
-
21
+ primitive signin
23
22
  primitive whoami
24
23
  primitive functions templates
25
24
  primitive functions init my-fn
@@ -32,6 +31,14 @@ primitive emails latest --limit 5
32
31
 
33
32
  Run `primitive --help` for the full command list. Per-command help (`primitive functions deploy --help`) carries enough detail that an agent can compose any operation without leaving the terminal.
34
33
 
34
+ ## Authentication
35
+
36
+ Use `primitive signin` for existing accounts. It defaults to browser approval; `primitive signin browser` is the explicit form and `primitive login` remains available for compatibility.
37
+
38
+ Use `primitive signin otp <email> --signup-code <code> --accept-terms`, then `primitive signin otp confirm <email> <code>` for email-code sign-in.
39
+
40
+ Use `primitive signup <email>` for new account creation, then `primitive signup confirm <email> <code>` with the emailed verification code. Non-interactive signup is available with `--signup-code` and `--accept-terms`.
41
+
35
42
  ## Command style
36
43
 
37
44
  Use task-oriented commands for normal workflows:
@@ -11508,7 +11508,7 @@ var PrimitiveApiClient = class {
11508
11508
  const CREDENTIALS_FILE = "credentials.json";
11509
11509
  const CREDENTIALS_LOCK_DIR = "credentials.lock";
11510
11510
  const CREDENTIALS_LOCK_STALE_MS = 1800 * 1e3;
11511
- const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive login`.";
11511
+ const MALFORMED_CREDENTIALS_HINT = "Run `primitive logout` and then `primitive signin`.";
11512
11512
  function isRecord$2(value) {
11513
11513
  return value !== null && typeof value === "object" && !Array.isArray(value);
11514
11514
  }
@@ -11586,10 +11586,10 @@ function loadCliCredentials(configDir) {
11586
11586
  try {
11587
11587
  rmSync(path, { force: true });
11588
11588
  } catch {}
11589
- process.stderr.write("Removed local Primitive CLI API-key login state. API keys are still valid when passed explicitly, but `primitive login` now uses OAuth. Run `primitive login` to create an OAuth session. No API key was revoked.\n");
11589
+ process.stderr.write("Removed local Primitive CLI API-key login state. API keys are still valid when passed explicitly, but saved CLI auth now uses OAuth. Run `primitive signin` to create an OAuth session. No API key was revoked.\n");
11590
11590
  return null;
11591
11591
  }
11592
- if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive login`.");
11592
+ if (error instanceof SyntaxError) throw new Error("Stored Primitive CLI credentials are not valid JSON. Run `primitive logout` and then `primitive signin`.");
11593
11593
  throw error;
11594
11594
  }
11595
11595
  }
@@ -11872,7 +11872,7 @@ function redactCliEnvironment(environment) {
11872
11872
  //#region src/oclif/api-client.ts
11873
11873
  const API_HEADERS_ENV = "PRIMITIVE_API_HEADERS";
11874
11874
  const OAUTH_REFRESH_SKEW_MS = 60 * 1e3;
11875
- const SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE = "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive login` to authenticate again.";
11875
+ const SAVED_CLI_OAUTH_SESSION_EXPIRED_MESSAGE = "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
11876
11876
  function mergeHeaders(...headers) {
11877
11877
  const merged = {};
11878
11878
  for (const headerSet of headers) {
@@ -11970,7 +11970,7 @@ async function refreshStoredCliCredentials(params) {
11970
11970
  throw new Errors.CLIError(detail, { exit: 1 });
11971
11971
  }
11972
11972
  const current = loadCliCredentials(params.configDir);
11973
- if (!current) throw new Errors.CLIError("Saved Primitive CLI OAuth session is no longer available. Run `primitive login` to authenticate again.", { exit: 1 });
11973
+ if (!current) throw new Errors.CLIError("Saved Primitive CLI OAuth session is no longer available. Run `primitive signin` to authenticate again.", { exit: 1 });
11974
11974
  if (!shouldRefresh(current, now)) return current;
11975
11975
  const fetchImpl = params.fetch ?? fetch;
11976
11976
  const body = new URLSearchParams({
@@ -12279,26 +12279,26 @@ function coerceParameterValue(parameter, value) {
12279
12279
  if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return value;
12280
12280
  throw new Errors.CLIError(`Unsupported flag value for --${parameter.name}`);
12281
12281
  }
12282
- function cliError$6(message) {
12282
+ function cliError$7(message) {
12283
12283
  return new Errors.CLIError(message, { exit: 1 });
12284
12284
  }
12285
12285
  function parseJson(source, flagLabel) {
12286
12286
  try {
12287
12287
  return JSON.parse(source);
12288
12288
  } catch (error) {
12289
- throw cliError$6(`${flagLabel} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
12289
+ throw cliError$7(`${flagLabel} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
12290
12290
  }
12291
12291
  }
12292
12292
  function readJsonBody(flags) {
12293
12293
  const bodyFile = flags["body-file"];
12294
12294
  const rawBody = flags["raw-body"];
12295
- if (bodyFile && rawBody) throw cliError$6("Use either --raw-body or --body-file, not both");
12295
+ if (bodyFile && rawBody) throw cliError$7("Use either --raw-body or --body-file, not both");
12296
12296
  if (typeof bodyFile === "string") {
12297
12297
  let contents;
12298
12298
  try {
12299
12299
  contents = readFileSync(bodyFile, "utf8");
12300
12300
  } catch (error) {
12301
- throw cliError$6(`Could not read --body-file ${bodyFile}: ${error instanceof Error ? error.message : String(error)}`);
12301
+ throw cliError$7(`Could not read --body-file ${bodyFile}: ${error instanceof Error ? error.message : String(error)}`);
12302
12302
  }
12303
12303
  return parseJson(contents, `--body-file ${bodyFile}`);
12304
12304
  }
@@ -12308,7 +12308,7 @@ function readTextFileFlag(path, flagLabel) {
12308
12308
  try {
12309
12309
  return readFileSync(path, "utf8");
12310
12310
  } catch (error) {
12311
- throw cliError$6(`Could not read ${flagLabel} ${path}: ${error instanceof Error ? error.message : String(error)}`);
12311
+ throw cliError$7(`Could not read ${flagLabel} ${path}: ${error instanceof Error ? error.message : String(error)}`);
12312
12312
  }
12313
12313
  }
12314
12314
  function extractErrorPayload(raw) {
@@ -12355,7 +12355,7 @@ function extractErrorCode(payload) {
12355
12355
  if (typeof direct === "string") return direct;
12356
12356
  }
12357
12357
  }
12358
- const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive login`, pass --api-key explicitly, or set PRIMITIVE_API_KEY in your environment. `primitive whoami` is the fastest way to verify auth is live." };
12358
+ const ERROR_CODE_HINTS = { [API_ERROR_CODES.unauthorized]: "Hint: run `primitive signin`, pass --api-key explicitly, or set PRIMITIVE_API_KEY in your environment. `primitive whoami` is the fastest way to verify auth is live." };
12359
12359
  const NETWORK_ERROR_HINTS = {
12360
12360
  ENETUNREACH: "Hint: the network is unreachable. If you're behind a proxy and set HTTP(S)_PROXY, re-run with NODE_USE_ENV_PROXY=1 (Node 22+ ignores those env vars by default). `primitive doctor` reports the local environment in one shot.",
12361
12361
  ECONNREFUSED: "Hint: the server refused the connection. Check that your firewall allows egress to *.primitive.dev, that your PRIMITIVE_API_BASE_URL_* overrides (if any) point at a reachable host, and re-run with NODE_USE_ENV_PROXY=1 if you're behind a proxy. `primitive doctor` reports the local environment in one shot.",
@@ -12393,7 +12393,7 @@ function surfaceUnauthorizedHint(params) {
12393
12393
  process.stderr.write("Saved Primitive CLI credentials were rejected by the overridden API base URL. The saved credential is preserved; unset PRIMITIVE_API_BASE_URL_1, run `primitive config reset` to clear configured URL overrides, or run `primitive logout` to remove the stored credential.\n");
12394
12394
  return;
12395
12395
  }
12396
- process.stderr.write("Your saved Primitive CLI OAuth session was rejected. If the command was working a moment ago, please retry; brief retries often clear transient rejections. If it keeps failing, run `primitive logout && primitive login` to mint a fresh session.\n");
12396
+ process.stderr.write("Your saved Primitive CLI OAuth session was rejected. If the command was working a moment ago, please retry; brief retries often clear transient rejections. If it keeps failing, run `primitive logout && primitive signin` to mint a fresh session.\n");
12397
12397
  }
12398
12398
  function formatElapsed(ms) {
12399
12399
  const seconds = ms / 1e3;
@@ -12756,11 +12756,11 @@ function sleep$1(ms) {
12756
12756
  //#region src/oclif/commands/chat.ts
12757
12757
  const DEFAULT_CHAT_TIMEOUT_SECONDS = 120;
12758
12758
  const DEFAULT_STRICT_PHASE_SECONDS = 60;
12759
- function cliError$5(message) {
12759
+ function cliError$6(message) {
12760
12760
  return new Errors.CLIError(message, { exit: 1 });
12761
12761
  }
12762
12762
  async function readStdinToString() {
12763
- if (process.stdin.isTTY) throw cliError$5("No message provided. Pass the message as the second positional argument or pipe it via stdin.");
12763
+ if (process.stdin.isTTY) throw cliError$6("No message provided. Pass the message as the second positional argument or pipe it via stdin.");
12764
12764
  const chunks = [];
12765
12765
  for await (const chunk of process.stdin) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
12766
12766
  return Buffer.concat(chunks).toString("utf8");
@@ -12796,7 +12796,7 @@ var ChatCommand = class ChatCommand extends Command {
12796
12796
  };
12797
12797
  static flags = {
12798
12798
  "api-key": Flags.string({
12799
- description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive login` credentials)",
12799
+ description: "Primitive API key (defaults to PRIMITIVE_API_KEY or saved `primitive signin` credentials)",
12800
12800
  env: "PRIMITIVE_API_KEY"
12801
12801
  }),
12802
12802
  "api-base-url-1": Flags.string({
@@ -12841,7 +12841,7 @@ var ChatCommand = class ChatCommand extends Command {
12841
12841
  async run() {
12842
12842
  const { args, flags } = await this.parse(ChatCommand);
12843
12843
  const message = args.message !== void 0 && args.message !== "" ? args.message : await readStdinToString();
12844
- if (!message.trim()) throw cliError$5("Message body is empty.");
12844
+ if (!message.trim()) throw cliError$6("Message body is empty.");
12845
12845
  await runWithTiming(flags.time, async () => {
12846
12846
  const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
12847
12847
  apiKey: flags["api-key"],
@@ -12879,7 +12879,7 @@ var ChatCommand = class ChatCommand extends Command {
12879
12879
  return;
12880
12880
  }
12881
12881
  const sent = sendResult.data?.data;
12882
- if (!sent) throw cliError$5("Send succeeded but the API returned no data.");
12882
+ if (!sent) throw cliError$6("Send succeeded but the API returned no data.");
12883
12883
  const reply = await waitForReply({
12884
12884
  apiClient,
12885
12885
  authFailureContext,
@@ -13203,23 +13203,23 @@ function checkApiKey(opts) {
13203
13203
  if (typeof parsed?.api_key === "string" && parsed.api_key.length > 0) return {
13204
13204
  status: "fail",
13205
13205
  message: `${credsPath} contains legacy API-key login state`,
13206
- hint: "Run `primitive login` to create saved OAuth credentials. Existing API keys still work with --api-key or PRIMITIVE_API_KEY."
13206
+ hint: "Run `primitive signin` to create saved OAuth credentials. Existing API keys still work with --api-key or PRIMITIVE_API_KEY."
13207
13207
  };
13208
13208
  if (parsed) return {
13209
13209
  status: "fail",
13210
13210
  message: `${credsPath} exists but contains no OAuth access_token`,
13211
- hint: "Run `primitive logout` to clear it, then `primitive login` to recreate."
13211
+ hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
13212
13212
  };
13213
13213
  return {
13214
13214
  status: "fail",
13215
13215
  message: `${credsPath} exists but is unreadable or malformed${parseError ? ` (${parseError})` : ""}`,
13216
- hint: "Run `primitive logout` to clear it, then `primitive login` to recreate."
13216
+ hint: "Run `primitive logout` to clear it, then `primitive signin` to recreate."
13217
13217
  };
13218
13218
  }
13219
13219
  return {
13220
13220
  status: "fail",
13221
13221
  message: "no CLI OAuth session or explicit API key found",
13222
- hint: "Run `primitive login`, pass --api-key explicitly, or export PRIMITIVE_API_KEY=prim_..."
13222
+ hint: "Run `primitive signin`, pass --api-key explicitly, or export PRIMITIVE_API_KEY=prim_..."
13223
13223
  };
13224
13224
  }
13225
13225
  async function checkAccount(client) {
@@ -13489,7 +13489,7 @@ var EmailsLatestCommand = class EmailsLatestCommand extends Command {
13489
13489
  //#endregion
13490
13490
  //#region src/oclif/commands/emails-wait.ts
13491
13491
  const DEFAULT_WAIT_TIMEOUT_SECONDS$1 = 300;
13492
- function cliError$4(message) {
13492
+ function cliError$5(message) {
13493
13493
  return new Errors.CLIError(message, { exit: 1 });
13494
13494
  }
13495
13495
  var EmailsWaitCommand = class EmailsWaitCommand extends Command {
@@ -13564,7 +13564,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
13564
13564
  try {
13565
13565
  since = sinceFromFlags(flags);
13566
13566
  } catch (error) {
13567
- throw cliError$4(error instanceof Error ? error.message : String(error));
13567
+ throw cliError$5(error instanceof Error ? error.message : String(error));
13568
13568
  }
13569
13569
  const filters = filtersFromFlags(flags);
13570
13570
  const deadline = flags.timeout === 0 ? null : Date.now() + flags.timeout * 1e3;
@@ -13615,7 +13615,7 @@ var EmailsWaitCommand = class EmailsWaitCommand extends Command {
13615
13615
  };
13616
13616
  //#endregion
13617
13617
  //#region src/oclif/commands/emails-watch.ts
13618
- function cliError$3(message) {
13618
+ function cliError$4(message) {
13619
13619
  return new Errors.CLIError(message, { exit: 1 });
13620
13620
  }
13621
13621
  var EmailsWatchCommand = class EmailsWatchCommand extends Command {
@@ -13686,7 +13686,7 @@ var EmailsWatchCommand = class EmailsWatchCommand extends Command {
13686
13686
  try {
13687
13687
  since = sinceFromFlags(flags);
13688
13688
  } catch (error) {
13689
- throw cliError$3(error instanceof Error ? error.message : String(error));
13689
+ throw cliError$4(error instanceof Error ? error.message : String(error));
13690
13690
  }
13691
13691
  const filters = filtersFromFlags(flags);
13692
13692
  const deadline = flags.seconds ? Date.now() + flags.seconds * 1e3 : null;
@@ -14731,7 +14731,7 @@ The deploy step calls \`primitive functions deploy\` (provided by the
14731
14731
  \`npm install -g @primitivedotdev/cli\` or run via
14732
14732
  \`npx @primitivedotdev/cli@latest <command>\`). It requires
14733
14733
  \`PRIMITIVE_API_KEY\` to be set in your shell (or pass \`--api-key\`).
14734
- Run \`primitive login\` once to save a key in your CLI config if you
14734
+ Run \`primitive signin\` once to save a key in your CLI config if you
14735
14735
  prefer that to an env var.
14736
14736
  `;
14737
14737
  }
@@ -15790,7 +15790,7 @@ var FunctionsTestFunctionCommand = class FunctionsTestFunctionCommand extends Co
15790
15790
  //#endregion
15791
15791
  //#region src/oclif/commands/login.ts
15792
15792
  const MAX_CLI_LOGIN_POLL_INTERVAL_SECONDS = 60;
15793
- function cliError$2(message) {
15793
+ function cliError$3(message) {
15794
15794
  return new Errors.CLIError(message, { exit: 1 });
15795
15795
  }
15796
15796
  function sleep(ms) {
@@ -15866,7 +15866,7 @@ async function checkExistingLogin(params) {
15866
15866
  message: code === API_ERROR_CODES.unauthorized ? "Saved Primitive CLI OAuth credentials were rejected by an API URL different from the one they were saved with. Run `primitive logout` to remove them, or switch back to the original environment before logging in again." : "A saved Primitive CLI OAuth session exists, but the CLI could not verify whether it is still valid. Run `primitive logout` before logging in again."
15867
15867
  };
15868
15868
  }
15869
- var LoginCommand = class LoginCommand extends Command {
15869
+ var LoginCommand = class extends Command {
15870
15870
  static description = "Log in by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
15871
15871
  static summary = "Log in with browser approval";
15872
15872
  static examples = [
@@ -15884,24 +15884,28 @@ var LoginCommand = class LoginCommand extends Command {
15884
15884
  "no-browser": Flags.boolean({ description: "Do not attempt to open the browser automatically" }),
15885
15885
  force: Flags.boolean({
15886
15886
  char: "f",
15887
- description: "Replace saved credentials without first verifying the existing login"
15887
+ description: "Replace saved credentials without first verifying the existing session"
15888
15888
  })
15889
15889
  };
15890
15890
  async run() {
15891
- const { flags } = await this.parse(LoginCommand);
15891
+ const commandClass = this.constructor;
15892
+ const { flags } = await this.parse(commandClass);
15892
15893
  let releaseCredentialsLock;
15893
15894
  try {
15894
15895
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
15895
15896
  } catch (error) {
15896
- throw cliError$2(error instanceof Error ? error.message : String(error));
15897
+ throw cliError$3(error instanceof Error ? error.message : String(error));
15897
15898
  }
15898
15899
  try {
15899
- await this.runWithCredentialLock(flags);
15900
+ await this.runWithCredentialLock(flags, this.retryCommand());
15900
15901
  } finally {
15901
15902
  releaseCredentialsLock();
15902
15903
  }
15903
15904
  }
15904
- async runWithCredentialLock(flags) {
15905
+ retryCommand() {
15906
+ return "login";
15907
+ }
15908
+ async runWithCredentialLock(flags, retryCommand) {
15905
15909
  const { apiClient, requestConfig } = createCliApiClient({
15906
15910
  apiBaseUrl1: flags["api-base-url-1"],
15907
15911
  configDir: this.config.configDir
@@ -15927,8 +15931,8 @@ var LoginCommand = class LoginCommand extends Command {
15927
15931
  if (existingStatus.status === "removed_stale") process.stderr.write("Continuing with a new Primitive CLI login...\n");
15928
15932
  else if (existingStatus.status === "blocked") {
15929
15933
  writeErrorWithHints(existingStatus.payload);
15930
- throw cliError$2(existingStatus.message);
15931
- } else throw cliError$2(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before logging in again.`);
15934
+ throw cliError$3(existingStatus.message);
15935
+ } else throw cliError$3(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before logging in again.`);
15932
15936
  }
15933
15937
  const started = await startCliLogin({
15934
15938
  body: { device_name: flags["device-name"] ?? hostname() },
@@ -15937,11 +15941,11 @@ var LoginCommand = class LoginCommand extends Command {
15937
15941
  });
15938
15942
  if (started.error) {
15939
15943
  writeErrorWithHints(extractErrorPayload(started.error));
15940
- throw cliError$2("Could not start Primitive CLI login.");
15944
+ throw cliError$3("Could not start Primitive CLI login.");
15941
15945
  }
15942
15946
  const start = unwrapData$2(started.data);
15943
- if (!start) throw cliError$2("Primitive API returned an empty CLI login response.");
15944
- process.stderr.write(`Your login code is: ${start.user_code}\n`);
15947
+ if (!start) throw cliError$3("Primitive API returned an empty CLI login response.");
15948
+ process.stderr.write(`Your sign-in code is: ${start.user_code}\n`);
15945
15949
  if (!flags["no-browser"]) {
15946
15950
  openBrowser(start.verification_uri_complete);
15947
15951
  process.stderr.write("Opening Primitive in your browser...\n");
@@ -15961,7 +15965,7 @@ var LoginCommand = class LoginCommand extends Command {
15961
15965
  });
15962
15966
  if (polled.data) {
15963
15967
  const login = unwrapData$2(polled.data);
15964
- if (!login) throw cliError$2("Primitive API returned an empty CLI poll response.");
15968
+ if (!login) throw cliError$3("Primitive API returned an empty CLI poll response.");
15965
15969
  saveCliCredentials(this.config.configDir, {
15966
15970
  access_token: login.access_token,
15967
15971
  api_base_url_1: apiBaseUrl1,
@@ -15991,25 +15995,25 @@ var LoginCommand = class LoginCommand extends Command {
15991
15995
  nextPollDelay = interval;
15992
15996
  continue;
15993
15997
  }
15994
- if (code === API_ERROR_CODES.accessDenied) throw cliError$2("Primitive CLI login was denied in the browser.");
15995
- if (code === API_ERROR_CODES.expiredToken) throw cliError$2("Primitive CLI login expired. Run `primitive login` again.");
15996
- if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$2("Primitive CLI login device code is invalid. Run `primitive login` again.");
15998
+ if (code === API_ERROR_CODES.accessDenied) throw cliError$3("Primitive CLI login was denied in the browser.");
15999
+ if (code === API_ERROR_CODES.expiredToken) throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
16000
+ if (code === API_ERROR_CODES.invalidDeviceCode) throw cliError$3(`Primitive CLI login device code is invalid. Run \`primitive ${retryCommand}\` again.`);
15997
16001
  writeErrorWithHints(payload);
15998
- throw cliError$2("Primitive CLI login failed while polling for approval.");
16002
+ throw cliError$3("Primitive CLI login failed while polling for approval.");
15999
16003
  }
16000
- throw cliError$2("Primitive CLI login expired. Run `primitive login` again.");
16004
+ throw cliError$3(`Primitive CLI login expired. Run \`primitive ${retryCommand}\` again.`);
16001
16005
  }
16002
16006
  };
16003
16007
  //#endregion
16004
16008
  //#region src/oclif/commands/logout.ts
16005
- function cliError$1(message) {
16009
+ function cliError$2(message) {
16006
16010
  return new Errors.CLIError(message, { exit: 1 });
16007
16011
  }
16008
16012
  function unwrapData$1(value) {
16009
16013
  return value?.data ?? null;
16010
16014
  }
16011
16015
  function isSavedOAuthSessionExpiredError(error) {
16012
- return error instanceof Error && error.message === "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive login` to authenticate again.";
16016
+ return error instanceof Error && error.message === "Saved Primitive CLI OAuth session expired or was revoked. Run `primitive signin` to authenticate again.";
16013
16017
  }
16014
16018
  async function runLogoutWithCredentialLock(params) {
16015
16019
  const deps = {
@@ -16027,7 +16031,7 @@ async function runLogoutWithCredentialLock(params) {
16027
16031
  process.exitCode = 1;
16028
16032
  return;
16029
16033
  }
16030
- if (!credentials) throw cliError$1("Not logged in. Run `primitive login` to create saved CLI credentials.");
16034
+ if (!credentials) throw cliError$2("Not logged in. Run `primitive signin` to create saved CLI credentials.");
16031
16035
  let authenticated;
16032
16036
  try {
16033
16037
  authenticated = await deps.createAuthenticatedCliApiClient({
@@ -16059,7 +16063,7 @@ async function runLogoutWithCredentialLock(params) {
16059
16063
  return;
16060
16064
  }
16061
16065
  writeErrorWithHints(payload);
16062
- throw cliError$1("Could not revoke the saved Primitive CLI OAuth grant.");
16066
+ throw cliError$2("Could not revoke the saved Primitive CLI OAuth grant.");
16063
16067
  }
16064
16068
  const logout = unwrapData$1(result.data);
16065
16069
  deleteCliCredentials(params.configDir);
@@ -16081,7 +16085,7 @@ var LogoutCommand = class LogoutCommand extends Command {
16081
16085
  try {
16082
16086
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
16083
16087
  } catch (error) {
16084
- throw cliError$1(error instanceof Error ? error.message : String(error));
16088
+ throw cliError$2(error instanceof Error ? error.message : String(error));
16085
16089
  }
16086
16090
  try {
16087
16091
  await runLogoutWithCredentialLock({
@@ -16401,7 +16405,14 @@ const EXPIRED_TOKEN = "expired_token";
16401
16405
  const INVALID_SIGNUP_TOKEN = "invalid_signup_token";
16402
16406
  const SLOW_DOWN = "slow_down";
16403
16407
  const PENDING_SIGNUP_FILE = "signup.json";
16404
- function cliError(message) {
16408
+ const DEFAULT_SIGNUP_COMMAND_COPY = {
16409
+ actionNoun: "signup",
16410
+ actionGerund: "creating a new account",
16411
+ confirmCommand: (email) => `signup confirm ${email} <code>`,
16412
+ resendCommand: (email) => `signup resend ${email}`,
16413
+ startCommand: (email) => `signup ${email}`
16414
+ };
16415
+ function cliError$1(message) {
16405
16416
  return new Errors.CLIError(message, { exit: 1 });
16406
16417
  }
16407
16418
  function unwrapData(value) {
@@ -16490,9 +16501,10 @@ function loadPendingAgentSignup(configDir, apiBaseUrl1) {
16490
16501
  };
16491
16502
  }
16492
16503
  function requirePendingSignupForEmail(params) {
16504
+ const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
16493
16505
  const pending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
16494
- if (!pending) throw cliError(`No pending signup for ${params.email}. Run \`primitive signup ${params.email}\` first.`);
16495
- if (normalizeEmail(pending.email) !== normalizeEmail(params.email)) throw cliError(`Pending signup is for ${pending.email}, not ${params.email}. Run \`primitive signup ${params.email} --force\` to replace it.`);
16506
+ if (!pending) throw cliError$1(`No pending ${copy.actionNoun} for ${params.email}. Run \`primitive ${copy.startCommand(params.email)}\` first.`);
16507
+ if (normalizeEmail(pending.email) !== normalizeEmail(params.email)) throw cliError$1(`Pending ${copy.actionNoun} is for ${pending.email}, not ${params.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
16496
16508
  return pending;
16497
16509
  }
16498
16510
  function retryAfterSeconds(result) {
@@ -16529,13 +16541,14 @@ async function promptRequired(question) {
16529
16541
  }
16530
16542
  }
16531
16543
  async function confirmTerms() {
16532
- process$1.stderr.write("By creating an account, you agree to Primitive's Terms of Service and Privacy Policy:\n");
16544
+ process$1.stderr.write("By continuing, you agree to Primitive's Terms of Service and Privacy Policy:\n");
16533
16545
  process$1.stderr.write(" https://primitive.dev/terms\n");
16534
16546
  process$1.stderr.write(" https://primitive.dev/privacy\n");
16535
16547
  const answer = (await promptRequired("Type 'yes' to continue: ")).toLowerCase();
16536
- if (answer !== "yes" && answer !== "y") throw cliError("You must accept the terms to create an account.");
16548
+ if (answer !== "yes" && answer !== "y") throw cliError$1("You must accept the terms to create an account.");
16537
16549
  }
16538
16550
  async function checkExistingCredentials(params) {
16551
+ const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
16539
16552
  const checkExistingLoginFn = params.deps.checkExistingLogin ?? checkExistingLogin;
16540
16553
  let existing;
16541
16554
  try {
@@ -16547,7 +16560,7 @@ async function checkExistingCredentials(params) {
16547
16560
  existing = null;
16548
16561
  }
16549
16562
  if (existing && params.flags.force) {
16550
- process$1.stderr.write("Replacing saved Primitive CLI credentials after signup because --force was set.\n");
16563
+ process$1.stderr.write(`Replacing saved Primitive CLI credentials after ${copy.actionNoun} because --force was set.\n`);
16551
16564
  return;
16552
16565
  }
16553
16566
  if (!existing) return;
@@ -16563,9 +16576,9 @@ async function checkExistingCredentials(params) {
16563
16576
  }
16564
16577
  if (existingStatus.status === "blocked") {
16565
16578
  writeErrorWithHints(existingStatus.payload);
16566
- throw cliError(existingStatus.message);
16579
+ throw cliError$1(existingStatus.message);
16567
16580
  }
16568
- throw cliError(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before creating a new account.`);
16581
+ throw cliError$1(`Already logged in${existing.org_name ? ` for ${existing.org_name}` : ""}. Run \`primitive logout\` before ${copy.actionGerund}.`);
16569
16582
  }
16570
16583
  function saveSignupCredentials(params) {
16571
16584
  saveCliCredentials(params.configDir, {
@@ -16582,23 +16595,24 @@ function saveSignupCredentials(params) {
16582
16595
  token_type: params.signup.token_type
16583
16596
  });
16584
16597
  }
16585
- function writeStartInstructions(start) {
16598
+ function writeStartInstructions(start, copy = DEFAULT_SIGNUP_COMMAND_COPY) {
16586
16599
  process$1.stderr.write(`Sent a ${start.verification_code_length}-digit verification code to ${start.email}.\n`);
16587
16600
  process$1.stderr.write(`The code expires in ${formatSignupSeconds(start.expires_in)}.\n`);
16588
- process$1.stderr.write(`Run \`primitive signup confirm ${start.email} <code>\` to finish.\n`);
16601
+ process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(start.email)}\` to finish.\n`);
16589
16602
  }
16590
16603
  async function startSignup(params) {
16604
+ const copy = params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY;
16591
16605
  const existingPending = loadPendingAgentSignup(params.configDir, params.apiBaseUrl1);
16592
16606
  if (existingPending && !params.flags.force) {
16593
16607
  if (normalizeEmail(existingPending.email) === normalizeEmail(params.email)) {
16594
- process$1.stderr.write(`Continuing pending Primitive signup for ${existingPending.email}.\n`);
16595
- process$1.stderr.write(`Run \`primitive signup confirm ${existingPending.email} <code>\` to finish, or \`primitive signup resend ${existingPending.email}\` to send a new code.\n`);
16608
+ process$1.stderr.write(`Continuing pending Primitive ${copy.actionNoun} for ${existingPending.email}.\n`);
16609
+ process$1.stderr.write(`Run \`primitive ${copy.confirmCommand(existingPending.email)}\` to finish, or \`primitive ${copy.resendCommand(existingPending.email)}\` to send a new code.\n`);
16596
16610
  return {
16597
16611
  pending: existingPending,
16598
16612
  started: false
16599
16613
  };
16600
16614
  }
16601
- throw cliError(`Pending signup is for ${existingPending.email}. Run \`primitive signup ${params.email} --force\` to replace it.`);
16615
+ throw cliError$1(`Pending ${copy.actionNoun} is for ${existingPending.email}. Run \`primitive ${copy.startCommand(params.email)} --force\` to replace it.`);
16602
16616
  }
16603
16617
  if (params.flags.force) deletePendingAgentSignup(params.configDir);
16604
16618
  const promptRequiredFn = params.deps.promptRequired ?? promptRequired;
@@ -16618,10 +16632,10 @@ async function startSignup(params) {
16618
16632
  });
16619
16633
  if (started.error) {
16620
16634
  writeErrorWithHints(extractErrorPayload(started.error));
16621
- throw cliError("Could not start Primitive agent signup.");
16635
+ throw cliError$1("Could not start Primitive agent signup.");
16622
16636
  }
16623
16637
  const startResult = unwrapData(started.data);
16624
- if (!startResult) throw cliError("Primitive API returned an empty agent signup response.");
16638
+ if (!startResult) throw cliError$1("Primitive API returned an empty agent signup response.");
16625
16639
  return {
16626
16640
  pending: savePendingAgentSignup(params.configDir, startResult, params.apiBaseUrl1),
16627
16641
  started: true
@@ -16659,7 +16673,7 @@ async function resendVerificationCode(params) {
16659
16673
  }
16660
16674
  if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(params.configDir);
16661
16675
  writeErrorWithHints(payload);
16662
- throw cliError("Could not resend Primitive agent signup verification email.");
16676
+ throw cliError$1("Could not resend Primitive agent signup verification email.");
16663
16677
  }
16664
16678
  async function runSignupStartWithCredentialLock(params) {
16665
16679
  const { configDir, flags } = params;
@@ -16669,6 +16683,7 @@ async function runSignupStartWithCredentialLock(params) {
16669
16683
  await checkExistingCredentials({
16670
16684
  apiBaseUrl1: flags["api-base-url-1"],
16671
16685
  configDir,
16686
+ copy: params.copy,
16672
16687
  deps,
16673
16688
  flags
16674
16689
  });
@@ -16680,11 +16695,12 @@ async function runSignupStartWithCredentialLock(params) {
16680
16695
  apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
16681
16696
  apiClient,
16682
16697
  configDir,
16698
+ copy: params.copy,
16683
16699
  deps,
16684
16700
  email,
16685
16701
  flags
16686
16702
  });
16687
- if (start.started) writeStartInstructions(start.pending);
16703
+ if (start.started) writeStartInstructions(start.pending, params.copy);
16688
16704
  }
16689
16705
  async function runSignupConfirmWithCredentialLock(params) {
16690
16706
  const { configDir, flags } = params;
@@ -16692,6 +16708,7 @@ async function runSignupConfirmWithCredentialLock(params) {
16692
16708
  if (!params.skipExistingCredentialCheck) await checkExistingCredentials({
16693
16709
  apiBaseUrl1: flags["api-base-url-1"],
16694
16710
  configDir,
16711
+ copy: params.copy,
16695
16712
  deps,
16696
16713
  flags
16697
16714
  });
@@ -16702,6 +16719,7 @@ async function runSignupConfirmWithCredentialLock(params) {
16702
16719
  const apiBaseUrl1 = requestConfig.resolvedApiBaseUrl1;
16703
16720
  const pending = requirePendingSignupForEmail({
16704
16721
  apiBaseUrl1,
16722
+ copy: params.copy,
16705
16723
  configDir,
16706
16724
  email: params.email
16707
16725
  });
@@ -16716,7 +16734,7 @@ async function runSignupConfirmWithCredentialLock(params) {
16716
16734
  });
16717
16735
  if (verified.data) {
16718
16736
  const signup = unwrapData(verified.data);
16719
- if (!signup) throw cliError("Primitive API returned an empty agent signup verification response.");
16737
+ if (!signup) throw cliError$1("Primitive API returned an empty agent signup verification response.");
16720
16738
  saveSignupCredentials({
16721
16739
  apiBaseUrl1,
16722
16740
  configDir,
@@ -16730,10 +16748,10 @@ async function runSignupConfirmWithCredentialLock(params) {
16730
16748
  }
16731
16749
  const payload = extractErrorPayload(verified.error);
16732
16750
  const code = extractErrorCode(payload);
16733
- if (code === INVALID_VERIFICATION_CODE) throw cliError("Invalid verification code. Try again or run signup resend.");
16751
+ if (code === INVALID_VERIFICATION_CODE) throw cliError$1(`Invalid verification code. Try again or run ${(params.copy ?? DEFAULT_SIGNUP_COMMAND_COPY).resendCommand(params.email)}.`);
16734
16752
  if (code === EXPIRED_TOKEN || code === INVALID_SIGNUP_TOKEN) deletePendingAgentSignup(configDir);
16735
16753
  writeErrorWithHints(payload);
16736
- throw cliError("Primitive agent signup failed while verifying the account.");
16754
+ throw cliError$1("Primitive agent signup failed while verifying the account.");
16737
16755
  }
16738
16756
  async function runSignupResendWithCredentialLock(params) {
16739
16757
  const deps = params.deps ?? {};
@@ -16743,6 +16761,7 @@ async function runSignupResendWithCredentialLock(params) {
16743
16761
  });
16744
16762
  const pending = requirePendingSignupForEmail({
16745
16763
  apiBaseUrl1: requestConfig.resolvedApiBaseUrl1,
16764
+ copy: params.copy,
16746
16765
  configDir: params.configDir,
16747
16766
  email: params.email
16748
16767
  });
@@ -16857,7 +16876,7 @@ var SignupCommand = class SignupCommand extends Command {
16857
16876
  try {
16858
16877
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
16859
16878
  } catch (error) {
16860
- throw cliError(error instanceof Error ? error.message : String(error));
16879
+ throw cliError$1(error instanceof Error ? error.message : String(error));
16861
16880
  }
16862
16881
  try {
16863
16882
  await runSignupStartWithCredentialLock({
@@ -16902,7 +16921,7 @@ var SignupConfirmCommand = class SignupConfirmCommand extends Command {
16902
16921
  try {
16903
16922
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
16904
16923
  } catch (error) {
16905
- throw cliError(error instanceof Error ? error.message : String(error));
16924
+ throw cliError$1(error instanceof Error ? error.message : String(error));
16906
16925
  }
16907
16926
  try {
16908
16927
  await runSignupConfirmWithCredentialLock({
@@ -16935,7 +16954,7 @@ var SignupResendCommand = class SignupResendCommand extends Command {
16935
16954
  try {
16936
16955
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
16937
16956
  } catch (error) {
16938
- throw cliError(error instanceof Error ? error.message : String(error));
16957
+ throw cliError$1(error instanceof Error ? error.message : String(error));
16939
16958
  }
16940
16959
  try {
16941
16960
  await runSignupResendWithCredentialLock({
@@ -16959,7 +16978,7 @@ var SignupInteractiveCommand = class SignupInteractiveCommand extends Command {
16959
16978
  try {
16960
16979
  releaseCredentialsLock = acquireCliCredentialsLock(this.config.configDir);
16961
16980
  } catch (error) {
16962
- throw cliError(error instanceof Error ? error.message : String(error));
16981
+ throw cliError$1(error instanceof Error ? error.message : String(error));
16963
16982
  }
16964
16983
  try {
16965
16984
  await runSignupInteractiveWithCredentialLock({
@@ -16972,6 +16991,167 @@ var SignupInteractiveCommand = class SignupInteractiveCommand extends Command {
16972
16991
  }
16973
16992
  };
16974
16993
  //#endregion
16994
+ //#region src/oclif/commands/signin.ts
16995
+ function cliError(message) {
16996
+ return new Errors.CLIError(message, { exit: 1 });
16997
+ }
16998
+ const SIGNIN_OTP_COPY = {
16999
+ actionNoun: "sign-in",
17000
+ actionGerund: "signing in",
17001
+ confirmCommand: (email) => `signin otp confirm ${email} <code>`,
17002
+ resendCommand: (email) => `signin otp resend ${email}`,
17003
+ startCommand: (email) => `signin otp ${email}`
17004
+ };
17005
+ function acquireCredentialsLock(configDir) {
17006
+ try {
17007
+ return acquireCliCredentialsLock(configDir);
17008
+ } catch (error) {
17009
+ throw cliError(error instanceof Error ? error.message : String(error));
17010
+ }
17011
+ }
17012
+ function commonOtpStartFlags() {
17013
+ return {
17014
+ "accept-terms": Flags.boolean({ description: "Confirm acceptance of Primitive's Terms of Service and Privacy Policy" }),
17015
+ "api-base-url-1": Flags.string({
17016
+ description: "Override the primary API base URL. Internal testing only; not documented to customers.",
17017
+ env: "PRIMITIVE_API_BASE_URL_1",
17018
+ hidden: true
17019
+ }),
17020
+ "device-name": Flags.string({ description: "Device name used for the created CLI OAuth session" }),
17021
+ force: Flags.boolean({
17022
+ char: "f",
17023
+ description: "Replace saved credentials or pending sign-in state when needed"
17024
+ }),
17025
+ "signup-code": Flags.string({
17026
+ description: "Signup code required to start OTP sign-in",
17027
+ env: "PRIMITIVE_SIGNUP_CODE"
17028
+ })
17029
+ };
17030
+ }
17031
+ var SigninCommand = class extends LoginCommand {
17032
+ static description = `Sign in to an existing Primitive account with browser approval and save an org-scoped OAuth session locally.
17033
+
17034
+ This is the canonical sign-in command. It defaults to the same browser approval flow as \`primitive signin browser\`. For email-code sign-in, use \`primitive signin otp <email> --signup-code <code>\`, then \`primitive signin otp confirm <email> <code>\`. For new account creation, use \`primitive signup <email>\`.`;
17035
+ static summary = "Sign in to an existing account";
17036
+ static examples = [
17037
+ "<%= config.bin %> signin",
17038
+ "<%= config.bin %> signin browser",
17039
+ "<%= config.bin %> signin --no-browser",
17040
+ "<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms",
17041
+ "<%= config.bin %> signin otp confirm user@example.com 123456"
17042
+ ];
17043
+ retryCommand() {
17044
+ return "signin";
17045
+ }
17046
+ };
17047
+ var SigninBrowserCommand = class extends LoginCommand {
17048
+ static description = "Sign in to an existing Primitive account by opening Primitive in your browser and saving an org-scoped OAuth session locally.";
17049
+ static summary = "Sign in with browser approval";
17050
+ static examples = [
17051
+ "<%= config.bin %> signin browser",
17052
+ "<%= config.bin %> signin browser --device-name work-laptop",
17053
+ "<%= config.bin %> signin browser --no-browser",
17054
+ "<%= config.bin %> signin browser --force"
17055
+ ];
17056
+ retryCommand() {
17057
+ return "signin browser";
17058
+ }
17059
+ };
17060
+ var SigninOtpCommand = class SigninOtpCommand extends Command {
17061
+ static args = { email: Args.string({
17062
+ description: "Email address to sign in with",
17063
+ required: false
17064
+ }) };
17065
+ static description = "Start email-code sign-in using Primitive's signup/auth OTP flow, send a verification code, and save the pending token locally. Requires a signup code.";
17066
+ static summary = "Start OTP sign-in";
17067
+ static examples = ["<%= config.bin %> signin otp user@example.com --signup-code invite-code --accept-terms", "<%= config.bin %> signin otp confirm user@example.com 123456"];
17068
+ static flags = commonOtpStartFlags();
17069
+ async run() {
17070
+ const { args, flags } = await this.parse(SigninOtpCommand);
17071
+ const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
17072
+ try {
17073
+ await runSignupStartWithCredentialLock({
17074
+ configDir: this.config.configDir,
17075
+ copy: SIGNIN_OTP_COPY,
17076
+ email: args.email,
17077
+ flags
17078
+ });
17079
+ } finally {
17080
+ releaseCredentialsLock();
17081
+ }
17082
+ }
17083
+ };
17084
+ var SigninOtpConfirmCommand = class SigninOtpConfirmCommand extends Command {
17085
+ static args = {
17086
+ email: Args.string({
17087
+ description: "Email address used to start OTP sign-in",
17088
+ required: true
17089
+ }),
17090
+ code: Args.string({
17091
+ description: "Verification code from the sign-in email",
17092
+ required: true
17093
+ })
17094
+ };
17095
+ static description = "Confirm a pending OTP sign-in, create an OAuth session, and save CLI credentials locally.";
17096
+ static summary = "Confirm OTP sign-in";
17097
+ static examples = ["<%= config.bin %> signin otp confirm user@example.com 123456", "<%= config.bin %> signin otp confirm user@example.com 123456 --org-id 00000000-0000-4000-8000-000000000000"];
17098
+ static flags = {
17099
+ "api-base-url-1": Flags.string({
17100
+ description: "Override the primary API base URL. Internal testing only; not documented to customers.",
17101
+ env: "PRIMITIVE_API_BASE_URL_1",
17102
+ hidden: true
17103
+ }),
17104
+ force: Flags.boolean({
17105
+ char: "f",
17106
+ description: "Replace saved credentials after verification"
17107
+ }),
17108
+ "org-id": Flags.string({ description: "Workspace id to target when the email belongs to multiple workspaces" })
17109
+ };
17110
+ async run() {
17111
+ const { args, flags } = await this.parse(SigninOtpConfirmCommand);
17112
+ const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
17113
+ try {
17114
+ await runSignupConfirmWithCredentialLock({
17115
+ code: args.code,
17116
+ configDir: this.config.configDir,
17117
+ copy: SIGNIN_OTP_COPY,
17118
+ email: args.email,
17119
+ flags
17120
+ });
17121
+ } finally {
17122
+ releaseCredentialsLock();
17123
+ }
17124
+ }
17125
+ };
17126
+ var SigninOtpResendCommand = class SigninOtpResendCommand extends Command {
17127
+ static args = { email: Args.string({
17128
+ description: "Email address used to start OTP sign-in",
17129
+ required: true
17130
+ }) };
17131
+ static description = "Resend the verification code for a pending OTP sign-in.";
17132
+ static summary = "Resend OTP sign-in code";
17133
+ static examples = ["<%= config.bin %> signin otp resend user@example.com"];
17134
+ static flags = { "api-base-url-1": Flags.string({
17135
+ description: "Override the primary API base URL. Internal testing only; not documented to customers.",
17136
+ env: "PRIMITIVE_API_BASE_URL_1",
17137
+ hidden: true
17138
+ }) };
17139
+ async run() {
17140
+ const { args, flags } = await this.parse(SigninOtpResendCommand);
17141
+ const releaseCredentialsLock = acquireCredentialsLock(this.config.configDir);
17142
+ try {
17143
+ await runSignupResendWithCredentialLock({
17144
+ configDir: this.config.configDir,
17145
+ copy: SIGNIN_OTP_COPY,
17146
+ email: args.email,
17147
+ flags
17148
+ });
17149
+ } finally {
17150
+ releaseCredentialsLock();
17151
+ }
17152
+ }
17153
+ };
17154
+ //#endregion
16975
17155
  //#region src/oclif/commands/whoami.ts
16976
17156
  var WhoamiCommand = class WhoamiCommand extends Command {
16977
17157
  static description = `Print the account currently authenticated by saved OAuth credentials or an explicit API key. Useful as a credentials smoke test: confirms auth is live and shows which account it belongs to.`;
@@ -17243,6 +17423,11 @@ const COMMANDS = {
17243
17423
  reply: ReplyCommand,
17244
17424
  chat: ChatCommand,
17245
17425
  login: LoginCommand,
17426
+ signin: SigninCommand,
17427
+ "signin:browser": SigninBrowserCommand,
17428
+ "signin:otp": SigninOtpCommand,
17429
+ "signin:otp:confirm": SigninOtpConfirmCommand,
17430
+ "signin:otp:resend": SigninOtpResendCommand,
17246
17431
  signup: SignupCommand,
17247
17432
  "signup:confirm": SignupConfirmCommand,
17248
17433
  "signup:interactive": SignupInteractiveCommand,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitivedotdev/cli",
3
- "version": "0.31.2",
3
+ "version": "0.31.3",
4
4
  "description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -46,6 +46,9 @@
46
46
  "sending": {
47
47
  "description": "Send outbound emails. Prefer `primitive send` for fresh sends and `primitive reply --id <inbound-id>` for replies; use `primitive sending list`, `primitive sending get`, and `primitive sending permissions` for outbound history and permissions."
48
48
  },
49
+ "signin": {
50
+ "description": "Sign in to an existing Primitive account"
51
+ },
49
52
  "sent": {
50
53
  "description": "Short aliases for outbound sent-email history: `primitive sent list` and `primitive sent get`."
51
54
  },