dhurandhar 2.0.2 → 2.1.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ 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.0] - 2026-04-02
9
+
10
+ ### Added - Setup Wizard! šŸŽ‰
11
+ - **`dhurandhar setup`** - Interactive first-time setup wizard
12
+ - Verifies/selects installation directory
13
+ - Configures AI coding assistant integration:
14
+ - Augment Code (auggie)
15
+ - Cursor
16
+ - Claude Code
17
+ - GitHub Copilot
18
+ - Codeium
19
+ - Tabnine
20
+ - Google Gemini Code
21
+ - OpenAI Codex
22
+ - Configures enterprise integrations (GitHub, Jira, Confluence)
23
+ - Selects AI provider for design suggestions
24
+ - Configures performance settings (cache, progress indicators)
25
+ - Saves configuration to `~/.dhurandhar/config.json`
26
+
27
+ ### Changed
28
+ - `dhurandhar init` now checks if setup is complete
29
+ - If setup not complete, prompts user to run setup first
30
+ - Better command suggestions: "install" now suggests "setup"
31
+ - Configuration persisted across all projects
32
+
33
+ ### Improved
34
+ - Much better first-time user experience
35
+ - Like BMAD's installation process
36
+ - Clear configuration summary after setup
37
+ - Guided workflow: setup → init → design
38
+
39
+ ---
40
+
8
41
  ## [2.0.2] - 2026-04-02
9
42
 
