@ouro.bot/cli 0.1.0-alpha.422 → 0.1.0-alpha.425

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.
@@ -94,8 +94,8 @@ exports.COMMAND_REGISTRY = {
94
94
  config: {
95
95
  category: "Agents",
96
96
  description: "View or change agent configuration",
97
- usage: "ouro config <subcommand> --agent <name>",
98
- example: "ouro config models --agent ouroboros",
97
+ usage: "ouro config <subcommand> [--agent <name>]",
98
+ example: "ouro config models",
99
99
  subcommands: ["model", "models"],
100
100
  },
101
101
  changelog: {
@@ -159,27 +159,27 @@ exports.COMMAND_REGISTRY = {
159
159
  auth: {
160
160
  category: "Auth",
161
161
  description: "Set up, verify, or switch agent credentials",
162
- usage: "ouro auth [verify|switch] --agent <name> [--provider <provider>]",
163
- example: "ouro auth --agent ouroboros",
162
+ usage: "ouro auth [verify|switch] [--agent <name>] [--provider <provider>]",
163
+ example: "ouro auth",
164
164
  subcommands: ["verify", "switch"],
165
165
  },
166
166
  connect: {
167
167
  category: "Auth",
168
- description: "Connect integrations and local senses such as Perplexity search and BlueBubbles iMessage",
169
- usage: "ouro connect [perplexity|bluebubbles] --agent <name>",
170
- example: "ouro connect perplexity --agent ouroboros",
171
- subcommands: ["perplexity", "bluebubbles"],
168
+ description: "Connect providers, portable integrations, and local senses from one guided bay",
169
+ usage: "ouro connect [providers|perplexity|embeddings|teams|bluebubbles] [--agent <name>]",
170
+ example: "ouro connect",
171
+ subcommands: ["providers", "perplexity", "embeddings", "teams", "bluebubbles"],
172
172
  },
173
173
  use: {
174
174
  category: "Auth",
175
175
  description: "Choose this machine's provider/model lane for an agent",
176
- usage: "ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]",
176
+ usage: "ouro use [--agent <name>] --lane outward|inner --provider <provider> --model <model> [--force]",
177
177
  example: "ouro use --agent ouroboros --lane outward --provider minimax --model MiniMax-M2.5",
178
178
  },
179
179
  check: {
180
180
  category: "Auth",
181
181
  description: "Run a live check for this machine's selected provider/model lane",
182
- usage: "ouro check --agent <name> --lane outward|inner",
182
+ usage: "ouro check [--agent <name>] --lane outward|inner",
183
183
  example: "ouro check --agent ouroboros --lane outward",
184
184
  },
185
185
  repair: {
@@ -191,15 +191,15 @@ exports.COMMAND_REGISTRY = {
191
191
  provider: {
192
192
  category: "Auth",
193
193
  description: "Refresh daemon provider credentials from an agent vault",
194
- usage: "ouro provider refresh --agent <name>",
194
+ usage: "ouro provider refresh [--agent <name>]",
195
195
  example: "ouro provider refresh --agent ouroboros",
196
196
  subcommands: ["refresh"],
197
197
  },
198
198
  vault: {
199
199
  category: "Auth",
200
200
  description: "Create, replace, recover, unlock, inspect, and populate the agent credential vault",
201
- usage: "ouro vault <create|replace|recover|unlock|status|config> --agent <name>",
202
- example: "ouro vault status --agent ouroboros",
201
+ usage: "ouro vault <create|replace|recover|unlock|status|config> [--agent <name>]",
202
+ example: "ouro vault status",
203
203
  subcommands: ["create", "replace", "recover", "unlock", "status", "config set", "config status"],
204
204
  },
205
205
  thoughts: {
@@ -244,8 +244,8 @@ exports.COMMAND_REGISTRY = {
244
244
  setup: {
245
245
  category: "System",
246
246
  description: "Register MCP server and hooks for a dev tool",
247
- usage: "ouro setup --tool <claude-code|codex> --agent <name>",
248
- example: "ouro setup --tool claude-code --agent ouroboros",
247
+ usage: "ouro setup --tool <claude-code|codex> [--agent <name>]",
248
+ example: "ouro setup --tool claude-code",
249
249
  },
250
250
  hook: {
251
251
  category: "System",
@@ -256,71 +256,86 @@ exports.COMMAND_REGISTRY = {
256
256
  bluebubbles: {
257
257
  category: "System",
258
258
  description: "BlueBubbles integration commands",
259
- usage: "ouro bluebubbles replay --agent <name> --message-guid <guid> [--event-type <type>] [--json]",
260
- example: "ouro bluebubbles replay --agent ouroboros --message-guid abc123",
259
+ usage: "ouro bluebubbles replay [--agent <name>] --message-guid <guid> [--event-type <type>] [--json]",
260
+ example: "ouro bluebubbles replay --message-guid abc123",
261
261
  subcommands: ["replay"],
262
262
  },
263
263
  };
264
264
  const SUBCOMMAND_HELP = {
265
265
  "auth verify": {
266
266
  description: "Verify agent provider credentials without changing provider/model lanes",
267
- usage: "ouro auth verify --agent <name> [--provider <provider>]",
268
- example: "ouro auth verify --agent ouroboros --provider openai-codex",
267
+ usage: "ouro auth verify [--agent <name>] [--provider <provider>]",
268
+ example: "ouro auth verify --provider openai-codex",
269
269
  },
270
270
  "auth switch": {
271
271
  description: "Switch local provider/model lanes after credentials are available",
272
- usage: "ouro auth switch --agent <name> --provider <provider> [--facing human|agent]",
273
- example: "ouro auth switch --agent ouroboros --provider minimax",
272
+ usage: "ouro auth switch [--agent <name>] --provider <provider> [--facing human|agent]",
273
+ example: "ouro auth switch --provider minimax",
274
274
  },
275
275
  "connect perplexity": {
276
276
  description: "Connect Perplexity search for this agent",
277
- usage: "ouro connect perplexity --agent <name>",
278
- example: "ouro connect perplexity --agent ouroboros",
277
+ usage: "ouro connect perplexity [--agent <name>]",
278
+ example: "ouro connect perplexity",
279
+ },
280
+ "connect providers": {
281
+ description: "Open provider auth from the connect bay without remembering the auth command",
282
+ usage: "ouro connect providers [--agent <name>]",
283
+ example: "ouro connect providers",
284
+ },
285
+ "connect embeddings": {
286
+ description: "Connect memory embeddings for this agent",
287
+ usage: "ouro connect embeddings [--agent <name>]",
288
+ example: "ouro connect embeddings",
289
+ },
290
+ "connect teams": {
291
+ description: "Connect Microsoft Teams credentials and enable the Teams sense",
292
+ usage: "ouro connect teams [--agent <name>]",
293
+ example: "ouro connect teams",
279
294
  },
280
295
  "connect bluebubbles": {
281
296
  description: "Attach BlueBubbles iMessage to this machine only",
282
- usage: "ouro connect bluebubbles --agent <name>",
283
- example: "ouro connect bluebubbles --agent ouroboros",
297
+ usage: "ouro connect bluebubbles [--agent <name>]",
298
+ example: "ouro connect bluebubbles",
284
299
  },
285
300
  "provider refresh": {
286
301
  description: "Reload this agent's provider credentials from its vault into daemon memory",
287
- usage: "ouro provider refresh --agent <name>",
288
- example: "ouro provider refresh --agent ouroboros",
302
+ usage: "ouro provider refresh [--agent <name>]",
303
+ example: "ouro provider refresh",
289
304
  },
290
305
  "vault create": {
291
306
  description: "Create an agent credential vault and store local unlock material",
292
- usage: "ouro vault create --agent <name> --email <email> [--server <url>] [--store <store>]",
293
- example: "ouro vault create --agent ouroboros --email ouroboros@ouro.bot",
307
+ usage: "ouro vault create [--agent <name>] --email <email> [--server <url>] [--store <store>]",
308
+ example: "ouro vault create --email ouroboros@ouro.bot",
294
309
  },
295
310
  "vault replace": {
296
311
  description: "Create an empty agent vault at the stable agent email when no unlock secret or JSON export exists",
297
- usage: "ouro vault replace --agent <name> [--email <email>] [--server <url>] [--store <store>]",
298
- example: "ouro vault replace --agent ouroboros",
312
+ usage: "ouro vault replace [--agent <name>] [--email <email>] [--server <url>] [--store <store>]",
313
+ example: "ouro vault replace",
299
314
  },
300
315
  "vault recover": {
301
316
  description: "Create an agent vault at the stable agent email and import local JSON credential exports",
302
- usage: "ouro vault recover --agent <name> --from <json> [--from <json> ...] [--email <email>] [--server <url>] [--store <store>]",
303
- example: "ouro vault recover --agent ouroboros --from ./credentials.json",
317
+ usage: "ouro vault recover [--agent <name>] --from <json> [--from <json> ...] [--email <email>] [--server <url>] [--store <store>]",
318
+ example: "ouro vault recover --from ./credentials.json",
304
319
  },
305
320
  "vault unlock": {
306
321
  description: "Unlock an existing agent credential vault on this machine",
307
- usage: "ouro vault unlock --agent <name> [--store <store>]",
308
- example: "ouro vault unlock --agent ouroboros",
322
+ usage: "ouro vault unlock [--agent <name>] [--store <store>]",
323
+ example: "ouro vault unlock",
309
324
  },
310
325
  "vault status": {
311
326
  description: "Show whether this machine can unlock an agent credential vault",
312
- usage: "ouro vault status --agent <name> [--store <store>]",
313
- example: "ouro vault status --agent ouroboros",
327
+ usage: "ouro vault status [--agent <name>] [--store <store>]",
328
+ example: "ouro vault status",
314
329
  },
315
330
  "vault config set": {
316
331
  description: "Write runtime configuration into the agent credential vault without printing values",
317
- usage: "ouro vault config set --agent <name> --key <path> [--value <value>] [--scope agent|machine]",
318
- example: "ouro vault config set --agent ouroboros --key teams.clientSecret",
332
+ usage: "ouro vault config set [--agent <name>] --key <path> [--value <value>] [--scope agent|machine]",
333
+ example: "ouro vault config set --key teams.clientSecret",
319
334
  },
320
335
  "vault config status": {
321
336
  description: "List runtime configuration keys stored in the agent credential vault",
322
- usage: "ouro vault config status --agent <name> [--scope agent|machine|all]",
323
- example: "ouro vault config status --agent ouroboros --scope all",
337
+ usage: "ouro vault config status [--agent <name>] [--scope agent|machine|all]",
338
+ example: "ouro vault config status --scope all",
324
339
  },
325
340
  };
326
341
  // ── Levenshtein distance ──
@@ -74,25 +74,25 @@ function usage() {
74
74
  " ouro dev [--repo-path <path>] [--clone [--clone-path <path>]]",
75
75
  " ouro stop|down|status|logs|hatch",
76
76
  " ouro status --agent <name>",
77
- " ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]",
78
- " ouro check --agent <name> --lane outward|inner",
77
+ " ouro use [--agent <name>] --lane outward|inner --provider <provider> --model <model> [--force]",
78
+ " ouro check [--agent <name>] --lane outward|inner",
79
79
  " ouro repair [--agent <name>]",
80
- " ouro provider refresh --agent <name>",
80
+ " ouro provider refresh [--agent <name>]",
81
81
  " ouro outlook [--json]",
82
82
  " ouro -v|--version",
83
- " ouro config model --agent <name> <model-name>",
84
- " ouro config models --agent <name>",
85
- " ouro auth --agent <name> [--provider <provider>]",
86
- " ouro connect [perplexity|bluebubbles] --agent <name>",
87
- " ouro auth verify --agent <name> [--provider <provider>]",
88
- " ouro auth switch --agent <name> --provider <provider>",
89
- " ouro vault create --agent <name> --email <email> [--server <url>] [--store <store>]",
90
- " ouro vault replace --agent <name> [--email <email>] [--server <url>] [--store <store>]",
91
- " ouro vault recover --agent <name> --from <json> [--from <json>] [--email <email>] [--server <url>] [--store <store>]",
92
- " ouro vault unlock --agent <name> [--store auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file]",
93
- " ouro vault status --agent <name> [--store auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file]",
94
- " ouro vault config set --agent <name> --key <path> [--value <value>] [--scope agent|machine]",
95
- " ouro vault config status --agent <name> [--scope agent|machine|all]",
83
+ " ouro config model [--agent <name>] <model-name>",
84
+ " ouro config models [--agent <name>]",
85
+ " ouro auth [--agent <name>] [--provider <provider>]",
86
+ " ouro connect [providers|perplexity|embeddings|teams|bluebubbles] [--agent <name>]",
87
+ " ouro auth verify [--agent <name>] [--provider <provider>]",
88
+ " ouro auth switch [--agent <name>] --provider <provider>",
89
+ " ouro vault create [--agent <name>] --email <email> [--server <url>] [--store <store>]",
90
+ " ouro vault replace [--agent <name>] [--email <email>] [--server <url>] [--store <store>]",
91
+ " ouro vault recover [--agent <name>] --from <json> [--from <json>] [--email <email>] [--server <url>] [--store <store>]",
92
+ " ouro vault unlock [--agent <name>] [--store auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file]",
93
+ " ouro vault status [--agent <name>] [--store auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file]",
94
+ " ouro vault config set [--agent <name>] --key <path> [--value <value>] [--scope agent|machine]",
95
+ " ouro vault config status [--agent <name>] [--scope agent|machine|all]",
96
96
  " ouro chat <agent>",
97
97
  " ouro msg --to <agent> [--session <id>] [--task <ref>] <message>",
98
98
  " ouro poke <agent> --task <task-id>",
@@ -100,7 +100,7 @@ function usage() {
100
100
  " ouro habit list [--agent <name>]",
101
101
  " ouro habit create [--agent <name>] <name> [--cadence <interval>]",
102
102
  " ouro link <agent> --friend <id> --provider <provider> --external-id <external-id>",
103
- " ouro bluebubbles replay --agent <name> --message-guid <guid> [--event-type new-message|updated-message] [--json]",
103
+ " ouro bluebubbles replay [--agent <name>] --message-guid <guid> [--event-type new-message|updated-message] [--json]",
104
104
  " ouro task board [<status>] [--agent <name>]",
105
105
  " ouro task create <title> [--type <type>] [--agent <name>]",
106
106
  " ouro task update <id> <status> [--agent <name>]",
@@ -415,15 +415,21 @@ function parseAuthCommand(args) {
415
415
  }
416
416
  }
417
417
  /* v8 ignore stop */
418
- /* v8 ignore next -- defensive: agent always provided in tests @preserve */
419
- if (!agent)
420
- throw new Error(`Usage\n${usage()}`);
421
418
  if (subcommand === "switch") {
422
419
  if (!provider)
423
420
  throw new Error(`auth switch requires --provider.\n${usage()}`);
424
- return facing ? { kind: "auth.switch", agent, provider, facing } : { kind: "auth.switch", agent, provider };
421
+ return {
422
+ kind: "auth.switch",
423
+ ...(agent ? { agent } : {}),
424
+ provider,
425
+ ...(facing ? { facing } : {}),
426
+ };
425
427
  }
426
- return provider ? { kind: "auth.verify", agent, provider } : { kind: "auth.verify", agent };
428
+ return {
429
+ kind: "auth.verify",
430
+ ...(agent ? { agent } : {}),
431
+ ...(provider ? { provider } : {}),
432
+ };
427
433
  }
428
434
  const { agent, rest } = extractAgentFlag(args);
429
435
  let provider;
@@ -437,15 +443,11 @@ function parseAuthCommand(args) {
437
443
  continue;
438
444
  }
439
445
  }
440
- if (!agent) {
441
- throw new Error([
442
- "Usage:",
443
- " ouro auth --agent <name> [--provider <provider>] Set up credentials",
444
- " ouro auth verify --agent <name> [--provider <p>] Verify credentials work",
445
- " ouro auth switch --agent <name> --provider <p> Switch active provider",
446
- ].join("\n"));
447
- }
448
- return provider ? { kind: "auth.run", agent, provider } : { kind: "auth.run", agent };
446
+ return {
447
+ kind: "auth.run",
448
+ ...(agent ? { agent } : {}),
449
+ ...(provider ? { provider } : {}),
450
+ };
449
451
  }
450
452
  function isVaultUnlockStoreKind(value) {
451
453
  return value === "auto" || value === "macos-keychain" || value === "windows-dpapi" || value === "linux-secret-service" || value === "plaintext-file";
@@ -487,7 +489,7 @@ function parseVaultCommand(args) {
487
489
  }
488
490
  const value = rest[i + 1];
489
491
  if (!value)
490
- throw new Error("Usage: ouro vault recover --agent <name> --from <json> [--from <json> ...]");
492
+ throw new Error("Usage: ouro vault recover [--agent <name>] --from <json> [--from <json> ...]");
491
493
  sources.push(value);
492
494
  i += 1;
493
495
  continue;
@@ -496,15 +498,15 @@ function parseVaultCommand(args) {
496
498
  generateUnlockSecret = true;
497
499
  continue;
498
500
  }
499
- throw new Error("Usage: ouro vault create|replace|recover|unlock|status --agent <name>");
501
+ throw new Error("Usage: ouro vault create|replace|recover|unlock|status [--agent <name>]");
500
502
  }
501
- if (!agent || (sub !== "create" && sub !== "replace" && sub !== "recover" && sub !== "unlock" && sub !== "status")) {
502
- throw new Error("Usage: ouro vault create|replace|recover|unlock|status --agent <name>");
503
+ if (sub !== "create" && sub !== "replace" && sub !== "recover" && sub !== "unlock" && sub !== "status") {
504
+ throw new Error("Usage: ouro vault create|replace|recover|unlock|status [--agent <name>]");
503
505
  }
504
506
  if (sub === "create") {
505
507
  return {
506
508
  kind: "vault.create",
507
- agent,
509
+ ...(agent ? { agent } : {}),
508
510
  ...(email ? { email } : {}),
509
511
  ...(serverUrl ? { serverUrl } : {}),
510
512
  ...(store ? { store } : {}),
@@ -514,7 +516,7 @@ function parseVaultCommand(args) {
514
516
  if (sub === "replace") {
515
517
  return {
516
518
  kind: "vault.replace",
517
- agent,
519
+ ...(agent ? { agent } : {}),
518
520
  ...(email ? { email } : {}),
519
521
  ...(serverUrl ? { serverUrl } : {}),
520
522
  ...(store ? { store } : {}),
@@ -523,11 +525,11 @@ function parseVaultCommand(args) {
523
525
  }
524
526
  if (sub === "recover") {
525
527
  if (sources.length === 0) {
526
- throw new Error("Usage: ouro vault recover --agent <name> --from <json> [--from <json> ...]");
528
+ throw new Error("Usage: ouro vault recover [--agent <name>] --from <json> [--from <json> ...]");
527
529
  }
528
530
  return {
529
531
  kind: "vault.recover",
530
- agent,
532
+ ...(agent ? { agent } : {}),
531
533
  sources,
532
534
  ...(email ? { email } : {}),
533
535
  ...(serverUrl ? { serverUrl } : {}),
@@ -536,9 +538,9 @@ function parseVaultCommand(args) {
536
538
  };
537
539
  }
538
540
  if (sub === "unlock") {
539
- return { kind: "vault.unlock", agent, ...(store ? { store } : {}) };
541
+ return { kind: "vault.unlock", ...(agent ? { agent } : {}), ...(store ? { store } : {}) };
540
542
  }
541
- return { kind: "vault.status", agent, ...(store ? { store } : {}) };
543
+ return { kind: "vault.status", ...(agent ? { agent } : {}), ...(store ? { store } : {}) };
542
544
  }
543
545
  function parseVaultConfigCommand(args) {
544
546
  const sub = args[0];
@@ -567,41 +569,45 @@ function parseVaultConfigCommand(args) {
567
569
  i += 1;
568
570
  continue;
569
571
  }
570
- throw new Error("Usage: ouro vault config set --agent <name> --key <path> [--value <value>] OR ouro vault config status --agent <name>");
572
+ throw new Error("Usage: ouro vault config set [--agent <name>] --key <path> [--value <value>] OR ouro vault config status [--agent <name>]");
571
573
  }
572
- if (!agent || (sub !== "set" && sub !== "status")) {
573
- throw new Error("Usage: ouro vault config set --agent <name> --key <path> [--value <value>] OR ouro vault config status --agent <name>");
574
+ if (sub !== "set" && sub !== "status") {
575
+ throw new Error("Usage: ouro vault config set [--agent <name>] --key <path> [--value <value>] OR ouro vault config status [--agent <name>]");
574
576
  }
575
577
  if (sub === "status") {
576
578
  if (key || value) {
577
- throw new Error("Usage: ouro vault config status --agent <name>");
579
+ throw new Error("Usage: ouro vault config status [--agent <name>]");
578
580
  }
579
- return { kind: "vault.config.status", agent, ...(scope ? { scope } : {}) };
581
+ return { kind: "vault.config.status", ...(agent ? { agent } : {}), ...(scope ? { scope } : {}) };
580
582
  }
581
583
  if (scope === "all")
582
584
  throw new Error("vault config --scope all is only valid for status");
583
585
  if (!key) {
584
- throw new Error("Usage: ouro vault config set --agent <name> --key <path> [--value <value>]");
586
+ throw new Error("Usage: ouro vault config set [--agent <name>] --key <path> [--value <value>]");
585
587
  }
586
- return { kind: "vault.config.set", agent, key, ...(value !== undefined ? { value } : {}), ...(scope ? { scope } : {}) };
588
+ return { kind: "vault.config.set", ...(agent ? { agent } : {}), key, ...(value !== undefined ? { value } : {}), ...(scope ? { scope } : {}) };
587
589
  }
588
590
  function normalizeConnectTarget(value) {
589
591
  if (!value)
590
592
  return undefined;
593
+ if (value === "providers" || value === "provider" || value === "auth")
594
+ return "providers";
591
595
  if (value === "perplexity" || value === "perplexity-search")
592
596
  return "perplexity";
597
+ if (value === "embeddings" || value === "embedding" || value === "memory" || value === "note-search" || value === "notes")
598
+ return "embeddings";
599
+ if (value === "teams" || value === "msteams" || value === "microsoft-teams")
600
+ return "teams";
593
601
  if (value === "bluebubbles" || value === "imessage" || value === "messages")
594
602
  return "bluebubbles";
595
- throw new Error("Usage: ouro connect [perplexity|bluebubbles] --agent <name>");
603
+ throw new Error("Usage: ouro connect [providers|perplexity|embeddings|teams|bluebubbles] [--agent <name>]");
596
604
  }
597
605
  function parseConnectCommand(args) {
598
606
  const { agent, rest } = extractAgentFlag(args);
599
- if (!agent)
600
- throw new Error("Usage: ouro connect --agent <name> [perplexity|bluebubbles]");
601
607
  if (rest.length > 1)
602
- throw new Error("Usage: ouro connect [perplexity|bluebubbles] --agent <name>");
608
+ throw new Error("Usage: ouro connect [providers|perplexity|embeddings|teams|bluebubbles] [--agent <name>]");
603
609
  const target = normalizeConnectTarget(rest[0]);
604
- return { kind: "connect", agent, ...(target ? { target } : {}) };
610
+ return { kind: "connect", ...(agent ? { agent } : {}), ...(target ? { target } : {}) };
605
611
  }
606
612
  function parseProviderUseCommand(args) {
607
613
  const { agent, rest: afterAgent } = extractAgentFlag(args);
@@ -615,7 +621,7 @@ function parseProviderUseCommand(args) {
615
621
  if (token === "--provider") {
616
622
  const value = rest[i + 1];
617
623
  if (!isAgentProvider(value))
618
- throw new Error(`Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model>`);
624
+ throw new Error("Usage: ouro use [--agent <name>] --lane outward|inner --provider <provider> --model <model>");
619
625
  provider = value;
620
626
  i += 1;
621
627
  continue;
@@ -629,15 +635,15 @@ function parseProviderUseCommand(args) {
629
635
  force = true;
630
636
  continue;
631
637
  }
632
- throw new Error("Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]");
638
+ throw new Error("Usage: ouro use [--agent <name>] --lane outward|inner --provider <provider> --model <model> [--force]");
633
639
  }
634
640
  const resolvedLane = lane ?? (facing ? facingToProviderLane(facing) : undefined);
635
- if (!agent || !resolvedLane || !provider || !model) {
636
- throw new Error("Usage: ouro use --agent <name> --lane outward|inner --provider <provider> --model <model> [--force]");
641
+ if (!resolvedLane || !provider || !model) {
642
+ throw new Error("Usage: ouro use [--agent <name>] --lane outward|inner --provider <provider> --model <model> [--force]");
637
643
  }
638
644
  return {
639
645
  kind: "provider.use",
640
- agent,
646
+ ...(agent ? { agent } : {}),
641
647
  lane: resolvedLane,
642
648
  provider,
643
649
  model,
@@ -650,12 +656,12 @@ function parseProviderCheckCommand(args) {
650
656
  const { facing, rest: afterFacing } = extractFacingFlag(afterAgent);
651
657
  const { lane, rest } = extractLaneFlag(afterFacing);
652
658
  const resolvedLane = lane ?? (facing ? facingToProviderLane(facing) : undefined);
653
- if (!agent || !resolvedLane || rest.length > 0) {
654
- throw new Error("Usage: ouro check --agent <name> --lane outward|inner");
659
+ if (!resolvedLane || rest.length > 0) {
660
+ throw new Error("Usage: ouro check [--agent <name>] --lane outward|inner");
655
661
  }
656
662
  return {
657
663
  kind: "provider.check",
658
- agent,
664
+ ...(agent ? { agent } : {}),
659
665
  lane: resolvedLane,
660
666
  ...(facing ? { legacyFacing: facing } : {}),
661
667
  };
@@ -663,10 +669,10 @@ function parseProviderCheckCommand(args) {
663
669
  function parseProviderCommand(args) {
664
670
  const sub = args[0];
665
671
  const { agent, rest } = extractAgentFlag(args.slice(1));
666
- if (sub === "refresh" && agent && rest.length === 0) {
667
- return { kind: "provider.refresh", agent };
672
+ if (sub === "refresh" && rest.length === 0) {
673
+ return { kind: "provider.refresh", ...(agent ? { agent } : {}) };
668
674
  }
669
- throw new Error("Usage: ouro provider refresh --agent <name>");
675
+ throw new Error("Usage: ouro provider refresh [--agent <name>]");
670
676
  }
671
677
  function parseReminderCommand(args) {
672
678
  const { agent, rest: cleaned } = extractAgentFlag(args);
@@ -830,17 +836,18 @@ function parseConfigCommand(args) {
830
836
  if (!sub)
831
837
  throw new Error(`Usage\n${usage()}`);
832
838
  if (sub === "model") {
833
- if (!agent)
834
- throw new Error("--agent is required for config model");
835
839
  const modelName = rest[0];
836
840
  if (!modelName)
837
- throw new Error(`Usage: ouro config model --agent <name> <model-name>`);
838
- return facing ? { kind: "config.model", agent, modelName, facing } : { kind: "config.model", agent, modelName };
841
+ throw new Error("Usage: ouro config model [--agent <name>] <model-name>");
842
+ return {
843
+ kind: "config.model",
844
+ ...(agent ? { agent } : {}),
845
+ modelName,
846
+ ...(facing ? { facing } : {}),
847
+ };
839
848
  }
840
849
  if (sub === "models") {
841
- if (!agent)
842
- throw new Error("--agent is required for config models");
843
- return { kind: "config.models", agent };
850
+ return { kind: "config.models", ...(agent ? { agent } : {}) };
844
851
  }
845
852
  throw new Error(`Usage\n${usage()}`);
846
853
  }
@@ -931,13 +938,13 @@ function parseSetupCommand(args) {
931
938
  continue;
932
939
  }
933
940
  }
941
+ if (args.includes("--agent") && !agent)
942
+ throw new Error("setup requires --agent <name>");
934
943
  if (!tool)
935
944
  throw new Error("setup requires --tool (claude-code | codex)");
936
945
  if (tool !== "claude-code" && tool !== "codex")
937
946
  throw new Error(`Unknown tool: ${tool}. Supported: claude-code, codex`);
938
- if (!agent)
939
- throw new Error("setup requires --agent <name>");
940
- return { kind: "setup", tool, agent };
947
+ return { kind: "setup", tool, ...(agent ? { agent } : {}) };
941
948
  }
942
949
  function parseBlueBubblesCommand(args) {
943
950
  const subcommand = args[0];
@@ -970,13 +977,11 @@ function parseBlueBubblesCommand(args) {
970
977
  continue;
971
978
  }
972
979
  }
973
- if (!agent)
974
- throw new Error("bluebubbles replay requires --agent <name>");
975
980
  if (!messageGuid)
976
981
  throw new Error("bluebubbles replay requires --message-guid <guid>");
977
982
  return {
978
983
  kind: "bluebubbles.replay",
979
- agent,
984
+ ...(agent ? { agent } : {}),
980
985
  messageGuid,
981
986
  eventType,
982
987
  ...(json ? { json: true } : {}),
@@ -20,6 +20,7 @@ const RESET = "\x1b[0m";
20
20
  const BOLD = "\x1b[1m";
21
21
  const DIM = "\x1b[2m";
22
22
  const GREEN = "\x1b[38;2;46;204;64m";
23
+ const RED = "\x1b[38;2;255;106;106m";
23
24
  // ── UpProgress class ──
24
25
  class UpProgress {
25
26
  write;
@@ -109,7 +110,7 @@ class UpProgress {
109
110
  return;
110
111
  }
111
112
  const elapsedMs = this.now() - this.currentPhase.startedAt;
112
- this.completed.push({ label, detail });
113
+ this.completed.push({ status: "success", label, detail });
113
114
  this.currentPhase = null;
114
115
  this.currentDetail = null;
115
116
  this.stopAutoRender();
@@ -137,6 +138,41 @@ class UpProgress {
137
138
  this.write(` \u2713 ${label}${detailStr}\n`);
138
139
  }
139
140
  }
141
+ failPhase(label, detail) {
142
+ if (!this.currentPhase) {
143
+ return;
144
+ }
145
+ const elapsedMs = this.now() - this.currentPhase.startedAt;
146
+ this.completed.push({ status: "failure", label, detail });
147
+ this.currentPhase = null;
148
+ this.currentDetail = null;
149
+ this.stopAutoRender();
150
+ if (this.eventScope === "command") {
151
+ (0, runtime_1.emitNervesEvent)({
152
+ level: "warn",
153
+ component: "daemon",
154
+ event: "daemon.cli_progress_phase_failed",
155
+ message: `phase failed: ${label}`,
156
+ meta: { command: this.commandName, phase: label, detail: detail ?? null, elapsedMs },
157
+ });
158
+ }
159
+ else {
160
+ (0, runtime_1.emitNervesEvent)({
161
+ level: "warn",
162
+ component: "daemon",
163
+ event: "daemon.up_phase_failed",
164
+ message: `phase failed: ${label}`,
165
+ meta: { phase: label, detail: detail ?? null, elapsedMs },
166
+ });
167
+ }
168
+ if (this.isTTY) {
169
+ this.flushRender();
170
+ }
171
+ else {
172
+ const detailStr = detail ? ` \u2014 ${detail}` : "";
173
+ this.write(` \u2717 ${label}${detailStr}\n`);
174
+ }
175
+ }
140
176
  /**
141
177
  * Build an ANSI string for in-place terminal display. Returns empty
142
178
  * string in non-TTY mode (output is written eagerly in completePhase).
@@ -149,7 +185,12 @@ class UpProgress {
149
185
  // Completed phases
150
186
  for (const phase of this.completed) {
151
187
  const detailStr = phase.detail ? ` ${DIM}\u2014 ${phase.detail}${RESET}` : "";
152
- lines.push(` ${GREEN}\u2713${RESET} ${phase.label}${detailStr}`);
188
+ if (phase.status === "failure") {
189
+ lines.push(` ${RED}\u2717${RESET} ${phase.label}${detailStr}`);
190
+ }
191
+ else {
192
+ lines.push(` ${GREEN}\u2713${RESET} ${phase.label}${detailStr}`);
193
+ }
153
194
  }
154
195
  // Current phase with spinner
155
196
  if (this.currentPhase) {
@@ -451,8 +451,8 @@ function senseRuntimeGuidance(channel, preReadStatusLines) {
451
451
  lines.push("- running = enabled and currently active");
452
452
  lines.push("- error = enabled but unhealthy");
453
453
  lines.push("If asked how to enable another sense, I explain the relevant agent.json senses entry and required agent-vault runtime/config fields instead of guessing.");
454
- lines.push("teams setup truth: enable `senses.teams.enabled`, then store `teams.clientId`, `teams.clientSecret`, and `teams.tenantId` in the agent vault runtime/config item.");
455
- lines.push("bluebubbles setup truth: run `ouro connect bluebubbles --agent <agent>`; it stores this machine's BlueBubbles URL/password/listener config in the agent vault machine runtime item.");
454
+ lines.push("teams setup truth: run `ouro connect teams --agent <agent>` from the connect bay; it stores Teams runtime/config fields and enables `senses.teams.enabled`.");
455
+ lines.push("bluebubbles setup truth: run `ouro connect bluebubbles --agent <agent>` from the connect bay; it stores this machine's BlueBubbles URL/password/listener config in the agent vault machine runtime item.");
456
456
  if (channel === "cli") {
457
457
  lines.push("cli is interactive: it is available when the user opens it, not something `ouro up` daemonizes.");
458
458
  }