dhurandhar 2.0.2 → 2.1.1

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,61 @@ All notable changes to Dhurandhar will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.1] - 2026-04-02
9
+
10
+ ### Fixed
11
+ - Better error handling in setup wizard (catches TTY issues with npx)
12
+ - Added try-catch for performance settings prompts
13
+ - Added helpful instructions: "Press Enter to confirm selections"
14
+ - Setup uses defaults if prompts fail
15
+
16
+ ### Added
17
+ - SETUP_TROUBLESHOOTING.md - Comprehensive troubleshooting guide
18
+ - Better user guidance in setup wizard
19
+
20
+ ### Note for npx users
21
+ If setup hangs on last question, **press Enter** to confirm selection!
22
+ Or install globally for better experience:
23
+ ```bash
24
+ npm install -g dhurandhar
25
+ dhurandhar setup
26
+ ```
27
+
28
+ ---
29
+
30
+ ## [2.1.0] - 2026-04-02
31
+
32
+ ### Added - Setup Wizard! šŸŽ‰
33
+ - **`dhurandhar setup`** - Interactive first-time setup wizard
34
+ - Verifies/selects installation directory
35
+ - Configures AI coding assistant integration:
36
+ - Augment Code (auggie)
37
+ - Cursor
38
+ - Claude Code
39
+ - GitHub Copilot
40
+ - Codeium
41
+ - Tabnine
42
+ - Google Gemini Code
43
+ - OpenAI Codex
44
+ - Configures enterprise integrations (GitHub, Jira, Confluence)
45
+ - Selects AI provider for design suggestions
46
+ - Configures performance settings (cache, progress indicators)
47
+ - Saves configuration to `~/.dhurandhar/config.json`
48
+
49
+ ### Changed
50
+ - `dhurandhar init` now checks if setup is complete
51
+ - If setup not complete, prompts user to run setup first
52
+ - Better command suggestions: "install" now suggests "setup"
53
+ - Configuration persisted across all projects
54
+
55
+ ### Improved
56
+ - Much better first-time user experience
57
+ - Like BMAD's installation process
58
+ - Clear configuration summary after setup
59
+ - Guided workflow: setup → init → design
60
+
61
+ ---
62
+
8
63
  ## [2.0.2] - 2026-04-02
9
64
 
10
65
  ### Fixed
@@ -8,10 +8,34 @@ import * as clack from '@clack/prompts';
8
8
  import chalk from 'chalk';
9
9
  import { writeFileSync, mkdirSync, existsSync } from 'fs';
10
10
  import { join } from 'path';
11
+ import { isSetupComplete, loadConfig } from '../../core/config/config-loader.js';
11
12
 
