@lobu/cli 6.0.1 → 7.0.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 (265) hide show
  1. package/README.md +20 -27
  2. package/dist/bundled-skills/lobu/SKILL.md +11 -11
  3. package/dist/commands/_lib/apply/apply-cmd.d.ts +38 -0
  4. package/dist/commands/_lib/apply/apply-cmd.d.ts.map +1 -1
  5. package/dist/commands/_lib/apply/apply-cmd.js +574 -40
  6. package/dist/commands/_lib/apply/apply-cmd.js.map +1 -1
  7. package/dist/commands/_lib/apply/client.d.ts +180 -1
  8. package/dist/commands/_lib/apply/client.d.ts.map +1 -1
  9. package/dist/commands/_lib/apply/client.js +308 -28
  10. package/dist/commands/_lib/apply/client.js.map +1 -1
  11. package/dist/commands/_lib/apply/desired-state.d.ts +134 -3
  12. package/dist/commands/_lib/apply/desired-state.d.ts.map +1 -1
  13. package/dist/commands/_lib/apply/desired-state.js +703 -89
  14. package/dist/commands/_lib/apply/desired-state.js.map +1 -1
  15. package/dist/commands/_lib/apply/diff.d.ts +61 -3
  16. package/dist/commands/_lib/apply/diff.d.ts.map +1 -1
  17. package/dist/commands/_lib/apply/diff.js +382 -92
  18. package/dist/commands/_lib/apply/diff.js.map +1 -1
  19. package/dist/commands/_lib/apply/prompt.d.ts +6 -0
  20. package/dist/commands/_lib/apply/prompt.d.ts.map +1 -1
  21. package/dist/commands/_lib/apply/prompt.js +16 -0
  22. package/dist/commands/_lib/apply/prompt.js.map +1 -1
  23. package/dist/commands/_lib/apply/render.d.ts +9 -0
  24. package/dist/commands/_lib/apply/render.d.ts.map +1 -1
  25. package/dist/commands/_lib/apply/render.js +80 -3
  26. package/dist/commands/_lib/apply/render.js.map +1 -1
  27. package/dist/commands/agent.d.ts +7 -0
  28. package/dist/commands/agent.d.ts.map +1 -1
  29. package/dist/commands/agent.js +65 -1
  30. package/dist/commands/agent.js.map +1 -1
  31. package/dist/commands/chat.d.ts +12 -9
  32. package/dist/commands/chat.d.ts.map +1 -1
  33. package/dist/commands/chat.js +125 -57
  34. package/dist/commands/chat.js.map +1 -1
  35. package/dist/commands/dev.d.ts +23 -7
  36. package/dist/commands/dev.d.ts.map +1 -1
  37. package/dist/commands/dev.js +197 -49
  38. package/dist/commands/dev.js.map +1 -1
  39. package/dist/commands/doctor.d.ts +1 -0
  40. package/dist/commands/doctor.d.ts.map +1 -1
  41. package/dist/commands/doctor.js +136 -0
  42. package/dist/commands/doctor.js.map +1 -1
  43. package/dist/commands/eval.d.ts +8 -0
  44. package/dist/commands/eval.d.ts.map +1 -1
  45. package/dist/commands/eval.js +72 -6
  46. package/dist/commands/eval.js.map +1 -1
  47. package/dist/commands/init.d.ts +22 -5
  48. package/dist/commands/init.d.ts.map +1 -1
  49. package/dist/commands/init.js +355 -182
  50. package/dist/commands/init.js.map +1 -1
  51. package/dist/commands/link.d.ts +11 -0
  52. package/dist/commands/link.d.ts.map +1 -0
  53. package/dist/commands/link.js +28 -0
  54. package/dist/commands/link.js.map +1 -0
  55. package/dist/commands/login.d.ts.map +1 -1
  56. package/dist/commands/login.js +14 -2
  57. package/dist/commands/login.js.map +1 -1
  58. package/dist/commands/memory/_lib/browser-auth-cmd.d.ts.map +1 -1
  59. package/dist/commands/memory/_lib/browser-auth-cmd.js +3 -3
  60. package/dist/commands/memory/_lib/browser-auth-cmd.js.map +1 -1
  61. package/dist/commands/memory/_lib/mcp.d.ts +2 -2
  62. package/dist/commands/memory/_lib/mcp.d.ts.map +1 -1
  63. package/dist/commands/memory/_lib/mcp.js +24 -12
  64. package/dist/commands/memory/_lib/mcp.js.map +1 -1
  65. package/dist/commands/memory/_lib/openclaw-auth.d.ts +1 -0
  66. package/dist/commands/memory/_lib/openclaw-auth.d.ts.map +1 -1
  67. package/dist/commands/memory/_lib/openclaw-auth.js +14 -3
  68. package/dist/commands/memory/_lib/openclaw-auth.js.map +1 -1
  69. package/dist/commands/memory/_lib/openclaw-cmd.js +1 -1
  70. package/dist/commands/memory/_lib/openclaw-cmd.js.map +1 -1
  71. package/dist/commands/memory/_lib/schema.d.ts +29 -2
  72. package/dist/commands/memory/_lib/schema.d.ts.map +1 -1
  73. package/dist/commands/memory/_lib/schema.js +121 -5
  74. package/dist/commands/memory/_lib/schema.js.map +1 -1
  75. package/dist/commands/memory/_lib/seed-cmd.d.ts.map +1 -1
  76. package/dist/commands/memory/_lib/seed-cmd.js +46 -24
  77. package/dist/commands/memory/_lib/seed-cmd.js.map +1 -1
  78. package/dist/commands/memory/run.d.ts.map +1 -1
  79. package/dist/commands/memory/run.js +2 -2
  80. package/dist/commands/memory/run.js.map +1 -1
  81. package/dist/commands/org.d.ts +4 -0
  82. package/dist/commands/org.d.ts.map +1 -1
  83. package/dist/commands/org.js +10 -0
  84. package/dist/commands/org.js.map +1 -1
  85. package/dist/commands/platforms/platform-prompts.d.ts +0 -1
  86. package/dist/commands/platforms/platform-prompts.d.ts.map +1 -1
  87. package/dist/commands/platforms/platform-prompts.js +54 -8
  88. package/dist/commands/platforms/platform-prompts.js.map +1 -1
  89. package/dist/commands/telemetry.d.ts +10 -0
  90. package/dist/commands/telemetry.d.ts.map +1 -0
  91. package/dist/commands/telemetry.js +68 -0
  92. package/dist/commands/telemetry.js.map +1 -0
  93. package/dist/commands/token.d.ts +9 -0
  94. package/dist/commands/token.d.ts.map +1 -1
  95. package/dist/commands/token.js +54 -0
  96. package/dist/commands/token.js.map +1 -1
  97. package/dist/commands/whoami.d.ts.map +1 -1
  98. package/dist/commands/whoami.js +1 -1
  99. package/dist/commands/whoami.js.map +1 -1
  100. package/dist/connectors/README.md +534 -0
  101. package/dist/connectors/__tests__/browser-scraper-utils.test.ts +186 -0
  102. package/dist/connectors/apple_health.ts +138 -0
  103. package/dist/connectors/apple_screen_time.ts +82 -0
  104. package/dist/connectors/browser-scraper-utils.ts +246 -0
  105. package/dist/connectors/capterra.ts +277 -0
  106. package/dist/connectors/g2.ts +290 -0
  107. package/dist/connectors/github.ts +1530 -0
  108. package/dist/connectors/glassdoor.ts +295 -0
  109. package/dist/connectors/gmaps.ts +197 -0
  110. package/dist/connectors/google_calendar.ts +641 -0
  111. package/dist/connectors/google_gmail.ts +754 -0
  112. package/dist/connectors/google_photos.ts +776 -0
  113. package/dist/connectors/google_play.ts +349 -0
  114. package/dist/connectors/hackernews.ts +471 -0
  115. package/dist/connectors/index.ts +28 -0
  116. package/dist/connectors/ios_appstore.ts +226 -0
  117. package/dist/connectors/linkedin.ts +494 -0
  118. package/dist/connectors/local_directory.ts +91 -0
  119. package/dist/connectors/microsoft_outlook.ts +410 -0
  120. package/dist/connectors/producthunt.ts +471 -0
  121. package/dist/connectors/reddit.ts +600 -0
  122. package/dist/connectors/revolut.ts +572 -0
  123. package/dist/connectors/rss.ts +448 -0
  124. package/dist/connectors/spotify.ts +590 -0
  125. package/dist/connectors/trustpilot.ts +203 -0
  126. package/dist/connectors/website.ts +629 -0
  127. package/dist/connectors/whatsapp.ts +1081 -0
  128. package/dist/connectors/whatsapp_local.ts +125 -0
  129. package/dist/connectors/x.ts +536 -0
  130. package/dist/connectors/youtube.ts +666 -0
  131. package/dist/db/migrations/00000000000000_baseline.sql +4867 -0
  132. package/dist/db/migrations/20260405193000_add_mcp_sessions.sql +33 -0
  133. package/dist/db/migrations/20260408120000_remove_system_connectors.sql +48 -0
  134. package/dist/db/migrations/20260408120001_optional_compiled_code.sql +6 -0
  135. package/dist/db/migrations/20260409110000_add_active_watcher_run_index.sql +9 -0
  136. package/dist/db/migrations/20260409130000_connector_default_config.sql +5 -0
  137. package/dist/db/migrations/20260410120000_add_agent_secrets.sql +25 -0
  138. package/dist/db/migrations/20260413170000_add_watcher_group_id.sql +67 -0
  139. package/dist/db/migrations/20260416120000_add_entity_wa_jid_index.sql +14 -0
  140. package/dist/db/migrations/20260417100000_add_entity_identities.sql +77 -0
  141. package/dist/db/migrations/20260418100000_add_auth_runs.sql +83 -0
  142. package/dist/db/migrations/20260418110000_add_runs_created_by_user.sql +18 -0
  143. package/dist/db/migrations/20260419120000_add_event_identity_indexes.sql +56 -0
  144. package/dist/db/migrations/20260420120000_extend_reserved_org_slugs.sql +56 -0
  145. package/dist/db/migrations/20260424030000_add_watcher_run_correlation.sql +52 -0
  146. package/dist/db/migrations/20260424130000_relax_events_client_id_fk.sql +47 -0
  147. package/dist/db/migrations/20260425100000_normalize_watcher_feedback.sql +91 -0
  148. package/dist/db/migrations/20260425120000_add_run_diagnostics.sql +20 -0
  149. package/dist/db/migrations/20260425130000_add_repair_agent_plumbing.sql +46 -0
  150. package/dist/db/migrations/20260426120000_entities_entity_type_fk.sql +101 -0
  151. package/dist/db/migrations/20260426130000_db_integrity_cleanup.sql +104 -0
  152. package/dist/db/migrations/20260426130001_db_integrity_cleanup_concurrent.sql +187 -0
  153. package/dist/db/migrations/20260427133000_events_created_by_nullable.sql +74 -0
  154. package/dist/db/migrations/20260427140000_identity_engine_indexes.sql +140 -0
  155. package/dist/db/migrations/20260427150000_drop_events_source_id.sql +177 -0
  156. package/dist/db/migrations/20260427160000_drop_dead_schema.sql +76 -0
  157. package/dist/db/migrations/20260427170000_market_founder_to_member.sql +364 -0
  158. package/dist/db/migrations/20260428040000_cascade_events_watchers_org_fk.sql +66 -0
  159. package/dist/db/migrations/20260428050000_add_runs_approved_input.sql +9 -0
  160. package/dist/db/migrations/20260429010000_auth_profile_tenant_scoped_fk.sql +79 -0
  161. package/dist/db/migrations/20260429060000_extend_runs_for_lobu_queue.sql +108 -0
  162. package/dist/db/migrations/20260429120000_agent_changed_notify.sql +97 -0
  163. package/dist/db/migrations/20260429120100_user_auth_profiles_and_model_prefs.sql +36 -0
  164. package/dist/db/migrations/20260429120200_fix_notify_old_keys.sql +130 -0
  165. package/dist/db/migrations/20260429130000_oauth_states_cli_sessions_rate_limits.sql +83 -0
  166. package/dist/db/migrations/20260429140000_phase8_grants_chat_connections_mcp_sessions.sql +84 -0
  167. package/dist/db/migrations/20260429140100_runs_priority_expires_at_retry_delay.sql +44 -0
  168. package/dist/db/migrations/20260429180000_drop_invalidatable_cache_triggers.sql +25 -0
  169. package/dist/db/migrations/20260430005614_agents_apply_fields.sql +21 -0
  170. package/dist/db/migrations/20260430022231_fix_connection_config_encryption.sql +69 -0
  171. package/dist/db/migrations/20260430151215_add_task_run_type.sql +77 -0
  172. package/dist/db/migrations/20260501000000_drop_cli_sessions.sql +27 -0
  173. package/dist/db/migrations/20260501133000_lobu_memory_mcp_id.sql +117 -0
  174. package/dist/db/migrations/20260502000000_drop_chat_connections.sql +60 -0
  175. package/dist/db/migrations/20260503000000_agent_secrets_org_scope.sql +56 -0
  176. package/dist/db/migrations/20260504000000_flatten_agents_drop_sandbox_model.sql +48 -0
  177. package/dist/db/migrations/20260510220000_connector_required_capability.sql +47 -0
  178. package/dist/db/migrations/20260512000000_device_worker_connection_binding.sql +113 -0
  179. package/dist/db/migrations/20260512131703_connections_slug.sql +131 -0
  180. package/dist/db/migrations/20260513000000_chat_user_identities.sql +24 -0
  181. package/dist/db/migrations/20260513120000_auth_profiles_device_binding.sql +50 -0
  182. package/dist/db/migrations/20260513150000_auth_profiles_cdp_url.sql +43 -0
  183. package/dist/db/migrations/20260513200000_notifications_as_events.sql +86 -0
  184. package/dist/db/migrations/20260514000000_scheduled_jobs.sql +97 -0
  185. package/dist/db/migrations/20260514120000_auth_profiles_connector_key_nullable.sql +42 -0
  186. package/dist/eval/types.d.ts +2 -0
  187. package/dist/eval/types.d.ts.map +1 -1
  188. package/dist/index.d.ts +11 -0
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +210 -132
  191. package/dist/index.js.map +1 -1
  192. package/dist/internal/api-client.d.ts +4 -8
  193. package/dist/internal/api-client.d.ts.map +1 -1
  194. package/dist/internal/api-client.js +1 -1
  195. package/dist/internal/api-client.js.map +1 -1
  196. package/dist/internal/context.js +2 -2
  197. package/dist/internal/context.js.map +1 -1
  198. package/dist/internal/credentials.d.ts.map +1 -1
  199. package/dist/internal/credentials.js +6 -1
  200. package/dist/internal/credentials.js.map +1 -1
  201. package/dist/internal/gateway-url.d.ts +14 -0
  202. package/dist/internal/gateway-url.d.ts.map +1 -1
  203. package/dist/internal/gateway-url.js +19 -0
  204. package/dist/internal/gateway-url.js.map +1 -1
  205. package/dist/internal/index.d.ts +3 -4
  206. package/dist/internal/index.d.ts.map +1 -1
  207. package/dist/internal/index.js +3 -3
  208. package/dist/internal/index.js.map +1 -1
  209. package/dist/internal/oauth.d.ts +6 -5
  210. package/dist/internal/oauth.d.ts.map +1 -1
  211. package/dist/internal/oauth.js +2 -2
  212. package/dist/internal/project-link.d.ts +10 -0
  213. package/dist/internal/project-link.d.ts.map +1 -0
  214. package/dist/internal/project-link.js +48 -0
  215. package/dist/internal/project-link.js.map +1 -0
  216. package/dist/providers.json +2 -2
  217. package/dist/server.bundle.mjs +31654 -30866
  218. package/dist/start-local.bundle.mjs +74409 -0
  219. package/dist/templates/README.md.tmpl +10 -11
  220. package/dist/templates/TESTING.md.tmpl +9 -9
  221. package/package.json +15 -13
  222. package/dist/__tests__/chat.integration.test.d.ts +0 -2
  223. package/dist/__tests__/chat.integration.test.d.ts.map +0 -1
  224. package/dist/__tests__/chat.integration.test.js +0 -337
  225. package/dist/__tests__/chat.integration.test.js.map +0 -1
  226. package/dist/__tests__/dev.test.d.ts +0 -2
  227. package/dist/__tests__/dev.test.d.ts.map +0 -1
  228. package/dist/__tests__/dev.test.js +0 -25
  229. package/dist/__tests__/dev.test.js.map +0 -1
  230. package/dist/__tests__/init-memory.test.d.ts +0 -2
  231. package/dist/__tests__/init-memory.test.d.ts.map +0 -1
  232. package/dist/__tests__/init-memory.test.js +0 -45
  233. package/dist/__tests__/init-memory.test.js.map +0 -1
  234. package/dist/__tests__/token.test.d.ts +0 -2
  235. package/dist/__tests__/token.test.d.ts.map +0 -1
  236. package/dist/__tests__/token.test.js +0 -52
  237. package/dist/__tests__/token.test.js.map +0 -1
  238. package/dist/commands/_lib/apply/__tests__/client.test.d.ts +0 -2
  239. package/dist/commands/_lib/apply/__tests__/client.test.d.ts.map +0 -1
  240. package/dist/commands/_lib/apply/__tests__/client.test.js +0 -23
  241. package/dist/commands/_lib/apply/__tests__/client.test.js.map +0 -1
  242. package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts +0 -2
  243. package/dist/commands/_lib/apply/__tests__/desired-state.test.d.ts.map +0 -1
  244. package/dist/commands/_lib/apply/__tests__/desired-state.test.js +0 -140
  245. package/dist/commands/_lib/apply/__tests__/desired-state.test.js.map +0 -1
  246. package/dist/commands/_lib/apply/__tests__/diff.test.d.ts +0 -2
  247. package/dist/commands/_lib/apply/__tests__/diff.test.d.ts.map +0 -1
  248. package/dist/commands/_lib/apply/__tests__/diff.test.js +0 -378
  249. package/dist/commands/_lib/apply/__tests__/diff.test.js.map +0 -1
  250. package/dist/commands/apply.d.ts +0 -3
  251. package/dist/commands/apply.d.ts.map +0 -1
  252. package/dist/commands/apply.js +0 -5
  253. package/dist/commands/apply.js.map +0 -1
  254. package/dist/commands/memory/_lib/openclaw-auth.test.d.ts +0 -2
  255. package/dist/commands/memory/_lib/openclaw-auth.test.d.ts.map +0 -1
  256. package/dist/commands/memory/_lib/openclaw-auth.test.js +0 -9
  257. package/dist/commands/memory/_lib/openclaw-auth.test.js.map +0 -1
  258. package/dist/internal/__tests__/api-client.test.d.ts +0 -2
  259. package/dist/internal/__tests__/api-client.test.d.ts.map +0 -1
  260. package/dist/internal/__tests__/api-client.test.js +0 -95
  261. package/dist/internal/__tests__/api-client.test.js.map +0 -1
  262. package/dist/internal/__tests__/context.test.d.ts +0 -2
  263. package/dist/internal/__tests__/context.test.d.ts.map +0 -1
  264. package/dist/internal/__tests__/context.test.js +0 -77
  265. package/dist/internal/__tests__/context.test.js.map +0 -1
