ultra-dex 1.7.3 → 2.2.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 (119) hide show
  1. package/README.md +160 -127
  2. package/assets/agents/0-orchestration/orchestrator.md +225 -0
  3. package/assets/agents/00-AGENT_INDEX.md +138 -0
  4. package/assets/agents/1-leadership/cto.md +186 -0
  5. package/assets/agents/1-leadership/planner.md +205 -0
  6. package/assets/agents/1-leadership/research.md +285 -0
  7. package/assets/agents/2-development/backend.md +472 -0
  8. package/assets/agents/2-development/database.md +516 -0
  9. package/assets/agents/2-development/frontend.md +144 -0
  10. package/assets/agents/3-security/auth.md +168 -0
  11. package/assets/agents/3-security/security.md +335 -0
  12. package/assets/agents/4-devops/devops.md +587 -0
  13. package/assets/agents/5-quality/debugger.md +188 -0
  14. package/assets/agents/5-quality/documentation.md +167 -0
  15. package/assets/agents/5-quality/reviewer.md +213 -0
  16. package/assets/agents/5-quality/testing.md +280 -0
  17. package/assets/agents/6-specialist/performance.md +323 -0
  18. package/assets/agents/6-specialist/refactoring.md +343 -0
  19. package/assets/agents/AGENT-INSTRUCTIONS.md +315 -0
  20. package/assets/agents/README.md +232 -0
  21. package/assets/cursor-rules/00-ultra-dex-core.mdc +48 -0
  22. package/assets/cursor-rules/01-database.mdc +50 -0
  23. package/assets/cursor-rules/02-api.mdc +81 -0
  24. package/assets/cursor-rules/03-auth.mdc +70 -0
  25. package/assets/cursor-rules/04-frontend.mdc +92 -0
  26. package/assets/cursor-rules/05-payments.mdc +88 -0
  27. package/assets/cursor-rules/06-testing.mdc +104 -0
  28. package/assets/cursor-rules/07-security.mdc +94 -0
  29. package/assets/cursor-rules/08-deployment.mdc +92 -0
  30. package/assets/cursor-rules/09-error-handling.mdc +137 -0
  31. package/assets/cursor-rules/10-performance.mdc +123 -0
  32. package/assets/cursor-rules/11-nextjs-v15.mdc +307 -0
  33. package/assets/cursor-rules/12-multi-tenancy.mdc +282 -0
  34. package/assets/cursor-rules/README.md +78 -0
  35. package/assets/cursor-rules/load.ps1 +108 -0
  36. package/assets/cursor-rules/load.sh +102 -0
  37. package/assets/docs/BUILD-AUTH-30M.md +113 -0
  38. package/assets/docs/CHECKLIST-21-STEP.md +86 -0
  39. package/assets/docs/CODEMAP.md +229 -0
  40. package/assets/docs/CUSTOMIZATION.md +127 -0
  41. package/assets/docs/LAUNCH-POSTS.md +238 -0
  42. package/assets/docs/QUICK-REFERENCE.md +338 -0
  43. package/assets/docs/README.md +21 -0
  44. package/assets/docs/ROADMAP.md +480 -0
  45. package/assets/docs/TROUBLESHOOTING.md +148 -0
  46. package/assets/docs/TUTORIAL.md +182 -0
  47. package/assets/docs/VERIFICATION.md +108 -0
  48. package/assets/docs/VISION-V2.md +187 -0
  49. package/assets/docs/WORKFLOW-DIAGRAMS.md +463 -0
  50. package/assets/docs/index.html +550 -0
  51. package/assets/live-templates/next15-prisma-clerk/.env.example +3 -0
  52. package/assets/live-templates/next15-prisma-clerk/README.md +10 -0
  53. package/assets/live-templates/next15-prisma-clerk/app/layout.tsx +7 -0
  54. package/assets/live-templates/next15-prisma-clerk/app/page.tsx +8 -0
  55. package/assets/live-templates/next15-prisma-clerk/next.config.js +6 -0
  56. package/assets/live-templates/next15-prisma-clerk/package.json +22 -0
  57. package/assets/live-templates/next15-prisma-clerk/prisma/schema.prisma +34 -0
  58. package/assets/live-templates/remix-supabase/.env.example +2 -0
  59. package/assets/live-templates/remix-supabase/README.md +9 -0
  60. package/assets/live-templates/remix-supabase/app/root.tsx +19 -0
  61. package/assets/live-templates/remix-supabase/app/routes/_index.tsx +8 -0
  62. package/assets/live-templates/remix-supabase/app/utils/supabase.server.ts +6 -0
  63. package/assets/live-templates/remix-supabase/package.json +20 -0
  64. package/assets/live-templates/remix-supabase/remix.config.js +6 -0
  65. package/assets/live-templates/sveltekit-drizzle/.env.example +1 -0
  66. package/assets/live-templates/sveltekit-drizzle/README.md +9 -0
  67. package/assets/live-templates/sveltekit-drizzle/drizzle/schema.ts +7 -0
  68. package/assets/live-templates/sveltekit-drizzle/drizzle.config.ts +5 -0
  69. package/assets/live-templates/sveltekit-drizzle/package.json +21 -0
  70. package/assets/live-templates/sveltekit-drizzle/src/lib/db.ts +5 -0
  71. package/assets/live-templates/sveltekit-drizzle/src/routes/+page.svelte +2 -0
  72. package/assets/live-templates/sveltekit-drizzle/svelte.config.js +5 -0
  73. package/assets/live-templates/sveltekit-drizzle/vite.config.js +5 -0
  74. package/assets/saas-plan/04-Imp-Template.md +5546 -0
  75. package/assets/templates/CASE-STUDY-TEMPLATE.md +139 -0
  76. package/assets/templates/MASTER-PLAN-TEMPLATE.md +647 -0
  77. package/assets/templates/ORDER-TRACKER-TEMPLATE.md +731 -0
  78. package/assets/templates/PHASE-TRACKER-TEMPLATE.md +577 -0
  79. package/assets/templates/README.md +419 -0
  80. package/bin/ultra-dex.js +1078 -422
  81. package/lib/commands/agents.js +154 -0
  82. package/lib/commands/audit.js +135 -0
  83. package/lib/commands/banner.js +21 -0
  84. package/lib/commands/build.js +214 -0
  85. package/lib/commands/examples.js +34 -0
  86. package/lib/commands/fetch.js +186 -0
  87. package/lib/commands/generate.js +217 -0
  88. package/lib/commands/hooks.js +105 -0
  89. package/lib/commands/init.js +337 -0
  90. package/lib/commands/placeholders.js +11 -0
  91. package/lib/commands/review.js +287 -0
  92. package/lib/commands/serve.js +56 -0
  93. package/lib/commands/suggest.js +126 -0
  94. package/lib/commands/validate.js +140 -0
  95. package/lib/commands/workflows.js +185 -0
  96. package/lib/config/paths.js +9 -0
  97. package/lib/config/urls.js +16 -0
  98. package/lib/providers/base.js +82 -0
  99. package/lib/providers/claude.js +177 -0
  100. package/lib/providers/gemini.js +170 -0
  101. package/lib/providers/index.js +93 -0
  102. package/lib/providers/openai.js +163 -0
  103. package/lib/templates/context.js +26 -0
  104. package/lib/templates/embedded.js +141 -0
  105. package/lib/templates/prompts/generate-plan.js +147 -0
  106. package/lib/templates/prompts/review-code.js +57 -0
  107. package/lib/templates/prompts/section-prompts.js +275 -0
  108. package/lib/templates/prompts/system-prompt.md +58 -0
  109. package/lib/templates/quick-start.js +43 -0
  110. package/lib/utils/build-helpers.js +257 -0
  111. package/lib/utils/fallback.js +36 -0
  112. package/lib/utils/files.js +67 -0
  113. package/lib/utils/network.js +18 -0
  114. package/lib/utils/output.js +20 -0
  115. package/lib/utils/parser.js +155 -0
  116. package/lib/utils/prompt-builder.js +93 -0
  117. package/lib/utils/review-helpers.js +334 -0
  118. package/lib/utils/validation.js +34 -0
  119. package/package.json +19 -5
