@neetru/cli 2.3.0 → 2.5.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 (48) hide show
  1. package/dist/commands/artifact-registry.d.ts +7 -0
  2. package/dist/commands/artifact-registry.js +60 -0
  3. package/dist/commands/artifact-registry.js.map +1 -0
  4. package/dist/commands/deploy.js +8 -8
  5. package/dist/commands/deployments.d.ts +5 -5
  6. package/dist/commands/deployments.js +32 -6
  7. package/dist/commands/deployments.js.map +1 -1
  8. package/dist/commands/env.d.ts +11 -0
  9. package/dist/commands/env.js +91 -0
  10. package/dist/commands/env.js.map +1 -1
  11. package/dist/commands/hosting-write.d.ts +6 -0
  12. package/dist/commands/hosting-write.js +52 -0
  13. package/dist/commands/hosting-write.js.map +1 -0
  14. package/dist/commands/products-db.d.ts +9 -9
  15. package/dist/commands/products-db.js +84 -19
  16. package/dist/commands/products-db.js.map +1 -1
  17. package/dist/commands/products.d.ts +2 -2
  18. package/dist/commands/products.js +8 -6
  19. package/dist/commands/products.js.map +1 -1
  20. package/dist/commands/schema.d.ts +25 -0
  21. package/dist/commands/schema.js +321 -0
  22. package/dist/commands/schema.js.map +1 -0
  23. package/dist/commands/servers.d.ts +5 -5
  24. package/dist/commands/servers.js +25 -17
  25. package/dist/commands/servers.js.map +1 -1
  26. package/dist/commands/status.js +3 -2
  27. package/dist/commands/status.js.map +1 -1
  28. package/dist/commands/tenants.d.ts +14 -14
  29. package/dist/commands/tenants.js +62 -30
  30. package/dist/commands/tenants.js.map +1 -1
  31. package/dist/commands/ui.d.ts +1 -0
  32. package/dist/commands/ui.js +454 -0
  33. package/dist/commands/ui.js.map +1 -0
  34. package/dist/commands/workspaces.d.ts +9 -9
  35. package/dist/commands/workspaces.js +66 -31
  36. package/dist/commands/workspaces.js.map +1 -1
  37. package/dist/index.js +164 -65
  38. package/dist/index.js.map +1 -1
  39. package/dist/lib/ai/orchestrator.js +46 -23
  40. package/dist/lib/ai/orchestrator.js.map +1 -1
  41. package/dist/lib/config-schema.d.ts +18 -18
  42. package/dist/lib/pickers.d.ts +123 -0
  43. package/dist/lib/pickers.js +336 -0
  44. package/dist/lib/pickers.js.map +1 -0
  45. package/dist/lib/schema-cache.d.ts +87 -0
  46. package/dist/lib/schema-cache.js +134 -0
  47. package/dist/lib/schema-cache.js.map +1 -0
  48. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,6 +16,14 @@ program
16
16
  const { runAiRepl } = await import('./commands/ai.js');
17
17
  await runAiRepl({ model: opts.model });
18
18
  });
19
+ program
20
+ .command('ui')
21
+ .alias('menu')
22
+ .description('Abrir a interface interativa do Neetru CLI')
23
+ .action(async () => {
24
+ const { runTerminalUi } = await import('./commands/ui.js');
25
+ await runTerminalUi();
26
+ });
19
27
  // ── neetru init ───────────────────────────────────────────────────────
20
28
  // v2.1.1 — prompt interativo de caminho + merge mode + preserva arquivos
21
29
  program
@@ -231,7 +239,7 @@ tenantsCmd
231
239
  });
232
240
  });
233
241
  tenantsCmd
234
- .command('get <id>')
242
+ .command('get [id]')
235
243
  .description('Mostrar detalhes de um tenant')
236
244
  .option('--json', 'saída em JSON')
237
245
  .action(async (id, opts) => {
@@ -241,11 +249,11 @@ tenantsCmd
241
249
  tenantsCmd
242
250
  .command('create')
243
251
  .description('Criar tenant (status inicial: em provisionamento)')
244
- .requiredOption('--name <name>', 'nome do tenant')
245
- .requiredOption('--slug <slug>', 'slug do tenant')
246
- .requiredOption('--customer <customerId>', 'id do customer')
247
- .requiredOption('--product <productId>', 'id do produto')
248
- .requiredOption('--env <env>', 'dev | staging | prod')
252
+ .option('--name <name>', 'nome do tenant')
253
+ .option('--slug <slug>', 'slug do tenant')
254
+ .option('--customer <customerId>', 'id do customer')
255
+ .option('--product <productId>', 'id do produto (interativo se ausente)')
256
+ .option('--env <env>', 'dev | staging | prod (default: dev)')
249
257
  .option('--domain <domain>', 'domínio primário')
250
258
  .option('--json', 'saída em JSON')
251
259
  .action(async (opts) => {
@@ -261,13 +269,13 @@ tenantsCmd
261
269
  });
262
270
  });
