@camunda8/cli 2.7.0-alpha.1 → 2.7.0-alpha.10

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 (144) hide show
  1. package/README.md +80 -1
  2. package/dist/command-dispatch.d.ts +16 -0
  3. package/dist/command-dispatch.d.ts.map +1 -0
  4. package/dist/command-dispatch.js +129 -0
  5. package/dist/command-dispatch.js.map +1 -0
  6. package/dist/command-framework.d.ts +248 -0
  7. package/dist/command-framework.d.ts.map +1 -0
  8. package/dist/command-framework.js +229 -0
  9. package/dist/command-framework.js.map +1 -0
  10. package/dist/command-registry.d.ts +2014 -14
  11. package/dist/command-registry.d.ts.map +1 -1
  12. package/dist/command-registry.js +653 -66
  13. package/dist/command-registry.js.map +1 -1
  14. package/dist/command-validation.d.ts +30 -4
  15. package/dist/command-validation.d.ts.map +1 -1
  16. package/dist/command-validation.js +90 -4
  17. package/dist/command-validation.js.map +1 -1
  18. package/dist/commands/completion.d.ts +25 -1
  19. package/dist/commands/completion.d.ts.map +1 -1
  20. package/dist/commands/completion.js +590 -1223
  21. package/dist/commands/completion.js.map +1 -1
  22. package/dist/commands/deployments.d.ts +2 -0
  23. package/dist/commands/deployments.d.ts.map +1 -1
  24. package/dist/commands/deployments.js +13 -2
  25. package/dist/commands/deployments.js.map +1 -1
  26. package/dist/commands/forms.d.ts +2 -20
  27. package/dist/commands/forms.d.ts.map +1 -1
  28. package/dist/commands/forms.js +76 -79
  29. package/dist/commands/forms.js.map +1 -1
  30. package/dist/commands/help.d.ts +4 -88
  31. package/dist/commands/help.d.ts.map +1 -1
  32. package/dist/commands/help.js +574 -1948
  33. package/dist/commands/help.js.map +1 -1
  34. package/dist/commands/identity-authorizations.d.ts +5 -24
  35. package/dist/commands/identity-authorizations.d.ts.map +1 -1
  36. package/dist/commands/identity-authorizations.js +113 -137
  37. package/dist/commands/identity-authorizations.js.map +1 -1
  38. package/dist/commands/identity-groups.d.ts +5 -26
  39. package/dist/commands/identity-groups.d.ts.map +1 -1
  40. package/dist/commands/identity-groups.js +91 -124
  41. package/dist/commands/identity-groups.js.map +1 -1
  42. package/dist/commands/identity-mapping-rules.d.ts +5 -30
  43. package/dist/commands/identity-mapping-rules.d.ts.map +1 -1
  44. package/dist/commands/identity-mapping-rules.js +106 -136
  45. package/dist/commands/identity-mapping-rules.js.map +1 -1
  46. package/dist/commands/identity-roles.d.ts +5 -26
  47. package/dist/commands/identity-roles.d.ts.map +1 -1
  48. package/dist/commands/identity-roles.js +91 -124
  49. package/dist/commands/identity-roles.js.map +1 -1
  50. package/dist/commands/identity-tenants.d.ts +5 -26
  51. package/dist/commands/identity-tenants.d.ts.map +1 -1
  52. package/dist/commands/identity-tenants.js +92 -126
  53. package/dist/commands/identity-tenants.js.map +1 -1
  54. package/dist/commands/identity-users.d.ts +5 -29
  55. package/dist/commands/identity-users.d.ts.map +1 -1
  56. package/dist/commands/identity-users.js +95 -129
  57. package/dist/commands/identity-users.js.map +1 -1
  58. package/dist/commands/identity.d.ts +6 -6
  59. package/dist/commands/identity.d.ts.map +1 -1
  60. package/dist/commands/identity.js +6 -7
  61. package/dist/commands/identity.js.map +1 -1
  62. package/dist/commands/incidents.d.ts +3 -16
  63. package/dist/commands/incidents.d.ts.map +1 -1
  64. package/dist/commands/incidents.js +71 -98
  65. package/dist/commands/incidents.js.map +1 -1
  66. package/dist/commands/jobs.d.ts +4 -26
  67. package/dist/commands/jobs.d.ts.map +1 -1
  68. package/dist/commands/jobs.js +143 -159
  69. package/dist/commands/jobs.js.map +1 -1
  70. package/dist/commands/mcp-proxy.d.ts +1 -0
  71. package/dist/commands/mcp-proxy.d.ts.map +1 -1
  72. package/dist/commands/mcp-proxy.js +10 -2
  73. package/dist/commands/mcp-proxy.js.map +1 -1
  74. package/dist/commands/messages.d.ts +2 -12
  75. package/dist/commands/messages.d.ts.map +1 -1
  76. package/dist/commands/messages.js +87 -81
  77. package/dist/commands/messages.js.map +1 -1
  78. package/dist/commands/open.d.ts +4 -0
  79. package/dist/commands/open.d.ts.map +1 -1
  80. package/dist/commands/open.js +18 -0
  81. package/dist/commands/open.js.map +1 -1
  82. package/dist/commands/plugins.d.ts +7 -9
  83. package/dist/commands/plugins.d.ts.map +1 -1
  84. package/dist/commands/plugins.js +32 -25
  85. package/dist/commands/plugins.js.map +1 -1
  86. package/dist/commands/process-definitions.d.ts +2 -14
  87. package/dist/commands/process-definitions.d.ts.map +1 -1
  88. package/dist/commands/process-definitions.js +57 -80
  89. package/dist/commands/process-definitions.js.map +1 -1
  90. package/dist/commands/process-instances.d.ts +8 -37
  91. package/dist/commands/process-instances.d.ts.map +1 -1
  92. package/dist/commands/process-instances.js +242 -193
  93. package/dist/commands/process-instances.js.map +1 -1
  94. package/dist/commands/profiles.d.ts +4 -0
  95. package/dist/commands/profiles.d.ts.map +1 -1
  96. package/dist/commands/profiles.js +29 -0
  97. package/dist/commands/profiles.js.map +1 -1
  98. package/dist/commands/run.d.ts +2 -0
  99. package/dist/commands/run.d.ts.map +1 -1
  100. package/dist/commands/run.js +10 -0
  101. package/dist/commands/run.js.map +1 -1
  102. package/dist/commands/search.d.ts +7 -100
  103. package/dist/commands/search.d.ts.map +1 -1
  104. package/dist/commands/search.js +530 -694
  105. package/dist/commands/search.js.map +1 -1
  106. package/dist/commands/session.d.ts +3 -0
  107. package/dist/commands/session.d.ts.map +1 -1
  108. package/dist/commands/session.js +30 -0
  109. package/dist/commands/session.js.map +1 -1
  110. package/dist/commands/topology.d.ts +1 -3
  111. package/dist/commands/topology.d.ts.map +1 -1
  112. package/dist/commands/topology.js +11 -18
  113. package/dist/commands/topology.js.map +1 -1
  114. package/dist/commands/user-tasks.d.ts +2 -16
  115. package/dist/commands/user-tasks.d.ts.map +1 -1
  116. package/dist/commands/user-tasks.js +73 -101
  117. package/dist/commands/user-tasks.js.map +1 -1
  118. package/dist/commands/watch.d.ts +1 -0
  119. package/dist/commands/watch.d.ts.map +1 -1
  120. package/dist/commands/watch.js +15 -0
  121. package/dist/commands/watch.js.map +1 -1
  122. package/dist/config.d.ts.map +1 -1
  123. package/dist/config.js +5 -0
  124. package/dist/config.js.map +1 -1
  125. package/dist/default-plugins/cluster/README.md +1 -1
  126. package/dist/default-plugins/cluster/c8ctl-plugin.js +281 -59
  127. package/dist/index.d.ts +0 -4
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +102 -979
  130. package/dist/index.js.map +1 -1
  131. package/dist/logger.d.ts +5 -0
  132. package/dist/logger.d.ts.map +1 -1
  133. package/dist/logger.js +7 -1
  134. package/dist/logger.js.map +1 -1
  135. package/dist/plugin-loader.d.ts +5 -0
  136. package/dist/plugin-loader.d.ts.map +1 -1
  137. package/dist/plugin-loader.js +1 -0
  138. package/dist/plugin-loader.js.map +1 -1
  139. package/dist/update-check.d.ts +67 -0
  140. package/dist/update-check.d.ts.map +1 -0
  141. package/dist/update-check.js +284 -0
  142. package/dist/update-check.js.map +1 -0
  143. package/package.json +3 -2
  144. /package/dist/templates/{tsconfig.json → tsconfig.json.template} +0 -0
