@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
@@ -4,543 +4,131 @@
4
4
  import { readFileSync } from "node:fs";
5
5
  import { dirname, join } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
+ import { COMMAND_REGISTRY, GLOBAL_FLAGS, RESOURCE_ALIASES, SEARCH_FLAGS, } from "../command-registry.js";
7
8
  import { getLogger } from "../logger.js";
8
- import { getPluginCommandsInfo, } from "../plugin-loader.js";
9
+ import { executePluginCommand, getPluginCommandsInfo, isPluginCommand, } from "../plugin-loader.js";
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = dirname(__filename);
12
+ /** Typed entries for COMMAND_REGISTRY — avoids `as CommandDef` on every loop. */
13
+ function registryEntries() {
14
+ return Object.entries(COMMAND_REGISTRY);
15
+ }
16
+ /** Typed entries for a flag record — avoids `as FlagDef` on every loop. */
17
+ function flagEntries(flags) {
18
+ return Object.entries(flags);
19
+ }
20
+ /** Look up a verb in COMMAND_REGISTRY, returning undefined for unknown verbs. */
21
+ function lookupVerb(verb) {
22
+ // biome-ignore lint/plugin: single isolation point — COMMAND_REGISTRY uses `satisfies` so Object index needs widening
23
+ return COMMAND_REGISTRY[verb];
24
+ }
25
+ /**
26
+ * Derive the display name for a resource, showing long name with alias.
27
+ * e.g. "pi" → "process-instance (pi)", "jobs" → "jobs"
28
+ */
29
+ function resourceDisplayName(resource) {
30
+ const canonical = RESOURCE_ALIASES[resource];
31
+ // No alias mapping — show as-is
32
+ if (!canonical || canonical === resource)
33
+ return resource;
34
+ // Resource is longer than canonical (e.g. "process-instances" → "process-instance")
35
+ if (resource.length > canonical.length)
36
+ return `${resource} (${canonical})`;
37
+ // Resource is a short alias (e.g. "pi" → "process-instance")
38
+ return `${canonical} (${resource})`;
39
+ }
40
+ /**
41
+ * Format a single flag for display.
42
+ */
43
+ function formatFlag(name, def, col) {
44
+ const flag = def.short ? `--${name}, -${def.short}` : `--${name}`;
45
+ const typeHint = def.type === "string" ? ` <${name}>` : "";
46
+ return ` ${(flag + typeHint).padEnd(col)}${def.description}`;
47
+ }
48
+ /**
49
+ * Build structured JSON help data for machine/agent consumption.
50
+ * Derived entirely from COMMAND_REGISTRY.
51
+ */
11
52
  function buildHelpJson(version, pluginCommandsInfo) {
53
+ const commands = [];
54
+ for (const [verb, def] of registryEntries()) {
55
+ commands.push({
56
+ verb,
57
+ resource: deriveResourcePlaceholder(verb, def),
58
+ resources: [...def.resources],
59
+ description: def.helpDescription ?? def.description,
60
+ mutating: def.mutating,
61
+ });
62
+ }
63
+ for (const cmd of pluginCommandsInfo) {
64
+ commands.push({
65
+ verb: cmd.commandName,
66
+ resource: "",
67
+ resources: [],
68
+ description: cmd.description || "",
69
+ mutating: false,
70
+ examples: cmd.examples || [],
71
+ });
72
+ }
73
+ // Derive resource aliases: short alias → canonical(s)
74
+ const resourceAliases = {};
75
+ for (const [alias, canonical] of Object.entries(RESOURCE_ALIASES)) {
76
+ if (alias.length <= 4 && alias !== canonical) {
77
+ resourceAliases[alias] = `${canonical}(s)`;
78
+ }
79
+ }
80
+ // Derive global flags from GLOBAL_FLAGS + SEARCH_FLAGS
81
+ const globalFlags = [];
82
+ for (const [name, def] of flagEntries(GLOBAL_FLAGS)) {
83
+ globalFlags.push({
84
+ flag: `--${name}`,
85
+ type: def.type,
86
+ description: def.description,
87
+ ...(def.short ? { short: `-${def.short}` } : {}),
88
+ });
89
+ }
90
+ for (const [name, def] of Object.entries(SEARCH_FLAGS)) {
91
+ globalFlags.push({
92
+ flag: `--${name}`,
93
+ type: def.type,
94
+ description: def.description,
95
+ });
96
+ }
97
+ // Derive search flags from list/search resourceFlags
98
+ const searchFlags = [];
99
+ const seenSearchFlags = new Set();
100
+ for (const verb of ["list", "search"]) {
101
+ const cmdDef = lookupVerb(verb);
102
+ if (cmdDef?.resourceFlags) {
103
+ for (const resourceFlags of Object.values(cmdDef.resourceFlags)) {
104
+ for (const [name, fd] of flagEntries(resourceFlags)) {
105
+ if (!seenSearchFlags.has(name)) {
106
+ seenSearchFlags.add(name);
107
+ searchFlags.push({
108
+ flag: `--${name}`,
109
+ type: fd.type,
110
+ description: fd.description,
111
+ });
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
12
117
  return {
13
118
  version,
14
119
  usage: "c8ctl <command> [resource] [options]",
15
- commands: [
16
- {
17
- verb: "list",
18
- resource: "<resource>",
19
- resources: [
20
- "pi",
21
- "pd",
22
- "ut",
23
- "inc",
24
- "jobs",
25
- "profiles",
26
- "plugins",
27
- "users",
28
- "roles",
29
- "groups",
30
- "tenants",
31
- "auth",
32
- "mapping-rules",
33
- ],
34
- description: "List resources (process, identity)",
35
- mutating: false,
36
- },
37
- {
38
- verb: "search",
39
- resource: "<resource>",
40
- resources: [
41
- "pi",
42
- "pd",
43
- "ut",
44
- "inc",
45
- "jobs",
46
- "vars",
47
- "users",
48
- "roles",
49
- "groups",
50
- "tenants",
51
- "auth",
52
- "mapping-rules",
53
- ],
54
- description: "Search resources with filters",
55
- mutating: false,
56
- },
57
- {
58
- verb: "get",
59
- resource: "<resource> <key>",
60
- resources: [
61
- "pi",
62
- "pd",
63
- "inc",
64
- "topology",
65
- "form",
66
- "user",
67
- "role",
68
- "group",
69
- "tenant",
70
- "auth",
71
- "mapping-rule",
72
- ],
73
- description: "Get resource by key",
74
- mutating: false,
75
- },
76
- {
77
- verb: "create",
78
- resource: "<resource>",
79
- resources: [
80
- "pi",
81
- "user",
82
- "role",
83
- "group",
84
- "tenant",
85
- "auth",
86
- "mapping-rule",
87
- ],
88
- description: "Create resource",
89
- mutating: true,
90
- },
91
- {
92
- verb: "delete",
93
- resource: "<resource> <key>",
94
- resources: ["user", "role", "group", "tenant", "auth", "mapping-rule"],
95
- description: "Delete resource",
96
- mutating: true,
97
- },
98
- {
99
- verb: "assign",
100
- resource: "<resource> <id> --to-<target>=<id>",
101
- resources: ["role", "user", "group", "mapping-rule"],
102
- description: "Assign resource to target",
103
- mutating: true,
104
- },
105
- {
106
- verb: "unassign",
107
- resource: "<resource> <id> --from-<target>=<id>",
108
- resources: ["role", "user", "group", "mapping-rule"],
109
- description: "Unassign resource from target",
110
- mutating: true,
111
- },
112
- {
113
- verb: "cancel",
114
- resource: "<resource> <key>",
115
- resources: ["pi"],
116
- description: "Cancel resource",
117
- mutating: true,
118
- },
119
- {
120
- verb: "await",
121
- resource: "<resource>",
122
- resources: ["pi"],
123
- description: "Create and await completion (alias for create --awaitCompletion)",
124
- mutating: true,
125
- },
126
- {
127
- verb: "complete",
128
- resource: "<resource> <key>",
129
- resources: ["ut", "job"],
130
- description: "Complete resource",
131
- mutating: true,
132
- },
133
- {
134
- verb: "fail",
135
- resource: "job <key>",
136
- resources: ["job"],
137
- description: "Fail a job",
138
- mutating: true,
139
- },
140
- {
141
- verb: "activate",
142
- resource: "jobs <type>",
143
- resources: ["jobs"],
144
- description: "Activate jobs by type",
145
- mutating: true,
146
- },
147
- {
148
- verb: "resolve",
149
- resource: "inc <key>",
150
- resources: ["inc"],
151
- description: "Resolve incident",
152
- mutating: true,
153
- },
154
- {
155
- verb: "publish",
156
- resource: "msg <name>",
157
- resources: ["msg"],
158
- description: "Publish message",
159
- mutating: true,
160
- },
161
- {
162
- verb: "correlate",
163
- resource: "msg <name>",
164
- resources: ["msg"],
165
- description: "Correlate message",
166
- mutating: true,
167
- },
168
- {
169
- verb: "deploy",
170
- resource: "[path...]",
171
- resources: [],
172
- description: "Deploy BPMN/DMN/forms",
173
- mutating: true,
174
- },
175
- {
176
- verb: "run",
177
- resource: "<path>",
178
- resources: [],
179
- description: "Deploy and start process",
180
- mutating: true,
181
- },
182
- {
183
- verb: "watch",
184
- resource: "[path...]",
185
- resources: [],
186
- description: "Watch files for changes and auto-deploy",
187
- mutating: false,
188
- },
189
- {
190
- verb: "open",
191
- resource: "<app>",
192
- resources: ["operate", "tasklist", "modeler", "optimize"],
193
- description: "Open Camunda web application in browser",
194
- mutating: false,
195
- },
196
- {
197
- verb: "add",
198
- resource: "profile <name>",
199
- resources: ["profile"],
200
- description: "Add a profile",
201
- mutating: false,
202
- },
203
- {
204
- verb: "remove",
205
- resource: "profile <name>",
206
- resources: ["profile"],
207
- description: "Remove a profile (alias: rm)",
208
- mutating: false,
209
- },
210
- {
211
- verb: "load",
212
- resource: "plugin <name>",
213
- resources: ["plugin"],
214
- description: "Load a c8ctl plugin",
215
- mutating: false,
216
- },
217
- {
218
- verb: "unload",
219
- resource: "plugin <name>",
220
- resources: ["plugin"],
221
- description: "Unload a c8ctl plugin",
222
- mutating: false,
223
- },
224
- {
225
- verb: "upgrade",
226
- resource: "plugin <name>",
227
- resources: ["plugin"],
228
- description: "Upgrade a plugin",
229
- mutating: false,
230
- },
231
- {
232
- verb: "downgrade",
233
- resource: "plugin <name> <version>",
234
- resources: ["plugin"],
235
- description: "Downgrade a plugin to a specific version",
236
- mutating: false,
237
- },
238
- {
239
- verb: "sync",
240
- resource: "plugin",
241
- resources: ["plugin"],
242
- description: "Synchronize plugins",
243
- mutating: false,
244
- },
245
- {
246
- verb: "init",
247
- resource: "plugin [name]",
248
- resources: ["plugin"],
249
- description: "Create a new plugin from TypeScript template",
250
- mutating: false,
251
- },
252
- {
253
- verb: "use",
254
- resource: "profile|tenant",
255
- resources: ["profile", "tenant"],
256
- description: "Set active profile or tenant",
257
- mutating: false,
258
- },
259
- {
260
- verb: "output",
261
- resource: "[json|text]",
262
- resources: ["json", "text"],
263
- description: "Show or set output format",
264
- mutating: false,
265
- },
266
- {
267
- verb: "completion",
268
- resource: "bash|zsh|fish",
269
- resources: ["bash", "zsh", "fish"],
270
- description: "Generate shell completion script",
271
- mutating: false,
272
- },
273
- {
274
- verb: "mcp-proxy",
275
- resource: "[mcp-path]",
276
- resources: [],
277
- description: "Start a STDIO to remote HTTP MCP proxy server",
278
- mutating: false,
279
- },
280
- {
281
- verb: "feedback",
282
- resource: "",
283
- resources: [],
284
- description: "Open the feedback page to report issues or request features",
285
- mutating: false,
286
- },
287
- {
288
- verb: "help",
289
- resource: "[command]",
290
- resources: [],
291
- description: "Show help",
292
- mutating: false,
293
- },
294
- ...pluginCommandsInfo.map((cmd) => ({
295
- verb: cmd.commandName,
296
- resource: "",
297
- resources: [],
298
- description: cmd.description || "",
299
- mutating: false,
300
- examples: cmd.examples || [],
301
- })),
302
- ],
303
- resourceAliases: {
304
- pi: "process-instance(s)",
305
- pd: "process-definition(s)",
306
- ut: "user-task(s)",
307
- inc: "incident(s)",
308
- msg: "message",
309
- vars: "variable(s)",
310
- auth: "authorization(s)",
311
- mr: "mapping-rule(s)",
312
- },
313
- globalFlags: [
314
- {
315
- flag: "--profile",
316
- type: "string",
317
- description: "Use specific profile for this command",
318
- },
319
- {
320
- flag: "--sortBy",
321
- type: "string",
322
- description: "Sort list/search output by column name",
323
- },
324
- {
325
- flag: "--asc",
326
- type: "boolean",
327
- description: "Sort in ascending order (default)",
328
- },
329
- {
330
- flag: "--desc",
331
- type: "boolean",
332
- description: "Sort in descending order",
333
- },
334
- {
335
- flag: "--limit",
336
- type: "string",
337
- description: "Maximum number of items to fetch (default: 1000000)",
338
- },
339
- {
340
- flag: "--between",
341
- type: "string",
342
- description: "Filter by date range: <from>..<to> (YYYY-MM-DD or ISO 8601; open-ended: ..to or from..)",
343
- },
344
- {
345
- flag: "--dateField",
346
- type: "string",
347
- description: "Date field to filter on with --between (default depends on resource)",
348
- },
349
- {
350
- flag: "--state",
351
- type: "string",
352
- description: "Filter by state (ACTIVE, COMPLETED, etc.)",
353
- },
354
- {
355
- flag: "--id",
356
- type: "string",
357
- description: "Process definition ID (alias for --bpmnProcessId)",
358
- },
359
- {
360
- flag: "--verbose",
361
- type: "boolean",
362
- description: "Enable SDK trace logging and show full error details",
363
- },
364
- {
365
- flag: "--version",
366
- type: "string",
367
- short: "-v",
368
- description: "Show version",
369
- },
370
- {
371
- flag: "--help",
372
- type: "boolean",
373
- short: "-h",
374
- description: "Show help",
375
- },
376
- ],
377
- searchFlags: [
378
- {
379
- flag: "--bpmnProcessId",
380
- type: "string",
381
- description: "Filter by process definition ID",
382
- },
383
- {
384
- flag: "--processDefinitionKey",
385
- type: "string",
386
- description: "Filter by process definition key",
387
- },
388
- {
389
- flag: "--processInstanceKey",
390
- type: "string",
391
- description: "Filter by process instance key",
392
- },
393
- {
394
- flag: "--parentProcessInstanceKey",
395
- type: "string",
396
- description: "Filter by parent process instance key",
397
- },
398
- {
399
- flag: "--name",
400
- type: "string",
401
- description: "Filter by name (variables, process definitions); supports wildcards * and ?",
402
- },
403
- { flag: "--key", type: "string", description: "Filter by key" },
404
- {
405
- flag: "--assignee",
406
- type: "string",
407
- description: "Filter by assignee (user tasks)",
408
- },
409
- {
410
- flag: "--elementId",
411
- type: "string",
412
- description: "Filter by element ID (user tasks)",
413
- },
414
- {
415
- flag: "--errorType",
416
- type: "string",
417
- description: "Filter by error type (incidents)",
418
- },
419
- {
420
- flag: "--errorMessage",
421
- type: "string",
422
- description: "Filter by error message (incidents); supports wildcards",
423
- },
424
- {
425
- flag: "--type",
426
- type: "string",
427
- description: "Filter by type (jobs); supports wildcards",
428
- },
429
- {
430
- flag: "--value",
431
- type: "string",
432
- description: "Filter by variable value",
433
- },
434
- {
435
- flag: "--scopeKey",
436
- type: "string",
437
- description: "Filter by scope key (variables)",
438
- },
439
- {
440
- flag: "--fullValue",
441
- type: "boolean",
442
- description: "Return full variable values (default: truncated)",
443
- },
444
- {
445
- flag: "--iname",
446
- type: "string",
447
- description: "Case-insensitive --name filter (supports wildcards)",
448
- },
449
- {
450
- flag: "--iid",
451
- type: "string",
452
- description: "Case-insensitive --bpmnProcessId filter",
453
- },
454
- {
455
- flag: "--iassignee",
456
- type: "string",
457
- description: "Case-insensitive --assignee filter",
458
- },
459
- {
460
- flag: "--ierrorMessage",
461
- type: "string",
462
- description: "Case-insensitive --errorMessage filter",
463
- },
464
- {
465
- flag: "--itype",
466
- type: "string",
467
- description: "Case-insensitive --type filter",
468
- },
469
- {
470
- flag: "--ivalue",
471
- type: "string",
472
- description: "Case-insensitive --value filter",
473
- },
474
- {
475
- flag: "--username",
476
- type: "string",
477
- description: "Filter by username (users)",
478
- },
479
- {
480
- flag: "--email",
481
- type: "string",
482
- description: "Filter by email (users)",
483
- },
484
- {
485
- flag: "--roleId",
486
- type: "string",
487
- description: "Filter by role ID (roles)",
488
- },
489
- {
490
- flag: "--groupId",
491
- type: "string",
492
- description: "Filter by group ID (groups)",
493
- },
494
- {
495
- flag: "--ownerId",
496
- type: "string",
497
- description: "Filter by owner ID (authorizations)",
498
- },
499
- {
500
- flag: "--ownerType",
501
- type: "string",
502
- description: "Filter by owner type (authorizations)",
503
- },
504
- {
505
- flag: "--resourceType",
506
- type: "string",
507
- description: "Filter by resource type (authorizations)",
508
- },
509
- {
510
- flag: "--resourceId",
511
- type: "string",
512
- description: "Filter by resource ID (authorizations)",
513
- },
514
- {
515
- flag: "--claimName",
516
- type: "string",
517
- description: "Filter by claim name (mapping rules)",
518
- },
519
- {
520
- flag: "--claimValue",
521
- type: "string",
522
- description: "Filter by claim value (mapping rules)",
523
- },
524
- {
525
- flag: "--mappingRuleId",
526
- type: "string",
527
- description: "Filter by mapping rule ID (mapping rules)",
528
- },
529
- ],
530
- agentFlags: [
531
- {
532
- flag: "--fields",
533
- type: "string",
534
- description: "Comma-separated list of output fields to include. Reduces context window size. Case-insensitive. Example: --fields Key,State,processDefinitionId",
535
- appliesTo: "all list/search/get commands",
536
- },
537
- {
538
- flag: "--dry-run",
539
- type: "boolean",
540
- description: "Preview the API request that would be sent without executing it. Emits { dryRun, command, method, url, body } as JSON. Always exits 0.",
541
- appliesTo: "mutating commands: create, cancel, deploy, complete, fail, activate, resolve, publish, correlate, delete, assign, unassign",
542
- },
543
- ],
120
+ commands,
121
+ resourceAliases,
122
+ globalFlags,
123
+ searchFlags,
124
+ agentFlags: flagEntries(GLOBAL_FLAGS)
125
+ .filter(([, f]) => f.agentDescription)
126
+ .map(([name, f]) => ({
127
+ flag: `--${name}`,
128
+ type: f.type,
129
+ description: (f.agentDescription ?? "").replace(/\n/g, " "),
130
+ ...(f.agentAppliesTo ? { appliesTo: f.agentAppliesTo } : {}),
131
+ })),
544
132
  };
545
133
  }
546
134
  /**
@@ -558,6 +146,261 @@ export function showVersion() {
558
146
  const logger = getLogger();
559
147
  logger.info(`c8ctl v${getVersion()}`);
560
148
  }
149
+ // ─── Derived help generation ─────────────────────────────────────────────────
150
+ /**
151
+ * Derive the resource placeholder for a command's help line.
152
+ * Uses helpResource override if set, otherwise auto-derives from
153
+ * resources list, positionals, and requiresResource flag.
154
+ */
155
+ function deriveResourcePlaceholder(_verb, def) {
156
+ if (def.helpResource)
157
+ return def.helpResource;
158
+ const resources = def.resources;
159
+ // Single-resource commands: show "resource <positional>"
160
+ if (resources.length === 1) {
161
+ const canonical = RESOURCE_ALIASES[resources[0]] ?? resources[0];
162
+ const positionals = def.resourcePositionals?.[canonical];
163
+ if (positionals && positionals.length > 0) {
164
+ const posArgs = positionals
165
+ .map((p) => (p.required ? `<${p.name}>` : `[${p.name}]`))
166
+ .join(" ");
167
+ return `${resources[0]} ${posArgs}`;
168
+ }
169
+ return resources[0];
170
+ }
171
+ // Multi-resource commands
172
+ if (resources.length > 1 && def.requiresResource) {
173
+ // Find common positional shape across resources
174
+ const allPositionals = def.resourcePositionals
175
+ ? Object.values(def.resourcePositionals)
176
+ : [];
177
+ if (allPositionals.length > 0) {
178
+ // Use the first resource's positionals as representative
179
+ const first = allPositionals[0];
180
+ if (first.length > 0) {
181
+ const posArgs = first
182
+ .map((p) => (p.required ? `<${p.name}>` : `[${p.name}]`))
183
+ .join(" ");
184
+ return `<resource> ${posArgs}`;
185
+ }
186
+ }
187
+ return "<resource>";
188
+ }
189
+ return "";
190
+ }
191
+ /**
192
+ * Build the resource suffix for description (e.g. "(pi, pd, ut, inc)")
193
+ * Shows the valid resources when the placeholder is generic (<resource>, <app>).
194
+ */
195
+ function deriveResourceSuffix(verb, def) {
196
+ if (def.resources.length === 0)
197
+ return "";
198
+ const placeholder = deriveResourcePlaceholder(verb, def);
199
+ // Show suffix only when placeholder is generic (contains <resource> or <app>)
200
+ if (placeholder.includes("<resource>") || placeholder.includes("<app>")) {
201
+ return ` (${def.resources.join(", ")})`;
202
+ }
203
+ return "";
204
+ }
205
+ /**
206
+ * Generate the Commands section lines from the registry.
207
+ */
208
+ function generateCommandLines() {
209
+ const lines = [];
210
+ const DESC_COL = 36; // description starts at column 36
211
+ for (const [verb, def] of registryEntries()) {
212
+ const resource = deriveResourcePlaceholder(verb, def);
213
+ const desc = def.helpDescription ?? def.description;
214
+ const suffix = deriveResourceSuffix(verb, def);
215
+ // Ensure at least 2 spaces between verb and resource, and between resource and desc
216
+ const verbPadded = verb.length >= 10 ? `${verb} ` : verb.padEnd(10);
217
+ const leftPart = ` ${verbPadded}${resource}`;
218
+ const padding = Math.max(2, DESC_COL - leftPart.length);
219
+ lines.push(`${leftPart}${" ".repeat(padding)}${desc}${suffix}`);
220
+ }
221
+ return lines.join("\n");
222
+ }
223
+ /**
224
+ * Generate the Flags section from GLOBAL_FLAGS and select verb-specific flags.
225
+ * Uses the curated descriptions from the registry.
226
+ */
227
+ function generateFlagsSection() {
228
+ const lines = [];
229
+ const FLAG_COL = 36;
230
+ // Global flags first
231
+ for (const [name, def] of flagEntries(GLOBAL_FLAGS)) {
232
+ const flag = def.short ? `--${name}, -${def.short}` : `--${name}`;
233
+ const typeHint = def.type === "string" ? ` <${name}>` : "";
234
+ lines.push(` ${(flag + typeHint).padEnd(FLAG_COL)}${def.description}`);
235
+ }
236
+ // Collect notable verb-specific flags marked with showInTopLevelHelp
237
+ const seen = new Set(Object.keys(GLOBAL_FLAGS));
238
+ function addFlag(name, flagDef) {
239
+ if (!flagDef.showInTopLevelHelp || seen.has(name))
240
+ return;
241
+ seen.add(name);
242
+ const flag = flagDef.short ? `--${name}, --${flagDef.short}` : `--${name}`;
243
+ const typeHint = flagDef.type === "string" ? ` <${name}>` : "";
244
+ const hint = flagDef.helpHint ? ` (${flagDef.helpHint})` : "";
245
+ lines.push(` ${(flag + typeHint).padEnd(FLAG_COL)}${flagDef.description}${hint}`);
246
+ }
247
+ for (const [, cmd] of registryEntries()) {
248
+ for (const [name, flagDef] of flagEntries(cmd.flags)) {
249
+ addFlag(name, flagDef);
250
+ }
251
+ if (cmd.resourceFlags) {
252
+ for (const resourceFlags of Object.values(cmd.resourceFlags)) {
253
+ for (const [name, flagDef] of flagEntries(resourceFlags)) {
254
+ addFlag(name, flagDef);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ return lines.join("\n");
260
+ }
261
+ /**
262
+ * Generate the Search Flags section from SEARCH_FLAGS and
263
+ * all unique search-specific flags across command resourceFlags.
264
+ */
265
+ function generateSearchFlagsSection() {
266
+ const lines = [];
267
+ const FLAG_COL = 36;
268
+ // Collect unique search flags from list and search commands
269
+ const searchFlagMap = new Map();
270
+ for (const verb of ["list", "search"]) {
271
+ const def = COMMAND_REGISTRY[verb];
272
+ if (def.resourceFlags) {
273
+ for (const resourceFlags of Object.values(def.resourceFlags)) {
274
+ for (const [name, flagDef] of Object.entries(resourceFlags)) {
275
+ if (!searchFlagMap.has(name)) {
276
+ searchFlagMap.set(name, flagDef);
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ // Search/list shared flags
283
+ for (const [name, def] of Object.entries(SEARCH_FLAGS)) {
284
+ const typeHint = def.type === "string" ? ` <${name}>` : "";
285
+ lines.push(` ${(`--${name}${typeHint}`).padEnd(FLAG_COL)}${def.description}`);
286
+ }
287
+ // Separate case-sensitive and case-insensitive flags
288
+ const caseSensitive = [];
289
+ const caseInsensitive = [];
290
+ for (const [name, def] of searchFlagMap) {
291
+ // Skip flags already in SEARCH_FLAGS
292
+ if (name in SEARCH_FLAGS)
293
+ continue;
294
+ if (name.startsWith("i") &&
295
+ name.length > 1 &&
296
+ name[1] === name[1].toLowerCase()) {
297
+ // Check if there's a non-i version
298
+ const baseName = name.slice(1);
299
+ const firstLower = baseName[0].toLowerCase() + baseName.slice(1);
300
+ if (searchFlagMap.has(firstLower)) {
301
+ caseInsensitive.push([name, def]);
302
+ continue;
303
+ }
304
+ }
305
+ caseSensitive.push([name, def]);
306
+ }
307
+ for (const [name, def] of caseSensitive) {
308
+ const typeHint = def.type === "string" ? ` <${name}>` : "";
309
+ lines.push(` ${(`--${name}${typeHint}`).padEnd(FLAG_COL)}${def.description}`);
310
+ }
311
+ if (caseInsensitive.length > 0) {
312
+ lines.push("");
313
+ lines.push(" Case-Insensitive Search (--i prefix):");
314
+ for (const [name, def] of caseInsensitive) {
315
+ const typeHint = def.type === "string" ? " <pattern>" : "";
316
+ lines.push(` ${(`--${name}${typeHint}`).padEnd(FLAG_COL)}${def.description}`);
317
+ }
318
+ }
319
+ return lines.join("\n");
320
+ }
321
+ /**
322
+ * Generate resource aliases section from RESOURCE_ALIASES.
323
+ */
324
+ function generateResourceAliases() {
325
+ // Collect unique alias → long-name mappings
326
+ // We want to show short aliases (pi, pd, ut, inc, msg, auth, mr)
327
+ const displayed = new Map();
328
+ for (const [alias, canonical] of Object.entries(RESOURCE_ALIASES)) {
329
+ // Only show short aliases (not the long plural forms)
330
+ if (alias.length <= 4 && alias !== canonical) {
331
+ if (!displayed.has(alias)) {
332
+ // Find the plural/long form for display
333
+ const plural = Object.entries(RESOURCE_ALIASES).find(([k, v]) => v === canonical && k.includes("-") && k !== alias);
334
+ const displayName = plural ? `${canonical}(s)` : canonical;
335
+ displayed.set(alias, displayName);
336
+ }
337
+ }
338
+ }
339
+ const lines = [];
340
+ for (const [alias, longName] of displayed) {
341
+ lines.push(` ${alias.padEnd(5)}= ${longName}`);
342
+ }
343
+ return lines.join("\n");
344
+ }
345
+ /**
346
+ * Generate the "For detailed help" footer from commands with hasDetailedHelp.
347
+ */
348
+ function generateHelpFooter() {
349
+ const lines = [];
350
+ const CMD_COL = 35;
351
+ for (const [verb, def] of registryEntries()) {
352
+ if (def.hasDetailedHelp) {
353
+ const label = def.helpFooterLabel ?? `Show ${verb} command with all flags`;
354
+ lines.push(` ${`c8ctl help ${verb}`.padEnd(CMD_COL)}${label}`);
355
+ }
356
+ }
357
+ // Special entries: profiles and plugin (virtual help topics)
358
+ lines.push(` ${`c8ctl help profiles`.padEnd(CMD_COL)}Show profile management help`);
359
+ lines.push(` ${`c8ctl help plugin`.padEnd(CMD_COL)}Show plugin management help`);
360
+ lines.push(` ${`c8ctl help plugins`.padEnd(CMD_COL)}Show plugin management help (alias)`);
361
+ return lines.join("\n");
362
+ }
363
+ /**
364
+ * Generate the Examples section from registry helpExamples.
365
+ */
366
+ function generateExamplesSection() {
367
+ const lines = [];
368
+ const DESC_COL = 36;
369
+ for (const [, def] of registryEntries()) {
370
+ if (!def.helpExamples)
371
+ continue;
372
+ for (const ex of def.helpExamples) {
373
+ const padding = Math.max(2, DESC_COL - ex.command.length - 2);
374
+ lines.push(` ${ex.command}${" ".repeat(padding)}${ex.description}`);
375
+ }
376
+ }
377
+ return lines.join("\n");
378
+ }
379
+ /**
380
+ * Generate the Agent Flags section from GLOBAL_FLAGS entries
381
+ * that have agentDescription set.
382
+ */
383
+ function generateAgentFlagsSection() {
384
+ const lines = [];
385
+ for (const [name, def] of flagEntries(GLOBAL_FLAGS)) {
386
+ if (!def.agentDescription)
387
+ continue;
388
+ const typeHint = def.type === "string" ? ` <${name}>` : "";
389
+ const flag = `--${name}${typeHint}`;
390
+ const descLines = def.agentDescription.split("\n");
391
+ // First line: flag + first description line
392
+ lines.push(` ${flag.padEnd(22)}${descLines[0]}`);
393
+ // Continuation lines: indented to align
394
+ for (let i = 1; i < descLines.length; i++) {
395
+ lines.push(` ${"".padEnd(22)}${descLines[i]}`);
396
+ }
397
+ if (def.agentAppliesTo) {
398
+ lines.push(` ${"".padEnd(22)}Applies to ${def.agentAppliesTo}.`);
399
+ }
400
+ lines.push("");
401
+ }
402
+ return lines.join("\n").trimEnd();
403
+ }
561
404
  /**
562
405
  * Display full help
563
406
  */
@@ -584,121 +427,33 @@ export function showHelp() {
584
427
  pluginExamples += `\n ${ex.command.padEnd(35)}${ex.description}`;
585
428
  }
586
429
  }
430
+ const commandLines = generateCommandLines();
431
+ const flagsSection = generateFlagsSection();
432
+ const searchFlagsSection = generateSearchFlagsSection();
433
+ const resourceAliases = generateResourceAliases();
434
+ const helpFooter = generateHelpFooter();
435
+ const examplesSection = generateExamplesSection();
436
+ const agentFlagsSection = generateAgentFlagsSection();
587
437
  console.log(`
588
438
  c8ctl - Camunda 8 CLI v${version}
589
439
 
590
440
  Usage: c8ctl <command> [resource] [options]
591
441
 
592
442
  Commands:
593
- list <resource> List resources (pi, pd, ut, inc, jobs, profiles, users, roles, groups, tenants, auth, mapping-rules)
594
- search <resource> Search resources with filters (pi, pd, ut, inc, jobs, variables/vars, users, roles, groups, tenants, auth, mapping-rules)
595
- get <resource> <key> Get resource by key (pi, pd, inc, topology, form, user, role, group, tenant, auth, mapping-rule)
596
- create <resource> Create resource (pi, user, role, group, tenant, auth, mapping-rule)
597
- delete <resource> <key> Delete resource (user, role, group, tenant, auth, mapping-rule)
598
- assign <resource> <id> Assign resource to target (role, user, group, mapping-rule)
599
- unassign <resource> <id> Unassign resource from target (role, user, group, mapping-rule)
600
- cancel <resource> <key> Cancel resource (pi)
601
- await <resource> Create and await completion (pi, alias for create --awaitCompletion)
602
- complete <resource> <key> Complete resource (ut, job)
603
- fail job <key> Fail a job
604
- activate jobs <type> Activate jobs by type
605
- resolve inc <key> Resolve incident
606
- publish msg <name> Publish message
607
- correlate msg <name> Correlate message
608
- deploy [path...] Deploy BPMN/DMN/forms
609
- run <path> Deploy and start process
610
- watch [path...] Watch files for changes and auto-deploy
611
- open <app> Open Camunda web app in browser (operate, tasklist, modeler, optimize)
612
- add profile <name> Add a profile
613
- remove profile <name> Remove a profile (alias: rm)
614
- load plugin <name> Load a c8ctl plugin from npm registry
615
- load plugin --from <url> Load a c8ctl plugin from URL (https://, git://, file://)
616
- unload plugin <name> Unload a c8ctl plugin (npm uninstall wrapper)
617
- upgrade plugin <name> [version] Upgrade a plugin (respects source type)
618
- downgrade plugin <name> <version> Downgrade a plugin to a specific version
619
- sync plugin Synchronize plugins from registry (rebuild/reinstall)
620
- init plugin [name] Create a new plugin from TypeScript template
621
- use profile|tenant Set active profile or tenant
622
- output [json|text] Show or set output format
623
- completion bash|zsh|fish Generate shell completion script
624
- mcp-proxy [mcp-path] Start a STDIO to remote HTTP MCP proxy server
625
- feedback Open the feedback page to report issues or request features
626
- help [command] Show help (detailed help for list, get, create, complete, await, delete, assign, unassign)${pluginSection}
443
+ ${commandLines}${pluginSection}
627
444
 
628
445
  Flags:
629
- --profile <name> Use specific profile for this command
630
- --from <url> Load plugin from URL (use with 'load plugin')
631
- --xml Get process definition as XML (use with 'get pd')
632
- --variables Get process instance with variables (use with 'get pi')
633
- --userTask, --ut Get form for a user task (optional, use with 'get form')
634
- --processDefinition, --pd Get start form for a process definition (optional, use with 'get form')
635
- --id <process-id> Process definition ID (alias for --bpmnProcessId)
636
- --awaitCompletion Wait for process instance to complete (use with 'create pi')
637
- --fetchVariables <v> Reserved for future use (all variables returned by default)
638
- --requestTimeout <ms> Timeout in milliseconds for process completion (use with --awaitCompletion)
639
- --sortBy <column> Sort list/search output by column name (use with 'list' or 'search')
640
- --asc Sort in ascending order (default)
641
- --desc Sort in descending order
642
- --limit <n> Maximum number of items to fetch (default: 1000000)
643
- --between <from>..<to> Filter by date range (use with 'list' or 'search'; short dates YYYY-MM-DD or ISO 8601; omit either end for open-ended range)
644
- --dateField <field> Date field to filter on with --between (default depends on resource)
645
- --verbose Enable SDK trace logging and show full error details
646
- --version, -v Show version
647
- --help, -h Show help
446
+ ${flagsSection}
648
447
 
649
448
  Search Flags:
650
- --bpmnProcessId <id> Filter by process definition ID
651
- --processDefinitionKey <key> Filter by process definition key
652
- --processInstanceKey <key> Filter by process instance key
653
- --parentProcessInstanceKey <key> Filter by parent process instance key
654
- --state <state> Filter by state (ACTIVE, COMPLETED, etc.)
655
- --name <name> Filter by name (variables, process definitions)
656
- --key <key> Filter by key
657
- --assignee <user> Filter by assignee (user tasks)
658
- --elementId <id> Filter by element ID (user tasks)
659
- --errorType <type> Filter by error type (incidents)
660
- --errorMessage <msg> Filter by error message (incidents)
661
- --type <type> Filter by type (jobs)
662
- --value <value> Filter by variable value
663
- --scopeKey <key> Filter by scope key (variables)
664
- --fullValue Return full variable values (default: truncated)
665
-
666
- Wildcard Search:
667
- String filters support wildcards: * (any chars) and ? (single char).
668
- Example: --name='*main*' matches all names containing "main".
669
-
670
- Case-Insensitive Search (--i prefix):
671
- --iname <pattern> Case-insensitive --name filter
672
- --iid <pattern> Case-insensitive --bpmnProcessId filter
673
- --iassignee <pattern> Case-insensitive --assignee filter
674
- --ierrorMessage <pattern> Case-insensitive --errorMessage filter
675
- --itype <pattern> Case-insensitive --type filter
676
- --ivalue <pattern> Case-insensitive --value filter
677
- Prefix any string filter with 'i' for case-insensitive matching.
678
- Wildcards (* and ?) are supported. Filtering is applied client-side.
679
- Example: --iname='*ORDER*' matches "order", "Order", "ORDER", etc.
449
+ ${searchFlagsSection}
680
450
 
681
451
  Resource Aliases:
682
- pi = process-instance(s)
683
- pd = process-definition(s)
684
- ut = user-task(s)
685
- inc = incident(s)
686
- msg = message
687
- auth = authorization(s)
688
- mr = mapping-rule(s)
452
+ ${resourceAliases}
689
453
 
690
454
  ━━━ Agent Flags (for programmatic / AI-agent consumption) ━━━
691
455
 
692
- --fields <columns> Comma-separated list of output fields to include.
693
- Reduces context window size when parsing output.
694
- Example: c8ctl list pi --fields Key,State,processDefinitionId
695
- Applies to all list/search/get commands. Case-insensitive.
696
-
697
- --dry-run Preview the API request that would be sent, without executing it.
698
- Emits JSON: { dryRun, command, method, url, body }
699
- Applies to all mutating commands: create, cancel, deploy, complete,
700
- fail, activate, resolve, publish, correlate, delete, assign, unassign.
701
- Always exits 0. Use before confirming a mutating operation.
456
+ ${agentFlagsSection}
702
457
 
703
458
  Note: In JSON output mode (c8ctl output json), help is returned as structured JSON.
704
459
  Use 'c8ctl output json && c8ctl help' to get machine-readable command reference.
@@ -706,1276 +461,194 @@ Resource Aliases:
706
461
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
707
462
 
708
463
  Examples:
709
- c8ctl list pi List process instances
710
- c8ctl list pd List process definitions
711
- c8ctl search pi --state=ACTIVE Search for active process instances
712
- c8ctl search pd --bpmnProcessId=myProcess Search process definitions by ID
713
- c8ctl search pd --name='*main*' Search process definitions with wildcard
714
- c8ctl search ut --assignee=john Search user tasks assigned to john
715
- c8ctl search inc --state=ACTIVE Search for active incidents
716
- c8ctl search jobs --type=myJobType Search jobs by type
717
- c8ctl search jobs --type='*service*' Search jobs with type containing "service"
718
- c8ctl search variables --name=myVar Search for variables by name
719
- c8ctl search variables --value=foo Search for variables by value
720
- c8ctl search variables --processInstanceKey=123 --fullValue Search variables with full values
721
- c8ctl search pd --iname='*order*' Case-insensitive search by name
722
- c8ctl search ut --iassignee=John Case-insensitive search by assignee
723
- c8ctl get pi 123456 Get process instance by key
724
- c8ctl get pi 123456 --variables Get process instance with variables
725
- c8ctl get pd 123456 Get process definition by key
726
- c8ctl get pd 123456 --xml Get process definition XML
727
- c8ctl get form 123456 Get form (searches both user task and process definition)
728
- c8ctl get form 123456 --ut Get form for user task only
729
- c8ctl get form 123456 --pd Get start form for process definition only
730
- c8ctl create pi --id=myProcess
731
- c8ctl create pi --id=myProcess --awaitCompletion
732
- c8ctl await pi --id=myProcess Create and wait for completion
733
- c8ctl deploy ./my-process.bpmn Deploy a BPMN file
734
- c8ctl run ./my-process.bpmn Deploy and start process
735
- c8ctl watch ./src Watch directory for changes
736
- c8ctl open operate Open Camunda Operate in browser
737
- c8ctl open tasklist Open Camunda Tasklist in browser
738
- c8ctl open operate --profile=prod Open Operate using a specific profile
739
- c8ctl use profile prod Set active profile
740
- c8ctl which profile Show currently active profile
741
- c8ctl output json Switch to JSON output
742
- c8ctl init plugin my-plugin Create new plugin from template (c8ctl-plugin-my-plugin)
743
- c8ctl load plugin my-plugin Load plugin from npm registry
744
- c8ctl load plugin --from https://github.com/org/plugin Load plugin from URL
745
- c8ctl upgrade plugin my-plugin Upgrade plugin to latest version
746
- c8ctl upgrade plugin my-plugin 1.2.3 Upgrade plugin to a specific version (source-aware)
747
- c8ctl sync plugin Synchronize plugins
748
- c8ctl completion bash Generate bash completion script
749
- c8ctl list users List users
750
- c8ctl get user john Get user by username
751
- c8ctl create user --username=john --name='John Doe' --email=john@example.com --password=secret
752
- c8ctl delete user john Delete user
753
- c8ctl assign role admin --to-user=john Assign role to user
754
- c8ctl unassign role admin --from-user=john Unassign role from user${pluginExamples}
464
+ ${examplesSection}${pluginExamples}
755
465
 
756
466
  For detailed help on specific commands with all available flags:
757
- c8ctl help list Show all list resources and their flags
758
- c8ctl help get Show all get resources and their flags
759
- c8ctl help create Show all create resources and their flags
760
- c8ctl help complete Show all complete resources and their flags
761
- c8ctl help await Show await command with all flags
762
- c8ctl help mcp-proxy Show mcp-proxy setup and usage
763
- c8ctl help search Show all search resources and their flags
764
- c8ctl help deploy Show deploy command with all flags
765
- c8ctl help run Show run command with all flags
766
- c8ctl help watch Show watch command with all flags
767
- c8ctl help open Show open command with all apps
768
- c8ctl help cancel Show cancel command with all flags
769
- c8ctl help resolve Show resolve command with all flags
770
- c8ctl help fail Show fail command with all flags
771
- c8ctl help activate Show activate command with all flags
772
- c8ctl help publish Show publish command with all flags
773
- c8ctl help correlate Show correlate command with all flags
774
- c8ctl help delete Show delete command with all flags
775
- c8ctl help assign Show assign command with all flags
776
- c8ctl help unassign Show unassign command with all flags
777
- c8ctl help profiles Show profile management help
778
- c8ctl help plugin Show plugin management help
779
- c8ctl help plugins Alias for plugin management help
467
+ ${helpFooter}
780
468
 
781
469
  Feedback & Issues:
782
470
  https://github.com/camunda/c8ctl/issues
783
471
  Or run: c8ctl feedback
784
472
  `.trim());
785
473
  }
474
+ // ─── Derived verb help ───────────────────────────────────────────────────────
786
475
  /**
787
- * Show available resources for a verb
476
+ * Show available resources for a verb. Derived from COMMAND_REGISTRY.
788
477
  */
789
478
  export function showVerbResources(verb) {
790
- const resources = {
791
- list: "process-instances (pi), process-definitions (pd), user-tasks (ut), incidents (inc), jobs, profiles, plugins, users, roles, groups, tenants, authorizations (auth), mapping-rules (mr)",
792
- search: "process-instances (pi), process-definitions (pd), user-tasks (ut), incidents (inc), jobs, variables (vars), users, roles, groups, tenants, authorizations (auth), mapping-rules (mr)",
793
- get: "process-instance (pi), process-definition (pd), incident (inc), topology, form, user, role, group, tenant, authorization (auth), mapping-rule (mr)",
794
- create: "process-instance (pi), user, role, group, tenant, authorization (auth), mapping-rule (mr)",
795
- delete: "user, role, group, tenant, authorization (auth), mapping-rule (mr)",
796
- assign: "role, user, group, mapping-rule",
797
- unassign: "role, user, group, mapping-rule",
798
- complete: "user-task (ut), job",
799
- cancel: "process-instance (pi)",
800
- await: "process-instance (pi)",
801
- resolve: "incident (inc)",
802
- activate: "jobs",
803
- fail: "job",
804
- publish: "message (msg)",
805
- correlate: "message (msg)",
806
- add: "profile",
807
- remove: "profile",
808
- rm: "profile",
809
- load: "plugin",
810
- unload: "plugin",
811
- sync: "plugin",
812
- upgrade: "plugin",
813
- downgrade: "plugin",
814
- init: "plugin",
815
- use: "profile, tenant",
816
- run: "<bpmn-file-path>",
817
- which: "profile",
818
- output: "json, text",
819
- open: "operate, tasklist, modeler, optimize",
820
- completion: "bash, zsh, fish",
821
- help: "list, get, create, complete, await, search, deploy, run, watch, open, cancel, resolve, fail, activate, publish, correlate, delete, assign, unassign, upgrade, downgrade, init, profiles, profile, plugin, plugins",
822
- };
823
- const available = resources[verb];
824
- if (available) {
825
- // Verbs that take a positional argument other than a resource name
826
- const positionalLabel = {
827
- run: "<bpmn-file-path>",
828
- };
829
- const placeholder = positionalLabel[verb] ?? "<resource>";
830
- const label = positionalLabel[verb] ? "Argument" : "Available resources";
831
- console.log(`\nUsage: c8ctl ${verb} ${placeholder}\n`);
832
- console.log(`${label}:\n ${available}`);
479
+ // Resolve verb aliases (e.g. "rm" → "remove", "w" → "watch")
480
+ let resolvedVerb = verb;
481
+ if (!lookupVerb(verb)) {
482
+ for (const [v, d] of registryEntries()) {
483
+ if (d.aliases?.includes(verb)) {
484
+ resolvedVerb = v;
485
+ break;
486
+ }
487
+ }
833
488
  }
834
- else {
489
+ const def = lookupVerb(resolvedVerb);
490
+ if (!def) {
835
491
  console.log(`\nUnknown command: ${verb}`);
836
492
  console.log('Run "c8ctl help" for usage information.');
493
+ return;
837
494
  }
838
- }
839
- /**
840
- * Show detailed help for list command with all resources and their flags
841
- */
842
- export function showListHelp() {
843
- console.log(`
844
- c8ctl list - List resources
845
-
846
- Usage: c8ctl list <resource> [flags]
847
-
848
- Resources and their available flags:
849
-
850
- process-instances (pi)
851
- --id <id> Filter by process definition ID (alias: --bpmnProcessId)
852
- --version <num> Filter by process definition version
853
- --state <state> Filter by state (ACTIVE, COMPLETED, etc.)
854
- --all List all instances (pagination)
855
- --between <from>..<to> Filter by date range (default field: startDate)
856
- --dateField <field> Date field for --between (startDate, endDate)
857
- --sortBy <column> Sort by column (Key, Process ID, State, Version, Start Date, Tenant ID)
858
- --asc Sort in ascending order (default)
859
- --desc Sort in descending order
860
- --limit <n> Maximum number of items to fetch (default: 1000000)
861
- --profile <name> Use specific profile
862
- Note: instances with an active incident are marked with ⚠ before the Key
863
-
864
- process-definitions (pd)
865
- --sortBy <column> Sort by column (Key, Process ID, Name, Version, Tenant ID)
866
- --asc Sort in ascending order (default)
867
- --desc Sort in descending order
868
- --limit <n> Maximum number of items to fetch (default: 1000000)
869
- --profile <name> Use specific profile
870
-
871
- user-tasks (ut)
872
- --state <state> Filter by state (CREATED, COMPLETED, etc.)
873
- --assignee <name> Filter by assignee
874
- --all List all tasks (pagination)
875
- --between <from>..<to> Filter by date range (default field: creationDate)
876
- --dateField <field> Date field for --between (creationDate, completionDate, followUpDate, dueDate)
877
- --sortBy <column> Sort by column (Key, Name, State, Assignee, Created, Process Instance, Tenant ID)
878
- --asc Sort in ascending order (default)
879
- --desc Sort in descending order
880
- --limit <n> Maximum number of items to fetch (default: 1000000)
881
- --profile <name> Use specific profile
882
-
883
- incidents (inc)
884
- --state <state> Filter by state (ACTIVE, RESOLVED, etc.)
885
- --processInstanceKey <key> Filter by process instance
886
- --between <from>..<to> Filter by date range (field: creationTime)
887
- --sortBy <column> Sort by column (Key, Type, Message, State, Created, Process Instance, Tenant ID)
888
- --asc Sort in ascending order (default)
889
- --desc Sort in descending order
890
- --limit <n> Maximum number of items to fetch (default: 1000000)
891
- --profile <name> Use specific profile
892
-
893
- jobs
894
- --state <state> Filter by state (ACTIVATABLE, ACTIVATED, etc.)
895
- --type <type> Filter by job type
896
- --between <from>..<to> Filter by date range (default field: creationTime)
897
- --dateField <field> Date field for --between (creationTime, lastUpdateTime)
898
- --sortBy <column> Sort by column (Key, Type, State, Retries, Created, Process Instance, Tenant ID)
899
- --asc Sort in ascending order (default)
900
- --desc Sort in descending order
901
- --limit <n> Maximum number of items to fetch (default: 1000000)
902
- --profile <name> Use specific profile
903
-
904
- profiles
905
- Lists both c8ctl and Camunda Modeler profiles
906
- (Modeler profiles are shown with 'modeler:' prefix)
907
-
908
- plugins
909
- Shows installed plugins with version and sync status
910
-
911
- users
912
- --sortBy <column> Sort by column (Username, Name, Email)
913
- --asc Sort in ascending order (default)
914
- --desc Sort in descending order
915
- --limit <n> Maximum number of items to fetch (default: 1000000)
916
- --profile <name> Use specific profile
917
-
918
- roles
919
- --sortBy <column> Sort by column (Role ID, Name, Description)
920
- --asc Sort in ascending order (default)
921
- --desc Sort in descending order
922
- --limit <n> Maximum number of items to fetch (default: 1000000)
923
- --profile <name> Use specific profile
924
-
925
- groups
926
- --sortBy <column> Sort by column (Group ID, Name, Description)
927
- --asc Sort in ascending order (default)
928
- --desc Sort in descending order
929
- --limit <n> Maximum number of items to fetch (default: 1000000)
930
- --profile <name> Use specific profile
931
-
932
- tenants
933
- --sortBy <column> Sort by column (Tenant ID, Name, Description)
934
- --asc Sort in ascending order (default)
935
- --desc Sort in descending order
936
- --limit <n> Maximum number of items to fetch (default: 1000000)
937
- --profile <name> Use specific profile
938
-
939
- authorizations (auth)
940
- --sortBy <column> Sort by column (Key, Owner ID, Owner Type, Resource Type, Resource ID, Permissions)
941
- --asc Sort in ascending order (default)
942
- --desc Sort in descending order
943
- --limit <n> Maximum number of items to fetch (default: 1000000)
944
- --profile <name> Use specific profile
945
-
946
- mapping-rules (mr)
947
- --sortBy <column> Sort by column (Mapping Rule ID, Name, Claim Name, Claim Value)
948
- --asc Sort in ascending order (default)
949
- --desc Sort in descending order
950
- --limit <n> Maximum number of items to fetch (default: 1000000)
951
- --profile <name> Use specific profile
952
-
953
- Examples:
954
- c8ctl list pi --state=ACTIVE
955
- c8ctl list pi --between=2024-01-01..2024-12-31
956
- c8ctl list pi --between=2024-01-01T00:00:00Z..2024-06-30T23:59:59Z --dateField=endDate
957
- c8ctl list pi --sortBy=State
958
- c8ctl list pi --sortBy=State --desc
959
- c8ctl list ut --assignee=john.doe
960
- c8ctl list ut --between=2024-01-01..2024-03-31 --dateField=dueDate
961
- c8ctl list ut --sortBy=Assignee
962
- c8ctl list inc --processInstanceKey=123456
963
- c8ctl list inc --between=2024-06-01..2024-06-30
964
- c8ctl list inc --sortBy=Type --desc
965
- c8ctl list jobs --type=email-service
966
- c8ctl list jobs --between=2024-01-01..2024-12-31
967
- c8ctl list jobs --sortBy=Retries --asc
968
- c8ctl list profiles
969
- c8ctl list plugins
970
- c8ctl list users
971
- c8ctl list roles
972
- c8ctl list groups
973
- c8ctl list tenants
974
- c8ctl list auth
975
- c8ctl list mapping-rules
976
- `.trim());
977
- }
978
- export function showGetHelp() {
979
- console.log(`
980
- c8ctl get - Get resource by key
981
-
982
- Usage: c8ctl get <resource> <key> [flags]
983
-
984
- Resources and their available flags:
985
-
986
- process-instance (pi) <key>
987
- --variables Include variables for the process instance
988
- --profile <name> Use specific profile
989
-
990
- process-definition (pd) <key>
991
- --xml Return process definition as XML
992
- --profile <name> Use specific profile
993
-
994
- incident (inc) <key>
995
- --profile <name> Use specific profile
996
-
997
- topology
998
- --profile <name> Use specific profile
999
-
1000
- form <key>
1001
- --userTask, --ut (Optional) Get form for a user task only
1002
- --processDefinition, --pd (Optional) Get start form for a process definition only
1003
- --profile <name> Use specific profile
1004
-
1005
- If no flag is specified, searches both user task and process definition.
1006
-
1007
- user <username>
1008
- --profile <name> Use specific profile
1009
-
1010
- role <roleId>
1011
- --profile <name> Use specific profile
1012
-
1013
- group <groupId>
1014
- --profile <name> Use specific profile
1015
-
1016
- tenant <tenantId>
1017
- --profile <name> Use specific profile
1018
-
1019
- authorization (auth) <key>
1020
- --profile <name> Use specific profile
1021
-
1022
- mapping-rule (mr) <id>
1023
- --profile <name> Use specific profile
1024
-
1025
- Examples:
1026
- c8ctl get pi 2251799813685249
1027
- c8ctl get pi 2251799813685249 --variables
1028
- c8ctl get pd 2251799813685250
1029
- c8ctl get pd 2251799813685250 --xml
1030
- c8ctl get inc 2251799813685251
1031
- c8ctl get topology
1032
- c8ctl get form 2251799813685251
1033
- c8ctl get form 2251799813685251 --ut
1034
- c8ctl get form 2251799813685252 --pd
1035
- c8ctl get user john
1036
- c8ctl get role my-role
1037
- c8ctl get group developers
1038
- c8ctl get tenant prod
1039
- c8ctl get auth 123456
1040
- c8ctl get mapping-rule abc123
1041
- `.trim());
1042
- }
1043
- /**
1044
- * Show detailed help for create command
1045
- */
1046
- export function showCreateHelp() {
1047
- console.log(`
1048
- c8ctl create - Create a resource
1049
-
1050
- Usage: c8ctl create <resource> [flags]
1051
-
1052
- Resources and their available flags:
1053
-
1054
- process-instance (pi)
1055
- --id <id> Process definition ID (required, alias: --bpmnProcessId)
1056
- --version <num> Process definition version
1057
- --variables <json> Process variables as JSON string
1058
- --awaitCompletion Wait for process instance to complete
1059
- --fetchVariables <vars> Reserved for future use (all variables returned by default)
1060
- --requestTimeout <ms> Timeout in milliseconds for process completion (use with --awaitCompletion)
1061
- --profile <name> Use specific profile
1062
-
1063
- user
1064
- --username <name> Username (required)
1065
- --name <name> Display name
1066
- --email <email> Email address
1067
- --password <pwd> Password (required)
1068
- --profile <name> Use specific profile
1069
-
1070
- role
1071
- --name <name> Role name (required)
1072
- --profile <name> Use specific profile
1073
-
1074
- group
1075
- --name <name> Group name (required)
1076
- --profile <name> Use specific profile
1077
-
1078
- tenant
1079
- --tenantId <id> Tenant ID (required)
1080
- --name <name> Tenant name (required)
1081
- --profile <name> Use specific profile
1082
-
1083
- authorization (auth)
1084
- --ownerId <id> Owner ID (required)
1085
- --ownerType <type> Owner type: USER, GROUP, ROLE, MAPPING_RULE (required)
1086
- --resourceType <type> Resource type (required)
1087
- --resourceId <id> Resource ID (required)
1088
- --permissions <perms> Comma-separated permissions: READ,CREATE,UPDATE,DELETE (required)
1089
- --profile <name> Use specific profile
1090
-
1091
- mapping-rule (mr)
1092
- --mappingRuleId <id> Mapping rule ID (required)
1093
- --name <name> Mapping rule name (required)
1094
- --claimName <name> Claim name (required)
1095
- --claimValue <value> Claim value (required)
1096
- --profile <name> Use specific profile
1097
-
1098
- Examples:
1099
- c8ctl create pi --id=order-process
1100
- c8ctl create pi --id=order-process --version=2
1101
- c8ctl create pi --id=order-process --variables='{"orderId":"12345"}'
1102
- c8ctl create pi --id=order-process --awaitCompletion
1103
- c8ctl create pi --id=order-process --awaitCompletion --requestTimeout=30000
1104
- c8ctl create user --username=john --name='John Doe' --email=john@example.com --password=secret
1105
- c8ctl create role --name=my-role
1106
- c8ctl create group --name=developers
1107
- c8ctl create tenant --tenantId=prod --name='Production'
1108
- c8ctl create auth --ownerId=john --ownerType=USER --resourceType=process-definition --resourceId='*' --permissions=READ,CREATE
1109
- c8ctl create mapping-rule --mappingRuleId=my-rule --name=my-rule --claimName=department --claimValue=engineering
1110
- `.trim());
1111
- }
1112
- /**
1113
- * Show detailed help for complete command
1114
- */
1115
- export function showCompleteHelp() {
1116
- console.log(`
1117
- c8ctl complete - Complete a resource
1118
-
1119
- Usage: c8ctl complete <resource> <key> [flags]
1120
-
1121
- Resources and their available flags:
1122
-
1123
- user-task (ut) <key>
1124
- --variables <json> Completion variables as JSON string
1125
- --profile <name> Use specific profile
1126
-
1127
- job <key>
1128
- --variables <json> Completion variables as JSON string
1129
- --profile <name> Use specific profile
1130
-
1131
- Examples:
1132
- c8ctl complete ut 2251799813685250
1133
- c8ctl complete ut 2251799813685250 --variables='{"approved":true}'
1134
- c8ctl complete job 2251799813685252 --variables='{"result":"success"}'
1135
- `.trim());
1136
- }
1137
- /**
1138
- * Show detailed help for await command
1139
- */
1140
- export function showAwaitHelp() {
1141
- console.log(`
1142
- c8ctl await - Create and await process instance completion
1143
-
1144
- Usage: c8ctl await <resource> [flags]
1145
-
1146
- Note: 'await pi' is an alias for 'create pi --awaitCompletion'
1147
-
1148
- Resources and their available flags:
1149
-
1150
- process-instance (pi)
1151
- --id <id> Process definition ID (required, alias: --bpmnProcessId)
1152
- --version <num> Process definition version
1153
- --variables <json> Process variables as JSON string
1154
- --fetchVariables <vars> Reserved for future use (all variables returned by default)
1155
- --requestTimeout <ms> Timeout in milliseconds for process completion
1156
- --profile <name> Use specific profile
1157
-
1158
- Description:
1159
- Creates a process instance and waits for it to reach a terminal state (COMPLETED, CANCELED).
1160
- Returns the full process instance with all variables when complete.
1161
- Uses the Camunda 8 API's built-in awaitCompletion parameter for reliable server-side waiting.
1162
-
1163
- Examples:
1164
- c8ctl await pi --id=order-process
1165
- c8ctl await pi --id=order-process --variables='{"orderId":"12345"}'
1166
- c8ctl await pi --id=order-process --requestTimeout=30000
1167
-
1168
- # Equivalent to:
1169
- c8ctl create pi --id=order-process --awaitCompletion
1170
- `.trim());
1171
- }
1172
- /**
1173
- * Show detailed help for mcp-proxy command
1174
- */
1175
- export function showMcpProxyHelp() {
1176
- console.log(`
1177
- c8ctl mcp-proxy - Start MCP proxy server
1178
-
1179
- Usage: c8ctl mcp-proxy [mcp-path] [flags]
1180
-
1181
- Description:
1182
- Starts a STDIO-based Model Context Protocol (MCP) proxy server that bridges
1183
- between local MCP clients (like VSCode or other AI assistants) and
1184
- remote Camunda 8 HTTP MCP servers. The proxy handles authentication by
1185
- injecting Camunda credentials from your active profile.
1186
-
1187
- Arguments:
1188
- mcp-path Path to the remote MCP endpoint (default: /mcp/cluster)
1189
-
1190
- Flags:
1191
- --profile <name> Use specific profile for authentication
1192
-
1193
- How it works:
1194
- 1. Accepts MCP requests via STDIO (standard input/output)
1195
- 2. Forwards requests to the remote Camunda 8 cluster's MCP endpoint
1196
- 3. Injects authentication headers from your c8ctl profile
1197
- 4. Returns responses back through STDIO
1198
-
1199
- Configuration:
1200
- VSCode example - add a block like the following to your mcp.json:
1201
-
1202
- {
1203
- "servers": {
1204
- "camunda-cluster": {
1205
- "type": "stdio",
1206
- "command": "npx",
1207
- "args": ["c8ctl", "mcp-proxy"]
1208
- }
495
+ const resources = def.resources;
496
+ // For "help" verb, show all verbs that have detailed help + virtual topics
497
+ if (resolvedVerb === "help") {
498
+ const helpTopics = [];
499
+ for (const [v, d] of registryEntries()) {
500
+ if (d.hasDetailedHelp)
501
+ helpTopics.push(v);
502
+ }
503
+ helpTopics.push("profiles", "profile", "plugin", "plugins");
504
+ const placeholder = deriveResourcePlaceholder(resolvedVerb, def);
505
+ console.log(`\nUsage: c8ctl ${resolvedVerb} ${placeholder}\n`);
506
+ console.log(`Available resources:\n ${helpTopics.join(", ")}`);
507
+ return;
1209
508
  }
1210
- }
1211
-
1212
- Examples:
1213
- # Start proxy with default MCP path and active profile
1214
- c8ctl mcp-proxy
1215
-
1216
- # Use specific MCP endpoint path
1217
- c8ctl mcp-proxy /api/mcp
1218
-
1219
- # Use specific profile for authentication
1220
- c8ctl mcp-proxy --profile=production
1221
-
1222
- # Combine custom path and profile
1223
- c8ctl mcp-proxy /mcp/v2 --profile=staging
1224
-
1225
- Note:
1226
- The mcp-proxy command runs in the foreground and communicates via STDIO.
1227
- It's designed to be launched by MCP clients, not run directly in a terminal.
1228
- `.trim());
1229
- }
1230
- /**
1231
- * Show detailed help for search command
1232
- */
1233
- export function showSearchHelp() {
1234
- console.log(`
1235
- c8ctl search - Search resources with filters
1236
-
1237
- Usage: c8ctl search <resource> [flags]
1238
-
1239
- Resources and their available flags:
1240
-
1241
- process-instances (pi)
1242
- --bpmnProcessId, --id <id> Filter by process definition ID
1243
- --iid <pattern> Case-insensitive --bpmnProcessId filter
1244
- --processDefinitionKey <key> Filter by process definition key
1245
- --version <num> Filter by process definition version
1246
- --state <state> Filter by state (ACTIVE, COMPLETED, etc.)
1247
- --key <key> Filter by key
1248
- --parentProcessInstanceKey <key> Filter by parent process instance key
1249
- --between <from>..<to> Filter by date range (default field: startDate)
1250
- --dateField <field> Date field for --between (startDate, endDate)
1251
- --sortBy <column> Sort by column (Key, Process ID, State, Version, Tenant ID)
1252
- --asc Sort in ascending order (default)
1253
- --desc Sort in descending order
1254
- --profile <name> Use specific profile
1255
-
1256
- process-definitions (pd)
1257
- --bpmnProcessId, --id <id> Filter by process definition ID
1258
- --iid <pattern> Case-insensitive --bpmnProcessId filter
1259
- --name <name> Filter by name
1260
- --iname <pattern> Case-insensitive --name filter
1261
- --version <num> Filter by process definition version
1262
- --key <key> Filter by key
1263
- --sortBy <column> Sort by column (Key, Process ID, Name, Version, Tenant ID)
1264
- --asc Sort in ascending order (default)
1265
- --desc Sort in descending order
1266
- --profile <name> Use specific profile
1267
-
1268
- user-tasks (ut)
1269
- --state <state> Filter by state (CREATED, COMPLETED, etc.)
1270
- --assignee <user> Filter by assignee
1271
- --iassignee <pattern> Case-insensitive --assignee filter
1272
- --processInstanceKey <key> Filter by process instance key
1273
- --processDefinitionKey <key> Filter by process definition key
1274
- --elementId <id> Filter by element ID
1275
- --between <from>..<to> Filter by date range (default field: creationDate)
1276
- --dateField <field> Date field for --between (creationDate, completionDate, followUpDate, dueDate)
1277
- --sortBy <column> Sort by column (Key, Name, State, Assignee, Process Instance, Tenant ID)
1278
- --asc Sort in ascending order (default)
1279
- --desc Sort in descending order
1280
- --profile <name> Use specific profile
1281
-
1282
- incidents (inc)
1283
- --state <state> Filter by state (ACTIVE, RESOLVED, etc.)
1284
- --processInstanceKey <key> Filter by process instance key
1285
- --processDefinitionKey <key> Filter by process definition key
1286
- --bpmnProcessId, --id <id> Filter by process definition ID
1287
- --iid <pattern> Case-insensitive --bpmnProcessId filter
1288
- --errorType <type> Filter by error type
1289
- --errorMessage <msg> Filter by error message
1290
- --ierrorMessage <pattern> Case-insensitive --errorMessage filter
1291
- --between <from>..<to> Filter by date range (field: creationTime)
1292
- --sortBy <column> Sort by column (Key, Type, Message, State, Process Instance, Tenant ID)
1293
- --asc Sort in ascending order (default)
1294
- --desc Sort in descending order
1295
- --profile <name> Use specific profile
1296
-
1297
- jobs
1298
- --state <state> Filter by state (ACTIVATABLE, ACTIVATED, etc.)
1299
- --type <type> Filter by job type
1300
- --itype <pattern> Case-insensitive --type filter
1301
- --processInstanceKey <key> Filter by process instance key
1302
- --processDefinitionKey <key> Filter by process definition key
1303
- --between <from>..<to> Filter by date range (default field: creationTime)
1304
- --dateField <field> Date field for --between (creationTime, lastUpdateTime)
1305
- --sortBy <column> Sort by column (Key, Type, State, Retries, Process Instance, Tenant ID)
1306
- --asc Sort in ascending order (default)
1307
- --desc Sort in descending order
1308
- --profile <name> Use specific profile
1309
-
1310
- variables
1311
- --name <name> Filter by variable name
1312
- --iname <pattern> Case-insensitive --name filter
1313
- --value <value> Filter by variable value
1314
- --ivalue <pattern> Case-insensitive --value filter
1315
- --processInstanceKey <key> Filter by process instance key
1316
- --scopeKey <key> Filter by scope key
1317
- --fullValue Return full variable values (default: truncated)
1318
- --sortBy <column> Sort by column (Name, Value, Process Instance, Scope Key, Tenant ID)
1319
- --asc Sort in ascending order (default)
1320
- --desc Sort in descending order
1321
- --limit <n> Maximum number of items to fetch (default: 1000000)
1322
- --profile <name> Use specific profile
1323
-
1324
- users
1325
- --username <name> Filter by username
1326
- --name <name> Filter by name
1327
- --email <email> Filter by email
1328
- --sortBy <column> Sort by column (Username, Name, Email)
1329
- --asc Sort in ascending order (default)
1330
- --desc Sort in descending order
1331
- --limit <n> Maximum number of items to fetch (default: 1000000)
1332
- --profile <name> Use specific profile
1333
-
1334
- roles
1335
- --roleId <id> Filter by role ID
1336
- --name <name> Filter by name
1337
- --sortBy <column> Sort by column (Role ID, Name, Description)
1338
- --asc Sort in ascending order (default)
1339
- --desc Sort in descending order
1340
- --limit <n> Maximum number of items to fetch (default: 1000000)
1341
- --profile <name> Use specific profile
1342
-
1343
- groups
1344
- --groupId <id> Filter by group ID
1345
- --name <name> Filter by name
1346
- --sortBy <column> Sort by column (Group ID, Name, Description)
1347
- --asc Sort in ascending order (default)
1348
- --desc Sort in descending order
1349
- --limit <n> Maximum number of items to fetch (default: 1000000)
1350
- --profile <name> Use specific profile
1351
-
1352
- tenants
1353
- --name <name> Filter by name
1354
- --tenantId <id> Filter by tenant ID
1355
- --sortBy <column> Sort by column (Tenant ID, Name, Description)
1356
- --asc Sort in ascending order (default)
1357
- --desc Sort in descending order
1358
- --limit <n> Maximum number of items to fetch (default: 1000000)
1359
- --profile <name> Use specific profile
1360
-
1361
- authorizations (auth)
1362
- --ownerId <id> Filter by owner ID
1363
- --ownerType <type> Filter by owner type
1364
- --resourceType <type> Filter by resource type
1365
- --resourceId <id> Filter by resource ID
1366
- --sortBy <column> Sort by column (Key, Owner ID, Owner Type, Resource Type, Resource ID, Permissions)
1367
- --asc Sort in ascending order (default)
1368
- --desc Sort in descending order
1369
- --limit <n> Maximum number of items to fetch (default: 1000000)
1370
- --profile <name> Use specific profile
1371
-
1372
- mapping-rules (mr)
1373
- --mappingRuleId <id> Filter by mapping rule ID
1374
- --name <name> Filter by name
1375
- --claimName <name> Filter by claim name
1376
- --claimValue <value> Filter by claim value
1377
- --sortBy <column> Sort by column (Mapping Rule ID, Name, Claim Name, Claim Value)
1378
- --asc Sort in ascending order (default)
1379
- --desc Sort in descending order
1380
- --limit <n> Maximum number of items to fetch (default: 1000000)
1381
- --profile <name> Use specific profile
1382
-
1383
- Date Range Filter:
1384
- Use --between <from>..<to> to filter results by a date range.
1385
- Dates can be short (YYYY-MM-DD) or full ISO 8601 datetimes.
1386
- Short dates: 'from' is expanded to T00:00:00.000Z, 'to' to T23:59:59.999Z.
1387
- Either end may be omitted for an open-ended range.
1388
- Use --dateField to specify which date field to filter on (default depends on resource).
1389
- Example: --between=2024-01-01..2024-12-31
1390
- Example: --between=2024-01-01T00:00:00Z..2024-06-30T23:59:59Z --dateField=endDate
1391
- Example: --between=..2024-12-31 (everything until end of 2024)
1392
- Example: --between=2024-01-01.. (everything from start of 2024)
1393
-
1394
- Wildcard Search:
1395
- Some string filters support wildcards: * (any chars) and ? (single char).
1396
- Supported: process definitions (name, bpmnProcessId), process instances (bpmnProcessId),
1397
- jobs (type), variables (name, value), users (username, name, email), groups (groupId).
1398
- Not supported (exact match only): roles, tenants, mapping-rules, authorizations.
1399
- Example: --name='*main*' matches all names containing "main".
1400
-
1401
- Case-Insensitive Search:
1402
- Prefix any string filter with 'i' for case-insensitive matching.
1403
- Wildcards (* and ?) are supported. Filtering is applied client-side.
1404
- Example: --iname='*ORDER*' matches "order", "Order", "ORDER", etc.
1405
-
1406
- Examples:
1407
- c8ctl search pi --state=ACTIVE
1408
- c8ctl search pi --bpmnProcessId=order-process
1409
- c8ctl search pi --between=2024-01-01..2024-12-31
1410
- c8ctl search pi --between=2024-01-01..2024-06-30 --dateField=endDate
1411
- c8ctl search pd --name='*main*'
1412
- c8ctl search pd --iname='*order*'
1413
- c8ctl search pd --sortBy=Name --desc
1414
- c8ctl search ut --assignee=john.doe
1415
- c8ctl search ut --iassignee=John
1416
- c8ctl search ut --between=2024-01-01..2024-03-31 --dateField=dueDate
1417
- c8ctl search ut --sortBy=State --asc
1418
- c8ctl search inc --state=ACTIVE --processInstanceKey=123456
1419
- c8ctl search inc --between=2024-06-01..2024-06-30
1420
- c8ctl search jobs --type=email-service
1421
- c8ctl search jobs --itype='*SERVICE*'
1422
- c8ctl search jobs --between=2024-01-01..2024-12-31
1423
- c8ctl search jobs --sortBy=Type --desc
1424
- c8ctl search variables --name=orderId
1425
- c8ctl search variables --value=12345 --fullValue
1426
- c8ctl search variables --sortBy=Name
1427
- c8ctl search users --name=John
1428
- c8ctl search roles --name=admin
1429
- c8ctl search groups --name=developers
1430
- c8ctl search tenants --name=Production
1431
- c8ctl search auth --ownerId=john --resourceType=process-definition
1432
- c8ctl search auth --ownerId=john --resourceId=my-resource
1433
- c8ctl search mapping-rules --claimName=department
1434
- c8ctl search mapping-rules --mappingRuleId=my-rule
1435
- `.trim());
1436
- }
1437
- /**
1438
- * Show detailed help for deploy command
1439
- */
1440
- export function showDeployHelp() {
1441
- console.log(`
1442
- c8ctl deploy - Deploy BPMN, DMN, and form files
1443
-
1444
- Usage: c8ctl deploy [path...] [flags]
1445
-
1446
- Description:
1447
- Deploy BPMN process definitions, DMN decision tables, and forms to Camunda 8.
1448
- Automatically discovers all deployable files in the specified paths.
1449
- If no path is provided, deploys from the current directory.
1450
-
1451
- Flags:
1452
- --profile <name> Use specific profile
1453
-
1454
- Supported File Types:
1455
- - BPMN files (.bpmn)
1456
- - DMN files (.dmn)
1457
- - Form files (.form)
1458
-
1459
- Building Blocks:
1460
- Folders containing '_bb-' in their name are treated as building blocks
1461
- and are deployed before regular processes.
1462
-
1463
- Examples:
1464
- c8ctl deploy Deploy all files in current directory
1465
- c8ctl deploy ./src Deploy all files in ./src directory
1466
- c8ctl deploy ./process.bpmn Deploy a specific BPMN file
1467
- c8ctl deploy ./src ./forms Deploy from multiple directories
1468
- c8ctl deploy --profile=prod Deploy using specific profile
1469
- `.trim());
1470
- }
1471
- /**
1472
- * Show detailed help for run command
1473
- */
1474
- export function showRunHelp() {
1475
- console.log(`
1476
- c8ctl run - Deploy and start a process
1477
-
1478
- Usage: c8ctl run <path> [flags]
1479
-
1480
- Description:
1481
- Deploys a BPMN file and immediately creates a process instance from it.
1482
- This is a convenience command that combines deploy and create operations.
1483
-
1484
- Flags:
1485
- --profile <name> Use specific profile
1486
- --variables <json> Process variables as JSON string
1487
-
1488
- Examples:
1489
- c8ctl run ./my-process.bpmn
1490
- c8ctl run ./my-process.bpmn --variables='{"orderId":"12345"}'
1491
- c8ctl run ./my-process.bpmn --profile=prod
1492
- `.trim());
1493
- }
1494
- /**
1495
- * Show detailed help for watch command
1496
- */
1497
- export function showWatchHelp() {
1498
- console.log(`
1499
- c8ctl watch - Watch files for changes and auto-deploy
1500
-
1501
- Usage: c8ctl watch [path...] [flags]
1502
-
1503
- Alias: w
1504
-
1505
- Description:
1506
- Watches BPMN, DMN, and form files for changes and automatically deploys them.
1507
- Useful during development for rapid iteration.
1508
- If no path is provided, watches the current directory.
1509
-
1510
- Validation errors (INVALID_ARGUMENT) are reported but do not stop the watcher,
1511
- so you can fix the file and save again. Use --force to also continue on other
1512
- errors such as network or authentication failures.
1513
-
1514
- Flags:
1515
- --profile <name> Use specific profile
1516
- --force Continue watching after all deployment errors
1517
-
1518
- Supported File Types:
1519
- - BPMN files (.bpmn)
1520
- - DMN files (.dmn)
1521
- - Form files (.form)
1522
-
1523
- Examples:
1524
- c8ctl watch Watch current directory
1525
- c8ctl watch ./src Watch ./src directory
1526
- c8ctl watch ./src ./forms Watch multiple directories
1527
- c8ctl w ./src Use short alias
1528
- c8ctl watch --profile=dev Watch using specific profile
1529
- c8ctl watch --force Keep watching after all deployment errors
1530
- `.trim());
1531
- }
1532
- /**
1533
- * Show detailed help for open command
1534
- */
1535
- export function showOpenHelp() {
1536
- console.log(`
1537
- c8ctl open - Open a Camunda web application in the browser
1538
-
1539
- Usage: c8ctl open <app> [flags]
1540
-
1541
- Applications:
1542
- operate Camunda Operate – monitor process instances and incidents
1543
- tasklist Camunda Tasklist – manage user tasks
1544
- modeler Camunda Web Modeler – design BPMN/DMN processes
1545
- optimize Camunda Optimize – process analytics
1546
-
1547
- Description:
1548
- Derives the application URL from the active profile's base URL by stripping
1549
- the API path suffix (e.g. /v2) and appending the application path.
1550
-
1551
- Example: baseUrl=http://localhost:8080/v2 → http://localhost:8080/operate
1552
-
1553
- For this command, --dry-run resolves and prints the application URL instead
1554
- of launching the browser.
1555
-
1556
- Flags:
1557
- --profile <name> Use specific profile
1558
- --dry-run Resolve and print the URL without opening the browser
1559
-
1560
- Examples:
1561
- c8ctl open operate
1562
- c8ctl open tasklist
1563
- c8ctl open modeler
1564
- c8ctl open optimize
1565
- c8ctl open operate --profile=prod
1566
- c8ctl open operate --dry-run
1567
- `.trim());
1568
- }
1569
- /**
1570
- * Show detailed help for cancel command
1571
- */
1572
- export function showCancelHelp() {
1573
- console.log(`
1574
- c8ctl cancel - Cancel a resource
1575
-
1576
- Usage: c8ctl cancel <resource> <key> [flags]
1577
-
1578
- Resources and their available flags:
1579
-
1580
- process-instance (pi) <key>
1581
- --profile <name> Use specific profile
1582
-
1583
- Examples:
1584
- c8ctl cancel pi 2251799813685249
1585
- c8ctl cancel pi 2251799813685249 --profile=prod
1586
- `.trim());
1587
- }
1588
- /**
1589
- * Show detailed help for resolve command
1590
- */
1591
- export function showResolveHelp() {
1592
- console.log(`
1593
- c8ctl resolve - Resolve an incident
1594
-
1595
- Usage: c8ctl resolve incident <key> [flags]
1596
-
1597
- Alias: inc for incident
1598
-
1599
- Description:
1600
- Resolves an incident by its key. This marks the incident as resolved
1601
- and allows the process instance to continue.
1602
-
1603
- Flags:
1604
- --profile <name> Use specific profile
1605
-
1606
- Examples:
1607
- c8ctl resolve inc 2251799813685251
1608
- c8ctl resolve incident 2251799813685251
1609
- c8ctl resolve inc 2251799813685251 --profile=prod
1610
- `.trim());
1611
- }
1612
- /**
1613
- * Show detailed help for fail command
1614
- */
1615
- export function showFailHelp() {
1616
- console.log(`
1617
- c8ctl fail - Fail a job
1618
-
1619
- Usage: c8ctl fail job <key> [flags]
1620
-
1621
- Description:
1622
- Marks a job as failed with optional error message and retry count.
1623
-
1624
- Flags:
1625
- --profile <name> Use specific profile
1626
- --retries <num> Number of retries remaining (default: 0)
1627
- --errorMessage <msg> Error message describing the failure
1628
-
1629
- Examples:
1630
- c8ctl fail job 2251799813685252
1631
- c8ctl fail job 2251799813685252 --retries=3
1632
- c8ctl fail job 2251799813685252 --errorMessage="Connection timeout"
1633
- c8ctl fail job 2251799813685252 --retries=2 --errorMessage="Temporary failure"
1634
- `.trim());
1635
- }
1636
- /**
1637
- * Show detailed help for activate command
1638
- */
1639
- export function showActivateHelp() {
1640
- console.log(`
1641
- c8ctl activate - Activate jobs by type
1642
-
1643
- Usage: c8ctl activate jobs <type> [flags]
1644
-
1645
- Description:
1646
- Activates jobs of a specific type for processing by a worker.
1647
-
1648
- Flags:
1649
- --profile <name> Use specific profile
1650
- --maxJobsToActivate <num> Maximum number of jobs to activate (default: 10)
1651
- --timeout <ms> Job lock timeout in milliseconds (default: 60000)
1652
- --worker <name> Worker name (default: "c8ctl")
1653
-
1654
- Examples:
1655
- c8ctl activate jobs email-service
1656
- c8ctl activate jobs payment-processor --maxJobsToActivate=5
1657
- c8ctl activate jobs data-sync --timeout=120000 --worker=my-worker
1658
- c8ctl activate jobs batch-job --maxJobsToActivate=100 --profile=prod
1659
- `.trim());
1660
- }
1661
- /**
1662
- * Show detailed help for publish command
1663
- */
1664
- export function showPublishHelp() {
1665
- console.log(`
1666
- c8ctl publish - Publish a message
1667
-
1668
- Usage: c8ctl publish message <name> [flags]
1669
-
1670
- Alias: msg for message
1671
-
1672
- Description:
1673
- Publishes a message to Camunda 8 for message correlation.
1674
-
1675
- Flags:
1676
- --profile <name> Use specific profile
1677
- --correlationKey <key> Correlation key for the message
1678
- --variables <json> Message variables as JSON string
1679
- --timeToLive <ms> Message time-to-live in milliseconds
1680
-
1681
- Examples:
1682
- c8ctl publish msg payment-received
1683
- c8ctl publish message order-confirmed --correlationKey=order-123
1684
- c8ctl publish msg invoice-paid --variables='{"amount":1000}'
1685
- c8ctl publish msg notification --correlationKey=user-456 --timeToLive=30000
1686
- `.trim());
1687
- }
1688
- /**
1689
- * Show detailed help for correlate command
1690
- */
1691
- export function showCorrelateHelp() {
1692
- console.log(`
1693
- c8ctl correlate - Correlate a message
1694
-
1695
- Usage: c8ctl correlate message <name> [flags]
1696
-
1697
- Alias: msg for message
1698
-
1699
- Description:
1700
- Correlates a message to a specific process instance.
1701
-
1702
- Flags:
1703
- --profile <name> Use specific profile
1704
- --correlationKey <key> Correlation key for the message (required)
1705
- --variables <json> Message variables as JSON string
1706
- --timeToLive <ms> Message time-to-live in milliseconds
1707
-
1708
- Examples:
1709
- c8ctl correlate msg payment-received --correlationKey=order-123
1710
- c8ctl correlate message order-confirmed --correlationKey=order-456 --variables='{"status":"confirmed"}'
1711
- c8ctl correlate msg invoice-paid --correlationKey=inv-789 --timeToLive=60000
1712
- `.trim());
1713
- }
1714
- /**
1715
- * Show detailed help for profile management
1716
- */
1717
- export function showProfilesHelp() {
1718
- console.log(`
1719
- c8ctl profiles - Profile management
1720
-
1721
- Usage: c8ctl <command> profile[s] [args] [flags]
1722
-
1723
- Profile commands:
1724
-
1725
- list profiles
1726
- List all profiles (c8ctl + Camunda Modeler profiles).
1727
- Modeler profiles are shown with "modeler:" prefix.
1728
- The currently active profile is marked with "*".
1729
-
1730
- which profile
1731
- Show the name of the currently active profile.
1732
-
1733
- add profile <name> [flags]
1734
- Add a c8ctl-managed profile.
1735
-
1736
- remove profile <name>
1737
- rm profile <name>
1738
- Remove a c8ctl-managed profile.
1739
-
1740
- use profile <name>
1741
- Set active profile for the current session.
1742
-
1743
- use profile --none
1744
- Clear the active session profile so env vars take effect.
1745
-
1746
- Connection resolution order (highest to lowest priority):
1747
- 1. --profile <name> flag on the current command
1748
- 2. Active session profile (set with: c8ctl use profile <name>)
1749
- ⚠ Warns if CAMUNDA_* env vars are also present
1750
- 3. Environment variables (CAMUNDA_BASE_URL, CAMUNDA_CLIENT_ID, …)
1751
- 4. Default 'local' profile from profiles.json
1752
-
1753
- Default profile: "local"
1754
- c8ctl ships with a built-in 'local' profile (http://localhost:8080/v2, demo/demo).
1755
- It is created automatically in profiles.json on first use.
1756
- Override it: c8ctl add profile local --baseUrl <url>
1757
-
1758
- Flags for add profile:
1759
- Required for all add profile calls:
1760
- (none)
1761
-
1762
- Required for OAuth-secured clusters:
1763
- --clientId <id> OAuth client ID
1764
- --clientSecret <secret> OAuth client secret
1765
-
1766
- Optional (with defaults):
1767
- --baseUrl <url> Cluster base URL (default: http://localhost:8080/v2)
1768
- --defaultTenantId <id> Default tenant ID (default at runtime: <default>)
1769
-
1770
- Optional (no c8ctl default):
1771
- --audience <audience> OAuth audience
1772
- --oAuthUrl <url> OAuth token endpoint
1773
-
1774
- Import from file or environment:
1775
- --from-file <path> Create profile from a .env file containing CAMUNDA_* vars
1776
- --from-env Create profile from current CAMUNDA_* environment variables
1777
-
1778
- Examples:
1779
- c8ctl list profiles
1780
- c8ctl which profile
1781
- c8ctl add profile local --baseUrl=http://localhost:8080/v2
1782
- c8ctl add profile prod --baseUrl=https://camunda.example.com --clientId=xxx --clientSecret=yyy
1783
- c8ctl add profile staging --from-file .env.staging
1784
- c8ctl add profile ci --from-env
1785
- c8ctl use profile prod
1786
- c8ctl use profile "modeler:Local Dev"
1787
- c8ctl use profile --none
1788
- c8ctl remove profile local
1789
- `.trim());
1790
- }
1791
- /**
1792
- * Show detailed help for plugin management
1793
- */
1794
- export function showPluginHelp() {
1795
- console.log(`
1796
- c8ctl plugin - Plugin management
1797
-
1798
- Usage: c8ctl <command> plugin [args] [flags]
1799
-
1800
- Plugin commands:
1801
-
1802
- load plugin <name>
1803
- Load a plugin from npm registry.
1804
-
1805
- load plugin --from <url>
1806
- Load a plugin from URL source (file://, https://, git://, github:).
1807
-
1808
- unload plugin <name>
1809
- Unload and unregister a plugin.
1810
-
1811
- unload plugin <name> --force
1812
- Force-remove a plugin that is installed but not in the registry (limbo state).
1813
-
1814
- list plugins
1815
- List installed plugins with version and sync status.
1816
-
1817
- sync plugins
1818
- Rebuild/reinstall plugins from registry.
1819
-
1820
- upgrade plugin <name> [version]
1821
- Upgrade plugin source.
1822
- - without version: reinstalls registered source as-is
1823
- - npm source with version: installs <name>@<version>
1824
- - URL/git source with version: installs <source>#<version>
1825
- - file:// source with version: not supported, use load plugin --from
1826
-
1827
- downgrade plugin <name> <version>
1828
- Downgrade plugin source.
1829
- - npm source: installs <name>@<version>
1830
- - URL/git source: installs <source>#<version>
1831
- - file:// source: not supported, use load plugin --from
1832
-
1833
- init plugin [name]
1834
- Create a new plugin scaffold from template.
1835
- Default name: c8ctl-plugin-myplugin
1836
-
1837
- Convention over configuration: the directory is always prefixed with
1838
- "c8ctl-plugin-". The plugin is registered by the suffix after the prefix.
1839
- Example: "c8ctl init plugin foo" creates directory "c8ctl-plugin-foo"
1840
- and registers plugin name "foo". Likewise, "c8ctl init plugin
1841
- c8ctl-plugin-foo" produces the same result.
1842
-
1843
- Examples:
1844
- c8ctl load plugin my-plugin
1845
- c8ctl load plugin --from https://github.com/org/plugin
1846
- c8ctl load plugin --from file:///path/to/plugin
1847
- c8ctl list plugins
1848
- c8ctl unload plugin my-plugin
1849
- c8ctl unload plugin my-plugin --force
1850
- c8ctl upgrade plugin my-plugin
1851
- c8ctl upgrade plugin my-plugin 1.2.3
1852
- c8ctl downgrade plugin my-plugin 1.0.0
1853
- c8ctl init plugin my-plugin
1854
- `.trim());
1855
- }
1856
- /**
1857
- * Show detailed help for delete command
1858
- */
1859
- export function showDeleteHelp() {
1860
- console.log(`
1861
- c8ctl delete - Delete a resource
1862
-
1863
- Usage: c8ctl delete <resource> <id> [flags]
1864
-
1865
- Resources and their available flags:
1866
-
1867
- user <username>
1868
- --profile <name> Use specific profile
1869
-
1870
- role <roleId>
1871
- --profile <name> Use specific profile
1872
-
1873
- group <groupId>
1874
- --profile <name> Use specific profile
1875
-
1876
- tenant <tenantId>
1877
- --profile <name> Use specific profile
1878
-
1879
- authorization (auth) <key>
1880
- --profile <name> Use specific profile
1881
-
1882
- mapping-rule (mr) <id>
1883
- --profile <name> Use specific profile
1884
-
1885
- Examples:
1886
- c8ctl delete user john
1887
- c8ctl delete role my-role
1888
- c8ctl delete group developers
1889
- c8ctl delete tenant prod
1890
- c8ctl delete auth 123456
1891
- c8ctl delete mapping-rule abc123
1892
- `.trim());
509
+ if (resources.length === 0 && !def.requiresResource) {
510
+ const placeholder = deriveResourcePlaceholder(resolvedVerb, def);
511
+ console.log(`\nUsage: c8ctl ${resolvedVerb} ${placeholder}\n`);
512
+ console.log(`Argument:\n ${placeholder || "(none)"}`);
513
+ return;
514
+ }
515
+ const displayNames = resources.map((r) => resourceDisplayName(r));
516
+ const placeholder = deriveResourcePlaceholder(resolvedVerb, def);
517
+ console.log(`\nUsage: c8ctl ${resolvedVerb} ${placeholder}\n`);
518
+ console.log(`Available resources:\n ${displayNames.join(", ")}`);
1893
519
  }
1894
520
  /**
1895
- * Show detailed help for assign command
521
+ * Show detailed help for a verb, derived entirely from COMMAND_REGISTRY.
522
+ * Renders: title, usage, aliases, per-resource flags, verb-level flags.
1896
523
  */
1897
- export function showAssignHelp() {
1898
- console.log(`
1899
- c8ctl assign - Assign a resource to a target
1900
-
1901
- Usage: c8ctl assign <resource> <id> --to-<target>=<targetId> [flags]
1902
-
1903
- Resources:
1904
-
1905
- role <roleId>
1906
- --to-user <username> Assign role to user
1907
- --to-group <groupId> Assign role to group
1908
- --to-tenant <tenantId> Assign role to tenant
1909
- --to-mapping-rule <id> Assign role to mapping rule
1910
- --profile <name> Use specific profile
1911
-
1912
- user <username>
1913
- --to-group <groupId> Assign user to group
1914
- --to-tenant <tenantId> Assign user to tenant
1915
- --profile <name> Use specific profile
1916
-
1917
- group <groupId>
1918
- --to-tenant <tenantId> Assign group to tenant
1919
- --profile <name> Use specific profile
1920
-
1921
- mapping-rule <id>
1922
- --to-group <groupId> Assign mapping rule to group
1923
- --to-tenant <tenantId> Assign mapping rule to tenant
1924
- --profile <name> Use specific profile
1925
-
1926
- Examples:
1927
- c8ctl assign role admin --to-user=john
1928
- c8ctl assign role admin --to-group=developers
1929
- c8ctl assign user john --to-group=developers
1930
- c8ctl assign user john --to-tenant=prod
1931
- c8ctl assign group developers --to-tenant=prod
1932
- c8ctl assign mapping-rule my-rule --to-group=developers
1933
- `.trim());
524
+ function showGenericVerbHelp(verb) {
525
+ const def = lookupVerb(verb);
526
+ if (!def) {
527
+ console.log(`\nNo detailed help available for: ${verb}`);
528
+ console.log('Run "c8ctl help" for general usage information.');
529
+ return;
530
+ }
531
+ const lines = [];
532
+ const FLAG_COL = 32;
533
+ // Title
534
+ lines.push(`c8ctl ${verb} - ${def.helpDescription ?? def.description}`);
535
+ lines.push("");
536
+ // Usage
537
+ const resource = deriveResourcePlaceholder(verb, def);
538
+ lines.push(`Usage: c8ctl ${verb} ${resource} [flags]`.trim());
539
+ // Aliases
540
+ if (def.aliases?.length) {
541
+ lines.push("");
542
+ lines.push(`Alias: ${def.aliases.join(", ")}`);
543
+ }
544
+ // Per-resource sections (when resourceFlags exist)
545
+ if (def.resourceFlags && Object.keys(def.resourceFlags).length > 0) {
546
+ lines.push("");
547
+ lines.push("Resources and their available flags:");
548
+ for (const res of def.resources) {
549
+ const canonical = RESOURCE_ALIASES[res] ?? res;
550
+ const displayName = resourceDisplayName(res);
551
+ // Positionals for this resource
552
+ const positionals = def.resourcePositionals?.[canonical];
553
+ const posStr = positionals
554
+ ? ` ${positionals.map((p) => (p.required ? `<${p.name}>` : `[${p.name}]`)).join(" ")}`
555
+ : "";
556
+ lines.push("");
557
+ lines.push(` ${displayName}${posStr}`);
558
+ // Resource-specific flags
559
+ const resFlags = def.resourceFlags[canonical];
560
+ if (resFlags) {
561
+ for (const [name, flagDef] of flagEntries(resFlags)) {
562
+ lines.push(formatFlag(name, flagDef, FLAG_COL));
563
+ }
564
+ }
565
+ // SEARCH_FLAGS for list/search commands
566
+ if (verb === "list" || verb === "search") {
567
+ for (const [name, flagDef] of flagEntries(SEARCH_FLAGS)) {
568
+ lines.push(formatFlag(name, flagDef, FLAG_COL));
569
+ }
570
+ }
571
+ // --profile always applicable
572
+ lines.push(formatFlag("profile", { type: "string", description: "Use specific profile" }, FLAG_COL));
573
+ }
574
+ }
575
+ else if (def.resources.length > 0) {
576
+ // Simple resource list with positionals (no per-resource flags)
577
+ lines.push("");
578
+ lines.push("Resources:");
579
+ for (const res of def.resources) {
580
+ const canonical = RESOURCE_ALIASES[res] ?? res;
581
+ const displayName = resourceDisplayName(res);
582
+ const positionals = def.resourcePositionals?.[canonical];
583
+ const posStr = positionals
584
+ ? ` ${positionals.map((p) => (p.required ? `<${p.name}>` : `[${p.name}]`)).join(" ")}`
585
+ : "";
586
+ lines.push(` ${displayName}${posStr}`);
587
+ }
588
+ }
589
+ // Verb-level flags (excluding search flags already shown per-resource)
590
+ const verbFlags = Object.entries(def.flags).filter(([name]) => !(name in SEARCH_FLAGS));
591
+ if (verbFlags.length > 0) {
592
+ lines.push("");
593
+ lines.push("Flags:");
594
+ for (const [name, flagDef] of verbFlags) {
595
+ lines.push(formatFlag(name, flagDef, FLAG_COL));
596
+ }
597
+ // Add --profile if not already shown via resourceFlags
598
+ if (!def.resourceFlags || Object.keys(def.resourceFlags).length === 0) {
599
+ lines.push(formatFlag("profile", { type: "string", description: "Use specific profile" }, FLAG_COL));
600
+ }
601
+ }
602
+ else if (!def.resourceFlags ||
603
+ Object.keys(def.resourceFlags).length === 0) {
604
+ // No verb flags and no resource flags — still show --profile
605
+ lines.push("");
606
+ lines.push("Flags:");
607
+ lines.push(formatFlag("profile", { type: "string", description: "Use specific profile" }, FLAG_COL));
608
+ }
609
+ console.log(`\n${lines.join("\n")}`);
1934
610
  }
1935
611
  /**
1936
- * Show detailed help for unassign command
612
+ * Show help for a "virtual topic" that spans multiple verbs.
613
+ * Collects all verbs that operate on the given resource.
1937
614
  */
1938
- export function showUnassignHelp() {
1939
- console.log(`
1940
- c8ctl unassign - Unassign a resource from a target
1941
-
1942
- Usage: c8ctl unassign <resource> <id> --from-<target>=<targetId> [flags]
1943
-
1944
- Resources:
1945
-
1946
- role <roleId>
1947
- --from-user <username> Unassign role from user
1948
- --from-group <groupId> Unassign role from group
1949
- --from-tenant <tenantId> Unassign role from tenant
1950
- --from-mapping-rule <id> Unassign role from mapping rule
1951
- --profile <name> Use specific profile
1952
-
1953
- user <username>
1954
- --from-group <groupId> Unassign user from group
1955
- --from-tenant <tenantId> Unassign user from tenant
1956
- --profile <name> Use specific profile
1957
-
1958
- group <groupId>
1959
- --from-tenant <tenantId> Unassign group from tenant
1960
- --profile <name> Use specific profile
1961
-
1962
- mapping-rule <id>
1963
- --from-group <groupId> Unassign mapping rule from group
1964
- --from-tenant <tenantId> Unassign mapping rule from tenant
1965
- --profile <name> Use specific profile
1966
-
1967
- Examples:
1968
- c8ctl unassign role admin --from-user=john
1969
- c8ctl unassign role admin --from-group=developers
1970
- c8ctl unassign user john --from-group=developers
1971
- c8ctl unassign group developers --from-tenant=prod
1972
- c8ctl unassign mapping-rule my-rule --from-group=developers
1973
- `.trim());
615
+ function showVirtualTopicHelp(topic, resource) {
616
+ const lines = [];
617
+ const FLAG_COL = 32;
618
+ lines.push(`c8ctl ${topic} - ${topic.charAt(0).toUpperCase() + topic.slice(1)} management`);
619
+ lines.push("");
620
+ lines.push(`Usage: c8ctl <command> ${resource} [args] [flags]`);
621
+ lines.push("");
622
+ // Find all verbs that operate on this resource
623
+ for (const [verb, def] of registryEntries()) {
624
+ const canonical = RESOURCE_ALIASES[resource] ?? resource;
625
+ if (!def.resources.some((r) => (RESOURCE_ALIASES[r] ?? r) === canonical))
626
+ continue;
627
+ const positionals = def.resourcePositionals?.[canonical];
628
+ const posStr = positionals
629
+ ? ` ${positionals.map((p) => (p.required ? `<${p.name}>` : `[${p.name}]`)).join(" ")}`
630
+ : "";
631
+ lines.push(` ${verb} ${resource}${posStr}`);
632
+ lines.push(` ${def.description}`);
633
+ // Show flags for this verb (filtered to resource-specific or verb-level)
634
+ const resFlags = def.resourceFlags?.[canonical];
635
+ if (resFlags) {
636
+ for (const [name, flagDef] of flagEntries(resFlags)) {
637
+ lines.push(formatFlag(name, flagDef, FLAG_COL));
638
+ }
639
+ }
640
+ for (const [name, flagDef] of flagEntries(def.flags)) {
641
+ lines.push(formatFlag(name, flagDef, FLAG_COL));
642
+ }
643
+ lines.push("");
644
+ }
645
+ console.log(`\n${lines.join("\n").trimEnd()}`);
1974
646
  }
1975
647
  /**
1976
- * Show detailed help for specific commands
648
+ * Show detailed help for a specific command.
649
+ * Dispatches to the generic renderer for all verbs.
1977
650
  */
1978
- export function showCommandHelp(command) {
651
+ export async function showCommandHelp(command) {
1979
652
  const logger = getLogger();
1980
653
  // JSON mode: emit structured help for machine/agent consumption
1981
654
  if (logger.mode === "json") {
@@ -1995,79 +668,32 @@ export function showCommandHelp(command) {
1995
668
  });
1996
669
  return;
1997
670
  }
1998
- switch (command) {
1999
- case "list":
2000
- showListHelp();
2001
- break;
2002
- case "get":
2003
- showGetHelp();
2004
- break;
2005
- case "create":
2006
- showCreateHelp();
2007
- break;
2008
- case "complete":
2009
- showCompleteHelp();
2010
- break;
2011
- case "await":
2012
- showAwaitHelp();
2013
- break;
2014
- case "mcp-proxy":
2015
- showMcpProxyHelp();
2016
- break;
2017
- case "search":
2018
- showSearchHelp();
2019
- break;
2020
- case "deploy":
2021
- showDeployHelp();
2022
- break;
2023
- case "run":
2024
- showRunHelp();
2025
- break;
2026
- case "watch":
2027
- case "w":
2028
- showWatchHelp();
2029
- break;
2030
- case "open":
2031
- showOpenHelp();
2032
- break;
2033
- case "cancel":
2034
- showCancelHelp();
2035
- break;
2036
- case "resolve":
2037
- showResolveHelp();
2038
- break;
2039
- case "fail":
2040
- showFailHelp();
2041
- break;
2042
- case "activate":
2043
- showActivateHelp();
2044
- break;
2045
- case "publish":
2046
- showPublishHelp();
2047
- break;
2048
- case "correlate":
2049
- showCorrelateHelp();
2050
- break;
2051
- case "delete":
2052
- showDeleteHelp();
2053
- break;
2054
- case "assign":
2055
- showAssignHelp();
2056
- break;
2057
- case "unassign":
2058
- showUnassignHelp();
2059
- break;
2060
- case "profiles":
2061
- case "profile":
2062
- showProfilesHelp();
2063
- break;
2064
- case "plugin":
2065
- case "plugins":
2066
- showPluginHelp();
2067
- break;
2068
- default:
2069
- console.log(`\nNo detailed help available for: ${command}`);
2070
- console.log('Run "c8ctl help" for general usage information.');
671
+ // Virtual help topics that span multiple verbs
672
+ if (command === "profiles" || command === "profile") {
673
+ showVirtualTopicHelp("profiles", "profile");
674
+ return;
675
+ }
676
+ if (command === "plugin" || command === "plugins") {
677
+ showVirtualTopicHelp("plugin", "plugin");
678
+ return;
679
+ }
680
+ // Resolve verb aliases (e.g. "w" → "watch")
681
+ let resolvedVerb = command;
682
+ if (!lookupVerb(command)) {
683
+ for (const [v, d] of registryEntries()) {
684
+ if (d.aliases?.includes(command)) {
685
+ resolvedVerb = v;
686
+ break;
687
+ }
688
+ }
689
+ }
690
+ // If the verb is still not in the registry, check if it's a plugin command.
691
+ // Delegate to the plugin's own handler which renders its own help output.
692
+ if (!lookupVerb(resolvedVerb) && isPluginCommand(resolvedVerb)) {
693
+ // Plugin handlers show help when called with no valid subcommand
694
+ await executePluginCommand(resolvedVerb, []);
695
+ return;
2071
696
  }
697
+ showGenericVerbHelp(resolvedVerb);
2072
698
  }
2073
699
  //# sourceMappingURL=help.js.map