263
271
  tenantsCmd
264
- .command('update <id>')
272
+ .command('update [id]')
265
273
  .description('Atualizar dados de um tenant')
266
- .requiredOption('--name <name>', 'nome do tenant')
267
- .requiredOption('--slug <slug>', 'slug do tenant')
268
- .requiredOption('--customer <customerId>', 'id do customer')
269
- .requiredOption('--product <productId>', 'id do produto')
270
- .requiredOption('--env <env>', 'dev | staging | prod')
274
+ .option('--name <name>', 'nome do tenant')
275
+ .option('--slug <slug>', 'slug do tenant')
276
+ .option('--customer <customerId>', 'id do customer')
277
+ .option('--product <productId>', 'id do produto (interativo se ausente)')
278
+ .option('--env <env>', 'dev | staging | prod (default: dev)')
271
279
  .option('--domain <domain>', 'domínio primário')
272
280
  .option('--json', 'saída em JSON')
273
281
  .action(async (id, opts) => {
@@ -283,7 +291,7 @@ tenantsCmd
283
291
  });
284
292
  });
285
293
  tenantsCmd
286
- .command('suspend <id>')
294
+ .command('suspend [id]')
287
295
  .description('Suspender tenant (destrutivo — exige confirmação)')
288
296
  .option('--yes', 'pula a confirmação interativa (modo script)')
289
297
  .option('--force', 'alias de --yes')
@@ -293,7 +301,7 @@ tenantsCmd
293
301
  await runTenantsSuspend(id, { yes: !!opts.yes, force: !!opts.force, json: !!opts.json });
294
302
  });
295
303
  tenantsCmd
296
- .command('reactivate <id>')
304
+ .command('reactivate [id]')
297
305
  .description('Reativar tenant suspenso')
298
306
  .option('--json', 'saída em JSON')
299
307
  .action(async (id, opts) => {
@@ -343,14 +351,20 @@ const serversCmd = program
343
351
  serversCmd
344
352
  .command('list')
345
353
  .description('Listar servers')
346
- .option('--status <status>', 'online (operacional + heartbeat fresco)')
354
+ .option('--status <status>', 'online | operacional (ativo) ou offline | desconectado (inativo)')
347
355
  .option('--provider <provider>', 'hetzner | digitalocean | aws | ...')
348
356
  .option('--capacity', 'inclui colunas de RAM/CPU/disco')
349
357
  .option('--json', 'saída em JSON')
350
358
  .action(async (opts) => {
359
+ const STATUS_ALIASES = {
360
+ operacional: 'online',
361
+ desconectado: 'offline',
362
+ };
363
+ const rawStatus = opts.status;
364
+ const resolvedStatus = rawStatus ? (STATUS_ALIASES[rawStatus] ?? rawStatus) : undefined;
351
365
  const { runServersList } = await import('./commands/servers.js');
352
366
  await runServersList({
353
- status: opts.status,
367
+ status: resolvedStatus,
354
368
  provider: opts.provider,
355
369
  capacity: !!opts.capacity,
356
370
  json: !!opts.json,
@@ -359,9 +373,9 @@ serversCmd
359
373
  serversCmd
360
374
  .command('provision')
361
375
  .description('Provisionar VM GCP e gerar registration token (admin)')
362
- .requiredOption('--name <name>', 'nome do servidor')
363
- .requiredOption('--zone <zone>', 'zona GCP (ex: us-central1-a)')
364
- .requiredOption('--machine-type <type>', 'machine type GCP (ex: e2-small)')
376
+ .option('--name <name>', 'nome do servidor')
377
+ .option('--zone <zone>', 'zona GCP (ex: us-central1-a)')
378
+ .option('--machine-type <type>', 'machine type GCP (ex: e2-small)')
365
379
  .option('--tenant <tenantId>', 'tenant associado')
366
380
  .option('--customer <customerId>', 'customer associado')
367
381
  .option('--json', 'saída em JSON')
@@ -377,7 +391,7 @@ serversCmd
377
391
  });
378
392
  });
379
393
  serversCmd
380
- .command('deactivate <serverId>')
394
+ .command('deactivate [serverId]')
381
395
  .description('Desativar server (destrutivo top-tier — exige MFA)')
382
396
  .option('--yes', 'pula a confirmação interativa (modo script)')
383
397
  .option('--force', 'alias de --yes')
@@ -395,7 +409,7 @@ serversCmd
395
409
  });