@@ -5,6 +5,7 @@
5
5
  * Consumers (help, completion, validation, dispatch) derive their
6
6
  * data from this registry instead of maintaining separate copies.
7
7
  */
8
+ import { AuthorizationKey, IncidentKey, JobKey, ProcessDefinitionId, ProcessDefinitionKey, ProcessInstanceKey, TenantId, Username, UserTaskKey, } from "@camunda8/orchestration-cluster-api";
8
9
  // ─── Resource Aliases ────────────────────────────────────────────────────────
9
10
  /**
10
11
  * Maps short/plural resource names to their canonical singular form.
@@ -12,11 +13,16 @@
12
13
  */
13
14
  export const RESOURCE_ALIASES = {
14
15
  pi: "process-instance",
16
+ "process-instances": "process-instance",
15
17
  pd: "process-definition",
18
+ "process-definitions": "process-definition",
16
19
  ut: "user-task",
20
+ "user-tasks": "user-task",
17
21
  inc: "incident",
22
+ incidents: "incident",
18
23
  msg: "message",
19
24
  vars: "variable",
25
+ variables: "variable",
20
26
  profile: "profile",
21
27
  profiles: "profile",
22
28
  plugin: "plugin",
@@ -45,11 +51,15 @@ export const GLOBAL_FLAGS = {
45
51
  "dry-run": {
46
52
  type: "boolean",
47
53
  description: "Preview the API request without executing",
54
+ agentDescription: "Preview the API request that would be sent, without executing it.\nEmits JSON: { dryRun, command, method, url, body }\nAlways exits 0.",
55
+ agentAppliesTo: "all commands",
48
56
  },
49
57
  verbose: { type: "boolean", description: "Show verbose output" },
50
58
  fields: {
51
59
  type: "string",
52
60
  description: "Comma-separated list of fields to display",
61
+ agentDescription: "Comma-separated list of output fields to include.\nReduces context window size when parsing output.\nExample: c8ctl list pi --fields Key,State,processDefinitionId\nCase-insensitive.",
62
+ agentAppliesTo: "all list/search/get commands",
53
63
  },
54
64
  };
55
65
  /**
@@ -79,16 +89,22 @@ const PI_SEARCH_FLAGS = {
79
89
  processDefinitionId: {
80
90
  type: "string",
81
91
  description: "Filter by process definition ID",
92
+ validate: ProcessDefinitionId.assumeExists,
82
93
  },
83
94
  processDefinitionKey: {
84
95
  type: "string",
85
96
  description: "Filter by process definition key",
97
+ validate: ProcessDefinitionKey.assumeExists,
98
+ },
99
+ state: {
100
+ type: "string",
101
+ description: "Filter by state (ACTIVE, COMPLETED, etc)",
86
102
  },
87
- state: { type: "string", description: "Filter by state" },
88
103
  key: { type: "string", description: "Filter by key" },
89
104
  parentProcessInstanceKey: {
90
105
  type: "string",
91
106
  description: "Filter by parent process instance key",
107
+ validate: ProcessInstanceKey.assumeExists,
92
108
  },
93
109
  iid: {
94
110
  type: "string",
@@ -104,6 +120,7 @@ const PD_SEARCH_FLAGS = {
104
120
  processDefinitionId: {
105
121
  type: "string",
106
122
  description: "Filter by process definition ID",
123
+ validate: ProcessDefinitionId.assumeExists,
107
124
  },
108
125
  name: { type: "string", description: "Filter by name" },
109
126
  key: { type: "string", description: "Filter by key" },
@@ -119,10 +136,12 @@ const UT_SEARCH_FLAGS = {
119
136
  processInstanceKey: {
120
137
  type: "string",
121
138
  description: "Filter by process instance key",
139
+ validate: ProcessInstanceKey.assumeExists,
122
140
  },
123
141
  processDefinitionKey: {
124
142
  type: "string",
125
143
  description: "Filter by process definition key",
144
+ validate: ProcessDefinitionKey.assumeExists,
126
145
  },
127
146
  elementId: { type: "string", description: "Filter by element ID" },
128
147
  iassignee: {
@@ -135,10 +154,12 @@ const INC_SEARCH_FLAGS = {
135
154
  processInstanceKey: {
136
155
  type: "string",
137
156
  description: "Filter by process instance key",
157
+ validate: ProcessInstanceKey.assumeExists,
138
158
  },
139
159
  processDefinitionKey: {
140
160
  type: "string",
141
161
  description: "Filter by process definition key",
162
+ validate: ProcessDefinitionKey.assumeExists,
142
163
  },
143
164
  bpmnProcessId: {
144
165
  type: "string",
@@ -148,6 +169,7 @@ const INC_SEARCH_FLAGS = {
148
169
  processDefinitionId: {
149
170
  type: "string",
150
171
  description: "Filter by process definition ID",
172
+ validate: ProcessDefinitionId.assumeExists,
151
173
  },
152
174
  errorType: { type: "string", description: "Filter by error type" },
153
175
  errorMessage: {
@@ -169,10 +191,12 @@ const JOB_SEARCH_FLAGS = {
169
191
  processInstanceKey: {
170
192
  type: "string",
171
193
  description: "Filter by process instance key",
194
+ validate: ProcessInstanceKey.assumeExists,
172
195
  },
173
196
  processDefinitionKey: {
174
197
  type: "string",
175
198
  description: "Filter by process definition key",
199
+ validate: ProcessDefinitionKey.assumeExists,
176
200
  },
177
201
  itype: {
178
202
  type: "string",
@@ -185,6 +209,7 @@ const VAR_SEARCH_FLAGS = {
185
209
  processInstanceKey: {
186
210
  type: "string",
187
211
  description: "Filter by process instance key",
212
+ validate: ProcessInstanceKey.assumeExists,
188
213
  },
189
214
  scopeKey: { type: "string", description: "Filter by scope key" },
190
215
  fullValue: {
@@ -201,7 +226,11 @@ const VAR_SEARCH_FLAGS = {
201
226
  },
202
227
  };
203
228
  const USER_SEARCH_FLAGS = {
204
- username: { type: "string", description: "Filter by username" },
229
+ username: {
230
+ type: "string",
231
+ description: "Filter by username",
232
+ validate: Username.assumeExists,
233
+ },
205
234
  name: { type: "string", description: "Filter by name" },
206
235
  email: { type: "string", description: "Filter by email" },
207
236
  };
@@ -214,7 +243,11 @@ const GROUP_SEARCH_FLAGS = {
214
243
  name: { type: "string", description: "Filter by name" },
215
244
  };
216
245
  const TENANT_SEARCH_FLAGS = {
217
- tenantId: { type: "string", description: "Filter by tenant ID" },
246
+ tenantId: {
247
+ type: "string",
248
+ description: "Filter by tenant ID",
249
+ validate: TenantId.assumeExists,
250
+ },
218
251
  name: { type: "string", description: "Filter by name" },
219
252
  };
220
253
  const AUTH_SEARCH_FLAGS = {
@@ -268,13 +301,115 @@ const PROFILE_CONNECTION_FLAGS = {
268
301
  description: "Import from environment variables",
269
302
  },
270
303
  };
304
+ // ─── Per-resource get flags ──────────────────────────────────────────────────
305
+ export const GET_PD_FLAGS = {
306
+ xml: {
307
+ type: "boolean",
308
+ description: "Get BPMN XML (process definitions)",
309
+ showInTopLevelHelp: true,
310
+ helpHint: "use with 'get pd'",
311
+ },
312
+ };
313
+ const GET_FORM_FLAGS = {
314
+ userTask: {
315
+ type: "boolean",
316
+ description: "Get form for user task",
317
+ showInTopLevelHelp: true,
318
+ helpHint: "use with 'get form'",
319
+ },
320
+ ut: {
321
+ type: "boolean",
322
+ description: "Alias for --userTask",
323
+ },
324
+ processDefinition: {
325
+ type: "boolean",
326
+ description: "Get form for process definition",
327
+ showInTopLevelHelp: true,
328
+ helpHint: "use with 'get form'",
329
+ },
330
+ pd: {
331
+ type: "boolean",
332
+ description: "Alias for --processDefinition",
333
+ },
334
+ };
335
+ const GET_PI_FLAGS = {
336
+ variables: {
337
+ type: "boolean",
338
+ description: "Include variables in output",
339
+ showInTopLevelHelp: true,
340
+ helpHint: "use with 'get pi'",
341
+ },
342
+ };
343
+ // ─── Per-resource get positionals ────────────────────────────────────────────
344
+ export const GET_PD_POSITIONALS = [
345
+ {
346
+ name: "key",
347
+ required: true,
348
+ validate: ProcessDefinitionKey.assumeExists,
349
+ },
350
+ ];
351
+ const GET_PI_POSITIONALS = [
352
+ {
353
+ name: "key",
354
+ required: true,
355
+ validate: ProcessInstanceKey.assumeExists,
356
+ },
357
+ ];
358
+ const GET_INCIDENT_POSITIONALS = [
359
+ {
360
+ name: "key",
361
+ required: true,
362
+ validate: IncidentKey.assumeExists,
363
+ },
364
+ ];
365
+ const GET_USER_POSITIONALS = [
366
+ {
367
+ name: "username",
368
+ required: true,
369
+ validate: Username.assumeExists,
370
+ },
371
+ ];
372
+ const GET_ROLE_POSITIONALS = [
373
+ { name: "roleId", required: true },
374
+ ];
375
+ const GET_GROUP_POSITIONALS = [
376
+ { name: "groupId", required: true },
377
+ ];
378
+ const GET_TENANT_POSITIONALS = [
379
+ {
380
+ name: "tenantId",
381
+ required: true,
382
+ validate: TenantId.assumeExists,
383
+ },
384
+ ];
385
+ const GET_AUTHORIZATION_POSITIONALS = [
386
+ {
387
+ name: "authorizationKey",
388
+ required: true,
389
+ validate: AuthorizationKey.assumeExists,
390
+ },
391
+ ];
392
+ const GET_MAPPING_RULE_POSITIONALS = [
393
+ { name: "mappingRuleId", required: true },
394
+ ];
395
+ const GET_FORM_POSITIONALS = [
396
+ { name: "key", required: true },
397
+ ];
271
398
  // ─── Command Registry ────────────────────────────────────────────────────────
272
399
  export const COMMAND_REGISTRY = {
273
400
  // ── Read commands ──────────────────────────────────────────────────────
274
401
  list: {
275
402
  description: "List resources (process, identity)",
403
+ helpDescription: "List resources",
404
+ hasDetailedHelp: true,
405
+ helpFooterLabel: "Show all list resources and their flags",
276
406
  mutating: false,
277
407
  requiresResource: true,
408
+ helpExamples: [
409
+ { command: "c8ctl list pi", description: "List process instances" },
410
+ { command: "c8ctl list pd", description: "List process definitions" },
411
+ { command: "c8ctl list users", description: "List users" },
412
+ ],
278
413
  resources: [
279
414
  "pi",
280
415
  "pd",
@@ -296,8 +431,6 @@ export const COMMAND_REGISTRY = {
296
431
  description: "List all (disable pagination limit)",
297
432
  },
298
433
  ...SEARCH_FLAGS,
299
- // List supports the same resource-specific filters as search;
300
- // per-resource scoping is handled by SEARCH_RESOURCE_FLAGS.
301
434
  ...PI_SEARCH_FLAGS,
302
435
  ...PD_SEARCH_FLAGS,
303
436
  ...UT_SEARCH_FLAGS,
@@ -310,11 +443,77 @@ export const COMMAND_REGISTRY = {
310
443
  ...AUTH_SEARCH_FLAGS,
311
444
  ...MR_SEARCH_FLAGS,
312
445
  },
446
+ resourceFlags: {
447
+ "process-definition": PD_SEARCH_FLAGS,
448
+ "process-instance": PI_SEARCH_FLAGS,
449
+ "user-task": UT_SEARCH_FLAGS,
450
+ incident: INC_SEARCH_FLAGS,
451
+ jobs: JOB_SEARCH_FLAGS,
452
+ user: USER_SEARCH_FLAGS,
453
+ role: ROLE_SEARCH_FLAGS,
454
+ group: GROUP_SEARCH_FLAGS,
455
+ tenant: TENANT_SEARCH_FLAGS,
456
+ authorization: AUTH_SEARCH_FLAGS,
457
+ "mapping-rule": MR_SEARCH_FLAGS,
458
+ },
313
459
  },
314
460
  search: {
315
461
  description: "Search resources with filters",
462
+ helpDescription: "Search resources with filters (wildcards, date ranges, case-insensitive)",
463
+ hasDetailedHelp: true,
464
+ helpFooterLabel: "Show all search resources and their flags",
316
465
  mutating: false,
317
466
  requiresResource: true,
467
+ helpExamples: [
468
+ {
469
+ command: "c8ctl search pi --state=ACTIVE",
470
+ description: "Search for active process instances",
471
+ },
472
+ {
473
+ command: "c8ctl search pd --bpmnProcessId=myProcess",
474
+ description: "Search process definitions by ID",
475
+ },
476
+ {
477
+ command: "c8ctl search pd --name='*main*'",
478
+ description: "Search process definitions with wildcard",
479
+ },
480
+ {
481
+ command: "c8ctl search ut --assignee=john",
482
+ description: "Search user tasks assigned to john",
483
+ },
484
+ {
485
+ command: "c8ctl search inc --state=ACTIVE",
486
+ description: "Search for active incidents",
487
+ },
488
+ {
489
+ command: "c8ctl search jobs --type=myJobType",
490
+ description: "Search jobs by type",
491
+ },
492
+ {
493
+ command: "c8ctl search jobs --type='*service*'",
494
+ description: 'Search jobs with type containing "service"',
495
+ },
496
+ {
497
+ command: "c8ctl search variables --name=myVar",
498
+ description: "Search for variables by name",
499
+ },
500
+ {
501
+ command: "c8ctl search variables --value=foo",
502
+ description: "Search for variables by value",
503
+ },
504
+ {
505
+ command: "c8ctl search variables --processInstanceKey=123 --fullValue",
506
+ description: "Search variables with full values",
507
+ },
508
+ {
509
+ command: "c8ctl search pd --iname='*order*'",
510
+ description: "Case-insensitive search by name",
511
+ },
512
+ {
513
+ command: "c8ctl search ut --iassignee=John",
514
+ description: "Case-insensitive search by assignee",
515
+ },
516
+ ],
318
517
  resources: [
319
518
  "pi",
320
519
  "pd",
@@ -331,8 +530,6 @@ export const COMMAND_REGISTRY = {
331
530
  ],
332
531
  flags: {
333
532
  ...SEARCH_FLAGS,
334
- // Resource-specific flags are all accepted; per-resource scoping
335
- // is handled by SEARCH_RESOURCE_FLAGS below.
336
533
  ...PI_SEARCH_FLAGS,
337
534
  ...PD_SEARCH_FLAGS,
338
535
  ...UT_SEARCH_FLAGS,
@@ -346,11 +543,59 @@ export const COMMAND_REGISTRY = {
346
543
  ...AUTH_SEARCH_FLAGS,
347
544
  ...MR_SEARCH_FLAGS,
348
545
  },
546
+ resourceFlags: {
547
+ "process-definition": PD_SEARCH_FLAGS,
548
+ "process-instance": PI_SEARCH_FLAGS,
549
+ "user-task": UT_SEARCH_FLAGS,
550
+ incident: INC_SEARCH_FLAGS,
551
+ jobs: JOB_SEARCH_FLAGS,
552
+ variable: VAR_SEARCH_FLAGS,
553
+ user: USER_SEARCH_FLAGS,
554
+ role: ROLE_SEARCH_FLAGS,
555
+ group: GROUP_SEARCH_FLAGS,
556
+ tenant: TENANT_SEARCH_FLAGS,
557
+ authorization: AUTH_SEARCH_FLAGS,
558
+ "mapping-rule": MR_SEARCH_FLAGS,
559
+ },
349
560
  },
350
561
  get: {
351
562
  description: "Get resource by key",
563
+ helpDescription: "Get a resource by key",
564
+ hasDetailedHelp: true,
565
+ helpFooterLabel: "Show all get resources and their flags",
352
566
  mutating: false,
353
567
  requiresResource: true,
568
+ helpExamples: [
569
+ {
570
+ command: "c8ctl get pi 123456",
571
+ description: "Get process instance by key",
572
+ },
573
+ {
574
+ command: "c8ctl get pi 123456 --variables",
575
+ description: "Get process instance with variables",
576
+ },
577
+ {
578
+ command: "c8ctl get pd 123456",
579
+ description: "Get process definition by key",
580
+ },
581
+ {
582
+ command: "c8ctl get pd 123456 --xml",
583
+ description: "Get process definition XML",
584
+ },
585
+ {
586
+ command: "c8ctl get form 123456",
587
+ description: "Get form (searches both user task and process definition)",
588
+ },
589
+ {
590
+ command: "c8ctl get form 123456 --ut",
591
+ description: "Get form for user task only",
592
+ },
593
+ {
594
+ command: "c8ctl get form 123456 --pd",
595
+ description: "Get start form for process definition only",
596
+ },
597
+ { command: "c8ctl get user john", description: "Get user by username" },
598
+ ],
354
599
  resources: [
355
600
  "pi",
356
601
  "pd",
@@ -364,26 +609,47 @@ export const COMMAND_REGISTRY = {
364
609
  "auth",
365
610
  "mapping-rule",
366
611
  ],
367
- flags: {
368
- xml: {
369
- type: "boolean",
370
- description: "Get BPMN XML (process definitions)",
371
- },
372
- userTask: {
373
- type: "boolean",
374
- description: "Get form for user task",
375
- },
376
- processDefinition: {
377
- type: "boolean",
378
- description: "Get form for process definition",
379
- },
612
+ flags: { ...GET_PD_FLAGS, ...GET_FORM_FLAGS, ...GET_PI_FLAGS },
613
+ resourceFlags: {
614
+ "process-definition": GET_PD_FLAGS,
615
+ form: GET_FORM_FLAGS,
616
+ "process-instance": GET_PI_FLAGS,
617
+ },
618
+ resourcePositionals: {
619
+ "process-definition": GET_PD_POSITIONALS,
620
+ "process-instance": GET_PI_POSITIONALS,
621
+ incident: GET_INCIDENT_POSITIONALS,
622
+ user: GET_USER_POSITIONALS,
623
+ role: GET_ROLE_POSITIONALS,
624
+ group: GET_GROUP_POSITIONALS,
625
+ tenant: GET_TENANT_POSITIONALS,
626
+ authorization: GET_AUTHORIZATION_POSITIONALS,
627
+ "mapping-rule": GET_MAPPING_RULE_POSITIONALS,
628
+ form: GET_FORM_POSITIONALS,
380
629
  },
381
630
  },
382
631
  // ── Mutating commands ──────────────────────────────────────────────────
383
632
  create: {
384
633
  description: "Create resource",
634
+ helpDescription: "Create a resource (process instance, identity)",
635
+ hasDetailedHelp: true,
636
+ helpFooterLabel: "Show all create resources and their flags",
385
637
  mutating: true,
386
638
  requiresResource: true,
639
+ helpExamples: [
640
+ {
641
+ command: "c8ctl create pi --id=myProcess",
642
+ description: "Create a process instance",
643
+ },
644
+ {
645
+ command: "c8ctl create pi --id=myProcess --awaitCompletion",
646
+ description: "Create and await completion",
647
+ },
648
+ {
649
+ command: "c8ctl create user --username=john --name='John Doe' --email=john@example.com --password=secret",
650
+ description: "Create a user",
651
+ },
652
+ ],
387
653
  resources: [
388
654
  "pi",
389
655
  "user",
@@ -398,10 +664,13 @@ export const COMMAND_REGISTRY = {
398
664
  processDefinitionId: {
399
665
  type: "string",
400
666
  description: "Process definition ID (BPMN process ID)",
667
+ validate: ProcessDefinitionId.assumeExists,
401
668
  },
402
669
  id: {
403
670
  type: "string",
404
671
  description: "Process definition ID (alias for --processDefinitionId)",
672
+ showInTopLevelHelp: true,
673
+ helpHint: "alias for --bpmnProcessId",
405
674
  },
406
675
  bpmnProcessId: {
407
676
  type: "string",
@@ -411,17 +680,26 @@ export const COMMAND_REGISTRY = {
411
680
  awaitCompletion: {
412
681
  type: "boolean",
413
682
  description: "Wait for process to complete",
683
+ showInTopLevelHelp: true,
684
+ helpHint: "use with 'create pi'",
414
685
  },
415
686
  fetchVariables: {
416
687
  type: "boolean",
417
688
  description: "Fetch result variables on completion",
689
+ showInTopLevelHelp: true,
418
690
  },
419
691
  requestTimeout: {
420
692
  type: "string",
421
693
  description: "Await timeout in milliseconds",
694
+ showInTopLevelHelp: true,
695
+ helpHint: "use with --awaitCompletion",
422
696
  },
423
697
  // Identity user
424
- username: { type: "string", description: "Username" },
698
+ username: {
699
+ type: "string",
700
+ description: "Username",
701
+ validate: Username.assumeExists,
702
+ },
425
703
  name: { type: "string", description: "Display name" },
426
704
  email: { type: "string", description: "Email address" },
427
705
  password: { type: "string", description: "Password" },
@@ -430,7 +708,11 @@ export const COMMAND_REGISTRY = {
430
708
  // Identity group
431
709
  groupId: { type: "string", description: "Group ID" },
432
710
  // Identity tenant
433
- tenantId: { type: "string", description: "Tenant ID" },
711
+ tenantId: {
712
+ type: "string",
713
+ description: "Tenant ID",
714
+ validate: TenantId.assumeExists,
715
+ },
434
716
  // Identity authorization
435
717
  ownerId: {
436
718
  type: "string",
@@ -469,27 +751,60 @@ export const COMMAND_REGISTRY = {
469
751
  },
470
752
  delete: {
471
753
  description: "Delete resource",
754
+ helpDescription: "Delete a resource by key",
755
+ helpResource: "<resource> <key>",
756
+ hasDetailedHelp: true,
757
+ helpFooterLabel: "Show delete command with all flags",
472
758
  mutating: true,
473
759
  requiresResource: true,
760
+ helpExamples: [
761
+ { command: "c8ctl delete user john", description: "Delete user" },
762
+ ],
474
763
  resources: ["user", "role", "group", "tenant", "auth", "mapping-rule"],
475
764
  flags: {},
765
+ resourcePositionals: {
766
+ user: GET_USER_POSITIONALS,
767
+ role: GET_ROLE_POSITIONALS,
768
+ group: GET_GROUP_POSITIONALS,
769
+ tenant: GET_TENANT_POSITIONALS,
770
+ authorization: GET_AUTHORIZATION_POSITIONALS,
771
+ "mapping-rule": GET_MAPPING_RULE_POSITIONALS,
772
+ },
476
773
  },
477
774
  cancel: {
478
775
  description: "Cancel resource",
776
+ helpDescription: "Cancel a process instance",
777
+ helpResource: "<resource> <key>",
778
+ hasDetailedHelp: true,
779
+ helpFooterLabel: "Show cancel command with all flags",
479
780
  mutating: true,
480
781
  requiresResource: true,
481
782
  resources: ["pi"],
482
783
  flags: {},
784
+ resourcePositionals: {
785
+ "process-instance": GET_PI_POSITIONALS,
786
+ },
483
787
  },
484
788
  await: {
485
789
  description: "Create and await completion (alias for create --awaitCompletion)",
790
+ helpDescription: "Create and await process instance completion (server-side waiting)",
791
+ helpResource: "<resource>",
792
+ hasDetailedHelp: true,
793
+ helpFooterLabel: "Show await command with all flags",
486
794
  mutating: true,
487
795
  requiresResource: true,
796
+ helpExamples: [
797
+ {
798
+ command: "c8ctl await pi --id=myProcess",
799
+ description: "Create and wait for completion",
800
+ },
801
+ ],
488
802
  resources: ["pi"],
489
803
  flags: {
490
804
  processDefinitionId: {
491
805
  type: "string",
492
806
  description: "Process definition ID (BPMN process ID)",
807
+ validate: ProcessDefinitionId.assumeExists,
493
808
  },
494
809
  id: {
495
810
  type: "string",
@@ -512,15 +827,38 @@ export const COMMAND_REGISTRY = {
512
827
  },
513
828
  complete: {
514
829
  description: "Complete resource",
830
+ helpDescription: "Complete a user task or job",
831
+ helpResource: "<resource> <key>",
832
+ hasDetailedHelp: true,
833
+ helpFooterLabel: "Show all complete resources and their flags",
515
834
  mutating: true,
516
835
  requiresResource: true,
517
836
  resources: ["ut", "job"],
518
837
  flags: {
519
838
  variables: { type: "string", description: "JSON variables" },
520
839
  },
840
+ resourcePositionals: {
841
+ "user-task": [
842
+ {
843
+ name: "key",
844
+ required: true,
845
+ validate: UserTaskKey.assumeExists,
846
+ },
847
+ ],
848
+ job: [
849
+ {
850
+ name: "key",
851
+ required: true,
852
+ validate: JobKey.assumeExists,
853
+ },
854
+ ],
855
+ },
521
856
  },
522
857
  fail: {
523
858
  description: "Fail a job",
859
+ helpDescription: "Mark a job as failed with optional error message and retry count",
860
+ hasDetailedHelp: true,
861
+ helpFooterLabel: "Show fail command with all flags",
524
862
  mutating: true,
525
863
  requiresResource: true,
526
864
  resources: ["job"],
@@ -534,9 +872,21 @@ export const COMMAND_REGISTRY = {
534
872
  description: "Error message",
535
873
  },
536
874
  },
875
+ resourcePositionals: {
876
+ job: [
877
+ {
878
+ name: "key",
879
+ required: true,
880
+ validate: JobKey.assumeExists,
881
+ },
882
+ ],
883
+ },
537
884
  },
538
885
  activate: {
539
886
  description: "Activate jobs by type",
887
+ helpDescription: "Activate jobs of a specific type for processing",
888
+ hasDetailedHelp: true,
889
+ helpFooterLabel: "Show activate command with all flags",
540
890
  mutating: true,
541
891
  requiresResource: true,
542
892
  resources: ["jobs"],
@@ -551,16 +901,30 @@ export const COMMAND_REGISTRY = {
551
901
  },
552
902
  worker: { type: "string", description: "Worker name" },
553
903
  },
904
+ resourcePositionals: {
905
+ jobs: [
906
+ { name: "type", required: true },
907
+ ],
908
+ },
554
909
  },
555
910
  resolve: {
556
911
  description: "Resolve incident",
912
+ helpDescription: "Resolve an incident (marks resolved, allows process to continue)",
913
+ hasDetailedHelp: true,
914
+ helpFooterLabel: "Show resolve command with all flags",
557
915
  mutating: true,
558
916
  requiresResource: true,
559
917
  resources: ["inc"],
560
918
  flags: {},
919
+ resourcePositionals: {
920
+ incident: GET_INCIDENT_POSITIONALS,
921
+ },
561
922
  },
562
923
  publish: {
563
924
  description: "Publish message",
925
+ helpDescription: "Publish a message for message correlation",
926
+ hasDetailedHelp: true,
927
+ helpFooterLabel: "Show publish command with all flags",
564
928
  mutating: true,
565
929
  requiresResource: true,
566
930
  resources: ["msg"],
@@ -575,9 +939,17 @@ export const COMMAND_REGISTRY = {
575
939
  description: "Time to live in milliseconds",
576
940
  },
577
941
  },
942
+ resourcePositionals: {
943
+ message: [
944
+ { name: "name", required: true },
945
+ ],
946
+ },
578
947
  },
579
948
  correlate: {
580
949
  description: "Correlate message",
950
+ helpDescription: "Correlate a message to a specific process instance",
951
+ hasDetailedHelp: true,
952
+ helpFooterLabel: "Show correlate command with all flags",
581
953
  mutating: true,
582
954
  requiresResource: true,
583
955
  resources: ["msg"],
@@ -593,18 +965,43 @@ export const COMMAND_REGISTRY = {
593
965
  description: "Time to live in milliseconds",
594
966
  },
595
967
  },
968
+ resourcePositionals: {
969
+ message: [
970
+ { name: "name", required: true },
971
+ ],
972
+ },
596
973
  },
597
974
  deploy: {
598
975
  description: "Deploy BPMN/DMN/forms",
976
+ helpDescription: "Deploy BPMN, DMN, and form files (auto-discovers deployable files)",
977
+ helpResource: "[path...]",
978
+ hasDetailedHelp: true,
979
+ helpFooterLabel: "Show deploy command with all flags",
599
980
  mutating: true,
600
981
  requiresResource: false,
982
+ helpExamples: [
983
+ {
984
+ command: "c8ctl deploy ./my-process.bpmn",
985
+ description: "Deploy a BPMN file",
986
+ },
987
+ ],
601
988
  resources: [],
602
989
  flags: {},
603
990
  },
604
991
  run: {
605
992
  description: "Deploy and start process",
993
+ helpDescription: "Deploy and start a process instance from a BPMN file",
994
+ helpResource: "<path>",
995
+ hasDetailedHelp: true,
996
+ helpFooterLabel: "Show run command with all flags",
606
997
  mutating: true,
607
998
  requiresResource: true,
999
+ helpExamples: [
1000
+ {
1001
+ command: "c8ctl run ./my-process.bpmn",
1002
+ description: "Deploy and start process",
1003
+ },
1004
+ ],
608
1005
  resources: [],
609
1006
  flags: {
610
1007
  variables: { type: "string", description: "JSON variables" },
@@ -613,36 +1010,96 @@ export const COMMAND_REGISTRY = {
613
1010
  // ── Assignment commands ────────────────────────────────────────────────
614
1011
  assign: {
615
1012
  description: "Assign resource to target",
1013
+ helpDescription: "Assign a resource to a target (--to-user, --to-group, etc.)",
1014
+ helpResource: "<resource> <id>",
1015
+ hasDetailedHelp: true,
1016
+ helpFooterLabel: "Show assign command with all flags",
616
1017
  mutating: true,
617
1018
  requiresResource: true,
1019
+ helpExamples: [
1020
+ {
1021
+ command: "c8ctl assign role admin --to-user=john",
1022
+ description: "Assign role to user",
1023
+ },
1024
+ ],
618
1025
  resources: ["role", "user", "group", "mapping-rule"],
619
1026
  flags: { ...ASSIGN_FLAGS },
1027
+ resourcePositionals: {
1028
+ role: GET_ROLE_POSITIONALS,
1029
+ user: GET_USER_POSITIONALS,
1030
+ group: GET_GROUP_POSITIONALS,
1031
+ "mapping-rule": GET_MAPPING_RULE_POSITIONALS,
1032
+ },
620
1033
  },
621
1034
  unassign: {
622
1035
  description: "Unassign resource from target",
1036
+ helpDescription: "Unassign a resource from a target (--from-user, --from-group, etc.)",
1037
+ helpResource: "<resource> <id>",
1038
+ hasDetailedHelp: true,
1039
+ helpFooterLabel: "Show unassign command with all flags",
623
1040
  mutating: true,
624
1041
  requiresResource: true,
1042
+ helpExamples: [
1043
+ {
1044
+ command: "c8ctl unassign role admin --from-user=john",
1045
+ description: "Unassign role from user",
1046
+ },
1047
+ ],
625
1048
  resources: ["role", "user", "group", "mapping-rule"],
626
1049
  flags: { ...UNASSIGN_FLAGS },
1050
+ resourcePositionals: {
1051
+ role: GET_ROLE_POSITIONALS,
1052
+ user: GET_USER_POSITIONALS,
1053
+ group: GET_GROUP_POSITIONALS,
1054
+ "mapping-rule": GET_MAPPING_RULE_POSITIONALS,
1055
+ },
627
1056
  },
628
1057
  // ── Operational commands ───────────────────────────────────────────────
629
1058
  watch: {
630
1059
  description: "Watch files for changes and auto-deploy",
1060
+ helpDescription: "Watch files for changes and auto-deploy (BPMN, DMN, forms)",
1061
+ helpResource: "[path...]",
1062
+ hasDetailedHelp: true,
1063
+ helpFooterLabel: "Show watch command with all flags",
631
1064
  mutating: false,
632
1065
  requiresResource: false,
1066
+ helpExamples: [
1067
+ {
1068
+ command: "c8ctl watch ./src",
1069
+ description: "Watch directory for changes",
1070
+ },
1071
+ ],
633
1072
  resources: [],
634
1073
  flags: {
635
1074
  force: {
636
1075
  type: "boolean",
637
- description: "Force re-deploy unchanged files",
1076
+ description: "Continue watching after all deployment errors",
638
1077
  },
639
1078
  },
640
1079
  aliases: ["w"],
641
1080
  },
642
1081
  open: {
643
1082
  description: "Open Camunda web application in browser",
1083
+ helpDescription: "Open Camunda web app in browser",
1084
+ helpResource: "<app>",
1085
+ hasDetailedHelp: true,
1086
+ helpFooterLabel: "Show open command with all apps",
644
1087
  mutating: false,
645
1088
  requiresResource: true,
1089
+ helpExamples: [
1090
+ {
1091
+ command: "c8ctl open operate",
1092
+ description: "Open Camunda Operate in browser",
1093
+ },
1094
+ {
1095
+ command: "c8ctl open tasklist",
1096
+ description: "Open Camunda Tasklist in browser",
1097
+ },
1098
+ {
1099
+ command: "c8ctl open operate --profile=prod",
1100
+ description: "Open Operate using a specific profile",
1101
+ },
1102
+ ],
646
1103
  resources: ["operate", "tasklist", "modeler", "optimize"],
647
1104
  flags: {},
648
1105
  },
@@ -653,12 +1110,19 @@ export const COMMAND_REGISTRY = {
653
1110
  requiresResource: true,
654
1111
  resources: ["profile"],
655
1112
  flags: { ...PROFILE_CONNECTION_FLAGS },
1113
+ resourcePositionals: {
1114
+ profile: [
1115
+ { name: "name", required: true },
1116
+ ],
1117
+ },
656
1118
  },
657
1119
  remove: {
658
- description: "Remove a profile",
1120
+ description: "Remove a profile or plugin",
1121
+ helpResource: "profile <name>",
1122
+ helpDescription: "Remove a profile (alias: rm)",
659
1123
  mutating: false,
660
1124
  requiresResource: true,
661
- resources: ["profile"],
1125
+ resources: ["profile", "plugin"],
662
1126
  flags: {
663
1127
  none: {
664
1128
  type: "boolean",
@@ -666,21 +1130,50 @@ export const COMMAND_REGISTRY = {
666
1130
  },
667
1131
  },
668
1132
  aliases: ["rm"],
1133
+ resourcePositionals: {
1134
+ profile: [
1135
+ { name: "name", required: true },
1136
+ ],
1137
+ plugin: [
1138
+ { name: "package", required: true },
1139
+ ],
1140
+ },
669
1141
  },
670
1142
  load: {
671
1143
  description: "Load a c8ctl plugin",
1144
+ helpResource: "plugin [name|--from url]",
1145
+ helpDescription: "Load a c8ctl plugin (npm registry or URL)",
672
1146
  mutating: false,
673
1147
  requiresResource: true,
1148
+ helpExamples: [
1149
+ {
1150
+ command: "c8ctl load plugin my-plugin",
1151
+ description: "Load plugin from npm registry",
1152
+ },
1153
+ {
1154
+ command: "c8ctl load plugin --from https://github.com/org/plugin",
1155
+ description: "Load plugin from URL",
1156
+ },
1157
+ ],
674
1158
  resources: ["plugin"],
675
1159
  flags: {
676
1160
  from: {
677
1161
  type: "string",
678
1162
  description: "Load plugin from URL",
1163
+ showInTopLevelHelp: true,
1164
+ helpHint: "use with 'load plugin'",
679
1165
  },
680
1166
  },
1167
+ resourcePositionals: {
1168
+ plugin: [
1169
+ { name: "package", required: false },
1170
+ ],
1171
+ },
681
1172
  },
682
1173
  unload: {
683
1174
  description: "Unload a c8ctl plugin",
1175
+ helpResource: "plugin <name>",
1176
+ helpDescription: "Unload a c8ctl plugin (npm uninstall wrapper)",
684
1177
  mutating: false,
685
1178
  requiresResource: true,
686
1179
  resources: ["plugin"],
@@ -691,25 +1184,59 @@ export const COMMAND_REGISTRY = {
691
1184
  },
692
1185
  },
693
1186
  aliases: ["rm"],
1187
+ resourcePositionals: {
1188
+ plugin: [
1189
+ { name: "package", required: true },
1190
+ ],
1191
+ },
694
1192
  },
695
1193
  upgrade: {
696
1194
  description: "Upgrade a plugin",
1195
+ helpResource: "plugin <name> [version]",
1196
+ helpDescription: "Upgrade a plugin (respects source type)",
697
1197
  mutating: false,
698
1198
  requiresResource: true,
1199
+ helpExamples: [
1200
+ {
1201
+ command: "c8ctl upgrade plugin my-plugin",
1202
+ description: "Upgrade plugin to latest version",
1203
+ },
1204
+ {
1205
+ command: "c8ctl upgrade plugin my-plugin 1.2.3",
1206
+ description: "Upgrade plugin to a specific version (source-aware)",
1207
+ },
1208
+ ],
699
1209
  resources: ["plugin"],
700
1210
  flags: {},
1211
+ resourcePositionals: {
1212
+ plugin: [
1213
+ { name: "package", required: true },
1214
+ { name: "version", required: false },
1215
+ ],
1216
+ },
701
1217
  },
702
1218
  downgrade: {
703
1219
  description: "Downgrade a plugin to a specific version",
1220
+ helpResource: "plugin <name> <version>",
704
1221
  mutating: false,
705
1222
  requiresResource: true,
706
1223
  resources: ["plugin"],
707
1224
  flags: {},
1225
+ resourcePositionals: {
1226
+ plugin: [
1227
+ { name: "package", required: true },
1228
+ { name: "version", required: true },
1229
+ ],
1230
+ },
708
1231
  },
709
1232
  sync: {
710
1233
  description: "Synchronize plugins",
1234
+ helpDescription: "Synchronize plugins from registry (rebuild/reinstall)",
711
1235
  mutating: false,
712
1236
  requiresResource: true,
1237
+ helpExamples: [
1238
+ { command: "c8ctl sync plugin", description: "Synchronize plugins" },
1239
+ ],
713
1240
  resources: ["plugin"],
714
1241
  flags: {},
715
1242
  },
@@ -717,14 +1244,29 @@ export const COMMAND_REGISTRY = {
717
1244
  description: "Create a new plugin from TypeScript template",
718
1245
  mutating: false,
719
1246
  requiresResource: true,
1247
+ helpExamples: [
1248
+ {
1249
+ command: "c8ctl init plugin my-plugin",
1250
+ description: "Create new plugin from template (c8ctl-plugin-my-plugin)",
1251
+ },
1252
+ ],
720
1253
  resources: ["plugin"],
721
1254
  flags: {},
1255
+ resourcePositionals: {
1256
+ plugin: [
1257
+ { name: "name", required: false },
1258
+ ],
1259
+ },
722
1260
  },
723
1261
  // ── Session commands ───────────────────────────────────────────────────
724
1262
  use: {
725
1263
  description: "Set active profile or tenant",
1264
+ helpResource: "profile|tenant",
726
1265
  mutating: false,
727
1266
  requiresResource: true,
1267
+ helpExamples: [
1268
+ { command: "c8ctl use profile prod", description: "Set active profile" },
1269
+ ],
728
1270
  resources: ["profile", "tenant"],
729
1271
  flags: {
730
1272
  none: {
@@ -732,24 +1274,63 @@ export const COMMAND_REGISTRY = {
732
1274
  description: "Clear active profile/tenant",
733
1275
  },
734
1276
  },
1277
+ resourcePositionals: {
1278
+ profile: [
1279
+ { name: "name", required: false },
1280
+ ],
1281
+ tenant: [
1282
+ { name: "tenantId", required: true },
1283
+ ],
1284
+ },
735
1285
  },
736
1286
  output: {
737
1287
  description: "Show or set output format",
1288
+ helpResource: "[json|text]",
738
1289
  mutating: false,
739
1290
  requiresResource: false,
1291
+ helpExamples: [
1292
+ { command: "c8ctl output json", description: "Switch to JSON output" },
1293
+ ],
740
1294
  resources: ["json", "text"],
741
1295
  flags: {},
742
1296
  },
743
1297
  // ── Utility commands ───────────────────────────────────────────────────
744
1298
  completion: {
745
1299
  description: "Generate shell completion script",
746
- mutating: false,
1300
+ helpResource: "bash|zsh|fish|install",
1301
+ mutating: true,
747
1302
  requiresResource: false,
748
- resources: ["bash", "zsh", "fish"],
1303
+ helpExamples: [
1304
+ {
1305
+ command: "c8ctl completion bash",
1306
+ description: "Generate bash completion script",
1307
+ },
1308
+ {
1309
+ command: "c8ctl completion install",
1310
+ description: "Auto-detect shell and install completions (auto-refreshes on upgrade)",
1311
+ },
1312
+ {
1313
+ command: "c8ctl completion install --shell zsh",
1314
+ description: "Install completions for a specific shell",
1315
+ },
1316
+ ],
1317
+ resources: ["bash", "zsh", "fish", "install"],
749
1318
  flags: {},
1319
+ resourceFlags: {
1320
+ install: {
1321
+ shell: {
1322
+ type: "string",
1323
+ description: "Shell to install completions for (bash, zsh, fish)",
1324
+ },
1325
+ },
1326
+ },
750
1327
  },
751
1328
  "mcp-proxy": {
752
1329
  description: "Start a STDIO to remote HTTP MCP proxy server",
1330
+ helpDescription: "Start a STDIO MCP proxy (bridges local MCP clients to remote Camunda 8)",
1331
+ helpResource: "[mcp-path]",
1332
+ hasDetailedHelp: true,
1333
+ helpFooterLabel: "Show mcp-proxy setup and usage",
753
1334
  mutating: false,
754
1335
  requiresResource: false,
755
1336
  resources: [],
@@ -764,39 +1345,28 @@ export const COMMAND_REGISTRY = {
764
1345
  },
765
1346
  help: {
766
1347
  description: "Show help",
1348
+ helpResource: "[command]",
1349
+ helpDescription: "Show help (run 'c8ctl help <command>' for details)",
767
1350
  mutating: false,
768
1351
  requiresResource: false,
769
1352
  resources: [],
770
1353
  flags: {},
1354
+ aliases: ["menu"],
771
1355
  },
772
1356
  which: {
773
1357
  description: "Show active profile",
774
1358
  mutating: false,
775
1359
  requiresResource: true,
1360
+ helpExamples: [
1361
+ {
1362
+ command: "c8ctl which profile",
1363
+ description: "Show currently active profile",
1364
+ },
1365
+ ],
776
1366
  resources: ["profile"],
777
1367
  flags: {},
778
1368
  },
779
1369
  };
780
- // ─── Per-resource search flag scoping ────────────────────────────────────────
781
- /**
782
- * Maps each searchable resource (canonical name) to the set of flag names
783
- * that are valid for that resource's search command. Used for unknown-flag
784
- * detection in search commands.
785
- */
786
- export const SEARCH_RESOURCE_FLAGS = {
787
- "process-definition": new Set(Object.keys(PD_SEARCH_FLAGS)),
788
- "process-instance": new Set(Object.keys(PI_SEARCH_FLAGS)),
789
- "user-task": new Set(Object.keys(UT_SEARCH_FLAGS)),
790
- incident: new Set(Object.keys(INC_SEARCH_FLAGS)),
791
- jobs: new Set(Object.keys(JOB_SEARCH_FLAGS)),
792
- variable: new Set([...Object.keys(VAR_SEARCH_FLAGS), "limit"]),
793
- user: new Set([...Object.keys(USER_SEARCH_FLAGS), "limit"]),
794
- role: new Set([...Object.keys(ROLE_SEARCH_FLAGS), "limit"]),
795
- group: new Set([...Object.keys(GROUP_SEARCH_FLAGS), "limit"]),
796
- tenant: new Set([...Object.keys(TENANT_SEARCH_FLAGS), "limit"]),
797
- authorization: new Set([...Object.keys(AUTH_SEARCH_FLAGS), "limit"]),
798
- "mapping-rule": new Set([...Object.keys(MR_SEARCH_FLAGS), "limit"]),
799
- };
800
1370
  // ─── Helpers ─────────────────────────────────────────────────────────────────
801
1371
  /**
802
1372
  * Maps verb aliases to their canonical verb names.
@@ -805,6 +1375,7 @@ export const SEARCH_RESOURCE_FLAGS = {
805
1375
  */
806
1376
  export const VERB_ALIASES = (() => {
807
1377
  const map = {};
1378
+ // biome-ignore lint/plugin: widen to CommandDef to access optional aliases property
808
1379
  for (const [verb, def] of Object.entries(COMMAND_REGISTRY)) {
809
1380
  for (const alias of def.aliases ?? []) {
810
1381
  if (!map[alias]) {
@@ -828,11 +1399,15 @@ export function resolveAlias(resource) {
828
1399
  * returns the first match. Use VERB_ALIASES directly for multi-target aliases.
829
1400
  */
830
1401
  export function getCommandDef(verb) {
1402
+ // biome-ignore lint/plugin: trust boundary — verb is unvalidated CLI input, must index dynamically
831
1403
  const direct = COMMAND_REGISTRY[verb];
832
1404
  if (direct)
833
1405
  return direct;
834
1406
  const targets = VERB_ALIASES[verb];
835
- return targets ? COMMAND_REGISTRY[targets[0]] : undefined;
1407
+ return targets
1408
+ ? // biome-ignore lint/plugin: trust boundary — alias target is a dynamic string
1409
+ COMMAND_REGISTRY[targets[0]]
1410
+ : undefined;
836
1411
  }
837
1412
  /**
838
1413
  * Get all flags accepted for a given verb, including global flags.
@@ -843,12 +1418,6 @@ export function getAcceptedFlags(verb) {
843
1418
  return undefined;
844
1419
  return { ...GLOBAL_FLAGS, ...def.flags };
845
1420
  }
846
- /**
847
- * Get the set of resource-specific search flags for a given canonical resource.
848
- */
849
- export function getSearchFlagsForResource(resource) {
850
- return SEARCH_RESOURCE_FLAGS[resource];
851
- }
852
1421
  /**
853
1422
  * Check whether a verb×resource combination is valid.
854
1423
  * Accepts both raw aliases and canonical resource names.
@@ -868,26 +1437,44 @@ export function isValidCommand(verb, resource) {
868
1437
  * Derive parseArgs options from the registry. This produces the flat
869
1438
  * options object that node:util parseArgs expects, covering all flags
870
1439
  * from all commands plus global flags.
1440
+ *
1441
+ * When the same flag name appears with different types across commands
1442
+ * (e.g. `--variables` is boolean for `get pi` but string for `create pi`),
1443
+ * "string" wins because parseArgs with `type: "string"` can accept any
1444
+ * value, whereas `type: "boolean"` would discard the string payload.
871
1445
  */
872
1446
  export function deriveParseArgsOptions() {
873
1447
  const options = {};
874
- // Global flags
875
- for (const [name, def] of Object.entries(GLOBAL_FLAGS)) {
876
- options[name] = { type: def.type, ...(def.short && { short: def.short }) };
877
- }
878
- // Search flags
879
- for (const [name, def] of Object.entries(SEARCH_FLAGS)) {
880
- options[name] = { type: def.type, ...(def.short && { short: def.short }) };
881
- }
882
- // All command-specific flags
883
- for (const cmd of Object.values(COMMAND_REGISTRY)) {
884
- for (const [name, def] of Object.entries(cmd.flags)) {
885
- if (!options[name]) {
1448
+ function addFlags(flags) {
1449
+ for (const [name, def] of Object.entries(flags)) {
1450
+ const existing = options[name];
1451
+ if (!existing) {
886
1452
  options[name] = {
887
1453
  type: def.type,
888
1454
  ...(def.short && { short: def.short }),
889
1455
  };
890
1456
  }
1457
+ else {
1458
+ // String is more permissive — upgrade when any usage is string
1459
+ if (def.type === "string")
1460
+ existing.type = "string";
1461
+ if (def.short && !existing.short)
1462
+ existing.short = def.short;
1463
+ }
1464
+ }
1465
+ }
1466
+ // Global flags
1467
+ addFlags(GLOBAL_FLAGS);
1468
+ // Search flags
1469
+ addFlags(SEARCH_FLAGS);
1470
+ // All command-specific flags
1471
+ for (const cmd of Object.values(COMMAND_REGISTRY)) {
1472
+ addFlags(cmd.flags);
1473
+ // Include resource-specific flags so parseArgs can parse them
1474
+ if ("resourceFlags" in cmd && cmd.resourceFlags) {
1475
+ for (const rFlags of Object.values(cmd.resourceFlags)) {
1476
+ addFlags(rFlags);
1477
+ }
891
1478
  }
892
1479
  }
893
1480
  return options;