aiwcli 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +1248 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +16 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +19 -0
  6. package/dist/commands/branch.d.ts +45 -0
  7. package/dist/commands/branch.js +488 -0
  8. package/dist/commands/clean.d.ts +34 -0
  9. package/dist/commands/clean.js +186 -0
  10. package/dist/commands/clear.d.ts +51 -0
  11. package/dist/commands/clear.js +835 -0
  12. package/dist/commands/init/index.d.ts +107 -0
  13. package/dist/commands/init/index.js +565 -0
  14. package/dist/commands/launch.d.ts +21 -0
  15. package/dist/commands/launch.js +108 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/lib/base-command.d.ts +114 -0
  19. package/dist/lib/base-command.js +153 -0
  20. package/dist/lib/bmad-installer.d.ts +38 -0
  21. package/dist/lib/bmad-installer.js +145 -0
  22. package/dist/lib/claude-settings-types.d.ts +102 -0
  23. package/dist/lib/claude-settings-types.js +5 -0
  24. package/dist/lib/config.d.ts +25 -0
  25. package/dist/lib/config.js +46 -0
  26. package/dist/lib/debug.d.ts +39 -0
  27. package/dist/lib/debug.js +74 -0
  28. package/dist/lib/env-compat.d.ts +26 -0
  29. package/dist/lib/env-compat.js +35 -0
  30. package/dist/lib/errors.d.ts +126 -0
  31. package/dist/lib/errors.js +145 -0
  32. package/dist/lib/generic-merge.d.ts +74 -0
  33. package/dist/lib/generic-merge.js +105 -0
  34. package/dist/lib/git/branch.d.ts +67 -0
  35. package/dist/lib/git/branch.js +155 -0
  36. package/dist/lib/git/index.d.ts +11 -0
  37. package/dist/lib/git/index.js +13 -0
  38. package/dist/lib/git/safety-checks.d.ts +44 -0
  39. package/dist/lib/git/safety-checks.js +102 -0
  40. package/dist/lib/git/types.d.ts +31 -0
  41. package/dist/lib/git/types.js +6 -0
  42. package/dist/lib/git/worktree.d.ts +67 -0
  43. package/dist/lib/git/worktree.js +220 -0
  44. package/dist/lib/gitignore-manager.d.ts +10 -0
  45. package/dist/lib/gitignore-manager.js +60 -0
  46. package/dist/lib/hooks-merger.d.ts +28 -0
  47. package/dist/lib/hooks-merger.js +94 -0
  48. package/dist/lib/ide-path-resolver.d.ts +102 -0
  49. package/dist/lib/ide-path-resolver.js +129 -0
  50. package/dist/lib/index.d.ts +13 -0
  51. package/dist/lib/index.js +22 -0
  52. package/dist/lib/output.d.ts +51 -0
  53. package/dist/lib/output.js +76 -0
  54. package/dist/lib/paths.d.ts +66 -0
  55. package/dist/lib/paths.js +136 -0
  56. package/dist/lib/quiet.d.ts +12 -0
  57. package/dist/lib/quiet.js +17 -0
  58. package/dist/lib/settings-hierarchy.d.ts +42 -0
  59. package/dist/lib/settings-hierarchy.js +105 -0
  60. package/dist/lib/spawn.d.ts +105 -0
  61. package/dist/lib/spawn.js +157 -0
  62. package/dist/lib/spinner.d.ts +19 -0
  63. package/dist/lib/spinner.js +34 -0
  64. package/dist/lib/stdin.d.ts +48 -0
  65. package/dist/lib/stdin.js +60 -0
  66. package/dist/lib/template-installer.d.ts +92 -0
  67. package/dist/lib/template-installer.js +375 -0
  68. package/dist/lib/template-linter.d.ts +49 -0
  69. package/dist/lib/template-linter.js +173 -0
  70. package/dist/lib/template-merger.d.ts +47 -0
  71. package/dist/lib/template-merger.js +173 -0
  72. package/dist/lib/template-resolver.d.ts +20 -0
  73. package/dist/lib/template-resolver.js +60 -0
  74. package/dist/lib/terminal.d.ts +102 -0
  75. package/dist/lib/terminal.js +245 -0
  76. package/dist/lib/tty-detection.d.ts +62 -0
  77. package/dist/lib/tty-detection.js +83 -0
  78. package/dist/lib/user-utils.d.ts +5 -0
  79. package/dist/lib/user-utils.js +23 -0
  80. package/dist/lib/version.d.ts +99 -0
  81. package/dist/lib/version.js +144 -0
  82. package/dist/lib/watch-templates.d.ts +6 -0
  83. package/dist/lib/watch-templates.js +73 -0
  84. package/dist/lib/windsurf-hooks-hierarchy.d.ts +30 -0
  85. package/dist/lib/windsurf-hooks-hierarchy.js +66 -0
  86. package/dist/lib/windsurf-hooks-merger.d.ts +26 -0
  87. package/dist/lib/windsurf-hooks-merger.js +53 -0
  88. package/dist/lib/windsurf-hooks-types.d.ts +33 -0
  89. package/dist/lib/windsurf-hooks-types.js +5 -0
  90. package/dist/templates/CLAUDE.md +174 -0
  91. package/dist/templates/_shared/.claude/commands/handoff.md +14 -0
  92. package/dist/templates/_shared/.claude/settings.json +61 -0
  93. package/dist/templates/_shared/.codex/workflows/handoff.md +14 -0
  94. package/dist/templates/_shared/.windsurf/workflows/handoff.md +14 -0
  95. package/dist/templates/_shared/hooks/__init__.py +16 -0
  96. package/dist/templates/_shared/hooks/archive_plan.py +270 -0
  97. package/dist/templates/_shared/hooks/context_enforcer.py +621 -0
  98. package/dist/templates/_shared/hooks/context_monitor.py +322 -0
  99. package/dist/templates/_shared/hooks/file-suggestion.py +188 -0
  100. package/dist/templates/_shared/hooks/task_create_capture.py +194 -0
  101. package/dist/templates/_shared/hooks/task_update_capture.py +254 -0
  102. package/dist/templates/_shared/hooks/user_prompt_submit.py +157 -0
  103. package/dist/templates/_shared/lib/__init__.py +1 -0
  104. package/dist/templates/_shared/lib/base/__init__.py +49 -0
  105. package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
  106. package/dist/templates/_shared/lib/base/atomic_write.py +180 -0
  107. package/dist/templates/_shared/lib/base/constants.py +299 -0
  108. package/dist/templates/_shared/lib/base/inference.py +189 -0
  109. package/dist/templates/_shared/lib/base/utils.py +216 -0
  110. package/dist/templates/_shared/lib/context/__init__.py +119 -0
  111. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  112. package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
  113. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  114. package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
  115. package/dist/templates/_shared/lib/context/cache.py +446 -0
  116. package/dist/templates/_shared/lib/context/context_manager.py +1171 -0
  117. package/dist/templates/_shared/lib/context/discovery.py +486 -0
  118. package/dist/templates/_shared/lib/context/event_log.py +308 -0
  119. package/dist/templates/_shared/lib/context/plan_archive.py +247 -0
  120. package/dist/templates/_shared/lib/context/task_sync.py +367 -0
  121. package/dist/templates/_shared/lib/handoff/__init__.py +22 -0
  122. package/dist/templates/_shared/lib/handoff/document_generator.py +307 -0
  123. package/dist/templates/_shared/lib/templates/README.md +215 -0
  124. package/dist/templates/_shared/lib/templates/__init__.py +40 -0
  125. package/dist/templates/_shared/lib/templates/formatters.py +147 -0
  126. package/dist/templates/_shared/lib/templates/plan_context.py +119 -0
  127. package/dist/templates/_shared/scripts/save_handoff.py +99 -0
  128. package/dist/templates/_shared/workflows/handoff.md +212 -0
  129. package/dist/templates/cc-native/.claude/agents/cc-native/ACCESSIBILITY-TESTER.md +80 -0
  130. package/dist/templates/cc-native/.claude/agents/cc-native/ARCHITECT-REVIEWER.md +75 -0
  131. package/dist/templates/cc-native/.claude/agents/cc-native/ASSUMPTION-CHAIN-TRACER.md +239 -0
  132. package/dist/templates/cc-native/.claude/agents/cc-native/CLARITY-AUDITOR.md +109 -0
  133. package/dist/templates/cc-native/.claude/agents/cc-native/CODE-REVIEWER.md +71 -0
  134. package/dist/templates/cc-native/.claude/agents/cc-native/COMPLETENESS-CHECKER.md +104 -0
  135. package/dist/templates/cc-native/.claude/agents/cc-native/CONTEXT-EXTRACTOR.md +93 -0
  136. package/dist/templates/cc-native/.claude/agents/cc-native/DEVILS-ADVOCATE.md +223 -0
  137. package/dist/templates/cc-native/.claude/agents/cc-native/DOCUMENTATION-REVIEWER.md +73 -0
  138. package/dist/templates/cc-native/.claude/agents/cc-native/FEASIBILITY-ANALYST.md +93 -0
  139. package/dist/templates/cc-native/.claude/agents/cc-native/FRESH-PERSPECTIVE.md +103 -0
  140. package/dist/templates/cc-native/.claude/agents/cc-native/HANDOFF-READINESS.md +145 -0
  141. package/dist/templates/cc-native/.claude/agents/cc-native/HIDDEN-COMPLEXITY-DETECTOR.md +248 -0
  142. package/dist/templates/cc-native/.claude/agents/cc-native/INCENTIVE-MAPPER.md +235 -0
  143. package/dist/templates/cc-native/.claude/agents/cc-native/PENETRATION-TESTER.md +80 -0
  144. package/dist/templates/cc-native/.claude/agents/cc-native/PERFORMANCE-ENGINEER.md +76 -0
  145. package/dist/templates/cc-native/.claude/agents/cc-native/PLAN-ORCHESTRATOR.md +141 -0
  146. package/dist/templates/cc-native/.claude/agents/cc-native/PRECEDENT-FINDER.md +240 -0
  147. package/dist/templates/cc-native/.claude/agents/cc-native/REVERSIBILITY-ANALYST.md +211 -0
  148. package/dist/templates/cc-native/.claude/agents/cc-native/RISK-ASSESSOR.md +101 -0
  149. package/dist/templates/cc-native/.claude/agents/cc-native/SECOND-ORDER-ANALYST.md +197 -0
  150. package/dist/templates/cc-native/.claude/agents/cc-native/SIMPLICITY-GUARDIAN.md +97 -0
  151. package/dist/templates/cc-native/.claude/agents/cc-native/SKEPTIC.md +349 -0
  152. package/dist/templates/cc-native/.claude/agents/cc-native/STAKEHOLDER-ADVOCATE.md +106 -0
  153. package/dist/templates/cc-native/.claude/agents/cc-native/TRADE-OFF-ILLUMINATOR.md +205 -0
  154. package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +8 -0
  155. package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +10 -0
  156. package/dist/templates/cc-native/.claude/settings.json +119 -0
  157. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fix.md +8 -0
  158. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +8 -0
  159. package/dist/templates/cc-native/.windsurf/workflows/cc-native/implement.md +8 -0
  160. package/dist/templates/cc-native/.windsurf/workflows/cc-native/research.md +8 -0
  161. package/dist/templates/cc-native/CC-NATIVE-README.md +192 -0
  162. package/dist/templates/cc-native/MIGRATION.md +86 -0
  163. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +331 -0
  164. package/dist/templates/cc-native/_cc-native/docs/PERMISSION_REQUEST_VERIFICATION.md +147 -0
  165. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  166. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  167. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-agent-review.cpython-313.pyc +0 -0
  168. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  169. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/test_permission_request.cpython-313.pyc +0 -0
  170. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +150 -0
  171. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +746 -0
  172. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +339 -0
  173. package/dist/templates/cc-native/_cc-native/lib/__init__.py +57 -0
  174. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  175. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  176. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  177. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  178. package/dist/templates/cc-native/_cc-native/lib/async_archive.py +68 -0
  179. package/dist/templates/cc-native/_cc-native/lib/atomic_write.py +98 -0
  180. package/dist/templates/cc-native/_cc-native/lib/constants.py +45 -0
  181. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +273 -0
  182. package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +28 -0
  183. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  184. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  185. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  186. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  187. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  188. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +164 -0
  189. package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +89 -0
  190. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +119 -0
  191. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +103 -0
  192. package/dist/templates/cc-native/_cc-native/lib/state.py +251 -0
  193. package/dist/templates/cc-native/_cc-native/lib/utils.py +830 -0
  194. package/dist/templates/cc-native/_cc-native/plan-review.config.json +76 -0
  195. package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
  196. package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +151 -0
  197. package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +134 -0
  198. package/dist/templates/cc-native/_cc-native/workflows/specdev.md +9 -0
  199. package/dist/types/exit-codes.d.ts +11 -0
  200. package/dist/types/exit-codes.js +10 -0
  201. package/dist/types/index.d.ts +5 -0
  202. package/dist/types/index.js +7 -0
  203. package/oclif.manifest.json +405 -0
  204. package/package.json +109 -0