10
43
  ### 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,247 @@
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
+ console.clear();
19
+
20
+ clack.intro(chalk.cyan.bold('šŸ•‰ļø DHURANDHAR SETUP WIZARD'));
21
+
22
+ console.log(chalk.gray('Welcome! Let\'s configure Dhurandhar for your environment.\n'));
23
+
24
+ const config = {};
25
+
26
+ // Step 1: Installation Directory
27
+ await selectInstallationDirectory(config);
28
+
29
+ // Step 2: AI Coding Assistant
30
+ await selectAICodingAssistant(config);
31
+
32
+ // Step 3: Enterprise Integrations
33
+ await setupEnterpriseIntegrations(config);
34
+
35
+ // Step 4: AI Provider
36
+ await selectAIProvider(config);
37
+
38
+ // Step 5: Performance Settings
39
+ await configurePerformance(config);
40
+
41
+ // Step 6: Save Configuration
42
+ await saveConfiguration(config);
43
+
44
+ clack.outro(chalk.green.bold('āœ… Setup Complete!'));
45
+
46
+ console.log(chalk.cyan('\nšŸ“š Next Steps:'));
47
+ console.log(chalk.gray(' 1. cd to your project directory'));
48
+ console.log(chalk.gray(' 2. Run: dhurandhar init'));
49
+ console.log(chalk.gray(' 3. Start designing: dhurandhar yudhishthira\n'));
50
+ }
51
+
52
+ /**
53
+ * Step 1: Select installation directory
54
+ */
55
+ async function selectInstallationDirectory(config) {
56
+ const s = clack.spinner();
57
+ s.start('Detecting current directory...');
58
+
59
+ const cwd = process.cwd();
60
+ const home = homedir();
61
+
62
+ s.stop('Current directory detected');
63
+
64
+ const dirChoice = await clack.select({
65
+ message: 'Where should Dhurandhar projects be created?',
66
+ options: [
67
+ { value: 'current', label: `Current directory: ${cwd}` },
68
+ { value: 'home', label: `Home directory: ${home}/dhurandhar-projects` },
69
+ { value: 'custom', label: 'Custom directory (I\'ll specify)' },
70
+ ],
71
+ });
72
+
73
+ if (clack.isCancel(dirChoice)) {
74
+ clack.cancel('Setup cancelled');
75
+ process.exit(0);
76
+ }
77
+
78
+ if (dirChoice === 'current') {
79
+ config.projectsDirectory = cwd;
80
+ } else if (dirChoice === 'home') {
81
+ config.projectsDirectory = join(home, 'dhurandhar-projects');
82
+ } else {
83
+ const customDir = await clack.text({
84
+ message: 'Enter custom directory path:',
85
+ placeholder: '/path/to/projects',
86
+ validate: (value) => {
87
+ if (!value) return 'Directory path is required';
88
+ },
89
+ });
90
+
91
+ if (clack.isCancel(customDir)) {
92
+ clack.cancel('Setup cancelled');
93
+ process.exit(0);
94
+ }
95
+
96
+ config.projectsDirectory = customDir;
97
+ }
98
+
99
+ // Create directory if it doesn't exist
100
+ if (!existsSync(config.projectsDirectory)) {
101
+ mkdirSync(config.projectsDirectory, { recursive: true });
102
+ clack.log.success(`Created directory: ${config.projectsDirectory}`);
103
+ } else {
104
+ clack.log.info(`Using existing directory: ${config.projectsDirectory}`);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Step 2: Select AI coding assistant
110
+ */
111
+ async function selectAICodingAssistant(config) {
112
+ const assistant = await clack.select({
113
+ message: 'Which AI coding assistant do you use?',
114
+ options: [
115
+ { value: 'augment', label: 'šŸ¤– Augment Code (auggie)' },
116
+ { value: 'cursor', label: '⚔ Cursor' },
117
+ { value: 'claude', label: '🧠 Claude Code (Code Claude)' },
118
+ { value: 'copilot', label: 'šŸ™ GitHub Copilot' },
119
+ { value: 'codeium', label: 'šŸ’« Codeium' },
120
+ { value: 'tabnine', label: 'šŸ”® Tabnine' },
121
+ { value: 'gemini', label: 'šŸ’Ž Google Gemini Code' },
122
+ { value: 'codex', label: '🌟 OpenAI Codex' },
123
+ { value: 'none', label: 'āŒ None / I\'ll configure later' },
124
+ ],
125
+ });
126
+
127
+ if (clack.isCancel(assistant)) {
128
+ clack.cancel('Setup cancelled');
129
+ process.exit(0);
130
+ }
131
+
132
+ config.aiCodingAssistant = assistant;
133
+
134
+ if (assistant !== 'none') {
135
+ clack.log.success(`Selected: ${assistant}`);
136
+
137
+ const integrate = await clack.confirm({
138
+ message: `Enable deep integration with ${assistant}?`,
139
+ initialValue: true,
140
+ });
141
+
142
+ if (!clack.isCancel(integrate)) {
143
+ config.deepIntegration = integrate;
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Step 3: Setup enterprise integrations
150
+ */
151
+ async function setupEnterpriseIntegrations(config) {
152
+ const integrations = await clack.multiselect({
153
+ message: 'Which integrations would you like to enable?',
154
+ options: [
155
+ { value: 'github', label: 'šŸ™ GitHub (Issues, PRs, Repository)' },
156
+ { value: 'jira', label: 'šŸ“‹ Jira (Epics, Stories, Tasks)' },
157
+ { value: 'confluence', label: 'šŸ“š Confluence (Documentation)' },
158
+ ],
159
+ required: false,
160
+ });
161
+
162
+ if (clack.isCancel(integrations)) {
163
+ config.integrations = [];
164
+ } else {
165
+ config.integrations = integrations;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Step 4: Select AI provider
171
+ */
172
+ async function selectAIProvider(config) {
173
+ const provider = await clack.select({
174
+ message: 'Which AI provider for design suggestions?',
175
+ options: [
176
+ { value: 'mock', label: 'šŸŽ­ Mock (No API key needed, for testing)' },
177
+ { value: 'openai', label: 'šŸ¤– OpenAI (GPT-4)' },
178
+ { value: 'anthropic', label: '🧠 Anthropic (Claude)' },
179
+ ],
180
+ });
181
+
182
+ if (clack.isCancel(provider)) {
183
+ provider = 'mock';
184
+ }
185
+
186
+ config.aiProvider = provider;
187
+ }
188
+
189
+ /**
190
+ * Step 5: Configure performance settings
191
+ */
192
+ async function configurePerformance(config) {
193
+ const enableCache = await clack.confirm({
194
+ message: 'Enable caching for faster performance?',
195
+ initialValue: true,
196
+ });
197
+
198
+ if (!clack.isCancel(enableCache)) {
199
+ config.enableCache = enableCache;
200
+ }
201
+
202
+ const enableProgress = await clack.confirm({
203
+ message: 'Show progress indicators for long operations?',
204
+ initialValue: true,
205
+ });
206
+
207
+ if (!clack.isCancel(enableProgress)) {
208
+ config.enableProgress = enableProgress;
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Step 6: Save configuration
214
+ */
215
+ async function saveConfiguration(config) {
216
+ const s = clack.spinner();
217
+ s.start('Saving configuration...');
218
+
219
+ const configDir = join(homedir(), '.dhurandhar');
220
+ const configPath = join(configDir, 'config.json');
221
+
222
+ // Create config directory if it doesn't exist
223
+ if (!existsSync(configDir)) {
224
+ mkdirSync(configDir, { recursive: true });
225
+ }
226
+
227
+ // Add metadata
228
+ config.version = '2.0.2';
229
+ config.setupDate = new Date().toISOString();
230
+ config.setupCompleted = true;
231
+
232
+ // Write config
233
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
234
+
235
+ s.stop('Configuration saved');
236
+
237
+ clack.log.success(`Configuration saved to: ${configPath}`);
238
+
239
+ // Display summary
240
+ console.log(chalk.cyan('\nšŸ“‹ Configuration Summary:\n'));
241
+ console.log(chalk.gray(` Projects Directory: ${config.projectsDirectory}`));
242
+ console.log(chalk.gray(` AI Coding Assistant: ${config.aiCodingAssistant || 'None'}`));
243
+ console.log(chalk.gray(` AI Provider: ${config.aiProvider}`));
244
+ console.log(chalk.gray(` Integrations: ${config.integrations?.join(', ') || 'None'}`));
245
+ console.log(chalk.gray(` Cache Enabled: ${config.enableCache ? 'Yes' : 'No'}`));
246
+ console.log(chalk.gray(` Progress Indicators: ${config.enableProgress ? 'Yes' : 'No'}\n`));
247
+ }
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.0",
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",