396
410
  });
397
411
  serversCmd
398
- .command('dispatch <serverId> <commandType>')
412
+ .command('dispatch [serverId] [commandType]')
399
413
  .description('Enfileirar comando para o agente Linux do server')
400
414
  .option('--params <json>', 'objeto JSON de params do comando')
401
415
  .option('--json', 'saída em JSON')
@@ -410,10 +424,10 @@ const workspacesCmd = program
410
424
  workspacesCmd
411
425
  .command('create')
412
426
  .description('Criar workspace (retorna OAuth secret one-time)')
413
- .requiredOption('--product <productId>', 'id do produto')
414
- .requiredOption('--customer <customerId>', 'id do customer')
415
- .requiredOption('--env <env>', 'dev | staging | prod')
416
- .requiredOption('--tier <tier>', 'dev | standard | enterprise')
427
+ .option('--product <productId>', 'id do produto (interativo se ausente)')
428
+ .option('--customer <customerId>', 'id do customer (default: self/Neetru)')
429
+ .option('--env <env>', 'dev | staging | prod (default: dev)')
430
+ .option('--tier <tier>', 'dev | standard | enterprise (default: standard)')
417
431
  .option('--name <name>', 'label do workspace')
418
432
  .option('--json', 'saída em JSON')
419
433
  .action(async (opts) => {
@@ -428,10 +442,10 @@ workspacesCmd
428
442
  });
429
443
  });
430
444
  workspacesCmd
431
- .command('advance <workspaceId>')
445
+ .command('advance [workspaceId]')
432
446
  .description('Promover versão de bundle para running no workspace')
433
- .requiredOption('--product <slug>', 'productSlug do bundle')
434
- .requiredOption('--version <version>', 'versão do bundle a ativar')
447
+ .option('--product <slug>', 'productSlug do bundle (interativo se ausente)')
448
+ .option('--version <version>', 'versão do bundle a ativar')
435
449
  .option('--json', 'saída em JSON')
436
450
  .action(async (id, opts) => {
437
451
  const { runWorkspacesAdvance } = await import('./commands/workspaces.js');
@@ -458,7 +472,7 @@ workspacesCmd
458
472
  });
459
473
  });
460
474
  workspacesCmd
461
- .command('get <workspaceId>')
475
+ .command('get [workspaceId]')
462
476
  .description('Mostrar detalhes de um workspace')
463
477
  .option('--json', 'saída em JSON')
464
478
  .action(async (id, opts) => {
@@ -466,7 +480,7 @@ workspacesCmd
466
480
  await runWorkspacesGet(id, { json: !!opts.json });
467
481
  });
468
482
  workspacesCmd
469
- .command('open <workspaceId>')
483
+ .command('open [workspaceId]')
470
484
  .description('Abrir painel do workspace no browser')
471
485
  .action(async (id) => {
472
486
  const { runWorkspacesOpen } = await import('./commands/workspaces.js');
@@ -479,11 +493,11 @@ const deploymentsCmd = program
479
493
  deploymentsCmd
480
494
  .command('create')
481
495
  .description('Criar deployment (dispara comando para o agente)')
482
- .requiredOption('--product <productId>', 'id do produto')
483
- .requiredOption('--tenant <tenantId>', 'id do tenant alvo')
484
- .requiredOption('--version <version>', 'versão a deployar')
485
- .requiredOption('--env <env>', 'dev | staging | prod')
486
- .requiredOption('--server <serverId>', 'id do server alvo')
496
+ .option('--product <productId>', 'id do produto (interativo se ausente)')
497
+ .option('--tenant <tenantId>', 'id do tenant alvo (interativo se ausente)')
498
+ .option('--version <version>', 'versao a deployar')
499
+ .option('--env <env>', 'dev | staging | prod (default: dev)')
500
+ .option('--server <serverId>', 'id do server alvo (interativo se ausente)')
487
501
  .option('--json', 'saída em JSON')
488
502
  .action(async (opts) => {
489
503
  const { runDeploymentsCreate } = await import('./commands/deployments.js');
@@ -695,7 +709,7 @@ productsCmd
695
709
  });
696
710
  });