@@ -0,0 +1,186 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+ import { GITHUB_RAW_BASE } from '../config/urls.js';
6
+ import { fetchWithRetry } from '../utils/network.js';
7
+ import { validateSafePath } from '../utils/validation.js';
8
+
9
+ async function downloadFile(url, destPath) {
10
+ try {
11
+ const response = await fetchWithRetry(url);
12
+ const content = await response.text();
13
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
14
+ await fs.writeFile(destPath, content);
15
+ return true;
16
+ } catch (err) {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ export function registerFetchCommand(program) {
22
+ program
23
+ .command('fetch')
24
+ .description('Download all Ultra-Dex assets for offline use')
25
+ .option('-d, --dir <directory>', 'Target directory', '.ultra-dex')
26
+ .option('--agents', 'Fetch only agent prompts')
27
+ .option('--rules', 'Fetch only cursor rules')
28
+ .option('--docs', 'Fetch only documentation')
29
+ .action(async (options) => {
30
+ console.log(chalk.cyan('\nšŸ“¦ Ultra-Dex Asset Fetcher\n'));
31
+
32
+ const dirValidation = validateSafePath(options.dir, 'Target directory');
33
+ if (dirValidation !== true) {
34
+ console.log(chalk.red(dirValidation));
35
+ process.exit(1);
36
+ }
37
+
38
+ const targetDir = path.resolve(options.dir);
39
+ const fetchAll = !options.agents && !options.rules && !options.docs;
40
+
41
+ const spinner = ora('Preparing to fetch assets...').start();
42
+
43
+ await fs.mkdir(targetDir, { recursive: true });
44
+
45
+ let downloaded = 0;
46
+ let failed = 0;
47
+
48
+ if (fetchAll || options.rules) {
49
+ spinner.text = 'Fetching cursor rules...';
50
+ const rulesDir = path.join(targetDir, 'cursor-rules');
51
+ await fs.mkdir(rulesDir, { recursive: true });
52
+
53
+ const ruleFiles = [
54
+ '00-ultra-dex-core.mdc',
55
+ '01-database.mdc',
56
+ '02-api.mdc',
57
+ '03-auth.mdc',
58
+ '04-frontend.mdc',
59
+ '05-payments.mdc',
60
+ '06-testing.mdc',
61
+ '07-security.mdc',
62
+ '08-deployment.mdc',
63
+ '09-error-handling.mdc',
64
+ '10-performance.mdc',
65
+ '11-nextjs-v15.mdc',
66
+ '12-multi-tenancy.mdc',
67
+ ];
68
+
69
+ for (const file of ruleFiles) {
70
+ const url = `${GITHUB_RAW_BASE}/cursor-rules/${file}`;
71
+ const dest = path.join(rulesDir, file);
72
+ if (await downloadFile(url, dest)) {
73
+ downloaded++;
74
+ } else {
75
+ failed++;
76
+ }
77
+ }
78
+
79
+ await downloadFile(`${GITHUB_RAW_BASE}/cursor-rules/load.sh`, path.join(rulesDir, 'load.sh'));
80
+ try {
81
+ await fs.chmod(path.join(rulesDir, 'load.sh'), '755');
82
+ } catch {}
83
+ }
84
+
85
+ if (fetchAll || options.agents) {
86
+ spinner.text = 'Fetching agent prompts...';
87
+ const agentsDir = path.join(targetDir, 'agents');
88
+
89
+ const agentPaths = [
90
+ '00-AGENT_INDEX.md',
91
+ 'README.md',
92
+ 'AGENT-INSTRUCTIONS.md',
93
+ '1-leadership/cto.md',
94
+ '1-leadership/planner.md',
95
+ '1-leadership/research.md',
96
+ '2-development/backend.md',
97
+ '2-development/frontend.md',
98
+ '2-development/database.md',
99
+ '3-security/security.md',
100
+ '4-devops/devops.md',
101
+ '5-quality/reviewer.md',
102
+ '5-quality/testing.md',
103
+ '5-quality/debugger.md',
104
+ '6-specialist/performance.md',
105
+ '6-specialist/refactoring.md',
106
+ '6-specialist/documentation.md',
107
+ ];
108
+
109
+ for (const agentPath of agentPaths) {
110
+ const url = `${GITHUB_RAW_BASE}/agents/${agentPath}`;
111
+ const dest = path.join(agentsDir, agentPath);
112
+ if (await downloadFile(url, dest)) {
113
+ downloaded++;
114
+ } else {
115
+ failed++;
116
+ }
117
+ }
118
+ }
119
+
120
+ if (fetchAll || options.docs) {
121
+ spinner.text = 'Fetching documentation...';
122
+ const docsDir = path.join(targetDir, 'docs');
123
+
124
+ const docFiles = [
125
+ 'VERIFICATION.md',
126
+ 'BUILD-AUTH-30M.md',
127
+ 'QUICK-REFERENCE.md',
128
+ 'TROUBLESHOOTING.md',
129
+ ];
130
+
131
+ for (const file of docFiles) {
132
+ const url = `${GITHUB_RAW_BASE}/docs/${file}`;
133
+ const dest = path.join(docsDir, file);
134
+ if (await downloadFile(url, dest)) {
135
+ downloaded++;
136
+ } else {
137
+ failed++;
138
+ }
139
+ }
140
+
141
+ const guidesDir = path.join(targetDir, 'guides');
142
+ const guideFiles = [
143
+ 'PROJECT-ORCHESTRATION.md',
144
+ 'ADVANCED-WORKFLOWS.md',
145
+ 'DATABASE-DECISION-FRAMEWORK.md',
146
+ 'ARCHITECTURE-PATTERNS.md',
147
+ ];
148
+
149
+ for (const file of guideFiles) {
150
+ const url = `${GITHUB_RAW_BASE}/guides/${file}`;
151
+ const dest = path.join(guidesDir, file);
152
+ if (await downloadFile(url, dest)) {
153
+ downloaded++;
154
+ } else {
155
+ failed++;
156
+ }
157
+ }
158
+ }
159
+
160
+ if (failed === 0) {
161
+ spinner.succeed(chalk.green(`Downloaded ${downloaded} files to ${targetDir}`));
162
+ } else {
163
+ spinner.warn(chalk.yellow(`Downloaded ${downloaded} files, ${failed} failed`));
164
+ }
165
+
166
+ console.log(chalk.bold('\nšŸ“ Assets downloaded to:\n'));
167
+ if (fetchAll || options.rules) {
168
+ console.log(chalk.gray(` ${targetDir}/cursor-rules/ (12 .mdc files)`));
169
+ }
170
+ if (fetchAll || options.agents) {
171
+ console.log(chalk.gray(` ${targetDir}/agents/ (16 agent prompts)`));
172
+ }
173
+ if (fetchAll || options.docs) {
174
+ console.log(chalk.gray(` ${targetDir}/docs/ (documentation)`));
175
+ console.log(chalk.gray(` ${targetDir}/guides/ (guides)`));
176
+ }
177
+
178
+ console.log(chalk.bold('\nšŸ’” Usage:\n'));
179
+ console.log(chalk.cyan(' # Copy cursor rules to project'));
180
+ console.log(chalk.gray(` cp -r ${targetDir}/cursor-rules .cursor/rules`));
181
+ console.log(chalk.cyan('\n # Copy agents to project'));
182
+ console.log(chalk.gray(` cp -r ${targetDir}/agents .agents`));
183
+ console.log(chalk.cyan('\n # Works offline now!'));
184
+ console.log(chalk.gray(' No GitHub access needed after fetch.\n'));
185
+ });
186
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * ultra-dex generate command
3
+ * Generates a full 34-section implementation plan from an idea using AI
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import ora from 'ora';
8
+ import inquirer from 'inquirer';
9
+ import fs from 'fs/promises';
10
+ import path from 'path';
11
+ import { createProvider, getDefaultProvider, checkConfiguredProviders } from '../providers/index.js';
12
+ import { SYSTEM_PROMPT, generateUserPrompt } from '../templates/prompts/generate-plan.js';
13
+
14
+ export function registerGenerateCommand(program) {
15
+ program
16
+ .command('generate [idea]')
17
+ .description('Generate a full implementation plan from an idea using AI')
18
+ .option('-p, --provider <provider>', 'AI provider (claude, openai, gemini)')
19
+ .option('-m, --model <model>', 'Specific model to use')
20
+ .option('-o, --output <directory>', 'Output directory', '.')
21
+ .option('-k, --key <apiKey>', 'API key (or use environment variable)')
22
+ .option('--stream', 'Stream output in real-time', true)
23
+ .option('--no-stream', 'Disable streaming')
24
+ .action(async (idea, options) => {
25
+ console.log(chalk.cyan('\nšŸš€ Ultra-Dex Plan Generator\n'));
26
+
27
+ // Check configured providers
28
+ const configured = checkConfiguredProviders();
29
+ const hasProvider = configured.some(p => p.configured) || options.key;
30
+
31
+ if (!hasProvider) {
32
+ console.log(chalk.yellow('āš ļø No AI provider configured.\n'));
33
+ console.log(chalk.white('Set one of these environment variables:'));
34
+ configured.forEach(p => {
35
+ console.log(chalk.gray(` export ${p.envKey}=your-key-here`));
36
+ });
37
+ console.log(chalk.white('\nOr use --key option:'));
38
+ console.log(chalk.gray(' npx ultra-dex generate "your idea" --key sk-...\n'));
39
+ return;
40
+ }
41
+
42
+ // Get idea if not provided
43
+ if (!idea) {
44
+ const answers = await inquirer.prompt([
45
+ {
46
+ type: 'input',
47
+ name: 'idea',
48
+ message: 'Describe your SaaS idea:',
49
+ validate: input => input.trim().length > 10 || 'Please provide a more detailed description',
50
+ },
51
+ ]);
52
+ idea = answers.idea;
53
+ }
54
+
55
+ // Select provider
56
+ const providerId = options.provider || getDefaultProvider();
57
+ if (!providerId) {
58
+ console.log(chalk.red('No provider available. Set an API key.'));
59
+ return;
60
+ }
61
+
62
+ console.log(chalk.gray(`Using provider: ${providerId}`));
63
+ console.log(chalk.gray(`Idea: "${idea}"\n`));
64
+
65
+ // Create provider instance
66
+ let provider;
67
+ try {
68
+ provider = createProvider(providerId, {
69
+ apiKey: options.key,
70
+ model: options.model,
71
+ maxTokens: 16000, // Large output for full plan
72
+ });
73
+ } catch (err) {
74
+ console.log(chalk.red(`Error: ${err.message}`));
75
+ return;
76
+ }
77
+
78
+ // Generate the plan
79
+ const spinner = ora('Generating your implementation plan...').start();
80
+ const startTime = Date.now();
81
+
82
+ try {
83
+ let result;
84
+ let planContent = '';
85
+
86
+ if (options.stream) {
87
+ spinner.stop();
88
+ console.log(chalk.cyan('šŸ“ Generating plan:\n'));
89
+ console.log(chalk.gray('─'.repeat(60)));
90
+
91
+ result = await provider.generateStream(
92
+ SYSTEM_PROMPT,
93
+ generateUserPrompt(idea),
94
+ (chunk) => {
95
+ process.stdout.write(chunk);
96
+ planContent += chunk;
97
+ }
98
+ );
99
+
100
+ console.log(chalk.gray('\n' + '─'.repeat(60)));
101
+ } else {
102
+ result = await provider.generate(SYSTEM_PROMPT, generateUserPrompt(idea));
103
+ planContent = result.content;
104
+ spinner.succeed('Plan generated!');
105
+ }
106
+
107
+ // Calculate stats
108
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
109
+ const cost = provider.estimateCost(result.usage.inputTokens, result.usage.outputTokens);
110
+
111
+ // Save the plan
112
+ const outputDir = path.resolve(options.output);
113
+ await fs.mkdir(outputDir, { recursive: true });
114
+
115
+ const planPath = path.join(outputDir, 'IMPLEMENTATION-PLAN.md');
116
+ const contextPath = path.join(outputDir, 'CONTEXT.md');
117
+ const quickStartPath = path.join(outputDir, 'QUICK-START.md');
118
+
119
+ // Add header to plan
120
+ const header = `# Implementation Plan
121
+
122
+ > Generated by Ultra-Dex on ${new Date().toISOString().split('T')[0]}
123
+ > Idea: "${idea}"
124
+
125
+ ---
126
+
127
+ `;
128
+ await fs.writeFile(planPath, header + planContent);
129
+
130
+ // Generate CONTEXT.md
131
+ const contextContent = `# Project Context
132
+
133
+ ## Overview
134
+ ${idea}
135
+
136
+ ## Generated
137
+ - Date: ${new Date().toISOString().split('T')[0]}
138
+ - Provider: ${provider.getName()}
139
+ - Model: ${provider.model}
140
+
141
+ ## Files
142
+ - IMPLEMENTATION-PLAN.md - Full 34-section plan
143
+ - QUICK-START.md - Quick reference
144
+ - CONTEXT.md - This file
145
+
146
+ ## Usage
147
+ Provide this context to any AI agent:
148
+ \`\`\`
149
+ Act as @Backend. Read CONTEXT.md and IMPLEMENTATION-PLAN.md first.
150
+ Task: [your task]
151
+ \`\`\`
152
+ `;
153
+ await fs.writeFile(contextPath, contextContent);
154
+
155
+ // Generate QUICK-START.md
156
+ const quickStartContent = `# Quick Start
157
+
158
+ ## Your Idea
159
+ ${idea}
160
+
161
+ ## Next Steps
162
+
163
+ 1. **Review the plan**: Open IMPLEMENTATION-PLAN.md
164
+ 2. **Load into AI**: Copy CONTEXT.md to your AI tool
165
+ 3. **Start building**: Use \`npx ultra-dex build\` or paste prompts
166
+
167
+ ## Useful Commands
168
+
169
+ \`\`\`bash
170
+ npx ultra-dex build # Start AI-assisted build
171
+ npx ultra-dex review # Check code against plan
172
+ npx ultra-dex serve # Serve context via HTTP
173
+ npx ultra-dex agents # List available agents
174
+ \`\`\`
175
+
176
+ ## Agent Quick Start
177
+
178
+ \`\`\`
179
+ @Planner - Break down tasks
180
+ @Backend - API endpoints
181
+ @Frontend - UI components
182
+ @Database - Schema design
183
+ @Auth - Authentication
184
+ @Testing - Write tests
185
+ \`\`\`
186
+ `;
187
+ await fs.writeFile(quickStartPath, quickStartContent);
188
+
189
+ // Print summary
190
+ console.log(chalk.green('\nāœ… Plan generated successfully!\n'));
191
+ console.log(chalk.white('Files created:'));
192
+ console.log(chalk.gray(` šŸ“„ ${planPath}`));
193
+ console.log(chalk.gray(` šŸ“„ ${contextPath}`));
194
+ console.log(chalk.gray(` šŸ“„ ${quickStartPath}`));
195
+
196
+ console.log(chalk.white('\nStats:'));
197
+ console.log(chalk.gray(` ā±ļø Time: ${elapsed}s`));
198
+ console.log(chalk.gray(` šŸ“Š Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out`));
199
+ console.log(chalk.gray(` šŸ’° Cost: ~$${cost.total.toFixed(4)}`));
200
+
201
+ console.log(chalk.cyan('\nšŸ“‹ Next steps:'));
202
+ console.log(chalk.white(' 1. Review IMPLEMENTATION-PLAN.md'));
203
+ console.log(chalk.white(' 2. Run: npx ultra-dex build'));
204
+ console.log(chalk.white(' 3. Start coding with AI agents\n'));
205
+
206
+ } catch (err) {
207
+ spinner.fail('Generation failed');
208
+ console.log(chalk.red(`\nError: ${err.message}`));
209
+
210
+ if (err.message.includes('API')) {
211
+ console.log(chalk.yellow('\nTip: Check your API key and try again.'));
212
+ }
213
+ }
214
+ });
215
+ }
216
+
217
+ export default { registerGenerateCommand };
@@ -0,0 +1,105 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+
5
+ export function registerHooksCommand(program) {
6
+ program
7
+ .command('hooks')
8
+ .description('Set up git hooks for automated verification')
9
+ .option('--remove', 'Remove Ultra-Dex git hooks')
10
+ .action(async (options) => {
11
+ console.log(chalk.cyan('\nšŸŖ Ultra-Dex Git Hooks Setup\n'));
12
+
13
+ const gitDir = path.join(process.cwd(), '.git');
14
+ const hooksDir = path.join(gitDir, 'hooks');
15
+
16
+ try {
17
+ await fs.access(gitDir);
18
+ } catch {
19
+ console.log(chalk.red('āŒ Not a git repository. Run "git init" first.\n'));
20
+ process.exit(1);
21
+ }
22
+
23
+ await fs.mkdir(hooksDir, { recursive: true });
24
+
25
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
26
+
27
+ if (options.remove) {
28
+ try {
29
+ const content = await fs.readFile(preCommitPath, 'utf-8');
30
+ if (content.includes('ultra-dex')) {
31
+ await fs.unlink(preCommitPath);
32
+ console.log(chalk.green('āœ… Ultra-Dex pre-commit hook removed.\n'));
33
+ } else {
34
+ console.log(chalk.yellow('āš ļø Pre-commit hook exists but is not from Ultra-Dex.\n'));
35
+ }
36
+ } catch {
37
+ console.log(chalk.gray('No Ultra-Dex hooks found.\n'));
38
+ }
39
+ return;
40
+ }
41
+
42
+ const preCommitScript = `#!/bin/sh
43
+ # Ultra-Dex Pre-Commit Hook
44
+ # Validates project structure before allowing commits
45
+ # Remove with: npx ultra-dex hooks --remove
46
+
47
+ echo "šŸ” Ultra-Dex: Validating project structure..."
48
+
49
+ # Run validation
50
+ npx ultra-dex validate --dir . > /tmp/ultra-dex-validate.log 2>&1
51
+ RESULT=$?
52
+
53
+ if [ $RESULT -ne 0 ]; then
54
+ echo ""
55
+ echo "āŒ Ultra-Dex validation failed. Commit blocked."
56
+ echo ""
57
+ echo "Run 'npx ultra-dex validate' to see details."
58
+ echo "Fix issues or bypass with: git commit --no-verify"
59
+ echo ""
60
+ exit 1
61
+ fi
62
+
63
+ # Check for required files
64
+ if [ ! -f "QUICK-START.md" ]; then
65
+ echo "āš ļø Warning: QUICK-START.md not found"
66
+ fi
67
+
68
+ if [ ! -f "IMPLEMENTATION-PLAN.md" ]; then
69
+ echo "āš ļø Warning: IMPLEMENTATION-PLAN.md not found"
70
+ fi
71
+
72
+ echo "āœ… Ultra-Dex validation passed."
73
+ exit 0
74
+ `;
75
+
76
+ try {
77
+ const existing = await fs.readFile(preCommitPath, 'utf-8');
78
+ if (existing.includes('ultra-dex')) {
79
+ console.log(chalk.yellow('āš ļø Ultra-Dex pre-commit hook already exists.\n'));
80
+ console.log(chalk.gray(' Use --remove to remove it first.\n'));
81
+ return;
82
+ } else {
83
+ const combined = existing + '\n\n' + preCommitScript;
84
+ await fs.writeFile(preCommitPath, combined);
85
+ await fs.chmod(preCommitPath, '755');
86
+ console.log(chalk.green('āœ… Ultra-Dex hook appended to existing pre-commit.\n'));
87
+ }
88
+ } catch {
89
+ await fs.writeFile(preCommitPath, preCommitScript);
90
+ await fs.chmod(preCommitPath, '755');
91
+ console.log(chalk.green('āœ… Pre-commit hook installed.\n'));
92
+ }
93
+
94
+ console.log(chalk.bold('What this does:\n'));
95
+ console.log(chalk.gray(' • Runs "ultra-dex validate" before each commit'));
96
+ console.log(chalk.gray(' • Blocks commits if required files are missing'));
97
+ console.log(chalk.gray(' • Warns about incomplete sections\n'));
98
+
99
+ console.log(chalk.bold('To bypass (not recommended):\n'));
100
+ console.log(chalk.cyan(' git commit --no-verify\n'));
101
+
102
+ console.log(chalk.bold('To remove:\n'));
103
+ console.log(chalk.cyan(' npx ultra-dex hooks --remove\n'));
104
+ });
105
+ }