@tolinax/ayoune-cli 2026.3.0 → 2026.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/data/contextSlots.js +189 -0
  2. package/data/modelsAndRights.js +56 -0
  3. package/data/modules.js +16 -0
  4. package/lib/api/apiCallHandler.js +6 -2
  5. package/lib/api/apiClient.js +9 -1
  6. package/lib/api/auditCallHandler.js +2 -2
  7. package/lib/api/handleAPIError.js +20 -18
  8. package/lib/api/login.js +3 -3
  9. package/lib/api/searchClient.js +119 -0
  10. package/lib/commands/createAccessCommand.js +126 -0
  11. package/lib/commands/createActionsCommand.js +40 -9
  12. package/lib/commands/createAiCommand.js +17 -17
  13. package/lib/commands/createAliasCommand.js +4 -6
  14. package/lib/commands/createAuditCommand.js +5 -9
  15. package/lib/commands/createBatchCommand.js +15 -28
  16. package/lib/commands/createCompletionsCommand.js +6 -3
  17. package/lib/commands/createConfigCommand.js +8 -14
  18. package/lib/commands/createContextCommand.js +163 -0
  19. package/lib/commands/createCopyCommand.js +4 -7
  20. package/lib/commands/createCreateCommand.js +4 -7
  21. package/lib/commands/createDeleteCommand.js +4 -6
  22. package/lib/commands/createDeployCommand.js +31 -55
  23. package/lib/commands/createDescribeCommand.js +12 -10
  24. package/lib/commands/createEditCommand.js +13 -8
  25. package/lib/commands/createEventsCommand.js +4 -4
  26. package/lib/commands/createExecCommand.js +65 -35
  27. package/lib/commands/createExportCommand.js +21 -24
  28. package/lib/commands/createGetCommand.js +13 -14
  29. package/lib/commands/createJobsCommand.js +8 -13
  30. package/lib/commands/createListCommand.js +13 -14
  31. package/lib/commands/createLoginCommand.js +16 -4
  32. package/lib/commands/createLogoutCommand.js +2 -2
  33. package/lib/commands/createModulesCommand.js +16 -19
  34. package/lib/commands/createMonitorCommand.js +9 -16
  35. package/lib/commands/createPermissionsCommand.js +10 -18
  36. package/lib/commands/createProgram.js +47 -21
  37. package/lib/commands/createSearchCommand.js +219 -69
  38. package/lib/commands/createSelfHostUpdateCommand.js +166 -0
  39. package/lib/commands/createServicesCommand.js +5 -8
  40. package/lib/commands/createSetupCommand.js +305 -0
  41. package/lib/commands/createStatusCommand.js +147 -0
  42. package/lib/commands/createStorageCommand.js +2 -3
  43. package/lib/commands/createStreamCommand.js +4 -4
  44. package/lib/commands/createSyncCommand.js +5 -8
  45. package/lib/commands/createTemplateCommand.js +9 -16
  46. package/lib/commands/createUpdateCommand.js +12 -15
  47. package/lib/commands/createUsersCommand.js +21 -31
  48. package/lib/commands/createWebhooksCommand.js +15 -22
  49. package/lib/commands/createWhoAmICommand.js +8 -6
  50. package/lib/helpers/cliError.js +24 -0
  51. package/lib/helpers/config.js +1 -0
  52. package/lib/helpers/configLoader.js +6 -0
  53. package/lib/helpers/contextInjector.js +65 -0
  54. package/lib/helpers/contextResolver.js +70 -0
  55. package/lib/helpers/contextStore.js +46 -0
  56. package/lib/helpers/handleResponseFormatOptions.js +59 -10
  57. package/lib/helpers/logo.js +48 -0
  58. package/lib/helpers/resolveCollectionArgs.js +36 -0
  59. package/lib/helpers/sanitizeFields.js +18 -0
  60. package/lib/helpers/secureStorage.js +72 -0
  61. package/lib/helpers/tokenPayload.js +21 -0
  62. package/lib/helpers/updateNotifier.js +49 -0
  63. package/lib/models/getModuleFromCollection.js +4 -1
  64. package/lib/operations/handleCopySingleOperation.js +10 -2
  65. package/lib/operations/handleCreateSingleOperation.js +3 -0
  66. package/lib/operations/handleDescribeSingleOperation.js +23 -0
  67. package/lib/operations/handleGetOperation.js +9 -3
  68. package/lib/operations/handleListOperation.js +14 -10
  69. package/lib/prompts/promptModule.js +9 -6
  70. package/package.json +163 -158
