@trading-boy/cli 1.8.0 → 1.9.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.
@@ -56362,7 +56362,7 @@ function registerConfigCommand(program2) {
56362
56362
  process.exitCode = 1;
56363
56363
  }
56364
56364
  });
56365
- configCmd.command("set-llm-key <apiKey>").description("Store your LLM API key for thesis extraction + coaching (BYOK)").addOption(new Option("-p, --provider <provider>", "LLM provider (auto-detected from key prefix if omitted)").choices(["anthropic", "openai", "openrouter", "ollama", "gemini", "custom"])).option("-m, --model <model>", "Model name (default for all phases)").option("--base-url <url>", "Custom base URL (for openrouter/ollama/custom providers)").option("--scan-model <model>", "Model for market scanning (e.g. claude-haiku-4-5)").option("--analyze-model <model>", "Model for deep analysis (e.g. claude-sonnet-4-6)").option("--decide-model <model>", "Model for trade decisions (e.g. claude-opus-4-6)").action(async (apiKey, opts) => {
56365
+ configCmd.command("set-llm-key <apiKey>").description("Store your LLM API key for thesis extraction + coaching (BYOK)").addOption(new Option("-p, --provider <provider>", "LLM provider (auto-detected from key prefix if omitted)").choices(["anthropic", "openai", "openrouter", "ollama", "gemini", "custom"])).option("-m, --model <model>", "Model name (default for all phases)").option("--base-url <url>", "Custom base URL (for openrouter/ollama/custom providers)").option("--scan-model <model>", "Model for market scanning (e.g. claude-haiku-4-5)").option("--analyze-model <model>", "Model for deep analysis (e.g. claude-sonnet-4-6)").option("--decide-model <model>", "Model for trade decisions (e.g. claude-opus-4-6)").addOption(new Option("--scan-provider <provider>", "Provider for scan phase").choices(["anthropic", "openai", "openrouter", "ollama", "gemini", "custom"])).option("--scan-key <key>", "API key for scan phase provider").addOption(new Option("--analyze-provider <provider>", "Provider for analyze phase").choices(["anthropic", "openai", "openrouter", "ollama", "gemini", "custom"])).option("--analyze-key <key>", "API key for analyze phase provider").addOption(new Option("--decide-provider <provider>", "Provider for decide phase").choices(["anthropic", "openai", "openrouter", "ollama", "gemini", "custom"])).option("--decide-key <key>", "API key for decide phase provider").action(async (apiKey, opts) => {
56366
56366
  try {
56367
56367
  const result = await apiRequest("/api/v1/llm-config", {
56368
56368
  method: "PUT",
@@ -56373,23 +56373,29 @@ function registerConfigCommand(program2) {
56373
56373
  ...opts.baseUrl ? { baseUrl: opts.baseUrl } : {},
56374
56374
  ...opts.scanModel ? { scanModel: opts.scanModel } : {},
56375
56375
  ...opts.analyzeModel ? { analyzeModel: opts.analyzeModel } : {},
56376
- ...opts.decideModel ? { decideModel: opts.decideModel } : {}
56376
+ ...opts.decideModel ? { decideModel: opts.decideModel } : {},
56377
+ ...opts.scanProvider ? { scanProvider: opts.scanProvider } : {},
56378
+ ...opts.scanKey ? { scanApiKey: opts.scanKey } : {},
56379
+ ...opts.analyzeProvider ? { analyzeProvider: opts.analyzeProvider } : {},
56380
+ ...opts.analyzeKey ? { analyzeApiKey: opts.analyzeKey } : {},
56381
+ ...opts.decideProvider ? { decideProvider: opts.decideProvider } : {},
56382
+ ...opts.decideKey ? { decideApiKey: opts.decideKey } : {}
56377
56383
  }
56378
56384
  });
56379
56385
  console.log("");
56380
56386
  console.log(source_default.green(" LLM API key saved successfully"));
56381
- console.log(` ${source_default.gray("Provider:")} ${result.provider}`);
56382
- console.log(` ${source_default.gray("Model:")} ${result.model}`);
56383
- if (result.scanModel) {
56384
- console.log(` ${source_default.gray("Scan model:")} ${result.scanModel}`);
56387
+ console.log(` ${source_default.gray("Provider:")} ${result.provider}`);
56388
+ console.log(` ${source_default.gray("Model:")} ${result.model}`);
56389
+ if (result.scanProvider || result.scanModel) {
56390
+ console.log(` ${source_default.gray("Scan:")} ${result.scanProvider ?? result.provider} / ${result.scanModel ?? result.model}${opts.scanKey ? " (own key)" : ""}`);
56385
56391
  }
56386
- if (result.analyzeModel) {
56387
- console.log(` ${source_default.gray("Analyze model:")} ${result.analyzeModel}`);
56392
+ if (result.analyzeProvider || result.analyzeModel) {
56393
+ console.log(` ${source_default.gray("Analyze:")} ${result.analyzeProvider ?? result.provider} / ${result.analyzeModel ?? result.model}${opts.analyzeKey ? " (own key)" : ""}`);
56388
56394
  }
56389
- if (result.decideModel) {
56390
- console.log(` ${source_default.gray("Decide model:")} ${result.decideModel}`);
56395
+ if (result.decideProvider || result.decideModel) {
56396
+ console.log(` ${source_default.gray("Decide:")} ${result.decideProvider ?? result.provider} / ${result.decideModel ?? result.model}${opts.decideKey ? " (own key)" : ""}`);
56391
56397
  }
56392
- console.log(` ${source_default.gray("Key:")} ${apiKey.slice(0, 8)}${"*".repeat(Math.max(0, apiKey.length - 8))}`);
56398
+ console.log(` ${source_default.gray("Key:")} ${apiKey.slice(0, 8)}${"*".repeat(Math.max(0, apiKey.length - 8))}`);
56393
56399
  console.log("");
56394
56400
  console.log(source_default.dim(" Your key is encrypted at rest. Thesis extraction and coaching are now enabled."));
56395
56401
  console.log("");
@@ -56411,14 +56417,14 @@ function registerConfigCommand(program2) {
56411
56417
  console.log(source_default.gray(" " + "\u2500".repeat(40)));
56412
56418
  console.log(` ${source_default.gray("Provider:")} ${result.provider}`);
56413
56419
  console.log(` ${source_default.gray("Model:")} ${result.model}`);
56414
- if (result.scanModel) {
56415
- console.log(` ${source_default.gray("Scan model:")} ${result.scanModel}`);
56420
+ if (result.scanProvider || result.scanModel) {
56421
+ console.log(` ${source_default.gray("Scan:")} ${result.scanProvider ?? result.provider} / ${result.scanModel ?? result.model}`);
56416
56422
  }
56417
- if (result.analyzeModel) {
56418
- console.log(` ${source_default.gray("Analyze model:")} ${result.analyzeModel}`);
56423
+ if (result.analyzeProvider || result.analyzeModel) {
56424
+ console.log(` ${source_default.gray("Analyze:")} ${result.analyzeProvider ?? result.provider} / ${result.analyzeModel ?? result.model}`);
56419
56425
  }
56420
- if (result.decideModel) {
56421
- console.log(` ${source_default.gray("Decide model:")} ${result.decideModel}`);
56426
+ if (result.decideProvider || result.decideModel) {
56427
+ console.log(` ${source_default.gray("Decide:")} ${result.decideProvider ?? result.provider} / ${result.decideModel ?? result.model}`);
56422
56428
  }
56423
56429
  if (result.baseUrl) {
56424
56430
  console.log(` ${source_default.gray("Base URL:")} ${result.baseUrl}`);
@@ -57095,6 +57101,58 @@ async function runOnboarding() {
57095
57101
  }
57096
57102
  console.log("");
57097
57103
  }
57104
+ try {
57105
+ console.log(source_default.bold.cyan(" LLM API Key (required for agents)"));
57106
+ console.log(source_default.gray(" " + "\u2500".repeat(50)));
57107
+ console.log(source_default.dim(" Your agent needs an LLM to analyze markets and make decisions."));
57108
+ console.log(source_default.dim(" Bring your own key from any supported provider:"));
57109
+ console.log("");
57110
+ console.log(` ${source_default.white("Anthropic")} ${source_default.dim("(default) \u2014 Claude Sonnet/Opus/Haiku")}`);
57111
+ console.log(` ${source_default.white("Gemini")} ${source_default.dim("\u2014 Gemini 2.5 Pro")}`);
57112
+ console.log(` ${source_default.white("OpenAI")} ${source_default.dim("\u2014 GPT-4o")}`);
57113
+ console.log(` ${source_default.white("OpenRouter")} ${source_default.dim("\u2014 Any model via OpenRouter")}`);
57114
+ console.log(` ${source_default.white("Ollama")} ${source_default.dim("\u2014 Local models")}`);
57115
+ console.log("");
57116
+ console.log(source_default.dim(" The provider is auto-detected from the key prefix."));
57117
+ console.log(source_default.dim(" The model defaults to a sensible choice per provider."));
57118
+ console.log("");
57119
+ const wantsLlmKey = await confirm({
57120
+ message: "Set up your LLM API key now?",
57121
+ default: true
57122
+ });
57123
+ if (wantsLlmKey) {
57124
+ const llmKey = await input({
57125
+ message: "Paste your API key",
57126
+ validate: (v) => v.trim().length > 5 ? true : "Key is too short"
57127
+ });
57128
+ try {
57129
+ if (await isRemoteMode()) {
57130
+ const result = await apiRequest("/api/v1/llm-config", {
57131
+ method: "PUT",
57132
+ body: { apiKey: llmKey.trim() }
57133
+ });
57134
+ console.log(source_default.green(` \u2713 LLM key saved \u2014 ${result.provider} / ${result.model}`));
57135
+ console.log(source_default.dim(" Change model later: trading-boy config set-llm-key <key> --model <model>"));
57136
+ } else {
57137
+ console.log(source_default.yellow(" Skipped \u2014 not connected to API."));
57138
+ }
57139
+ } catch (error49) {
57140
+ const msg = error49 instanceof Error ? error49.message : String(error49);
57141
+ console.log(source_default.yellow(` Could not save LLM key: ${msg}`));
57142
+ console.log(source_default.dim(" Set it later: trading-boy config set-llm-key <your-api-key>"));
57143
+ }
57144
+ } else {
57145
+ console.log("");
57146
+ console.log(source_default.yellow(" \u26A0 Without an LLM key, agents can scan prices but cannot"));
57147
+ console.log(source_default.yellow(" analyze markets or make trade decisions."));
57148
+ console.log(source_default.dim(" Set it later: trading-boy config set-llm-key <your-api-key>"));
57149
+ }
57150
+ } catch (error49) {
57151
+ if (isUserAbort(error49))
57152
+ return;
57153
+ throw error49;
57154
+ }
57155
+ console.log("");
57098
57156
  try {
57099
57157
  const wantsTelegram = await confirm({
57100
57158
  message: "Connect Telegram for daily summaries?",
@@ -57116,13 +57174,33 @@ async function runOnboarding() {
57116
57174
  throw error49;
57117
57175
  }
57118
57176
  console.log("");
57177
+ console.log(source_default.bold.cyan(" How Agents Work"));
57178
+ console.log(source_default.gray(" " + "\u2500".repeat(50)));
57179
+ console.log("");
57180
+ console.log(source_default.dim(" Once you create an agent, it runs continuously on our servers:"));
57181
+ console.log("");
57182
+ console.log(` ${source_default.white("Scan")} ${source_default.dim("Every 5 min (configurable) \u2014 scans your watchlist for setups")}`);
57183
+ console.log(` ${source_default.white("Analyze")} ${source_default.dim("When a setup is found \u2014 deep context analysis via your LLM")}`);
57184
+ console.log(` ${source_default.white("Decide")} ${source_default.dim("After analysis \u2014 enter/exit/hold based on your strategy")}`);
57185
+ console.log(` ${source_default.white("Learn")} ${source_default.dim("After trades close \u2014 updates edge profile from outcomes")}`);
57186
+ console.log("");
57187
+ console.log(source_default.dim(" Autonomy levels:"));
57188
+ console.log(` ${source_default.cyan("OBSERVE_ONLY")} ${source_default.dim("Scans and analyzes \u2014 takes no action")}`);
57189
+ console.log(` ${source_default.cyan("SUGGEST")} ${source_default.dim("Sends trade ideas to your Telegram")}`);
57190
+ console.log(` ${source_default.cyan("AUTO_WITH_APPROVAL")} ${source_default.dim("Proposes trades, waits for your OK")}`);
57191
+ console.log(` ${source_default.cyan("FULLY_AUTONOMOUS")} ${source_default.dim("Trades within your guardrails, no human in the loop")}`);
57192
+ console.log("");
57193
+ console.log(source_default.dim(" Create your first agent:"));
57194
+ console.log(` ${source_default.white("trading-boy agent create --help")}`);
57195
+ console.log("");
57119
57196
  console.log(source_default.bold.cyan(" Quick Reference"));
57120
57197
  console.log(source_default.gray(" " + "\u2500".repeat(50)));
57121
57198
  console.log("");
57122
57199
  console.log(` ${source_default.white("trading-boy context SOL")} ${source_default.dim("Full context for any token")}`);
57123
- console.log(` ${source_default.white("trading-boy journal log entry SOL")} ${source_default.dim("Log a trade entry")}`);
57200
+ console.log(` ${source_default.white("trading-boy agent create")} ${source_default.dim("Create an autonomous agent")}`);
57201
+ console.log(` ${source_default.white("trading-boy agent list")} ${source_default.dim("View your running agents")}`);
57124
57202
  console.log(` ${source_default.white("trading-boy decisions")} ${source_default.dim("View trade history")}`);
57125
- console.log(` ${source_default.white("trading-boy journal review daily")} ${source_default.dim("Review your daily trades")}`);
57203
+ console.log(` ${source_default.white("trading-boy stats")} ${source_default.dim("Track performance")}`);
57126
57204
  console.log(` ${source_default.white("trading-boy narrative list")} ${source_default.dim("Active market narratives")}`);
57127
57205
  console.log(` ${source_default.white("trading-boy catalysts")} ${source_default.dim("Upcoming events")}`);
57128
57206
  if (traderRegistered) {
@@ -59213,7 +59291,7 @@ function registerAgentCommand(program2) {
59213
59291
  if (options.assetClass)
59214
59292
  body.assetClass = options.assetClass;
59215
59293
  if (options.exitReasoner)
59216
- body.exitReasoner = true;
59294
+ body.exitReasonerEnabled = true;
59217
59295
  if (options.soulFile) {
59218
59296
  const path5 = resolve2(options.soulFile);
59219
59297
  if (!existsSync3(path5)) {
@@ -59449,7 +59527,7 @@ function registerAgentCommand(program2) {
59449
59527
  if (options.name)
59450
59528
  body.name = options.name;
59451
59529
  if (options.exitReasoner)
59452
- body.exitReasoner = true;
59530
+ body.exitReasonerEnabled = true;
59453
59531
  if (options.autonomy)
59454
59532
  body.autonomyLevel = options.autonomy;
59455
59533
  if (options.scanIntervalHuman) {
@@ -159,7 +159,7 @@ export function registerAgentCommand(program) {
159
159
  if (options.assetClass)
160
160
  body.assetClass = options.assetClass;
161
161
  if (options.exitReasoner)
162
- body.exitReasoner = true;
162
+ body.exitReasonerEnabled = true;
163
163
  // Soul override — file takes precedence over inline text
164
164
  if (options.soulFile) {
165
165
  const path = resolve(options.soulFile);
@@ -482,7 +482,7 @@ export function registerAgentCommand(program) {
482
482
  if (options.name)
483
483
  body.name = options.name;
484
484
  if (options.exitReasoner)
485
- body.exitReasoner = true;
485
+ body.exitReasonerEnabled = true;
486
486
  if (options.autonomy)
487
487
  body.autonomyLevel = options.autonomy;
488
488
  // Resolve scan interval: --scan-interval-human takes precedence
@@ -328,6 +328,12 @@ export function registerConfigCommand(program) {
328
328
  .option('--scan-model <model>', 'Model for market scanning (e.g. claude-haiku-4-5)')
329
329
  .option('--analyze-model <model>', 'Model for deep analysis (e.g. claude-sonnet-4-6)')
330
330
  .option('--decide-model <model>', 'Model for trade decisions (e.g. claude-opus-4-6)')
331
+ .addOption(new Option('--scan-provider <provider>', 'Provider for scan phase').choices(['anthropic', 'openai', 'openrouter', 'ollama', 'gemini', 'custom']))
332
+ .option('--scan-key <key>', 'API key for scan phase provider')
333
+ .addOption(new Option('--analyze-provider <provider>', 'Provider for analyze phase').choices(['anthropic', 'openai', 'openrouter', 'ollama', 'gemini', 'custom']))
334
+ .option('--analyze-key <key>', 'API key for analyze phase provider')
335
+ .addOption(new Option('--decide-provider <provider>', 'Provider for decide phase').choices(['anthropic', 'openai', 'openrouter', 'ollama', 'gemini', 'custom']))
336
+ .option('--decide-key <key>', 'API key for decide phase provider')
331
337
  .action(async (apiKey, opts) => {
332
338
  try {
333
339
  const result = await apiRequest('/api/v1/llm-config', {
@@ -340,22 +346,28 @@ export function registerConfigCommand(program) {
340
346
  ...(opts.scanModel ? { scanModel: opts.scanModel } : {}),
341
347
  ...(opts.analyzeModel ? { analyzeModel: opts.analyzeModel } : {}),
342
348
  ...(opts.decideModel ? { decideModel: opts.decideModel } : {}),
349
+ ...(opts.scanProvider ? { scanProvider: opts.scanProvider } : {}),
350
+ ...(opts.scanKey ? { scanApiKey: opts.scanKey } : {}),
351
+ ...(opts.analyzeProvider ? { analyzeProvider: opts.analyzeProvider } : {}),
352
+ ...(opts.analyzeKey ? { analyzeApiKey: opts.analyzeKey } : {}),
353
+ ...(opts.decideProvider ? { decideProvider: opts.decideProvider } : {}),
354
+ ...(opts.decideKey ? { decideApiKey: opts.decideKey } : {}),
343
355
  },
344
356
  });
345
357
  console.log('');
346
358
  console.log(chalk.green(' LLM API key saved successfully'));
347
- console.log(` ${chalk.gray('Provider:')} ${result.provider}`);
348
- console.log(` ${chalk.gray('Model:')} ${result.model}`);
349
- if (result.scanModel) {
350
- console.log(` ${chalk.gray('Scan model:')} ${result.scanModel}`);
359
+ console.log(` ${chalk.gray('Provider:')} ${result.provider}`);
360
+ console.log(` ${chalk.gray('Model:')} ${result.model}`);
361
+ if (result.scanProvider || result.scanModel) {
362
+ console.log(` ${chalk.gray('Scan:')} ${result.scanProvider ?? result.provider} / ${result.scanModel ?? result.model}${opts.scanKey ? ' (own key)' : ''}`);
351
363
  }
352
- if (result.analyzeModel) {
353
- console.log(` ${chalk.gray('Analyze model:')} ${result.analyzeModel}`);
364
+ if (result.analyzeProvider || result.analyzeModel) {
365
+ console.log(` ${chalk.gray('Analyze:')} ${result.analyzeProvider ?? result.provider} / ${result.analyzeModel ?? result.model}${opts.analyzeKey ? ' (own key)' : ''}`);
354
366
  }
355
- if (result.decideModel) {
356
- console.log(` ${chalk.gray('Decide model:')} ${result.decideModel}`);
367
+ if (result.decideProvider || result.decideModel) {
368
+ console.log(` ${chalk.gray('Decide:')} ${result.decideProvider ?? result.provider} / ${result.decideModel ?? result.model}${opts.decideKey ? ' (own key)' : ''}`);
357
369
  }
358
- console.log(` ${chalk.gray('Key:')} ${apiKey.slice(0, 8)}${'*'.repeat(Math.max(0, apiKey.length - 8))}`);
370
+ console.log(` ${chalk.gray('Key:')} ${apiKey.slice(0, 8)}${'*'.repeat(Math.max(0, apiKey.length - 8))}`);
359
371
  console.log('');
360
372
  console.log(chalk.dim(' Your key is encrypted at rest. Thesis extraction and coaching are now enabled.'));
361
373
  console.log('');
@@ -384,14 +396,14 @@ export function registerConfigCommand(program) {
384
396
  console.log(chalk.gray(' ' + '\u2500'.repeat(40)));
385
397
  console.log(` ${chalk.gray('Provider:')} ${result.provider}`);
386
398
  console.log(` ${chalk.gray('Model:')} ${result.model}`);
387
- if (result.scanModel) {
388
- console.log(` ${chalk.gray('Scan model:')} ${result.scanModel}`);
399
+ if (result.scanProvider || result.scanModel) {
400
+ console.log(` ${chalk.gray('Scan:')} ${result.scanProvider ?? result.provider} / ${result.scanModel ?? result.model}`);
389
401
  }
390
- if (result.analyzeModel) {
391
- console.log(` ${chalk.gray('Analyze model:')} ${result.analyzeModel}`);
402
+ if (result.analyzeProvider || result.analyzeModel) {
403
+ console.log(` ${chalk.gray('Analyze:')} ${result.analyzeProvider ?? result.provider} / ${result.analyzeModel ?? result.model}`);
392
404
  }
393
- if (result.decideModel) {
394
- console.log(` ${chalk.gray('Decide model:')} ${result.decideModel}`);
405
+ if (result.decideProvider || result.decideModel) {
406
+ console.log(` ${chalk.gray('Decide:')} ${result.decideProvider ?? result.provider} / ${result.decideModel ?? result.model}`);
395
407
  }
396
408
  if (result.baseUrl) {
397
409
  console.log(` ${chalk.gray('Base URL:')} ${result.baseUrl}`);
@@ -2,8 +2,11 @@
2
2
  //
3
3
  // Guided setup after a new user subscribes. Walks through:
4
4
  // 1. Register a trader profile (name + risk tolerance)
5
- // 2. Connect Telegram bot for daily summaries
6
- // 3. Next steps cheat sheet
5
+ // 2. Identity setup (SOUL wizard)
6
+ // 3. LLM API key (BYOK — required for agents to analyze/decide)
7
+ // 4. Connect Telegram bot for daily summaries
8
+ // 5. Agent runtime overview (scan intervals, autonomy levels)
9
+ // 6. Quick reference cheat sheet
7
10
  import chalk from 'chalk';
8
11
  import { isRemoteMode, apiRequest, ApiError } from '../api-client.js';
9
12
  import { runSoulWizardAndUpload } from './soul-wizard.js';
@@ -120,7 +123,64 @@ export async function runOnboarding() {
120
123
  }
121
124
  console.log('');
122
125
  }
123
- // ─── Step 3: Telegram Bot ───
126
+ // ─── Step 3: LLM API Key (BYOK) ───
127
+ try {
128
+ console.log(chalk.bold.cyan(' LLM API Key (required for agents)'));
129
+ console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
130
+ console.log(chalk.dim(' Your agent needs an LLM to analyze markets and make decisions.'));
131
+ console.log(chalk.dim(' Bring your own key from any supported provider:'));
132
+ console.log('');
133
+ console.log(` ${chalk.white('Anthropic')} ${chalk.dim('(default) — Claude Sonnet/Opus/Haiku')}`);
134
+ console.log(` ${chalk.white('Gemini')} ${chalk.dim('— Gemini 2.5 Pro')}`);
135
+ console.log(` ${chalk.white('OpenAI')} ${chalk.dim('— GPT-4o')}`);
136
+ console.log(` ${chalk.white('OpenRouter')} ${chalk.dim('— Any model via OpenRouter')}`);
137
+ console.log(` ${chalk.white('Ollama')} ${chalk.dim('— Local models')}`);
138
+ console.log('');
139
+ console.log(chalk.dim(' The provider is auto-detected from the key prefix.'));
140
+ console.log(chalk.dim(' The model defaults to a sensible choice per provider.'));
141
+ console.log('');
142
+ const wantsLlmKey = await confirm({
143
+ message: 'Set up your LLM API key now?',
144
+ default: true,
145
+ });
146
+ if (wantsLlmKey) {
147
+ const llmKey = await input({
148
+ message: 'Paste your API key',
149
+ validate: (v) => (v.trim().length > 5 ? true : 'Key is too short'),
150
+ });
151
+ try {
152
+ if (await isRemoteMode()) {
153
+ const result = await apiRequest('/api/v1/llm-config', {
154
+ method: 'PUT',
155
+ body: { apiKey: llmKey.trim() },
156
+ });
157
+ console.log(chalk.green(` ✓ LLM key saved — ${result.provider} / ${result.model}`));
158
+ console.log(chalk.dim(' Change model later: trading-boy config set-llm-key <key> --model <model>'));
159
+ }
160
+ else {
161
+ console.log(chalk.yellow(' Skipped — not connected to API.'));
162
+ }
163
+ }
164
+ catch (error) {
165
+ const msg = error instanceof Error ? error.message : String(error);
166
+ console.log(chalk.yellow(` Could not save LLM key: ${msg}`));
167
+ console.log(chalk.dim(' Set it later: trading-boy config set-llm-key <your-api-key>'));
168
+ }
169
+ }
170
+ else {
171
+ console.log('');
172
+ console.log(chalk.yellow(' ⚠ Without an LLM key, agents can scan prices but cannot'));
173
+ console.log(chalk.yellow(' analyze markets or make trade decisions.'));
174
+ console.log(chalk.dim(' Set it later: trading-boy config set-llm-key <your-api-key>'));
175
+ }
176
+ }
177
+ catch (error) {
178
+ if (isUserAbort(error))
179
+ return;
180
+ throw error;
181
+ }
182
+ console.log('');
183
+ // ─── Step 4: Telegram Bot ───
124
184
  try {
125
185
  const wantsTelegram = await confirm({
126
186
  message: 'Connect Telegram for daily summaries?',
@@ -144,14 +204,35 @@ export async function runOnboarding() {
144
204
  throw error;
145
205
  }
146
206
  console.log('');
147
- // ─── Step 4: Next Steps Cheat Sheet ───
207
+ // ─── Step 5: Agent Runtime Overview ───
208
+ console.log(chalk.bold.cyan(' How Agents Work'));
209
+ console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
210
+ console.log('');
211
+ console.log(chalk.dim(' Once you create an agent, it runs continuously on our servers:'));
212
+ console.log('');
213
+ console.log(` ${chalk.white('Scan')} ${chalk.dim('Every 5 min (configurable) — scans your watchlist for setups')}`);
214
+ console.log(` ${chalk.white('Analyze')} ${chalk.dim('When a setup is found — deep context analysis via your LLM')}`);
215
+ console.log(` ${chalk.white('Decide')} ${chalk.dim('After analysis — enter/exit/hold based on your strategy')}`);
216
+ console.log(` ${chalk.white('Learn')} ${chalk.dim('After trades close — updates edge profile from outcomes')}`);
217
+ console.log('');
218
+ console.log(chalk.dim(' Autonomy levels:'));
219
+ console.log(` ${chalk.cyan('OBSERVE_ONLY')} ${chalk.dim('Scans and analyzes — takes no action')}`);
220
+ console.log(` ${chalk.cyan('SUGGEST')} ${chalk.dim('Sends trade ideas to your Telegram')}`);
221
+ console.log(` ${chalk.cyan('AUTO_WITH_APPROVAL')} ${chalk.dim('Proposes trades, waits for your OK')}`);
222
+ console.log(` ${chalk.cyan('FULLY_AUTONOMOUS')} ${chalk.dim('Trades within your guardrails, no human in the loop')}`);
223
+ console.log('');
224
+ console.log(chalk.dim(' Create your first agent:'));
225
+ console.log(` ${chalk.white('trading-boy agent create --help')}`);
226
+ console.log('');
227
+ // ─── Step 6: Quick Reference ───
148
228
  console.log(chalk.bold.cyan(' Quick Reference'));
149
229
  console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
150
230
  console.log('');
151
231
  console.log(` ${chalk.white('trading-boy context SOL')} ${chalk.dim('Full context for any token')}`);
152
- console.log(` ${chalk.white('trading-boy journal log entry SOL')} ${chalk.dim('Log a trade entry')}`);
232
+ console.log(` ${chalk.white('trading-boy agent create')} ${chalk.dim('Create an autonomous agent')}`);
233
+ console.log(` ${chalk.white('trading-boy agent list')} ${chalk.dim('View your running agents')}`);
153
234
  console.log(` ${chalk.white('trading-boy decisions')} ${chalk.dim('View trade history')}`);
154
- console.log(` ${chalk.white('trading-boy journal review daily')} ${chalk.dim('Review your daily trades')}`);
235
+ console.log(` ${chalk.white('trading-boy stats')} ${chalk.dim('Track performance')}`);
155
236
  console.log(` ${chalk.white('trading-boy narrative list')} ${chalk.dim('Active market narratives')}`);
156
237
  console.log(` ${chalk.white('trading-boy catalysts')} ${chalk.dim('Upcoming events')}`);
157
238
  if (traderRegistered) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trading-boy/cli",
3
- "version": "1.8.0",
3
+ "version": "1.9.2",
4
4
  "description": "Trading Boy CLI — crypto context intelligence for traders and AI agents. Query real-time prices, funding rates, whale activity, and DeFi risk for 100+ Solana tokens and 229 Hyperliquid perpetuals.",
5
5
  "homepage": "https://cabal.ventures",
6
6
  "repository": {