697
711
  productsCmd
698
- .command('publish <slug>')
712
+ .command('publish [slug]')
699
713
  .description('Publicar produto no catálogo público')
700
714
  .option('--json', 'saída em JSON')
701
715
  .action(async (slug, opts) => {
@@ -703,7 +717,7 @@ productsCmd
703
717
  await runProductsPublish(slug, { json: !!opts.json });
704
718
  });
705
719
  productsCmd
706
- .command('unpublish <slug>')
720
+ .command('unpublish [slug]')
707
721
  .description('Remover produto do catálogo público')
708
722
  .option('--json', 'saída em JSON')
709
723
  .action(async (slug, opts) => {
@@ -717,10 +731,10 @@ const productsDbCmd = productsCmd
717
731
  productsDbCmd
718
732
  .command('list')
719
733
  .description('Listar bancos de produtos')
720
- .option('--product-id <id>')
721
- .option('--engine <engine>')
722
- .option('--status <status>')
723
- .option('--json')
734
+ .option('--product-id <id>', 'ID do produto')
735
+ .option('--engine <engine>', 'firestore-instance | cloud-sql-postgres | cloud-sql-mysql | vm-postgres-single | vm-postgres-cluster | vm-mysql-single | vm-mysql-cluster')
736
+ .option('--status <status>', 'Filtrar por status (ativo, provisionando, falha, arquivado)')
737
+ .option('--json', 'Saída em JSON estruturado')
724
738
  .action(async (opts) => {
725
739
  const { runDbList } = await import('./commands/products-db.js');
726
740
  await runDbList({
@@ -741,21 +755,21 @@ productsDbCmd
741
755
  productsDbCmd
742
756
  .command('create')
743
757
  .description('Criar banco de produto (Phase A: registra + audit)')
744
- .requiredOption('--product-id <id>')
745
- .requiredOption('--label <label>')
746
- .requiredOption('--engine <engine>', 'firestore-instance|cloud-sql-postgres|cloud-sql-mysql|vm-postgres-single|vm-postgres-cluster|vm-mysql-single|vm-mysql-cluster')
747
- .requiredOption('--environment <env>', 'dev|staging|production')
748
- .option('--region <region>', 'região GCP', 'us-central1')
749
- .option('--server-id <serverId>', 'target VM (obrigatório pra engines vm-*)')
750
- .option('--replica-count <n>', 'pra engines *-cluster (default 2)')
751
- .option('--json')
758
+ .option('--product-id <id>', 'ID do produto')
759
+ .option('--label <label>', 'Nome descritivo do banco')
760
+ .option('--engine <engine>', 'firestore-instance | cloud-sql-postgres | cloud-sql-mysql | vm-postgres-single | vm-postgres-cluster | vm-mysql-single | vm-mysql-cluster')
761
+ .option('--env <env>', 'Ambiente: dev | staging | production')
762
+ .option('--region <region>', 'Região GCP', 'us-central1')
763
+ .option('--server-id <serverId>', 'ID da VM alvo (obrigatório para engines vm-*)')
764
+ .option('--replica-count <n>', 'Número de réplicas para engines *-cluster (padrão 2)')
765
+ .option('--json', 'Saída em JSON estruturado')
752
766
  .action(async (opts) => {
753
767
  const { runDbCreate } = await import('./commands/products-db.js');
754
768
  await runDbCreate({
755
769
  productId: opts.productId,
756
770
  label: opts.label,
757
771
  engine: opts.engine,
758
- environment: opts.environment,
772
+ env: opts.env,
759
773
  region: opts.region,
760
774
  serverId: opts.serverId,
761
775
  replicaCount: opts.replicaCount,
@@ -763,7 +777,7 @@ productsDbCmd
763
777
  });
764
778
  });
765
779
  productsDbCmd
766
- .command('get <id>')
780
+ .command('get [id]')
767
781
  .description('Mostrar detalhes de um banco')
768
782
  .option('--json')
769
783
  .action(async (id, opts) => {
@@ -771,7 +785,7 @@ productsDbCmd
771
785
  await runDbGet(id, { json: !!opts.json });
772
786
  });
773
787
  productsDbCmd
774
- .command('status <id> <status>')
788
+ .command('status [id] [status]')
775
789
  .description('Atualizar status de um banco de produto')
776
790
  .option('--reason <text>')
777
791
  .option('--json')
@@ -780,7 +794,7 @@ productsDbCmd
780
794
  await runDbStatus(id, status, { reason: opts.reason, json: !!opts.json });
781
795
  });
782
796
  productsDbCmd
783
- .command('retry <id>')
797
+ .command('retry [id]')
784
798
  .description('Reenfileirar provisionamento de banco')
785
799
  .option('--json')
786
800
  .action(async (id, opts) => {
@@ -788,7 +802,7 @@ productsDbCmd
788
802
  await runDbRetry(id, { json: !!opts.json });
789
803
  });
790
804
  productsDbCmd
791
- .command('rotate <id>')
805
+ .command('rotate [id]')
792
806
  .description('Rotacionar credenciais do banco (admin)')
793
807
  .option('--json')
794
808
  .action(async (id, opts) => {
@@ -796,7 +810,7 @@ productsDbCmd
796
810
  await runDbRotate(id, { json: !!opts.json });
797
811
  });
798
812
  productsDbCmd
799
- .command('delete <id>')
813
+ .command('delete [id]')
800
814
  .description('Arquivar banco por soft-delete (admin)')
801
815
  .option('--json')
802
816
  .action(async (id, opts) => {
@@ -899,14 +913,38 @@ mocksCmd
899
913
  // ── neetru env ────────────────────────────────────────────────────────
900
914
  const envCmd = program
901
915
  .command('env')
902
- .description('Gerenciar NEETRU_ENV no .env.local');
916
+ .description('Gerenciar NEETRU_ENV (.env.local) e env vars de serviços Cloud Run');
903
917
  envCmd
904
918
  .command('switch <target>')
905
- .description('Alternar NEETRU_ENV (dev/workspace/production)')
919
+ .description('Alternar NEETRU_ENV (dev/workspace/production) no .env.local')
906
920
  .action(async (target) => {
907
921
  const { runEnvSwitch } = await import('./commands/env.js');
908
922
  await runEnvSwitch({ target });
909
923
  });
924
+ envCmd
925
+ .command('set')
926
+ .description('Setar env vars de um serviço Cloud Run (merge, step-up MFA)')
927
+ .requiredOption('--service <service>', 'nome do serviço Cloud Run alvo')
928
+ .option('--set <KEY=VALUE>', 'env var literal (repetível)', (v, acc = []) => [...acc, v], [])
929
+ .option('--secret <KEY=secretName[:version]>', 'env var via Secret Manager (repetível)', (v, acc = []) => [...acc, v], [])
930
+ .option('--unset <KEY>', 'remover env var (repetível)', (v, acc = []) => [...acc, v], [])
931
+ .option('--mfa-token <code>', 'código TOTP (step-up MFA, pula prompt)')
932
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
933
+ .option('--yes', 'pula confirmações (modo script)')
934
+ .option('--json', 'saída em JSON')
935
+ .action(async (opts) => {
936
+ const { runEnvSet } = await import('./commands/env.js');
937
+ await runEnvSet({
938
+ service: opts.service,
939
+ set: opts.set,
940
+ secret: opts.secret,
941
+ unset: opts.unset,
942
+ mfaToken: opts.mfaToken,
943
+ dryRun: !!opts.dryRun,
944
+ yes: !!opts.yes,
945
+ json: !!opts.json,
946
+ });
947
+ });
910
948
  // ── neetru db ─────────────────────────────────────────────────────────
911
949
  const dbCmd = program
912
950
  .command('db')
@@ -1139,10 +1177,13 @@ supportTicketsCmd
1139
1177
  await runSupportTicketsStatus(id, { to: opts.to, json: !!opts.json });
1140
1178
  });
1141
1179
  // ── neetru dns ───────────────────────────────────────────────────────
1142
- const dnsCmd = program.command('dns').description('Gerenciar Cloud DNS managed zones');
1143
- dnsCmd
1180
+ const dnsCmd = program
1181
+ .command('dns')
1182
+ .description('Gerenciar Cloud DNS managed zones');
1183
+ const dnsZonesCmd = dnsCmd
1144
1184
  .command('zones')
1145
- .description('Operar managed zones do Cloud DNS')
1185
+ .description('Operar managed zones do Cloud DNS');
1186
+ dnsZonesCmd
1146
1187
  .command('list')
1147
1188
  .description('Listar managed zones do projeto')
1148
1189
  .option('--json', 'saída em JSON')
@@ -1151,9 +1192,10 @@ dnsCmd
1151
1192
  await runDnsZonesList({ json: !!opts.json });
1152
1193
  });
1153
1194
  // ── neetru hosting ───────────────────────────────────────────────────
1154
- program
1195
+ const hostingCmd = program
1155
1196
  .command('hosting')
1156
- .description('Gerenciar customer domains e hosting setup')
1197
+ .description('Gerenciar customer domains e hosting setup');
1198
+ hostingCmd
1157
1199
  .command('list')
1158
1200
  .description('Listar customer domains com scope de tenant')
1159
1201
  .option('--json', 'saída em JSON')
@@ -1161,6 +1203,49 @@ program
1161
1203
  const { runHostingList } = await import('./commands/infra-read.js');
1162
1204
  await runHostingList({ json: !!opts.json });
1163
1205
  });