@@ -13,13 +13,19 @@ import { aYOUneModules } from "../../data/modules.js";
13
13
  import { getModelsInModules } from "../models/getModelsInModules.js";
14
14
  import { apiCallHandler } from "../api/apiCallHandler.js";
15
15
  import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
16
+ import { isSuperUser } from "../helpers/tokenPayload.js";
16
17
  import { spinner } from "../../index.js";
17
18
  import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
19
+ import { cliError } from "../helpers/cliError.js";
18
20
  const DIRECT_OPERATIONS = ["list", "get", "create", "delete"];
19
21
  function resolveModule(input) {
20
22
  const lower = input.toLowerCase();
21
23
  const match = aYOUneModules.find((m) => m.module === lower || m.label.toLowerCase() === lower);
22
- return match ? match.module : null;
24
+ if (!match)
25
+ return null;
26
+ if (match.superuserOnly && !isSuperUser())
27
+ return null;
28
+ return match.module;
23
29
  }
24
30
  function resolveCollection(module, input) {
25
31
  const lower = input.toLowerCase();
@@ -55,15 +61,13 @@ Examples:
55
61
  if (moduleArg) {
56
62
  const resolved = resolveModule(moduleArg);
57
63
  if (!resolved) {
58
- spinner.error({ text: `Unknown module: ${moduleArg}` });
59
- process.exit(EXIT_MISUSE);
64
+ cliError(`Unknown module: ${moduleArg}`, EXIT_MISUSE);
60
65
  }
61
66
  module = resolved;
62
67
  }
63
68
  else {
64
69
  if (!process.stdin.isTTY) {
65
- spinner.error({ text: "The modules command requires an interactive terminal" });
66
- process.exit(EXIT_MISUSE);
70
+ cliError("The modules command requires an interactive terminal", EXIT_MISUSE);
67
71
  }
68
72
  module = await promptModule();
69
73
  }
@@ -72,15 +76,13 @@ Examples:
72
76
  if (collectionArg) {
73
77
  const resolved = resolveCollection(module, collectionArg);
74
78
  if (!resolved) {
75
- spinner.error({ text: `Unknown collection: ${collectionArg} in module ${module}` });
76
- process.exit(EXIT_MISUSE);
79
+ cliError(`Unknown collection: ${collectionArg} in module ${module}`, EXIT_MISUSE);
77
80
  }
78
81
  collection = resolved;
79
82
  }
80
83
  else {
81
84
  if (!process.stdin.isTTY) {
82
- spinner.error({ text: "Missing required argument: collection" });
83
- process.exit(EXIT_MISUSE);
85
+ cliError("Missing required argument: collection", EXIT_MISUSE);
84
86
  }
85
87
  collection = await promptCollectionInModule(module);
86
88
  }
@@ -95,8 +97,7 @@ Examples:
95
97
  }
96
98
  if (op === "get") {
97
99
  if (!subjectArg) {
98
- spinner.error({ text: "Missing required argument: id" });
99
- process.exit(EXIT_MISUSE);
100
+ cliError("Missing required argument: id", EXIT_MISUSE);
100
101
  }
101
102
  spinner.start({ text: `Getting ${collection} ${subjectArg}...`, color: "magenta" });
102
103
  const res = await apiCallHandler(module, `${collection.toLowerCase()}/${subjectArg}`, "get", null, {
@@ -110,16 +111,14 @@ Examples:
110
111
  }
111
112
  if (op === "create") {
112
113
  if (!subjectArg) {
113
- spinner.error({ text: "Missing required argument: name/subject" });
114
- process.exit(EXIT_MISUSE);
114
+ cliError("Missing required argument: name/subject", EXIT_MISUSE);
115
115
  }
116
116
  await handleCreateSingleOperation(module, collection, subjectArg, opts);
117
117
  return;
118
118
  }
119
119
  if (op === "delete") {
120
120
  if (!subjectArg) {
121
- spinner.error({ text: "Missing required argument: id" });
122
- process.exit(EXIT_MISUSE);
121
+ cliError("Missing required argument: id", EXIT_MISUSE);
123
122
  }
124
123
  await handleDeleteSingleOperation(module, collection, subjectArg, opts);
125
124
  return;
@@ -127,8 +126,7 @@ Examples:
127
126
  }
128
127
  // ─── Interactive mode (no operation provided) ────────
129
128
  if (!process.stdin.isTTY) {
130
- spinner.error({ text: "Interactive mode requires a terminal. Use: ay m <module> <collection> <operation> [subject]" });
131
- process.exit(EXIT_MISUSE);
129
+ cliError("Interactive mode requires a terminal. Use: ay m <module> <collection> <operation> [subject]", EXIT_MISUSE);
132
130
  }
133
131
  const operation = await promptOperation();
134
132
  let entry = "";
@@ -143,8 +141,7 @@ Examples:
143
141
  await handleCollectionOperation(module, collection, entry, opts);
144
142
  }
145
143
  catch (e) {
146
- spinner.error({ text: e.message || "An unexpected error occurred" });
147
- process.exit(EXIT_GENERAL_ERROR);
144
+ cliError(e.message || "An unexpected error occurred", EXIT_GENERAL_ERROR);
148
145
  }
149
146
  });