@@ -0,0 +1,21 @@
1
+ import BaseCommand from '../lib/base-command.js';
2
+ /**
3
+ * Launch Claude Code or Codex with AIW configuration.
4
+ *
5
+ * Spawns Claude Code CLI with --dangerously-skip-permissions flag,
6
+ * or Codex CLI with --yolo flag, enabling unattended execution.
7
+ * Designed for AIW hook system safety guardrails (requires aiw setup).
8
+ * Supports multiple parallel sessions.
9
+ */
10
+ export default class LaunchCommand extends BaseCommand {
11
+ static description: string;
12
+ static examples: string[];
13
+ static flags: {
14
+ codex: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ new: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
18
+ quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ };
20
+ run(): Promise<void>;
21
+ }
@@ -0,0 +1,108 @@
1
+ import { Flags } from '@oclif/core';
2
+ import BaseCommand from '../lib/base-command.js';
3
+ import { ProcessSpawnError } from '../lib/errors.js';
4
+ import { spawnProcess } from '../lib/spawn.js';
5
+ import { launchTerminal } from '../lib/terminal.js';
6
+ import { checkVersionCompatibility, getClaudeCodeVersion } from '../lib/version.js';
7
+ import { EXIT_CODES } from '../types/index.js';
8
+ /**
9
+ * Launch Claude Code or Codex with AIW configuration.
10
+ *
11
+ * Spawns Claude Code CLI with --dangerously-skip-permissions flag,
12
+ * or Codex CLI with --yolo flag, enabling unattended execution.
13
+ * Designed for AIW hook system safety guardrails (requires aiw setup).
14
+ * Supports multiple parallel sessions.
15
+ */
16
+ export default class LaunchCommand extends BaseCommand {
17
+ static description = 'Launch Claude Code or Codex with AIW configuration (sandbox disabled, supports parallel sessions)\n\n' +
18
+ 'FLAGS\n' +
19
+ ' --codex/-c: Launch Codex instead of Claude Code (uses --yolo flag)\n' +
20
+ ' --new/-n: Open a new terminal in the current directory and launch there\n\n' +
21
+ 'EXIT CODES\n' +
22
+ ' 0 Success - AI assistant launched and exited successfully\n' +
23
+ ' 1 General error - unexpected runtime failure\n' +
24
+ ' 2 Invalid usage - check your arguments and flags\n' +
25
+ ' 3 Environment error - CLI not found (install Claude Code from https://claude.ai/download or Codex from npm)';
26
+ static examples = [
27
+ '<%= config.bin %> <%= command.id %>',
28
+ '<%= config.bin %> <%= command.id %> --codex # Launch Codex with --yolo flag',
29
+ '<%= config.bin %> <%= command.id %> -c # Short form for --codex',
30
+ '<%= config.bin %> <%= command.id %> --new # Launch in a new terminal window',
31
+ '<%= config.bin %> <%= command.id %> -n # Short form for --new',
32
+ '<%= config.bin %> <%= command.id %> --codex --new # Launch Codex in new terminal',
33
+ '<%= config.bin %> <%= command.id %> --debug # Enable verbose logging',
34
+ '# Check exit code in Bash\n<%= config.bin %> <%= command.id %>\necho $?',
35
+ '# Check exit code in PowerShell\n<%= config.bin %> <%= command.id %>\necho $LASTEXITCODE',
36
+ ];
37
+ static flags = {
38
+ ...BaseCommand.baseFlags,
39
+ codex: Flags.boolean({
40
+ char: 'c',
41
+ description: 'Launch Codex instead of Claude Code (uses --yolo flag for full auto mode)',
42
+ default: false,
43
+ }),
44
+ new: Flags.boolean({
45
+ char: 'n',
46
+ description: 'Open a new terminal in the current directory and run aiw launch there',
47
+ default: false,
48
+ }),
49
+ };
50
+ async run() {
51
+ const { flags } = await this.parse(LaunchCommand);
52
+ // Determine which CLI to launch
53
+ const useCodex = flags.codex;
54
+ const cliCommand = useCodex ? 'codex' : 'claude';
55
+ const cliArgs = useCodex ? ['--yolo'] : ['--dangerously-skip-permissions'];
56
+ const launchFlag = useCodex ? '--codex' : '';
57
+ // Handle --new flag: launch in a new terminal
58
+ if (flags.new) {
59
+ const cwd = process.cwd();
60
+ this.debug(`Launching new terminal in: ${cwd}`);
61
+ const launchCmd = useCodex ? 'aiw launch --codex' : 'aiw launch';
62
+ const result = await launchTerminal({
63
+ cwd,
64
+ command: launchCmd,
65
+ debugLog: (msg) => this.debug(msg),
66
+ });
67
+ if (!result.success) {
68
+ this.error(`Failed to launch new terminal: ${result.error}`, { exit: EXIT_CODES.GENERAL_ERROR });
69
+ }
70
+ this.log(`New terminal launched with aiw launch${launchFlag ? ` ${launchFlag}` : ''}`);
71
+ return;
72
+ }
73
+ // Normal launch flow
74
+ let exitCode;
75
+ try {
76
+ // Version check only applies to Claude Code (not Codex)
77
+ if (useCodex) {
78
+ this.debug('Launching Codex with --yolo flag');
79
+ }
80
+ else {
81
+ // Check Claude Code version compatibility (non-blocking)
82
+ const version = await getClaudeCodeVersion();
83
+ const versionCheck = checkVersionCompatibility(version);
84
+ // Debug logging: show version information
85
+ this.debug(`Claude Code version: ${versionCheck.version ?? 'unknown'}`);
86
+ this.debug(`Compatibility status: ${versionCheck.compatible ? 'compatible' : 'incompatible'}`);
87
+ // Non-blocking warning for incompatibility or unknown version
88
+ if (versionCheck.warning) {
89
+ this.warn(versionCheck.warning);
90
+ }
91
+ }
92
+ // Spawn AI CLI with sandbox permissions disabled
93
+ // AIW hook system provides safety guardrails
94
+ // Continue launch regardless of version check result (graceful degradation)
95
+ exitCode = await spawnProcess(cliCommand, cliArgs);
96
+ }
97
+ catch (error) {
98
+ if (error instanceof ProcessSpawnError) {
99
+ // Actionable error message (already includes installation link)
100
+ this.error(error.message, { exit: EXIT_CODES.ENVIRONMENT_ERROR });
101
+ }
102
+ // Unexpected error
103
+ this.error('Unexpected launch failure.', { exit: EXIT_CODES.GENERAL_ERROR });
104
+ }
105
+ // Pass through Claude Code's exit code (outside try-catch to avoid catching exit)
106
+ this.exit(exitCode);
107
+ }
108
+ }
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
@@ -0,0 +1,114 @@
1
+ import { Command } from '@oclif/core';
2
+ import { type Ora } from 'ora';
3
+ /**
4
+ * Base command class that all AI Workflow CLI commands should extend.
5
+ * Provides global --debug flag support for verbose logging.
6
+ *
7
+ * @example Basic command with debug support
8
+ * import {debug} from '../lib/debug.js'
9
+ *
10
+ * export default class MyCommand extends BaseCommand {
11
+ * static override flags = {
12
+ * ...BaseCommand.baseFlags,
13
+ * // command-specific flags
14
+ * }
15
+ *
16
+ * async run() {
17
+ * // debug mode is already enabled if --debug flag was passed
18
+ * // version info is automatically logged when debug enabled
19
+ * debug('My debug message')
20
+ * }
21
+ * }
22
+ *
23
+ * @example Command with spinner progress feedback
24
+ * import {ux} from '@oclif/core'
25
+ *
26
+ * export default class LongCommand extends BaseCommand {
27
+ * async run() {
28
+ * // Check if output is piped (suppress spinners for piped output)
29
+ * const isPiped = !process.stdout.isTTY
30
+ *
31
+ * if (!isPiped) {
32
+ * // Show spinner for long operations in interactive terminal
33
+ * ux.action.start('Processing')
34
+ * await longRunningOperation()
35
+ * ux.action.stop()
36
+ * } else {
37
+ * // Piped output - suppress spinner
38
+ * await longRunningOperation()
39
+ * }
40
+ * }
41
+ * }
42
+ *
43
+ * @example Spinner with status updates
44
+ * import {ux} from '@oclif/core'
45
+ *
46
+ * export default class MultiStepCommand extends BaseCommand {
47
+ * async run() {
48
+ * if (process.stdout.isTTY) {
49
+ * ux.action.start('Installing packages')
50
+ * await installPackages()
51
+ *
52
+ * // Update spinner status
53
+ * ux.action.status = 'Configuring'
54
+ * await configure()
55
+ *
56
+ * ux.action.stop('Done!')
57
+ * } else {
58
+ * await installPackages()
59
+ * await configure()
60
+ * }
61
+ * }
62
+ * }
63
+ */
64
+ export default abstract class BaseCommand extends Command {
65
+ /**
66
+ * Global flags inherited by all AI Workflow CLI commands.
67
+ * All command classes should spread these flags into their own flag definitions:
68
+ * `static override flags = { ...BaseCommand.baseFlags, /* command-specific flags *\/ }`
69
+ *
70
+ * @see Command Development Guide in README.md for usage patterns
71
+ */
72
+ static baseFlags: {
73
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
74
+ help: import("@oclif/core/interfaces").BooleanFlag<void>;
75
+ quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
76
+ };
77
+ init(): Promise<void>;
78
+ /**
79
+ * Check if quiet mode is enabled.
80
+ * Returns true if --quiet/-q flag was passed.
81
+ */
82
+ protected isQuiet(): boolean;
83
+ /**
84
+ * Log debug message (stdout, dim in TTY).
85
+ * Debug output is independent of quiet mode.
86
+ */
87
+ protected logDebug(message: string): void;
88
+ /**
89
+ * Log error message (stderr, red in TTY).
90
+ * Errors are NEVER suppressed, even in quiet mode.
91
+ */
92
+ protected logError(message: string): void;
93
+ /**
94
+ * Log informational message (stdout, no color).
95
+ * Suppressed in quiet mode.
96
+ */
97
+ protected logInfo(message: string): void;
98
+ /**
99
+ * Log success message (stdout, green in TTY).
100
+ * Suppressed in quiet mode.
101
+ */
102
+ protected logSuccess(message: string): void;
103
+ /**
104
+ * Log warning message (stdout, yellow in TTY).
105
+ * Suppressed in quiet mode.
106
+ */
107
+ protected logWarning(message: string): void;
108
+ abstract run(): Promise<void>;
109
+ /**
110
+ * Create a TTY-aware spinner for long-running operations.
111
+ * Automatically disabled when output is piped, in CI environments, or in quiet mode.
112
+ */
113
+ protected spinner(text: string): Ora;
114
+ }
@@ -0,0 +1,153 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { debugVersion, setDebugEnabled } from '../lib/debug.js';
3
+ import { logDebug, logError, logInfo, logSuccess, logWarning } from '../lib/output.js';
4
+ import { isQuietMode, setQuietMode } from '../lib/quiet.js';
5
+ import { createSpinner } from '../lib/spinner.js';
6
+ /**
7
+ * Base command class that all AI Workflow CLI commands should extend.
8
+ * Provides global --debug flag support for verbose logging.
9
+ *
10
+ * @example Basic command with debug support
11
+ * import {debug} from '../lib/debug.js'
12
+ *
13
+ * export default class MyCommand extends BaseCommand {
14
+ * static override flags = {
15
+ * ...BaseCommand.baseFlags,
16
+ * // command-specific flags
17
+ * }
18
+ *
19
+ * async run() {
20
+ * // debug mode is already enabled if --debug flag was passed
21
+ * // version info is automatically logged when debug enabled
22
+ * debug('My debug message')
23
+ * }
24
+ * }
25
+ *
26
+ * @example Command with spinner progress feedback
27
+ * import {ux} from '@oclif/core'
28
+ *
29
+ * export default class LongCommand extends BaseCommand {
30
+ * async run() {
31
+ * // Check if output is piped (suppress spinners for piped output)
32
+ * const isPiped = !process.stdout.isTTY
33
+ *
34
+ * if (!isPiped) {
35
+ * // Show spinner for long operations in interactive terminal
36
+ * ux.action.start('Processing')
37
+ * await longRunningOperation()
38
+ * ux.action.stop()
39
+ * } else {
40
+ * // Piped output - suppress spinner
41
+ * await longRunningOperation()
42
+ * }
43
+ * }
44
+ * }
45
+ *
46
+ * @example Spinner with status updates
47
+ * import {ux} from '@oclif/core'
48
+ *
49
+ * export default class MultiStepCommand extends BaseCommand {
50
+ * async run() {
51
+ * if (process.stdout.isTTY) {
52
+ * ux.action.start('Installing packages')
53
+ * await installPackages()
54
+ *
55
+ * // Update spinner status
56
+ * ux.action.status = 'Configuring'
57
+ * await configure()
58
+ *
59
+ * ux.action.stop('Done!')
60
+ * } else {
61
+ * await installPackages()
62
+ * await configure()
63
+ * }
64
+ * }
65
+ * }
66
+ */
67
+ export default class BaseCommand extends Command {
68
+ /**
69
+ * Global flags inherited by all AI Workflow CLI commands.
70
+ * All command classes should spread these flags into their own flag definitions:
71
+ * `static override flags = { ...BaseCommand.baseFlags, /* command-specific flags *\/ }`
72
+ *
73
+ * @see Command Development Guide in README.md for usage patterns
74
+ */
75
+ static baseFlags = {
76
+ debug: Flags.boolean({
77
+ char: 'd',
78
+ description: 'Enable verbose debug logging',
79
+ default: false,
80
+ }),
81
+ help: Flags.help({
82
+ char: 'h',
83
+ description: 'Show help for command',
84
+ }),
85
+ quiet: Flags.boolean({
86
+ char: 'q',
87
+ description: 'Suppress informational output (errors still shown)',
88
+ default: false,
89
+ }),
90
+ };
91
+ async init() {
92
+ await super.init();
93
+ const { flags } = await this.parse(this.constructor);
94
+ const debugEnabled = flags.debug ?? false;
95
+ const quietEnabled = flags.quiet ?? false;
96
+ setDebugEnabled(debugEnabled);
97
+ setQuietMode(quietEnabled);
98
+ // Automatically show version info in debug mode (AC4, FR24)
99
+ if (debugEnabled) {
100
+ debugVersion();
101
+ }
102
+ }
103
+ /**
104
+ * Check if quiet mode is enabled.
105
+ * Returns true if --quiet/-q flag was passed.
106
+ */
107
+ isQuiet() {
108
+ // Access via module-level state (set in init())
109
+ return isQuietMode();
110
+ }
111
+ /**
112
+ * Log debug message (stdout, dim in TTY).
113
+ * Debug output is independent of quiet mode.
114
+ */
115
+ logDebug(message) {
116
+ logDebug(message);
117
+ }
118
+ /**
119
+ * Log error message (stderr, red in TTY).
120
+ * Errors are NEVER suppressed, even in quiet mode.
121
+ */
122
+ logError(message) {
123
+ logError(message);
124
+ }
125
+ /**
126
+ * Log informational message (stdout, no color).
127
+ * Suppressed in quiet mode.
128
+ */
129
+ logInfo(message) {
130
+ logInfo(message, this.isQuiet());
131
+ }
132
+ /**
133
+ * Log success message (stdout, green in TTY).
134
+ * Suppressed in quiet mode.
135
+ */
136
+ logSuccess(message) {
137
+ logSuccess(message, this.isQuiet());
138
+ }
139
+ /**
140
+ * Log warning message (stdout, yellow in TTY).
141
+ * Suppressed in quiet mode.
142
+ */
143
+ logWarning(message) {
144
+ logWarning(message, this.isQuiet());
145
+ }
146
+ /**
147
+ * Create a TTY-aware spinner for long-running operations.
148
+ * Automatically disabled when output is piped, in CI environments, or in quiet mode.
149
+ */
150
+ spinner(text) {
151
+ return createSpinner(text, { quiet: isQuietMode() });
152
+ }
153
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * BMAD installation configuration
3
+ */
4
+ export interface BmadInstallConfig {
5
+ projectName: string;
6
+ targetDir: string;
7
+ username: string;
8
+ }
9
+ /**
10
+ * Generate core module configuration YAML
11
+ */
12
+ export declare function generateCoreConfig(username: string): string;
13
+ /**
14
+ * Generate BMM module configuration YAML
15
+ */
16
+ export declare function generateBmmConfig(projectName: string, username: string): string;
17
+ /**
18
+ * Generate installation manifest YAML
19
+ */
20
+ export declare function generateManifest(): string;
21
+ /**
22
+ * Install BMAD structure in target directory
23
+ */
24
+ export declare function installBmad(config: BmadInstallConfig): Promise<void>;
25
+ /**
26
+ * Generate BMAD configuration files in the target directory.
27
+ * Used as a post-install hook after template installation.
28
+ *
29
+ * @param targetDir - Directory where BMAD was installed
30
+ * @param username - Username for configuration
31
+ * @param projectName - Project name for configuration
32
+ */
33
+ export declare function generateBmadConfigs(targetDir: string, username: string, projectName: string): Promise<void>;
34
+ /**
35
+ * Detect username from git config or environment variables.
36
+ * Priority: git config user.name > USER env > USERNAME env > fallback to "User"
37
+ */
38
+ export declare function detectUsername(): Promise<string>;
@@ -0,0 +1,145 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { promises as fs } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { copyDir } from './template-installer.js';
5
+ import { getTemplatePath } from './template-resolver.js';
6
+ /**
7
+ * BMAD version to install
8
+ */
9
+ const BMAD_VERSION = '6.0.0-alpha.22';
10
+ /**
11
+ * Generate core module configuration YAML
12
+ */
13
+ export function generateCoreConfig(username) {
14
+ const now = new Date().toISOString();
15
+ return `# CORE Module Configuration
16
+ # Generated by AI Workflow CLI
17
+ # Version: ${BMAD_VERSION}
18
+ # Date: ${now}
19
+
20
+ user_name: ${username}
21
+ communication_language: English
22
+ document_output_language: English
23
+ output_folder: "{project-root}/_bmad-output"
24
+ `;
25
+ }
26
+ /**
27
+ * Generate BMM module configuration YAML
28
+ */
29
+ export function generateBmmConfig(projectName, username) {
30
+ const now = new Date().toISOString();
31
+ return `# BMM Module Configuration
32
+ # Generated by AI Workflow CLI
33
+ # Version: ${BMAD_VERSION}
34
+ # Date: ${now}
35
+
36
+ project_name: ${projectName}
37
+ user_skill_level: intermediate
38
+ planning_artifacts: "{project-root}/_bmad-output/planning-artifacts"
39
+ implementation_artifacts: "{project-root}/_bmad-output/implementation-artifacts"
40
+ project_knowledge: "{project-root}/docs"
41
+ tea_use_mcp_enhancements: false
42
+ tea_use_playwright_utils: false
43
+
44
+ # Core Configuration Values
45
+ user_name: ${username}
46
+ communication_language: English
47
+ document_output_language: English
48
+ output_folder: "{project-root}/_bmad-output"
49
+ `;
50
+ }
51
+ /**
52
+ * Generate installation manifest YAML
53
+ */
54
+ export function generateManifest() {
55
+ const now = new Date().toISOString();
56
+ return `installation:
57
+ version: ${BMAD_VERSION}
58
+ installDate: ${now}
59
+ lastUpdated: ${now}
60
+ installedBy: aiwcli
61
+ modules:
62
+ - core
63
+ - bmm
64
+ ides:
65
+ - claude-code
66
+ `;
67
+ }
68
+ /**
69
+ * Install BMAD structure in target directory
70
+ */
71
+ export async function installBmad(config) {
72
+ const { projectName, targetDir, username } = config;
73
+ // Get bundled BMAD template path (parent directory containing _bmad/ and .claude/)
74
+ const templateRootPath = await getTemplatePath('bmad');
75
+ const bmadPath = join(targetDir, '_bmad');
76
+ const claudePath = join(targetDir, '.claude');
77
+ // Create main _bmad directories
78
+ await fs.mkdir(join(bmadPath, '_config'), { recursive: true });
79
+ await fs.mkdir(join(bmadPath, 'core'), { recursive: true });
80
+ await fs.mkdir(join(bmadPath, 'bmm'), { recursive: true });
81
+ // Create output directories
82
+ await fs.mkdir(join(targetDir, '_bmad-output', 'planning-artifacts'), { recursive: true });
83
+ await fs.mkdir(join(targetDir, '_bmad-output', 'implementation-artifacts'), { recursive: true });
84
+ // Copy _bmad/ structure from template
85
+ const templateBmadPath = join(templateRootPath, '_bmad');
86
+ // Copy core module from template
87
+ const templateCorePath = join(templateBmadPath, 'core');
88
+ const targetCorePath = join(bmadPath, 'core');
89
+ await copyDir(templateCorePath, targetCorePath);
90
+ // Copy BMM module from template
91
+ const templateBmmPath = join(templateBmadPath, 'bmm');
92
+ const targetBmmPath = join(bmadPath, 'bmm');
93
+ await copyDir(templateBmmPath, targetBmmPath);
94
+ // Copy _config directory (manifest CSVs, ides, etc.) from template
95
+ const templateConfigPath = join(templateBmadPath, '_config');
96
+ const targetConfigPath = join(bmadPath, '_config');
97
+ await copyDir(templateConfigPath, targetConfigPath);
98
+ // Copy .claude/commands/bmad/ structure from template
99
+ const templateClaudeBmadPath = join(templateRootPath, '.claude', 'commands', 'bmad');
100
+ const targetClaudeBmadPath = join(claudePath, 'commands', 'bmad');
101
+ await copyDir(templateClaudeBmadPath, targetClaudeBmadPath);
102
+ // Generate and write custom configuration files (overwrite template configs)
103
+ await fs.writeFile(join(targetCorePath, 'config.yaml'), generateCoreConfig(username), 'utf8');
104
+ await fs.writeFile(join(targetBmmPath, 'config.yaml'), generateBmmConfig(projectName, username), 'utf8');
105
+ await fs.writeFile(join(targetConfigPath, 'manifest.yaml'), generateManifest(), 'utf8');
106
+ }
107
+ /**
108
+ * Generate BMAD configuration files in the target directory.
109
+ * Used as a post-install hook after template installation.
110
+ *
111
+ * @param targetDir - Directory where BMAD was installed
112
+ * @param username - Username for configuration
113
+ * @param projectName - Project name for configuration
114
+ */
115
+ export async function generateBmadConfigs(targetDir, username, projectName) {
116
+ const bmadPath = join(targetDir, '_bmad');
117
+ const coreConfigPath = join(bmadPath, 'core', 'config.yaml');
118
+ const bmmConfigPath = join(bmadPath, 'bmm', 'config.yaml');
119
+ const manifestPath = join(bmadPath, '_config', 'manifest.yaml');
120
+ await fs.writeFile(coreConfigPath, generateCoreConfig(username), 'utf8');
121
+ await fs.writeFile(bmmConfigPath, generateBmmConfig(projectName, username), 'utf8');
122
+ await fs.writeFile(manifestPath, generateManifest(), 'utf8');
123
+ }
124
+ /**
125
+ * Detect username from git config or environment variables.
126
+ * Priority: git config user.name > USER env > USERNAME env > fallback to "User"
127
+ */
128
+ export async function detectUsername() {
129
+ // Try git config first
130
+ try {
131
+ const gitUser = execSync('git config user.name', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
132
+ const username = gitUser.trim();
133
+ if (username)
134
+ return username;
135
+ }
136
+ catch {
137
+ // Git command failed or not configured, continue to env vars
138
+ }
139
+ // Try environment variables
140
+ const envUser = process.env['USER'] ?? process.env['USERNAME'];
141
+ if (envUser)
142
+ return envUser;
143
+ // Fallback
144
+ return 'User';
145
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * TypeScript interfaces for Claude Code settings.json structure
3
+ * Based on Claude Code documentation and research
4
+ */
5
+ /**
6
+ * Hook command configuration
7
+ */
8
+ export interface HookCommand {
9
+ /** Command to execute */
10
+ command: string;
11
+ /** Optional timeout in seconds */
12
+ timeout?: number;
13
+ /** Type of hook action */
14
+ type: 'command';
15
+ }
16
+ /**
17
+ * Hook matcher configuration
18
+ */
19
+ export interface HookMatcher {
20
+ /** Array of hook commands to execute */
21
+ hooks: HookCommand[];
22
+ /** Tool name pattern to match (regex supported) */
23
+ matcher: string;
24
+ /** Execute only once per session */
25
+ once?: boolean;
26
+ }
27
+ /**
28
+ * Hook event types supported by Claude Code
29
+ */
30
+ export type HookEventType = 'Notification' | 'PermissionRequest' | 'PostToolUse' | 'PreCompact' | 'PreToolUse' | 'SessionEnd' | 'SessionStart' | 'Stop' | 'SubagentStop' | 'UserPromptSubmit';
31
+ /**
32
+ * Hooks configuration
33
+ * Maps event types to arrays of hook matchers
34
+ */
35
+ export type HooksConfig = Partial<Record<HookEventType, HookMatcher[]>>;
36
+ /**
37
+ * Permission patterns for tool access
38
+ */
39
+ export interface Permissions {
40
+ /** Allowed tool patterns */
41
+ allow?: string[];
42
+ /** Denied tool patterns */
43
+ deny?: string[];
44
+ }
45
+ /**
46
+ * Enabled plugins configuration
47
+ */
48
+ export type EnabledPlugins = Record<string, boolean>;
49
+ /**
50
+ * Environment variables configuration
51
+ */
52
+ export type EnvConfig = Record<string, string>;
53
+ /**
54
+ * Method installation tracking metadata
55
+ */
56
+ export interface MethodTracking {
57
+ /** IDEs configured for this method */
58
+ ides?: string[];
59
+ /** ISO timestamp when method was installed */
60
+ installedAt: string;
61
+ }
62
+ /**
63
+ * Methods tracking object
64
+ * Maps method names to their installation metadata
65
+ */
66
+ export type MethodsConfig = Record<string, MethodTracking>;
67
+ /**
68
+ * Complete Claude Code settings.json structure
69
+ */
70
+ export interface ClaudeSettings {
71
+ /** Cleanup period in days */
72
+ cleanupPeriodDays?: number;
73
+ /** Enabled plugins */
74
+ enabledPlugins?: EnabledPlugins;
75
+ /** Environment variables */
76
+ env?: EnvConfig;
77
+ /** Hook configurations */
78
+ hooks?: HooksConfig;
79
+ /** Installed methods tracking */
80
+ methods?: MethodsConfig;
81
+ /** Default model to use */
82
+ model?: string;
83
+ /** Tool permissions */
84
+ permissions?: Permissions;
85
+ /** Spinner tips enabled */
86
+ spinnerTipsEnabled?: boolean;
87
+ }
88
+ /**
89
+ * Settings file types in hierarchy
90
+ */
91
+ export type SettingsFileType = 'local' | 'project' | 'user';
92
+ /**
93
+ * Settings file location
94
+ */
95
+ export interface SettingsLocation {
96
+ /** Whether file exists */
97
+ exists: boolean;
98
+ /** Absolute path to settings file */
99
+ path: string;
100
+ /** Type of settings file */
101
+ type: SettingsFileType;
102
+ }