1206
+ hostingCmd
1207
+ .command('create-mapping')
1208
+ .description('Criar domain mapping pra serviço Cloud Run (admin + step-up MFA)')
1209
+ .requiredOption('--service <service>', 'nome do serviço Cloud Run alvo')
1210
+ .requiredOption('--domain <domain>', 'domínio FQDN (ex: api.dev.neetru.com)')
1211
+ .option('--mfa-token <code>', 'código TOTP (step-up MFA, pula prompt)')
1212
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
1213
+ .option('--yes', 'pula confirmações (modo script)')
1214
+ .option('--json', 'saída em JSON')
1215
+ .action(async (opts) => {
1216
+ const { runHostingCreateMapping } = await import('./commands/hosting-write.js');
1217
+ await runHostingCreateMapping({
1218
+ service: opts.service,
1219
+ domain: opts.domain,
1220
+ mfaToken: opts.mfaToken,
1221
+ dryRun: !!opts.dryRun,
1222
+ yes: !!opts.yes,
1223
+ json: !!opts.json,
1224
+ });
1225
+ });
1226
+ // ── neetru artifact-registry ─────────────────────────────────────────
1227
+ const arCmd = program
1228
+ .command('artifact-registry')
1229
+ .alias('ar')
1230
+ .description('Gerenciar repositórios do Artifact Registry');
1231
+ arCmd
1232
+ .command('create <name>')
1233
+ .description('Criar repositório (one-shot por produto) — admin only')
1234
+ .option('--location <location>', 'região (default us-central1)', 'us-central1')
1235
+ .option('--format <format>', 'DOCKER (default) | NPM | MAVEN | PYTHON | APT | YUM | GO | KFP', 'DOCKER')
1236
+ .option('--description <text>', 'descrição opcional')
1237
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
1238
+ .option('--json', 'saída em JSON')
1239
+ .action(async (name, opts) => {
1240
+ const { runArtifactRegistryCreate } = await import('./commands/artifact-registry.js');
1241
+ await runArtifactRegistryCreate(name, {
1242
+ location: opts.location,
1243
+ format: opts.format,
1244
+ description: opts.description,
1245
+ dryRun: !!opts.dryRun,
1246
+ json: !!opts.json,
1247
+ });
1248
+ });
1164
1249
  // ── neetru builds ────────────────────────────────────────────────────
1165
1250
  program
1166
1251
  .command('builds')
@@ -1210,10 +1295,24 @@ drCmd
1210
1295
  json: !!opts.json,
1211
1296
  });
1212
1297
  });
1298
+ // ── neetru schema ─────────────────────────────────────────────────────
1299
+ // Inspecionar spec OpenAPI do Core — usado pela IA e devs pra entender endpoints.
1300
+ {
1301
+ const { registerSchemaCommand } = await import('./commands/schema.js');
1302
+ registerSchemaCommand(program);
1303
+ }
1213
1304
  // ── parse ─────────────────────────────────────────────────────────────
1214
- program.parse(process.argv);
1215
1305
  if (!process.argv.slice(2).length) {
1216
- log.banner();
1217
- program.outputHelp();
1306
+ if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {
1307
+ const { runTerminalUi } = await import('./commands/ui.js');
1308
+ await runTerminalUi();
1309
+ }
1310
+ else {
1311
+ log.banner();
1312
+ program.outputHelp();
1313
+ }
1314
+ }
1315
+ else {
1316
+ program.parse(process.argv);
1218
1317
  }
1219
1318
  //# sourceMappingURL=index.js.map