150
147
  }
@@ -3,6 +3,7 @@ import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOpti
3
3
  import { saveFile } from "../helpers/saveFile.js";
4
4
  import { spinner } from "../../index.js";
5
5
  import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
6
+ import { cliError } from "../helpers/cliError.js";
6
7
  export function createMonitorCommand(program) {
7
8
  const monitor = program
8
9
  .command("monitor")
@@ -74,8 +75,7 @@ Examples:
74
75
  await saveFile(`monitor-logs-${logType}`, opts, res);
75
76
  }
76
77
  catch (e) {
77
- spinner.error({ text: e.message || "Failed to fetch logs" });
78
- process.exit(EXIT_GENERAL_ERROR);
78
+ cliError(e.message || "Failed to fetch logs", EXIT_GENERAL_ERROR);
79
79
  }
80
80
  });
81
81
  // ay monitor alerts — command group
@@ -125,8 +125,7 @@ Examples:
125
125
  await saveFile("monitor-alerts", opts, res);
126
126
  }
127
127
  catch (e) {
128
- spinner.error({ text: e.message || "Failed to fetch alerts" });
129
- process.exit(EXIT_GENERAL_ERROR);
128
+ cliError(e.message || "Failed to fetch alerts", EXIT_GENERAL_ERROR);
130
129
  }
131
130
  });
132
131
  // ay monitor alerts ack <id>
@@ -146,8 +145,7 @@ Examples:
146
145
  spinner.stop();
147
146
  }
148
147
  catch (e) {
149
- spinner.error({ text: e.message || "Failed to acknowledge alert" });
150
- process.exit(EXIT_GENERAL_ERROR);
148
+ cliError(e.message || "Failed to acknowledge alert", EXIT_GENERAL_ERROR);
151
149
  }
152
150
  });
153
151
  // ay monitor alerts resolve <id>
@@ -166,8 +164,7 @@ Examples:
166
164
  spinner.stop();
167
165
  }
168
166
  catch (e) {
169
- spinner.error({ text: e.message || "Failed to resolve alert" });
170
- process.exit(EXIT_GENERAL_ERROR);
167
+ cliError(e.message || "Failed to resolve alert", EXIT_GENERAL_ERROR);
171
168
  }
172
169
  });
173
170
  // ay monitor sessions
@@ -193,8 +190,7 @@ Examples:
193
190
  await saveFile("monitor-sessions", opts, res);
194
191
  }
195
192
  catch (e) {
196
- spinner.error({ text: e.message || "Failed to fetch sessions" });
197
- process.exit(EXIT_GENERAL_ERROR);
193
+ cliError(e.message || "Failed to fetch sessions", EXIT_GENERAL_ERROR);
198
194
  }
199
195
  });
200
196
  // ay monitor checks
@@ -220,8 +216,7 @@ Examples:
220
216
  await saveFile("monitor-checks", opts, res);
221
217
  }
222
218
  catch (e) {
223
- spinner.error({ text: e.message || "Failed to fetch checks" });
224
- process.exit(EXIT_GENERAL_ERROR);
219
+ cliError(e.message || "Failed to fetch checks", EXIT_GENERAL_ERROR);
225
220
  }
226
221
  });
227
222
  // ay monitor activeusers
@@ -248,8 +243,7 @@ Examples:
248
243
  await saveFile("monitor-activeusers", opts, res);
249
244
  }
