@rashidee/co2 1.2.5

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 (190) hide show
  1. package/dist/index.js +25449 -0
  2. package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
  3. package/drizzle/0001_wise_wolf_cub.sql +13 -0
  4. package/drizzle/0002_secret_spyke.sql +16 -0
  5. package/drizzle/0003_workspace_config_singleton.sql +16 -0
  6. package/drizzle/0004_terminal_claim_v120.sql +11 -0
  7. package/drizzle/0005_brainstorm_v124.sql +10 -0
  8. package/drizzle/0006_project_v140.sql +6 -0
  9. package/drizzle/0007_prd_wizard_v124.sql +14 -0
  10. package/drizzle/0008_workflow_artifact_v126.sql +24 -0
  11. package/drizzle/0009_project_import_v150.sql +7 -0
  12. package/drizzle/0010_quality_v151.sql +3 -0
  13. package/drizzle/meta/0000_snapshot.json +1335 -0
  14. package/drizzle/meta/0001_snapshot.json +1416 -0
  15. package/drizzle/meta/0002_snapshot.json +1510 -0
  16. package/drizzle/meta/_journal.json +83 -0
  17. package/package.json +41 -0
  18. package/plugin/.claude-plugin/marketplace.json +36 -0
  19. package/plugin/.claude-plugin/plugin.json +22 -0
  20. package/plugin/README.md +625 -0
  21. package/plugin/SKILLS.md +350 -0
  22. package/plugin/co2.svg +5 -0
  23. package/plugin/commands/brainstorm-loop.md +129 -0
  24. package/plugin/skills/conductor-defect/SKILL.md +898 -0
  25. package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
  26. package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
  27. package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
  28. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
  29. package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
  30. package/plugin/skills/depgen-k8s/SKILL.md +468 -0
  31. package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
  32. package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
  33. package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
  34. package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
  35. package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
  36. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
  37. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
  38. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
  39. package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
  40. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
  41. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
  42. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
  43. package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
  44. package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
  45. package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
  46. package/plugin/skills/modelgen-relational/SKILL.md +707 -0
  47. package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
  48. package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
  49. package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
  50. package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
  51. package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
  52. package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
  53. package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
  54. package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
  55. package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
  56. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
  57. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
  58. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
  59. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
  60. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
  61. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
  62. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
  63. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
  64. package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
  65. package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
  66. package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
  67. package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
  68. package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
  69. package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
  70. package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
  71. package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
  72. package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
  73. package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
  74. package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
  75. package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
  76. package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
  77. package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
  78. package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
  79. package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
  80. package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
  81. package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
  82. package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
  83. package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
  84. package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
  85. package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
  86. package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
  87. package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
  88. package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
  89. package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
  90. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
  91. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
  92. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
  93. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
  94. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
  95. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
  96. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
  97. package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
  98. package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
  99. package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
  100. package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
  101. package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
  102. package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
  103. package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
  104. package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
  105. package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
  106. package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
  107. package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
  108. package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
  109. package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
  110. package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
  111. package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
  112. package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
  113. package/plugin/skills/testgen-functional/SKILL.md +1381 -0
  114. package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
  115. package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
  116. package/plugin/skills/util-projectinit/SKILL.md +307 -0
  117. package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
  118. package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
  119. package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
  120. package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
  121. package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
  122. package/plugin/skills/util-projectsync/SKILL.md +501 -0
  123. package/plugin/skills/util-updprd/SKILL.md +324 -0
  124. package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
  125. package/plugin/skills/util-ustagger/SKILL.md +154 -0
  126. package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
  127. package/static/assets/arc-DRKw7sjs.js +1 -0
  128. package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
  129. package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
  130. package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
  131. package/static/assets/channel-C2nVbuwv.js +1 -0
  132. package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
  133. package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
  134. package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
  135. package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
  136. package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
  137. package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
  138. package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
  139. package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
  140. package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
  141. package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
  142. package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
  143. package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
  144. package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
  145. package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
  146. package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
  147. package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  148. package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
  149. package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  150. package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
  151. package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
  152. package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
  153. package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
  154. package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
  155. package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
  156. package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
  157. package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
  158. package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
  159. package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
  160. package/static/assets/graph-C9eacEi8.js +1 -0
  161. package/static/assets/index-LZSQkLE2.css +41 -0
  162. package/static/assets/index-y7XDSgMG.js +495 -0
  163. package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
  164. package/static/assets/init-Gi6I4Gst.js +1 -0
  165. package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
  166. package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
  167. package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
  168. package/static/assets/katex-C5jXJg4s.js +257 -0
  169. package/static/assets/layout-DEXfKzaS.js +1 -0
  170. package/static/assets/linear-CLO--ryk.js +1 -0
  171. package/static/assets/map-Czzmt4hB.js +1 -0
  172. package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
  173. package/static/assets/ordinal-Cboi1Yqb.js +1 -0
  174. package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
  175. package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
  176. package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
  177. package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
  178. package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
  179. package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
  180. package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
  181. package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
  182. package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
  183. package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
  184. package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
  185. package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
  186. package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
  187. package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
  188. package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
  189. package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
  190. package/static/index.html +24 -0