package/dist/index.js CHANGED
@@ -11,6 +11,14 @@ async function getPackageVersion() {
11
11
  const pkg = JSON.parse(pkgContent);
12
12
  return pkg.version ?? "0.0.0";
13
13
  }
14
+ function withCommonOpts(cmd, opts = {}) {
15
+ cmd.option("-c, --context <name>", "Use a named context");
16
+ if (opts.org)
17
+ cmd.option("--org <slug>", "Org slug override");
18
+ if (opts.json)
19
+ cmd.option("--json", "Print JSON");
20
+ return cmd;
21
+ }
14
22
  function handleCliError(error) {
15
23
  const exitCode = typeof error === "object" &&
16
24
  error !== null &&
@@ -29,14 +37,77 @@ export async function runCli(argv = process.argv) {
29
37
  .name("lobu")
30
38
  .description("CLI for deploying and managing AI agents on Lobu")
31
39
  .version(version);
40
+ // Group commands in --help output. Commander v14 has no native grouping,
41
+ // so we override the help formatter via addHelpText to print our own
42
+ // categorized list. The flat command list is still available.
43
+ program.addHelpText("after", `
44
+ Local dev:
45
+ init [name] Scaffold a new agent project
46
+ run | dev | start Boot the embedded Lobu stack
47
+ chat <prompt> Send a prompt to an agent and stream the response
48
+ eval [name] Run agent evaluations
49
+ validate Validate lobu.toml
50
+ doctor Health checks (deps, DB, pgvector, ports, keys)
51
+ telemetry Show / toggle anonymous error reporting
52
+
53
+ Cloud:
54
+ login | logout OAuth device-code login (or --token for CI)
55
+ whoami | status Show user / agent state
56
+ context <subcmd> Manage API contexts
57
+ org <subcmd> Manage active org slug
58
+ link | unlink Bind this directory to a (context, org)
59
+ apply | deploy Sync lobu.toml to cloud (idempotent)
60
+ agent <subcmd> CRUD agents via REST
61
+ token [create] Print or mint personal access tokens
62
+
63
+ Memory:
64
+ memory run [tool] Invoke a memory MCP tool
65
+ memory exec <script> Run a ClientSDK script
66
+ memory health Validate login + MCP connectivity
67
+ memory configure Wire OpenClaw config
68
+ memory seed [path] Provision a memory workspace
69
+ memory init Wire agents to a memory MCP endpoint
70
+ `);
32
71
  // ─── init ───────────────────────────────────────────────────────────
33
72
  program
34
73
  .command("init [name]")
35
74
  .description("Scaffold a new agent project (lobu.toml + agent files + .env)")
36
- .action(async (name) => {
75
+ .option("-y, --yes", "Skip prompts; use defaults / flag values")
76
+ .option("--here", "Scaffold into the current directory (alias for `init .`)")
77
+ .option("--port <port>", "Gateway port (default 8787)")
78
+ .option("--public-url <url>", "Public gateway URL (OAuth/webhooks)")
79
+ .option("--network <policy>", "Worker network policy: restricted | open | isolated")
80
+ .option("--provider <id>", "Provider id from `config/providers.json`")
81
+ .option("--provider-key <key>", "Provider API key (else read from env)")
82
+ .option("--platform <type>", "Chat platform: telegram | slack | discord | whatsapp | teams | gchat")
83
+ .option("--memory <choice>", "Memory backend: none | lobu-cloud | lobu-custom")
84
+ .option("--memory-url <url>", "Custom memory MCP URL (with --memory lobu-custom)")
85
+ .option("--otel-endpoint <url>", "OpenTelemetry collector endpoint")
86
+ .option("--sentry", "Enable Sentry error reporting")
87
+ .option("--no-sentry", "Disable Sentry without prompting")
88
+ .option("--slack-preview", "Enable public Lobu Developer Slack Preview in lobu.toml")
89
+ .option("--no-slack-preview", "Disable Slack Preview without prompting")
90
+ .action(async (name, options) => {
37
91
  try {
38
92
  const { initCommand } = await import("./commands/init.js");
39
- await initCommand(process.cwd(), name);
93
+ // Commander gives a tristate: true for --sentry, false for
94
+ // --no-sentry, undefined for neither.
95
+ await initCommand(process.cwd(), name, {
96
+ yes: options.yes,
97
+ here: options.here,
98
+ port: options.port,
99
+ publicUrl: options.publicUrl,
100
+ network: options.network,
101
+ provider: options.provider,
102
+ providerKey: options.providerKey,
103
+ platform: options.platform,
104
+ memory: options.memory,
105
+ memoryUrl: options.memoryUrl,
106
+ otelEndpoint: options.otelEndpoint,
107
+ sentry: options.sentry === true,
108
+ noSentry: options.sentry === false,
109
+ slackPreview: options.slackPreview,
110
+ });
40
111
  }
41
112
  catch (error) {
42
113
  console.error(chalk.red("\n Error:"), error);
@@ -46,20 +117,23 @@ export async function runCli(argv = process.argv) {
46
117
  // ─── chat ──────────────────────────────────────────────────────────
47
118
  program
48
119
  .command("chat <prompt>")
49
- .description("Send a prompt to an agent and stream the response")
120
+ .description("Send a prompt to an agent and stream the response. With --user, routes through Telegram/Slack.")
50
121
  .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
51
122
  .option("-u, --user <id>", "User ID to impersonate (e.g. telegram:12345)")
52
123
  .option("-t, --thread <id>", "Thread/conversation ID for multi-turn")
53
124
  .option("-g, --gateway <url>", `Gateway URL (default: ${GATEWAY_DEFAULT_URL})`)
54
125
  .option("--dry-run", "Process without persisting history")
55
126
  .option("--new", "Force new session (ignore existing)")
127
+ .option("-C, --continue", "Resume the last thread for this (context, agent)")
128
+ .option("--auto-approve", "Auto-approve every tool call (use only in trusted environments)")
129
+ .option("--json", "Emit raw SSE events as JSON lines instead of text")
56
130
  .option("-c, --context <name>", "Use a named context")
57
131
  .action(async (prompt, options) => {
58
132
  const { chatCommand } = await import("./commands/chat.js");
59
133
  await chatCommand(process.cwd(), prompt, options);
60
134
  });
61
135
  // ─── eval ──────────────────────────────────────────────────────────
62
- program
136
+ const evalCmd = program
63
137
  .command("eval [name]")
64
138
  .description("Run agent evaluations")
65
139
  .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
@@ -74,6 +148,16 @@ export async function runCli(argv = process.argv) {
74
148
  const { evalCommand } = await import("./commands/eval.js");
75
149
  await evalCommand(process.cwd(), name, options);
76
150
  });
151
+ evalCmd
152
+ .command("new <name>")
153
+ .description("Scaffold a new YAML eval into the agent's evals/ directory")
154
+ .option("-a, --agent <id>", "Agent ID (defaults to first in lobu.toml)")
155
+ .option("--description <text>", "Eval description")
156
+ .option("--trials <n>", "Trial count", parseInt)
157
+ .action(async (name, options) => {
158
+ const { evalNewCommand } = await import("./commands/eval.js");
159
+ await evalNewCommand(name, options);
160
+ });
77
161
  // ─── validate ───────────────────────────────────────────────────────
78
162
  program
79
163
  .command("validate")
@@ -84,18 +168,17 @@ export async function runCli(argv = process.argv) {
84
168
  if (!valid)
85
169
  process.exit(1);
86
170
  });
87
- // ─── apply ──────────────────────────────────────────────────────────
88
- // One-way `lobu.toml` → cloud org converger. GETs current state, renders
89
- // a diff, prompts to confirm, then loops over the existing CRUD endpoints
90
- // in dependency order. Re-running converges on partial failure.
171
+ // ─── apply / deploy ─────────────────────────────────────────────────
91
172
  program
92
173
  .command("apply")
174
+ .alias("deploy")
93
175
  .description("Sync lobu.toml + agent dirs to your Lobu Cloud org (idempotent)")
94
176
  .option("--dry-run", "Show the plan and exit without mutating")
95
177
  .option("--yes", "Skip the confirmation prompt (CI mode)")
96
178
  .option("--only <kind>", "Restrict to one resource family: 'agents' | 'memory'")
97
179
  .option("--org <slug>", "Org slug override (defaults to active session)")
98
180
  .option("--url <url>", "Server URL override")
181
+ .option("--force", "Bypass the project-link guard if context/org don't match")
99
182
  .action(async (options) => {
100
183
  if (options.only !== undefined &&
101
184
  options.only !== "agents" &&
@@ -103,71 +186,59 @@ export async function runCli(argv = process.argv) {
103
186
  console.error(chalk.red("\n Error:"), `--only must be 'agents' or 'memory' (got: ${options.only})`);
104
187
  process.exit(2);
105
188
  }
106
- const { lobuApplyCommand } = await import("./commands/apply.js");
107
- await lobuApplyCommand({
189
+ const { applyCommand } = await import("./commands/_lib/apply/apply-cmd.js");
190
+ await applyCommand({
108
191
  dryRun: options.dryRun,
109
192
  yes: options.yes,
110
193
  only: options.only,
111
194
  org: options.org,
112
195
  url: options.url,
196
+ force: options.force,
113
197
  });
114
198
  });
115
- // ─── run ────────────────────────────────────────────────────────────
116
- // Boots the embedded Lobu stack (gateway + workers + memory backend) as
117
- // a single Node process. Extra args are forwarded to the bundle entry.
199
+ // ─── run / dev / start ──────────────────────────────────────────────
118
200
  program
119
201
  .command("run")
202
+ .aliases(["dev", "start"])
120
203
  .description("Run the embedded Lobu stack (gateway + workers in one Node process)")
121
- .allowUnknownOption(true)
122
- .helpOption(false)
123
- .action(async (_opts, cmd) => {
204
+ .option("--port <port>", "Gateway port (overrides GATEWAY_PORT in .env)")
205
+ .option("--quiet", "Suppress startup banner; raise log level to warn")
206
+ .option("--verbose", "Lower log level to debug")
207
+ .option("--log-level <level>", "Forwarded as LOG_LEVEL to the bundle")
208
+ .action(async (options) => {
124
209
  const { devCommand } = await import("./commands/dev.js");
125
- await devCommand(process.cwd(), cmd.args);
210
+ await devCommand(process.cwd(), options);
126
211
  });
127
212
  // ─── login ──────────────────────────────────────────────────────────
128
- program
213
+ withCommonOpts(program
129
214
  .command("login")
130
215
  .description("Authenticate with Lobu Cloud")
131
- .option("--token <token>", "Use API token directly (CI/CD)")
132
- .option("-c, --context <name>", "Use a named context")
216
+ .option("--token <token>", "Use API token directly (CI/CD)"))
133
217
  .option("-f, --force", "Re-authenticate (revokes existing session)")
134
218
  .action(async (options) => {
135
219
  const { loginCommand } = await import("./commands/login.js");
136
220
  await loginCommand({ ...options, cliVersion: version });
137
221
  });
138
222
  // ─── logout ─────────────────────────────────────────────────────────
139
- program
140
- .command("logout")
141
- .description("Clear stored credentials")
142
- .option("-c, --context <name>", "Use a named context")
143
- .action(async (options) => {
223
+ withCommonOpts(program.command("logout").description("Clear stored credentials")).action(async (options) => {
144
224
  const { logoutCommand } = await import("./commands/logout.js");
145
225
  await logoutCommand(options);
146
226
  });
147
227
  // ─── whoami ─────────────────────────────────────────────────────────
148
- program
149
- .command("whoami")
150
- .description("Show current user and linked agent")
151
- .option("-c, --context <name>", "Use a named context")
152
- .action(async (options) => {
228
+ withCommonOpts(program.command("whoami").description("Show current user and linked agent")).action(async (options) => {
153
229
  const { whoamiCommand } = await import("./commands/whoami.js");
154
230
  await whoamiCommand(options);
155
231
  });
156
232
  // ─── token ──────────────────────────────────────────────────────────
157
- const token = program
158
- .command("token")
159
- .description("Print or create Lobu access tokens")
160
- .option("-c, --context <name>", "Use a named context")
233
+ const token = withCommonOpts(program.command("token").description("Print or create Lobu access tokens"))
161
234
  .option("--raw", "Print token only (no labels)")
162
235
  .action(async (options) => {
163
236
  const { tokenCommand } = await import("./commands/token.js");
164
237
  await tokenCommand(options);
165
238
  });
166
- token
239
+ withCommonOpts(token
167
240
  .command("create")
168
- .description("Create an org-scoped personal access token for servers/CI")
169
- .option("-c, --context <name>", "Use a named context")
170
- .option("--org <slug>", "Org slug override")
241
+ .description("Create an org-scoped personal access token for servers/CI"), { org: true })
171
242
  .option("--name <name>", "Token name (default: lobu-cli-YYYY-MM-DD)")
172
243
  .option("--description <text>", "Token description")
173
244
  .option("--scope <scope>", "Space-separated scopes (default: mcp:read mcp:write)")
@@ -184,6 +255,14 @@ export async function runCli(argv = process.argv) {
184
255
  const { tokenCreateCommand } = await import("./commands/token.js");
185
256
  await tokenCreateCommand(options);
186
257
  });
258
+ token
259
+ .command("revoke <jti>")
260
+ .description("Revoke a worker/settings token by its jti (kill switch)")
261
+ .option("--expires-at <iso>", "Original token expiry (ISO 8601); the revocation row is GC'd past it. Defaults to 24h from now.")
262
+ .action(async (jti, options) => {
263
+ const { tokenRevokeCommand } = await import("./commands/token.js");
264
+ await tokenRevokeCommand(jti, options);
265
+ });
187
266
  // ─── context ────────────────────────────────────────────────────────
188
267
  const context = program
189
268
  .command("context")
@@ -218,192 +297,191 @@ export async function runCli(argv = process.argv) {
218
297
  await contextUseCommand(name);
219
298
  });
220
299
  // ─── status ─────────────────────────────────────────────────────────
221
- program
300
+ withCommonOpts(program
222
301
  .command("status")
223
- .description("Show agent status from the active org")
224
- .option("-c, --context <name>", "Use a named context")
225
- .option("--org <slug>", "Org slug override")
226
- .action(async (options) => {
302
+ .description("Show agent status from the active org"), { org: true }).action(async (options) => {
227
303
  const { statusCommand } = await import("./commands/status.js");
228
304
  await statusCommand(options);
229
305
  });
230
306
  // ─── org ────────────────────────────────────────────────────────────
231
307
  const org = program.command("org").description("Manage active Lobu org");
232
- org
308
+ withCommonOpts(org
233
309
  .command("list")
234
- .description("List organizations available to the current login")
235
- .option("-c, --context <name>", "Use a named context")
236
- .action(async (options) => {
310
+ .description("List organizations available to the current login")).action(async (options) => {
237
311
  const { orgListCommand } = await import("./commands/org.js");
238
312
  await orgListCommand(options);
239
313
  });
240
- org
241
- .command("current")
242
- .description("Show the active org")
243
- .option("-c, --context <name>", "Use a named context")
244
- .action(async (options) => {
314
+ withCommonOpts(org.command("current").description("Show the active org")).action(async (options) => {
245
315
  const { orgCurrentCommand } = await import("./commands/org.js");
246
316
  await orgCurrentCommand(options);
247
317
  });
248
- org
249
- .command("set <slug>")
250
- .description("Set the active org slug")
251
- .option("-c, --context <name>", "Use a named context")
252
- .action(async (slug, options) => {
318
+ withCommonOpts(org.command("set <slug>").description("Set the active org slug")).action(async (slug, options) => {
253
319
  const { orgSetCommand } = await import("./commands/org.js");
254
320
  await orgSetCommand(slug, options);
255
321
  });
322
+ withCommonOpts(org
323
+ .command("create <slug>")
324
+ .description("Open the browser to create an organization (slug pre-filled)")
325
+ .option("-n, --name <name>", "Organization display name")).action(async (slug, options) => {
326
+ const { orgCreateCommand } = await import("./commands/org.js");
327
+ await orgCreateCommand(slug, options);
328
+ });
329
+ // ─── link / unlink ──────────────────────────────────────────────────
330
+ withCommonOpts(program
331
+ .command("link")
332
+ .description("Bind the current directory to a (context, org). Stored at .lobu/project.json.")
333
+ .option("--org <slug>", "Org slug to link (defaults to active)")).action(async (options) => {
334
+ const { linkCommand } = await import("./commands/link.js");
335
+ await linkCommand(options);
336
+ });
337
+ program
338
+ .command("unlink")
339
+ .description("Remove the project link file")
340
+ .action(async () => {
341
+ const { unlinkCommand } = await import("./commands/link.js");
342
+ await unlinkCommand();
343
+ });
256
344
  // ─── agent ──────────────────────────────────────────────────────────
257
345
  const agent = program
258
346
  .command("agent")
259
347
  .description("Manage agents via the same REST API as the web app");
260
- agent
261
- .command("list")
262
- .description("List agents")
263
- .option("-c, --context <name>", "Use a named context")
264
- .option("--org <slug>", "Org slug override")
265
- .option("--json", "Print JSON")
266
- .action(async (options) => {
348
+ withCommonOpts(agent.command("list").description("List agents"), {
349
+ org: true,
350
+ json: true,
351
+ }).action(async (options) => {
267
352
  const { agentListCommand } = await import("./commands/agent.js");
268
353
  await agentListCommand(options);
269
354
  });
270
- agent
271
- .command("get <agentId>")
272
- .description("Get an agent")
273
- .option("-c, --context <name>", "Use a named context")
274
- .option("--org <slug>", "Org slug override")
275
- .action(async (agentId, options) => {
355
+ withCommonOpts(agent.command("get <agentId>").description("Get an agent"), {
356
+ org: true,
357
+ }).action(async (agentId, options) => {
276
358
  const { agentGetCommand } = await import("./commands/agent.js");
277
359
  await agentGetCommand(agentId, options);
278
360
  });
279
- agent
361
+ withCommonOpts(agent
280
362
  .command("create <agentId>")
281
363
  .description("Create an agent")
282
364
  .option("--name <name>", "Display name")
283
- .option("--description <text>", "Description")
284
- .option("-c, --context <name>", "Use a named context")
285
- .option("--org <slug>", "Org slug override")
286
- .option("--json", "Print JSON")
287
- .action(async (agentId, options) => {
365
+ .option("--description <text>", "Description"), { org: true, json: true }).action(async (agentId, options) => {
288
366
  const { agentCreateCommand } = await import("./commands/agent.js");
289
367
  await agentCreateCommand(agentId, options);
290
368
  });
291
369
  agent
292
- .command("update <agentId>")
293
- .description("Update agent metadata")
370
+ .command("scaffold <agentId>")
371
+ .description("Add a new local agent (agents/<id>/* + lobu.toml entry) without overwriting existing ones")
294
372
  .option("--name <name>", "Display name")
295
373
  .option("--description <text>", "Description")
296
- .option("-c, --context <name>", "Use a named context")
297
- .option("--org <slug>", "Org slug override")
298
- .option("--json", "Print JSON")
299
374
  .action(async (agentId, options) => {
375
+ const { agentScaffoldCommand } = await import("./commands/agent.js");
376
+ await agentScaffoldCommand(agentId, options);
377
+ });
378
+ withCommonOpts(agent
379
+ .command("update <agentId>")
380
+ .description("Update agent metadata")
381
+ .option("--name <name>", "Display name")
382
+ .option("--description <text>", "Description"), { org: true, json: true }).action(async (agentId, options) => {
300
383
  const { agentUpdateCommand } = await import("./commands/agent.js");
301
384
  await agentUpdateCommand(agentId, options);
302
385
  });
303
- agent
386
+ withCommonOpts(agent
304
387
  .command("delete <agentId>")
305
388
  .description("Delete an agent")
306
- .option("--yes", "Confirm deletion")
307
- .option("-c, --context <name>", "Use a named context")
308
- .option("--org <slug>", "Org slug override")
309
- .action(async (agentId, options) => {
389
+ .option("--yes", "Confirm deletion"), { org: true }).action(async (agentId, options) => {
310
390
  const { agentDeleteCommand } = await import("./commands/agent.js");
311
391
  await agentDeleteCommand(agentId, options);
312
392
  });
313
393
  const agentConfig = agent
314
394
  .command("config")
315
395
  .description("Read or patch agent config");
316
- agentConfig
396
+ withCommonOpts(agentConfig
317
397
  .command("get <agentId>")
318
398
  .description("Print agent config JSON")
319
- .option("--output <file>", "Write JSON to a file")
320
- .option("-c, --context <name>", "Use a named context")
321
- .option("--org <slug>", "Org slug override")
322
- .action(async (agentId, options) => {
399
+ .option("--output <file>", "Write JSON to a file"), { org: true }).action(async (agentId, options) => {
323
400
  const { agentConfigGetCommand } = await import("./commands/agent.js");
324
401
  await agentConfigGetCommand(agentId, options);
325
402
  });
326
- agentConfig
403
+ withCommonOpts(agentConfig
327
404
  .command("patch <agentId>")
328
405
  .description("Patch agent config from a JSON file")
329
- .requiredOption("--file <file>", "JSON file with config fields to update")
330
- .option("-c, --context <name>", "Use a named context")
331
- .option("--org <slug>", "Org slug override")
332
- .option("--json", "Print JSON")
333
- .action(async (agentId, options) => {
406
+ .requiredOption("--file <file>", "JSON file with config fields to update"), { org: true, json: true }).action(async (agentId, options) => {
334
407
  const { agentConfigPatchCommand } = await import("./commands/agent.js");
335
408
  await agentConfigPatchCommand(agentId, options);
336
409
  });
337
410
  // ─── doctor ─────────────────────────────────────────────────────────
338
411
  program
339
412
  .command("doctor")
340
- .description("Health checks (system deps, memory MCP)")
413
+ .description("Health checks (deps, DB, pgvector, ports, provider keys)")
341
414
  .option("--memory-only", "Only check memory MCP connectivity + auth")
342
415
  .action(async (options) => {
343
416
  const { doctorCommand } = await import("./commands/doctor.js");
344
417
  await doctorCommand(options);
345
418
  });
419
+ // ─── telemetry ──────────────────────────────────────────────────────
420
+ const telemetry = program
421
+ .command("telemetry")
422
+ .description("Show or toggle anonymous error reporting (Sentry)");
423
+ telemetry
424
+ .command("status", { isDefault: true })
425
+ .description("Show whether telemetry is on or off")
426
+ .action(async () => {
427
+ const { telemetryStatusCommand } = await import("./commands/telemetry.js");
428
+ await telemetryStatusCommand();
429
+ });
430
+ telemetry
431
+ .command("on")
432
+ .description("Enable telemetry (writes SENTRY_DSN to .env)")
433
+ .option("--dsn <dsn>", "Custom Sentry DSN (defaults to Lobu's)")
434
+ .action(async (options) => {
435
+ const { telemetryOnCommand } = await import("./commands/telemetry.js");
436
+ await telemetryOnCommand(options);
437
+ });
438
+ telemetry
439
+ .command("off")
440
+ .description("Disable telemetry (removes SENTRY_DSN from .env)")
441
+ .action(async () => {
442
+ const { telemetryOffCommand } = await import("./commands/telemetry.js");
443
+ await telemetryOffCommand();
444
+ });
346
445
  // ─── memory ─────────────────────────────────────────────────────────
347
- // Memory operations live under the Lobu CLI. Auth is top-level (`lobu login`);
348
- // memory subcommands only configure endpoints and call tools.
349
446
  const memory = program
350
447
  .command("memory")
351
448
  .description("Lobu memory MCP — tools, seeding, and client configuration");
352
449
  const memoryOrg = memory
353
450
  .command("org")
354
451
  .description("Manage active organization for memory MCP");
355
- memoryOrg
356
- .command("current")
357
- .description("Show the active org")
358
- .option("-c, --context <name>", "Use a named context")
359
- .action(async (options) => {
452
+ withCommonOpts(memoryOrg.command("current").description("Show the active org")).action(async (options) => {
360
453
  const { memoryOrgCurrentCommand } = await import("./commands/memory/org.js");
361
454
  await memoryOrgCurrentCommand(options);
362
455
  });
363
- memoryOrg
364
- .command("set <slug>")
365
- .description("Set the active org slug")
366
- .option("-c, --context <name>", "Use a named context")
367
- .action(async (slug, options) => {
456
+ withCommonOpts(memoryOrg.command("set <slug>").description("Set the active org slug")).action(async (slug, options) => {
368
457
  const { memoryOrgSetCommand } = await import("./commands/memory/org.js");
369
458
  await memoryOrgSetCommand(slug, options);
370
459
  });
371
- memory
460
+ withCommonOpts(memory
372
461
  .command("run [tool] [params]")
373
462
  .description("Invoke an MCP tool (or list tools when called bare)")
374
- .option("--url <url>", "Server URL override")
375
- .option("--org <slug>", "Org slug override")
376
- .option("-c, --context <name>", "Use a named context")
377
- .action(async (tool, params, options) => {
463
+ .option("--url <url>", "Server URL override"), { org: true }).action(async (tool, params, options) => {
378
464
  const { memoryRunCommand } = await import("./commands/memory/run.js");
379
465
  await memoryRunCommand(tool, params, options);
380
466
  });
381
- memory
467
+ withCommonOpts(memory
382
468
  .command("exec <script>")
383
469
  .description("Run a TypeScript ClientSDK script via the memory MCP")
384
- .option("--url <url>", "Server URL override")
385
- .option("--org <slug>", "Org slug override")
386
- .option("-c, --context <name>", "Use a named context")
387
- .action(async (script, options) => {
470
+ .option("--url <url>", "Server URL override"), { org: true }).action(async (script, options) => {
388
471
  const { memoryRunCommand } = await import("./commands/memory/run.js");
389
- await memoryRunCommand("run", JSON.stringify({ script }), options);
472
+ await memoryRunCommand("run_sdk", JSON.stringify({ script }), options);
390
473
  });
391
- memory
474
+ withCommonOpts(memory
392
475
  .command("health")
393
476
  .description("Validate Lobu login + MCP connectivity")
394
- .option("--url <url>", "Server URL override")
395
- .option("--org <slug>", "Org slug override")
396
- .option("-c, --context <name>", "Use a named context")
397
- .action(async (options) => {
477
+ .option("--url <url>", "Server URL override"), { org: true }).action(async (options) => {
398
478
  const { memoryHealthCommand } = await import("./commands/memory/health.js");
399
479
  await memoryHealthCommand(options);
400
480
  });
401
- memory
481
+ withCommonOpts(memory
402
482
  .command("configure")
403
483
  .description("Write OpenClaw plugin config pointing at the active memory MCP")
404
- .option("--url <url>", "Server URL override")
405
- .option("--org <slug>", "Org slug override")
406
- .option("-c, --context <name>", "Use a named context")
484
+ .option("--url <url>", "Server URL override"), { org: true })
407
485
  .option("--config-path <path>", "OpenClaw config path (defaults to ~/.openclaw/openclaw.json)")
408
486
  .option("--token-command <cmd>", "Override the plugin's token retrieval command")
409
487
  .action(async (options) => {
@@ -412,9 +490,9 @@ export async function runCli(argv = process.argv) {
412
490
  });
413
491
  memory
414
492
  .command("seed [path]")
415
- .description("Provision a Lobu memory workspace from [memory.owletto] in lobu.toml + ./models + optional ./data")
493
+ .description("Provision a Lobu memory workspace from [memory] in lobu.toml + ./models + optional ./data")
416
494
  .option("--dry-run", "Log what would be created without mutating")
417
- .option("--org <slug>", "Org slug override (defaults to [memory.owletto].org)")
495
+ .option("--org <slug>", "Org slug override (defaults to [memory].org)")
418
496
  .option("--url <url>", "Server URL override")
419
497
  .option("-c, --context <name>", "Use a named context")
420
498
  .action(async (pathArg, options) => {