250
245
  catch (e) {
251
- spinner.error({ text: e.message || "Failed to fetch active users" });
252
- process.exit(EXIT_GENERAL_ERROR);
246
+ cliError(e.message || "Failed to fetch active users", EXIT_GENERAL_ERROR);
253
247
  }
254
248
  });
255
249
  // ay monitor pagestats
@@ -276,8 +270,7 @@ Examples:
276
270
  await saveFile("monitor-pagestats", opts, res);
277
271
  }
278
272
  catch (e) {
279
- spinner.error({ text: e.message || "Failed to fetch page stats" });
280
- process.exit(EXIT_GENERAL_ERROR);
273
+ cliError(e.message || "Failed to fetch page stats", EXIT_GENERAL_ERROR);
281
274
  }
282
275
  });
283
276
  }
@@ -3,6 +3,7 @@ import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOpti
3
3
  import { saveFile } from "../helpers/saveFile.js";
4
4
  import { spinner } from "../../index.js";
5
5
  import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
6
+ import { cliError } from "../helpers/cliError.js";
6
7
  export function createPermissionsCommand(program) {
7
8
  const perms = program
8
9
  .command("permissions")
@@ -43,8 +44,7 @@ export function createPermissionsCommand(program) {
43
44
  await saveFile("permission-requests", opts, res);
44
45
  }
45
46
  catch (e) {
46
- spinner.error({ text: e.message || "Failed to list permission requests" });
47
- process.exit(EXIT_GENERAL_ERROR);
47
+ cliError(e.message || "Failed to list permission requests", EXIT_GENERAL_ERROR);
48
48
  }
49
49
  });
50
50
  // ay permissions requests approve <id>
@@ -61,8 +61,7 @@ export function createPermissionsCommand(program) {
61
61
  spinner.stop();
62
62
  }
63
63
  catch (e) {
64
- spinner.error({ text: e.message || "Failed to approve request" });
65
- process.exit(EXIT_GENERAL_ERROR);
64
+ cliError(e.message || "Failed to approve request", EXIT_GENERAL_ERROR);
66
65
  }
67
66
  });
68
67
  // ay permissions requests reject <id>
@@ -83,8 +82,7 @@ export function createPermissionsCommand(program) {
83
82
  spinner.stop();
84
83
  }
85
84
  catch (e) {
86
- spinner.error({ text: e.message || "Failed to reject request" });
87
- process.exit(EXIT_GENERAL_ERROR);
85
+ cliError(e.message || "Failed to reject request", EXIT_GENERAL_ERROR);
88
86
  }
89
87
  });
90
88
  // ay permissions requests create
@@ -103,8 +101,7 @@ export function createPermissionsCommand(program) {
103
101
  body = JSON.parse(opts.body);
104
102
  }
105
103
  catch (_a) {
106
- spinner.error({ text: "Invalid JSON in --body" });
107
- process.exit(EXIT_MISUSE);
104
+ cliError("Invalid JSON in --body", EXIT_MISUSE);
108
105
  }
109
106
  }
110
107
  else if (opts.right) {
@@ -113,8 +110,7 @@ export function createPermissionsCommand(program) {
113
110
  body.reason = opts.reason;
114
111
  }
115
112
  if (!body) {
116
- spinner.error({ text: "Provide request via --body or --right" });
117
- process.exit(EXIT_MISUSE);
113
+ cliError("Provide request via --body or --right", EXIT_MISUSE);
118
114
  }
119
115
  spinner.start({ text: "Creating permission request...", color: "magenta" });
120
116
  const res = await apiCallHandler("config", "permissionrequests", "post", body, {
@@ -125,8 +121,7 @@ export function createPermissionsCommand(program) {
125
121
  spinner.stop();
126
122
  }
127
123
  catch (e) {
128
- spinner.error({ text: e.message || "Failed to create permission request" });
129
- process.exit(EXIT_GENERAL_ERROR);
124
+ cliError(e.message || "Failed to create permission request", EXIT_GENERAL_ERROR);
130
125
  }
131
126
  });
132
127
  // ── USER RIGHTS ────────────────────────────────────────
@@ -163,8 +158,7 @@ export function createPermissionsCommand(program) {
163
158
  await saveFile("user-rights", opts, res);
164
159
  }
165
160
  catch (e) {
166
- spinner.error({ text: e.message || "Failed to list user rights" });
167
- process.exit(EXIT_GENERAL_ERROR);
161
+ cliError(e.message || "Failed to list user rights", EXIT_GENERAL_ERROR);
168
162
  }
169
163
  });