12
13
  export default async function initCommand(options) {
13
14
  console.log(chalk.cyan.bold('šŸš€ Initialize Dhurandhar Project\n'));
14
15
 
16
+ // Check if setup is complete
17
+ if (!isSetupComplete()) {
18
+ clack.log.warn('Dhurandhar setup not completed yet.');
19
+ console.log(chalk.yellow('\nšŸ’” Run setup first:'));
20
+ console.log(chalk.cyan(' dhurandhar setup\n'));
21
+
22
+ const runSetup = await clack.confirm({
23
+ message: 'Run setup now?',
24
+ initialValue: true,
25
+ });
26
+
27
+ if (clack.isCancel(runSetup) || !runSetup) {
28
+ clack.cancel('Initialization cancelled');
29
+ return;
30
+ }
31
+
32
+ // Run setup
33
+ const { default: setupCommand } = await import('./setup.js');
34
+ await setupCommand({});
35
+
36
+ console.log(chalk.cyan('\nšŸš€ Continuing with project initialization...\n'));
37
+ }
38
+
15
39
  // Check if already initialized
16
40
  if (existsSync('.dhurandhar')) {
17
41
  clack.log.error('Dhurandhar project already initialized in this directory.');
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Dhurandhar Setup Wizard
3
+ *
4
+ * Interactive installation process:
5
+ * - Verify installation directory
6
+ * - Configure AI coding assistant integration
7
+ * - Setup enterprise integrations
8
+ * - Configure preferences
9
+ */
10
+
11
+ import * as clack from '@clack/prompts';
12
+ import chalk from 'chalk';
13
+ import { existsSync, writeFileSync, mkdirSync } from 'fs';
14
+ import { homedir } from 'os';
15
+ import { join } from 'path';
16
+
17
+ export default async function setupCommand(options) {
18
+ try {
19
+ console.clear();
20
+
21
+ clack.intro(chalk.cyan.bold('šŸ•‰ļø DHURANDHAR SETUP WIZARD'));
22
+
23
+ console.log(chalk.gray('Welcome! Let\'s configure Dhurandhar for your environment.\n'));
24
+ console.log(chalk.gray('(Press Enter to confirm selections, Ctrl+C to cancel)\n'));
25
+
26
+ const config = {};
27
+
28
+ // Step 1: Installation Directory
29
+ await selectInstallationDirectory(config);
30
+
31
+ // Step 2: AI Coding Assistant
32
+ await selectAICodingAssistant(config);
33
+
34
+ // Step 3: Enterprise Integrations
35
+ await setupEnterpriseIntegrations(config);
36
+
37
+ // Step 4: AI Provider
38
+ await selectAIProvider(config);
39
+
40
+ // Step 5: Performance Settings
41
+ await configurePerformance(config);
42
+
43
+ // Step 6: Save Configuration
44
+ await saveConfiguration(config);
45
+
46
+ clack.outro(chalk.green.bold('āœ… Setup Complete!'));
47
+
48
+ console.log(chalk.cyan('\nšŸ“š Next Steps:'));
49
+ console.log(chalk.gray(' 1. cd to your project directory'));
50
+ console.log(chalk.gray(' 2. Run: dhurandhar init'));
51
+ console.log(chalk.gray(' 3. Start designing: dhurandhar yudhishthira\n'));
52
+ } catch (error) {
53
+ console.error(chalk.red('\nāŒ Setup failed:'), error.message);
54
+ console.log(chalk.yellow('\nšŸ’” Tip: Try running setup again with a stable terminal'));
55
+ console.log(chalk.gray(' dhurandhar setup\n'));
56
+ process.exit(1);
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Step 1: Select installation directory
62
+ */
63
+ async function selectInstallationDirectory(config) {
64
+ const s = clack.spinner();
65
+ s.start('Detecting current directory...');
66
+
67
+ const cwd = process.cwd();
68
+ const home = homedir();
69
+
70
+ s.stop('Current directory detected');
71
+
72
+ const dirChoice = await clack.select({
73
+ message: 'Where should Dhurandhar projects be created?',
74
+ options: [
75
+ { value: 'current', label: `Current directory: ${cwd}` },
76
+ { value: 'home', label: `Home directory: ${home}/dhurandhar-projects` },
77
+ { value: 'custom', label: 'Custom directory (I\'ll specify)' },
78
+ ],
79
+ });
80
+
81
+ if (clack.isCancel(dirChoice)) {
82
+ clack.cancel('Setup cancelled');
83
+ process.exit(0);
84
+ }
85
+
86
+ if (dirChoice === 'current') {
87
+ config.projectsDirectory = cwd;
88
+ } else if (dirChoice === 'home') {
89
+ config.projectsDirectory = join(home, 'dhurandhar-projects');
90
+ } else {
91
+ const customDir = await clack.text({
92
+ message: 'Enter custom directory path:',
93
+ placeholder: '/path/to/projects',
94
+ validate: (value) => {
95
+ if (!value) return 'Directory path is required';
96
+ },
97
+ });
98
+
99
+ if (clack.isCancel(customDir)) {
100
+ clack.cancel('Setup cancelled');
101
+ process.exit(0);
102
+ }
103
+
104
+ config.projectsDirectory = customDir;
105
+ }
106
+
107
+ // Create directory if it doesn't exist
108
+ if (!existsSync(config.projectsDirectory)) {
109
+ mkdirSync(config.projectsDirectory, { recursive: true });
110
+ clack.log.success(`Created directory: ${config.projectsDirectory}`);
111
+ } else {
112
+ clack.log.info(`Using existing directory: ${config.projectsDirectory}`);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Step 2: Select AI coding assistant
118
+ */
119
+ async function selectAICodingAssistant(config) {
120
+ const assistant = await clack.select({
121
+ message: 'Which AI coding assistant do you use?',
122
+ options: [
123
+ { value: 'augment', label: 'šŸ¤– Augment Code (auggie)' },
124
+ { value: 'cursor', label: '⚔ Cursor' },
125
+ { value: 'claude', label: '🧠 Claude Code (Code Claude)' },
126
+ { value: 'copilot', label: 'šŸ™ GitHub Copilot' },
127
+ { value: 'codeium', label: 'šŸ’« Codeium' },
128
+ { value: 'tabnine', label: 'šŸ”® Tabnine' },
129
+ { value: 'gemini', label: 'šŸ’Ž Google Gemini Code' },
130
+ { value: 'codex', label: '🌟 OpenAI Codex' },
131
+ { value: 'none', label: 'āŒ None / I\'ll configure later' },
132
+ ],
133
+ });
134
+
135
+ if (clack.isCancel(assistant)) {
136
+ clack.cancel('Setup cancelled');
137
+ process.exit(0);
138
+ }
139
+
140
+ config.aiCodingAssistant = assistant;
141
+
142
+ if (assistant !== 'none') {
143
+ clack.log.success(`Selected: ${assistant}`);
144
+
145
+ const integrate = await clack.confirm({
146
+ message: `Enable deep integration with ${assistant}?`,
147
+ initialValue: true,
148
+ });
149
+
150
+ if (!clack.isCancel(integrate)) {
151
+ config.deepIntegration = integrate;
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Step 3: Setup enterprise integrations
158
+ */
159
+ async function setupEnterpriseIntegrations(config) {
160
+ const integrations = await clack.multiselect({
161
+ message: 'Which integrations would you like to enable?',
162
+ options: [
163
+ { value: 'github', label: 'šŸ™ GitHub (Issues, PRs, Repository)' },
164
+ { value: 'jira', label: 'šŸ“‹ Jira (Epics, Stories, Tasks)' },
165
+ { value: 'confluence', label: 'šŸ“š Confluence (Documentation)' },
166
+ ],
167
+ required: false,
168
+ });
169
+
170
+ if (clack.isCancel(integrations)) {
171
+ config.integrations = [];
172
+ } else {
173
+ config.integrations = integrations;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Step 4: Select AI provider
179
+ */
180
+ async function selectAIProvider(config) {
181
+ const provider = await clack.select({
182
+ message: 'Which AI provider for design suggestions?',
183
+ options: [
184
+ { value: 'mock', label: 'šŸŽ­ Mock (No API key needed, for testing)' },
185
+ { value: 'openai', label: 'šŸ¤– OpenAI (GPT-4)' },
186
+ { value: 'anthropic', label: '🧠 Anthropic (Claude)' },
187
+ ],
188
+ });
189
+
190
+ if (clack.isCancel(provider)) {
191
+ provider = 'mock';
192
+ }
193
+
194
+ config.aiProvider = provider;
195
+ }
196
+
197
+ /**
198
+ * Step 5: Configure performance settings
199
+ */
200
+ async function configurePerformance(config) {
201
+ try {
202
+ const enableCache = await clack.confirm({
203
+ message: 'Enable caching for faster performance?',
204
+ initialValue: true,
205
+ });
206
+
207
+ if (clack.isCancel(enableCache)) {
208
+ config.enableCache = true; // Default to true if cancelled
209
+ } else {
210
+ config.enableCache = enableCache;
211
+ }
212
+
213
+ const enableProgress = await clack.confirm({
214
+ message: 'Show progress indicators for long operations?',
215
+ initialValue: true,
216
+ });
217
+
218
+ if (clack.isCancel(enableProgress)) {
219
+ config.enableProgress = true; // Default to true if cancelled
220
+ } else {
221
+ config.enableProgress = enableProgress;
222
+ }
223
+ } catch (error) {
224
+ // If prompts fail (e.g., with npx), use defaults
225
+ clack.log.warn('Using default performance settings (cache: on, progress: on)');
226
+ config.enableCache = true;
227
+ config.enableProgress = true;
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Step 6: Save configuration
233
+ */
234
+ async function saveConfiguration(config) {
235
+ const s = clack.spinner();
236
+ s.start('Saving configuration...');
237
+
238
+ const configDir = join(homedir(), '.dhurandhar');
239
+ const configPath = join(configDir, 'config.json');
240
+
241
+ // Create config directory if it doesn't exist
242
+ if (!existsSync(configDir)) {
243
+ mkdirSync(configDir, { recursive: true });
244
+ }
245
+
246
+ // Add metadata
247
+ config.version = '2.0.2';
248
+ config.setupDate = new Date().toISOString();
249
+ config.setupCompleted = true;
250
+
251
+ // Write config
252
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
253
+
254
+ s.stop('Configuration saved');
255
+
256
+ clack.log.success(`Configuration saved to: ${configPath}`);
257
+
258
+ // Display summary
259
+ console.log(chalk.cyan('\nšŸ“‹ Configuration Summary:\n'));
260
+ console.log(chalk.gray(` Projects Directory: ${config.projectsDirectory}`));
261
+ console.log(chalk.gray(` AI Coding Assistant: ${config.aiCodingAssistant || 'None'}`));
262
+ console.log(chalk.gray(` AI Provider: ${config.aiProvider}`));
263
+ console.log(chalk.gray(` Integrations: ${config.integrations?.join(', ') || 'None'}`));
264
+ console.log(chalk.gray(` Cache Enabled: ${config.enableCache ? 'Yes' : 'No'}`));
265
+ console.log(chalk.gray(` Progress Indicators: ${config.enableProgress ? 'Yes' : 'No'}\n`));
266
+ }
package/cli/dhurandhar.js CHANGED
@@ -46,6 +46,15 @@ program.hook('preAction', () => {
46
46
  console.log('');
47
47
  });
48
48
 
49
+ // Command: setup - First-time setup wizard
50
+ program
51
+ .command('setup')
52
+ .description('Run first-time setup wizard (configure AI assistants, integrations)')
53
+ .action(async (options) => {
54
+ const { default: setupCommand } = await import('./commands/setup.js');
55
+ await setupCommand(options);
56
+ });
57
+
49
58
  // Command: init - Initialize new project
50
59
  program
51
60
  .command('init')
@@ -271,8 +280,9 @@ program.on('command:*', function (operands) {
271
280
 
272
281
  // Suggest similar commands
273
282
  const suggestions = {
274
- 'install': 'init',
275
- 'setup': 'init',
283
+ 'install': 'setup',
284
+ 'configure': 'setup',
285
+ 'config': 'setup',
276
286
  'create': 'init',
277
287
  'start': 'init',
278
288
  'generate': 'codegen',
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Configuration Loader
3
+ *
4
+ * Loads and manages Dhurandhar configuration
5
+ */
6
+
7
+ import { existsSync, readFileSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+
11
+ /**
12
+ * Get configuration file path
13
+ */
14
+ export function getConfigPath() {
15
+ return join(homedir(), '.dhurandhar', 'config.json');
16
+ }
17
+
18
+ /**
19
+ * Check if setup has been completed
20
+ */
21
+ export function isSetupComplete() {
22
+ const configPath = getConfigPath();
23
+ if (!existsSync(configPath)) {
24
+ return false;
25
+ }
26
+
27
+ try {
28
+ const config = loadConfig();
29
+ return config.setupCompleted === true;
30
+ } catch (error) {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Load configuration
37
+ */
38
+ export function loadConfig() {
39
+ const configPath = getConfigPath();
40
+
41
+ if (!existsSync(configPath)) {
42
+ return getDefaultConfig();
43
+ }
44
+
45
+ try {
46
+ const content = readFileSync(configPath, 'utf-8');
47
+ return JSON.parse(content);
48
+ } catch (error) {
49
+ console.error('Error loading config:', error.message);
50
+ return getDefaultConfig();
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Get default configuration
56
+ */
57
+ export function getDefaultConfig() {
58
+ return {
59
+ version: '2.0.2',
60
+ projectsDirectory: process.cwd(),
61
+ aiCodingAssistant: 'none',
62
+ deepIntegration: false,
63
+ aiProvider: 'mock',
64
+ integrations: [],
65
+ enableCache: true,
66
+ enableProgress: true,
67
+ setupCompleted: false,
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Get configuration value
73
+ */
74
+ export function getConfigValue(key, defaultValue = null) {
75
+ const config = loadConfig();
76
+ return config[key] ?? defaultValue;
77
+ }
78
+
79
+ /**
80
+ * Check if integration is enabled
81
+ */
82
+ export function isIntegrationEnabled(integration) {
83
+ const config = loadConfig();
84
+ return config.integrations?.includes(integration) ?? false;
85
+ }
86
+
87
+ /**
88
+ * Get AI coding assistant info
89
+ */
90
+ export function getAICodingAssistant() {
91
+ const config = loadConfig();
92
+
93
+ const assistants = {
94
+ augment: {
95
+ name: 'Augment Code',
96
+ command: 'auggie',
97
+ configFile: '.augment',
98
+ description: 'Augment Code (auggie)',
99
+ },
100
+ cursor: {
101
+ name: 'Cursor',
102
+ command: 'cursor',
103
+ configFile: '.cursor',
104
+ description: 'Cursor AI Editor',
105
+ },
106
+ claude: {
107
+ name: 'Claude Code',
108
+ command: 'claude',
109
+ configFile: '.claude',
110
+ description: 'Anthropic Claude Code',
111
+ },
112
+ copilot: {
113
+ name: 'GitHub Copilot',
114
+ command: 'github-copilot',
115
+ configFile: '.github',
116
+ description: 'GitHub Copilot',
117
+ },
118
+ codeium: {
119
+ name: 'Codeium',
120
+ command: 'codeium',
121
+ configFile: '.codeium',
122
+ description: 'Codeium AI',
123
+ },
124
+ tabnine: {
125
+ name: 'Tabnine',
126
+ command: 'tabnine',
127
+ configFile: '.tabnine',
128
+ description: 'Tabnine AI',
129
+ },
130
+ gemini: {
131
+ name: 'Google Gemini Code',
132
+ command: 'gemini',
133
+ configFile: '.gemini',
134
+ description: 'Google Gemini Code',
135
+ },
136
+ codex: {
137
+ name: 'OpenAI Codex',
138
+ command: 'codex',
139
+ configFile: '.codex',
140
+ description: 'OpenAI Codex',
141
+ },
142
+ none: {
143
+ name: 'None',
144
+ command: null,
145
+ configFile: null,
146
+ description: 'No AI coding assistant',
147
+ },
148
+ };
149
+
150
+ const assistantKey = config.aiCodingAssistant || 'none';
151
+ return assistants[assistantKey] || assistants.none;
152
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "dhurandhar",
4
- "version": "2.0.2",
4
+ "version": "2.1.1",
5
5
  "description": "The world's first AI-powered dharma-centric design framework. 8 Pandava agents + 21 sub-agents guide you from idea to production code. Features → Requirements → Entities → API → HLD → LLD → Implementation → Blessing. Complete with code generation, enterprise integrations, and mythological accuracy.",
6
6
  "keywords": [
7
7
  "system-design",