@@ -0,0 +1,383 @@
1
+ # Command Patterns — Commander.js Architecture
2
+
3
+ This reference describes the CLI command architecture patterns. Include relevant content
4
+ in Sections 4 and the per-command SPEC.md files.
5
+
6
+ ---
7
+
8
+ ## Architecture Overview
9
+
10
+ ```
11
+ cli.ts (Program root)
12
+ └── registerXxxCommand(program) ← Each command in its own file
13
+ ├── program.command('xxx')
14
+ │ .argument(...)
15
+ │ .option(...)
16
+ │ .action(handleError(async (arg, opts) => {
17
+ │ // 1. Setup (verbose/json modes)
18
+ │ // 2. Collect missing inputs (prompts if not --yes)
19
+ │ // 3. Validate inputs
20
+ │ // 4. Call service
21
+ │ // 5. Format and print result
22
+ │ }))
23
+ └── (sub-commands registered via .addCommand())
24
+ ```
25
+
26
+ **Dependency direction rule:**
27
+ - `cli.ts` → imports command registrations
28
+ - command files → import services and UI utilities
29
+ - services → import config and HTTP client
30
+ - UI utilities → import chalk/ora/table (no service/config imports)
31
+ - No circular dependencies
32
+
33
+ ---
34
+
35
+ ## Commander.js Program Setup
36
+
37
+ ### Root Program
38
+
39
+ ```typescript
40
+ // src/cli.ts
41
+ import { Command } from 'commander'
42
+ import { fileURLToPath } from 'node:url'
43
+ import { dirname, join } from 'node:path'
44
+ import { readFileSync } from 'node:fs'
45
+
46
+ const __filename = fileURLToPath(import.meta.url)
47
+ const __dirname = dirname(__filename)
48
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8')) as {
49
+ name: string; version: string; description: string
50
+ }
51
+
52
+ const program = new Command()
53
+
54
+ program
55
+ .name(pkg.name)
56
+ .description(pkg.description)
57
+ .version(pkg.version, '-V, --version')
58
+ // Global options available on all sub-commands via parent resolution
59
+ .option('-v, --verbose', 'enable verbose output', false)
60
+ .option('--json', 'output as JSON', false)
61
+ .option('--no-color', 'disable ANSI colours')
62
+ .addHelpCommand('help [command]', 'Display help for command')
63
+ // Prevent Commander from catching process.exit(0) as an error
64
+ .exitOverride()
65
+
66
+ // Register commands
67
+ registerInitCommand(program)
68
+ registerDeployCommand(program)
69
+
70
+ // Allow top-level await in the entry point
71
+ await program.parseAsync(process.argv)
72
+ ```
73
+
74
+ ### Reading Parent Options Inside a Command
75
+
76
+ Commander stores parent options separately. Access global options from inside a command:
77
+
78
+ ```typescript
79
+ .action(handleError(async (arg: string, opts: LocalOptions, command: Command) => {
80
+ // Walk up to program root for global options
81
+ const globalOpts = command.parent?.opts<GlobalOptions>() ?? {
82
+ verbose: false,
83
+ json: false,
84
+ color: true,
85
+ }
86
+ if (globalOpts.verbose) logger.enableVerbose()
87
+ if (globalOpts.json) output.enableJson()
88
+ }))
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Command Patterns by Type
94
+
95
+ ### Simple Command (no sub-commands)
96
+
97
+ ```typescript
98
+ // src/commands/status/index.ts
99
+ import type { Command } from 'commander'
100
+ import { handleError } from '../../errors.js'
101
+ import { output } from '../../ui/output.js'
102
+ import { StatusService } from '../../services/status.service.js'
103
+
104
+ export interface StatusOptions {
105
+ environment: string
106
+ verbose: boolean
107
+ json: boolean
108
+ }
109
+
110
+ export function registerStatusCommand(program: Command): void {
111
+ program
112
+ .command('status')
113
+ .description('Check the deployment status of an environment')
114
+ .argument('[env]', 'target environment', 'production')
115
+ .option('-e, --environment <env>', 'environment override')
116
+ .action(handleError(async (env: string, opts: StatusOptions, cmd: Command) => {
117
+ const { verbose, json } = cmd.parent?.opts<{ verbose: boolean; json: boolean }>() ?? {}
118
+ if (verbose) logger.enableVerbose()
119
+ if (json) output.enableJson()
120
+
121
+ const service = new StatusService()
122
+ const result = await service.getStatus(opts.environment ?? env)
123
+ output.success(result, `Status: ${result.status}`)
124
+ }))
125
+ }
126
+ ```
127
+
128
+ ### Command with Sub-commands
129
+
130
+ Use `.addCommand()` to nest sub-commands. Each sub-command is its own registered handler.
131
+
132
+ ```typescript
133
+ // src/commands/config/index.ts
134
+ import type { Command } from 'commander'
135
+ import { registerConfigGetCommand } from './get.js'
136
+ import { registerConfigSetCommand } from './set.js'
137
+ import { registerConfigListCommand } from './list.js'
138
+ import { registerConfigResetCommand } from './reset.js'
139
+
140
+ export function registerConfigCommand(program: Command): void {
141
+ const configCmd = program
142
+ .command('config')
143
+ .description('Manage {{BINARY_NAME}} configuration')
144
+ .addHelpCommand(false)
145
+
146
+ registerConfigGetCommand(configCmd)
147
+ registerConfigSetCommand(configCmd)
148
+ registerConfigListCommand(configCmd)
149
+ registerConfigResetCommand(configCmd)
150
+ }
151
+ ```
152
+
153
+ ```typescript
154
+ // src/commands/config/get.ts
155
+ import type { Command } from 'commander'
156
+ import { handleError } from '../../errors.js'
157
+ import { getUserConfig } from '../../config/user.config.js'
158
+ import { output } from '../../ui/output.js'
159
+
160
+ export function registerConfigGetCommand(parent: Command): void {
161
+ parent
162
+ .command('get <key>')
163
+ .description('Print the value of a config key')
164
+ .action(handleError(async (key: string) => {
165
+ const config = getUserConfig()
166
+ const value = config.get(key as never)
167
+ if (value === undefined) {
168
+ output.failure('NOT_FOUND', `Config key not found: ${key}`)
169
+ process.exit(3)
170
+ }
171
+ output.success({ key, value }, `${key} = ${String(value)}`)
172
+ }))
173
+ }
174
+ ```
175
+
176
+ ### Command with Required Confirmation
177
+
178
+ For destructive operations, require explicit confirmation:
179
+
180
+ ```typescript
181
+ // src/commands/destroy/index.ts
182
+ import { confirm } from '@inquirer/prompts'
183
+
184
+ export function registerDestroyCommand(program: Command): void {
185
+ program
186
+ .command('destroy')
187
+ .description('Permanently delete a project (irreversible)')
188
+ .argument('<project-id>', 'ID of the project to delete')
189
+ .option('-f, --force', 'skip confirmation prompt', false)
190
+ .action(handleError(async (projectId: string, opts: DestroyOptions) => {
191
+ if (!opts.force) {
192
+ const confirmed = await confirm({
193
+ message: `Permanently delete project "${projectId}"? This cannot be undone.`,
194
+ default: false,
195
+ })
196
+ if (!confirmed) {
197
+ logger.info('Aborted.')
198
+ process.exit(0)
199
+ }
200
+ }
201
+
202
+ const service = new DestroyService()
203
+ await service.deleteProject(projectId)
204
+ output.success({ projectId, deleted: true }, `Project deleted: ${projectId}`)
205
+ }))
206
+ }
207
+ ```
208
+
209
+ ### Command with `--dry-run`
210
+
211
+ Every mutating command should support `--dry-run`. The service receives `dryRun` in its
212
+ options and returns a preview without side effects.
213
+
214
+ ```typescript
215
+ .option('--dry-run', 'preview changes without applying them', false)
216
+ .action(handleError(async (opts: DeployOptions) => {
217
+ const service = new DeployService()
218
+ const result = await service.deploy({ ...opts })
219
+
220
+ if (opts.dryRun) {
221
+ output.success(result, 'Dry run complete — no changes applied')
222
+ } else {
223
+ output.success(result, `Deployed to ${result.environment}`)
224
+ }
225
+ }))
226
+ ```
227
+
228
+ ### Command Producing Tabular Output
229
+
230
+ ```typescript
231
+ import { printTable } from '../../ui/table.js'
232
+ import type { GlobalOptions } from '../../types/index.js'
233
+
234
+ .action(handleError(async (_opts: ListOptions, cmd: Command) => {
235
+ const { json } = cmd.parent?.opts<GlobalOptions>() ?? { json: false }
236
+ output.enableJson() // conditionally
237
+
238
+ const service = new ListService()
239
+ const items = await service.list()
240
+
241
+ if (json) {
242
+ output.success(items, '')
243
+ return
244
+ }
245
+
246
+ if (items.length === 0) {
247
+ logger.info('No items found.')
248
+ return
249
+ }
250
+
251
+ printTable({
252
+ head: ['Name', 'Status', 'Created'],
253
+ rows: items.map(i => [i.name, i.status, i.createdAt]),
254
+ })
255
+ logger.info(`${items.length.toString()} item(s) found.`)
256
+ }))
257
+ ```
258
+
259
+ ---
260
+
261
+ ## Global Option Propagation Pattern
262
+
263
+ Commander does not automatically pass parent options to child commands. Adopt this
264
+ consistent pattern across all command action handlers:
265
+
266
+ ```typescript
267
+ /** Extract global options from the root program */
268
+ function getGlobalOptions(cmd: Command): GlobalOptions {
269
+ // Walk up to root
270
+ let current: Command = cmd
271
+ while (current.parent) current = current.parent
272
+ return current.opts<GlobalOptions>()
273
+ }
274
+ ```
275
+
276
+ Or as a shared utility:
277
+
278
+ ```typescript
279
+ // src/utils/command.ts
280
+ import type { Command } from 'commander'
281
+ import type { GlobalOptions } from '../types/index.js'
282
+
283
+ export function setupCommandContext(cmd: Command): void {
284
+ const { verbose, json } = getGlobalOptions(cmd)
285
+ if (verbose) logger.enableVerbose()
286
+ if (json) output.enableJson()
287
+ }
288
+
289
+ export function getGlobalOptions(cmd: Command): GlobalOptions {
290
+ let root: Command = cmd
291
+ while (root.parent) root = root.parent
292
+ return root.opts<GlobalOptions>()
293
+ }
294
+ ```
295
+
296
+ Usage in every action handler:
297
+
298
+ ```typescript
299
+ .action(handleError(async (arg: string, opts: MyOptions, cmd: Command) => {
300
+ setupCommandContext(cmd)
301
+ // rest of handler
302
+ }))
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Command Exit Code Conventions
308
+
309
+ | Scenario | Exit Code |
310
+ |----------------------------------|-----------|
311
+ | Success | `0` |
312
+ | General / unexpected error | `1` |
313
+ | Invalid argument / option value | `2` |
314
+ | Resource not found | `3` |
315
+ | Unauthorized / unauthenticated | `4` |
316
+ | Network / connectivity error | `5` |
317
+ | Configuration error | `6` |
318
+ | User aborted (Ctrl+C, no confirm)| `0` |
319
+
320
+ Always use `process.exit(code)` — never `throw` past the command action handler.
321
+
322
+ ---
323
+
324
+ ## Help Text Conventions
325
+
326
+ Every command and option must have descriptive help text. Commander auto-generates
327
+ `--help` from these strings.
328
+
329
+ **Descriptions should:**
330
+ - Start with a capital letter
331
+ - End without a period (Commander adds none)
332
+ - Be actionable: "Deploy the project to an environment" not "Deployment"
333
+ - Include the default value in option descriptions when non-obvious
334
+
335
+ ```typescript
336
+ program
337
+ .command('deploy')
338
+ .description('Deploy the current project to a target environment')
339
+ .option('-e, --environment <name>', 'target environment name', 'staging')
340
+ .option('--strategy <type>', 'deployment strategy: rolling|blue-green', 'rolling')
341
+ .option('--timeout <seconds>', 'deployment timeout in seconds', '300')
342
+ .option('--dry-run', 'preview what would be deployed without deploying')
343
+ ```
344
+
345
+ Resulting `--help`:
346
+ ```
347
+ Usage: my-tool deploy [options]
348
+
349
+ Deploy the current project to a target environment
350
+
351
+ Options:
352
+ -e, --environment <name> target environment name (default: "staging")
353
+ --strategy <type> deployment strategy: rolling|blue-green (default: "rolling")
354
+ --timeout <seconds> deployment timeout in seconds (default: "300")
355
+ --dry-run preview what would be deployed without deploying
356
+ -h, --help display help for command
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Async Error Handling in Commander
362
+
363
+ Commander v12+ supports `parseAsync`. All commands that do async work must be wrapped
364
+ with `handleError` (from `src/errors.ts`) to ensure clean exit codes:
365
+
366
+ ```typescript
367
+ // WRONG — unhandled rejection bubbles past Commander
368
+ .action(async (arg, opts) => {
369
+ const result = await service.execute(arg)
370
+ // ...
371
+ })
372
+
373
+ // CORRECT — handleError wraps and formats all thrown errors
374
+ .action(handleError(async (arg: string, opts: Opts) => {
375
+ const result = await service.execute(arg)
376
+ // ...
377
+ }))
378
+ ```
379
+
380
+ The `handleError` wrapper catches:
381
+ - `CliError` instances → formats with code and exits with `exitCode`
382
+ - Any other `Error` → prints generic message, logs stack in verbose mode, exits `1`
383
+ - Non-Error throws → converts to string, exits `1`