170
164
  // ay permissions rights get <id>
@@ -184,8 +178,7 @@ export function createPermissionsCommand(program) {
184
178
  spinner.stop();
185
179
  }
186
180
  catch (e) {
187
- spinner.error({ text: e.message || "Failed to get user right" });
188
- process.exit(EXIT_GENERAL_ERROR);
181
+ cliError(e.message || "Failed to get user right", EXIT_GENERAL_ERROR);
189
182
  }
190
183
  });
191
184
  // ── AUDIT (ENHANCED) ──────────────────────────────────
@@ -234,8 +227,7 @@ Examples:
234
227
  await saveFile("permissions-audit", opts, res);
235
228
  }
236
229
  catch (e) {
237
- spinner.error({ text: e.message || "Failed to fetch audit logs" });
238
- process.exit(EXIT_GENERAL_ERROR);
230
+ cliError(e.message || "Failed to fetch audit logs", EXIT_GENERAL_ERROR);
239
231
  }
240
232
  });
241
233
  }
@@ -1,5 +1,5 @@
1
1
  //Defines the main program structure for command line interface
2
- import { Option } from "commander";
2
+ import { Command, Option } from "commander";
3
3
  import chalk from "chalk";
4
4
  import path from "path";
5
5
  import os from "os";
@@ -26,7 +26,8 @@ import { createExecCommand } from "./createExecCommand.js";
26
26
  import { createAiCommand } from "./createAiCommand.js";
27
27
  import { enableDebug } from "../api/apiClient.js";
28
28
  import { enableDryRun } from "../api/apiCallHandler.js";
29
- import { enableJsonErrors } from "../api/handleAPIError.js";
29
+ import { setJsonErrorsEnabled } from "../helpers/cliError.js";
30
+ import { disableContext } from "../helpers/contextInjector.js";
30
31
  import { createServicesCommand } from "./createServicesCommand.js";
31
32
  import { createDeployCommand } from "./createDeployCommand.js";
32
33
  import { createMonitorCommand } from "./createMonitorCommand.js";
@@ -41,12 +42,22 @@ import { createUsersCommand } from "./createUsersCommand.js";
41
42
  import { createSyncCommand } from "./createSyncCommand.js";
42
43
  import { createPermissionsCommand } from "./createPermissionsCommand.js";
43
44
  import { createTemplateCommand } from "./createTemplateCommand.js";
44
- import { localStorage } from "../helpers/localStorage.js";
45
+ import { createSetupCommand } from "./createSetupCommand.js";
46
+ import { createStatusCommand } from "./createStatusCommand.js";
47
+ import { createSelfHostUpdateCommand } from "./createSelfHostUpdateCommand.js";
48
+ import { createContextCommand } from "./createContextCommand.js";
49
+ import { createAccessCommand } from "./createAccessCommand.js";
50
+ import { secureStorage } from "../helpers/secureStorage.js";
45
51
  import { login } from "../api/login.js";
46
52
  import { loadConfig } from "../helpers/configLoader.js";
53
+ import { getLogo, getDescription, BRAND_BLUE } from "../helpers/logo.js";
54
+ import { checkForUpdates } from "../helpers/updateNotifier.js";
55
+ import { createRequire } from "module";
56
+ const require = createRequire(import.meta.url);
57
+ const pkg = require("../../../package.json");
47
58
  export function createProgram(program) {
48
59
  program
49
- .version("2024.8.0")
60
+ .version(pkg.version || "0.0.0")
50
61
  .addOption(new Option("-r, --responseFormat <format>", "Set the output format")
51
62
  .choices(["json", "csv", "yaml", "table"])
52
63
  .default("json"))
@@ -68,7 +79,9 @@ export function createProgram(program) {
68
79
  .addOption(new Option("--columns <fields>", "Comma-separated list of columns to display"))
69
80
  .addOption(new Option("--no-color", "Disable colored output"))
70
81
  .addOption(new Option("--json-errors", "Output errors as JSON to stderr (for AI agents/scripts)"))
71
- .description("aYOUne - Business as a Service Command Line Interface");
82
+ .addOption(new Option("--token <jwt>", "Authenticate with a JWT token for this session"))
83
+ .addOption(new Option("--no-context", "Disable context injection for this command"))
84
+ .description(getDescription());
72
85
  program.showHelpAfterError();
73
86
  program.showSuggestionAfterError(true);
74
87
  createModulesCommand(program);
@@ -101,23 +114,26 @@ export function createProgram(program) {
101
114
  createSyncCommand(program);
102
115
  createPermissionsCommand(program);
103
116
  createTemplateCommand(program);
117
+ createAccessCommand(program);
118
+ createSetupCommand(program);
119
+ createStatusCommand(program);
120
+ createSelfHostUpdateCommand(program);
121
+ createContextCommand(program);
104
122
  createCompletionsCommand(program);
105
123
  createAliasCommand(program);
106
124
  createConfigCommand(program);
107
125
  registerUserAliases(program);
108
126
  createLoginCommand(program);
109
- program.addHelpText("beforeAll", `
110
- __ ______ _ _
111
- \\ \\ / / __ \\| | | |
112
- __ \\ \\_/ / | | | | | |_ __ ___
113
- / _\` \\ /| | | | | | | '_ \\ / _ \\
114
- | (_| || | | |__| | |__| | | | | __/
115
- \\__,_||_| \\____/ \\____/|_| |_|\\___|
116
- `);
127
+ program.addHelpText("beforeAll", getLogo());
128
+ program.addHelpText("afterAll", chalk.dim("\n Run ay <command> --help for more info\n"));
117
129
  program.configureHelp({
118
130
  sortOptions: true,
119
131
  sortSubcommands: true,
120
132
  showGlobalOptions: true,
133
+ formatHelp: (cmd, helper) => {
134
+ const defaultHelp = Command.prototype.createHelp().formatHelp(cmd, helper);
135
+ return defaultHelp.replace(/^(Usage:|Commands:|Options:|Global Options:)/gm, (match) => chalk.hex(BRAND_BLUE).bold(match));
136
+ },
121
137
  });
122
138
  // Respect NO_COLOR env var (no-color.org standard)
123
139
  if (process.env.NO_COLOR !== undefined) {
@@ -154,7 +170,10 @@ export function createProgram(program) {
154
170
  enableDryRun();
155
171
  }
156
172
  if (opts.jsonErrors) {
157
- enableJsonErrors();
173
+ setJsonErrorsEnabled(true);
174
+ }
175
+ if (opts.context === false) {
176
+ disableContext();
158
177
  }
159
178
  if (opts.quiet) {
160
179
  spinner.start = () => spinner;
@@ -163,22 +182,29 @@ export function createProgram(program) {
163
182
  spinner.stop = () => spinner;
164
183
  // spinner.error left intact
165
184
  }
166
- // Token from env var (headless/AI agent mode) takes precedence over stored token
167
- const envToken = process.env.AYOUNE_TOKEN;
168
- if (envToken && !localStorage.getItem("token")) {
169
- localStorage.setItem("token", envToken);
185
+ // Token from --token flag (highest priority), then env var, then stored token
186
+ if (opts.token) {
187
+ secureStorage.setItem("token", opts.token);
188
+ }
189
+ else {
190
+ const envToken = process.env.AYOUNE_TOKEN;
191
+ if (envToken && !secureStorage.getItem("token")) {
192
+ secureStorage.setItem("token", envToken);
193
+ }
170
194
  }
171
195
  // First-run onboarding: auto-login if no token stored
172
196
  const cmdName = thisCommand.name();
173
- const skipAuth = ["login", "logout", "whoami", "completions", "alias", "config", "help"];
197
+ const skipAuth = ["login", "logout", "whoami", "completions", "alias", "config", "help", "setup", "status", "self-host-update", "context"];
174
198
  if (!skipAuth.includes(cmdName) && process.stdin.isTTY) {
175
- const token = localStorage.getItem("token");
199
+ const token = secureStorage.getItem("token");
176
200
  if (!token) {
177
- console.error(chalk.cyan.bold("\n Welcome to aYOUne CLI!\n"));
201
+ console.error(chalk.hex('#2B8DC6').bold("\n Welcome to aYOUne CLI!\n"));
178
202
  console.error(chalk.dim(" You need to authenticate before using this command.\n"));
179
203
  await login();
180
204
  }
181
205
  }
206
+ // Non-blocking update check (throttled, silent on errors)
207
+ checkForUpdates(pkg.version || "0.0.0");
182
208
  });
183
209
  //Parse command line arguments
184
210
  program.parse(process.argv);