ai-devx 1.0.5 → 1.0.6

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/README.md CHANGED
@@ -20,38 +20,62 @@ AI-DEVX is a powerful CLI tool that installs AI agent templates into your projec
20
20
 
21
21
  ### Installation
22
22
 
23
+ AI-DEVX supports assistant-specific installations with different folder names:
24
+
23
25
  ```bash
24
- # Using npx (recommended)
26
+ # Default installation (universal, all assistants)
25
27
  npx ai-devx init
28
+ # Creates: .agent/ folder (includes both Claude and Gemini)
29
+
30
+ # Claude-specific installation
31
+ npx ai-devx init --assistant claude
32
+ # Creates: .claude/ folder (includes only Claude rules)
33
+
34
+ # Gemini-specific installation
35
+ npx ai-devx init --assistant gemini
36
+ # Creates: .gemini/ folder (includes only Gemini rules)
26
37
 
27
38
  # Or install globally
28
39
  npm install -g ai-devx
29
- ai-devx init
40
+ ai-devx init --assistant claude
30
41
  ```
31
42
 
32
- This installs the `.agent` folder containing all templates into your project.
43
+ **Folder Mapping:**
44
+
45
+ - No `--assistant` flag → `.agent/` folder (universal, all assistants)
46
+ - `--assistant claude` → `.claude/` folder (Claude-specific)
47
+ - `--assistant gemini` → `.gemini/` folder (Gemini-specific)
48
+
49
+ This allows you to have separate configurations for different AI assistants in the same project.
33
50
 
34
51
  ### Important: Git Configuration
35
52
 
36
- If you are using AI-powered editors like **Cursor** or **Windsurf**, adding the `.agent/` folder to your `.gitignore` may prevent the IDE from indexing the workflows. This results in slash commands (like `/plan`, `/debug`) not appearing in the chat suggestion dropdown.
53
+ If you are using AI-powered editors like **Cursor** or **Windsurf**, adding the agent folder to your `.gitignore` may prevent the IDE from indexing the workflows. This results in slash commands (like `/plan`, `/debug`) not appearing in the chat suggestion dropdown.
37
54
 
38
- **Recommended Solution:** To keep the `.agent/` folder local (not tracked by Git) while maintaining AI functionality:
55
+ **Recommended Solution:** To keep the agent folder local (not tracked by Git) while maintaining AI functionality:
39
56
 
40
- 1. Ensure `.agent/` is **NOT** in your project's `.gitignore`
57
+ 1. Ensure the agent folder (`.agent/`, `.claude/`, or `.gemini/`) is **NOT** in your project's `.gitignore`
41
58
  2. Instead, add it to your local exclude file: `.git/info/exclude`
42
59
 
43
60
  ```bash
61
+ # For .agent/ folder
44
62
  echo ".agent/" >> .git/info/exclude
63
+
64
+ # For .claude/ folder
65
+ echo ".claude/" >> .git/info/exclude
66
+
67
+ # For .gemini/ folder
68
+ echo ".gemini/" >> .git/info/exclude
45
69
  ```
46
70
 
47
71
  ## 📦 What's Included
48
72
 
49
- | Component | Count | Description |
50
- |-----------|-------|-------------|
51
- | **Agents** | 9 | Specialist AI personas |
52
- | **Skills** | 5+ | Domain-specific knowledge modules |
53
- | **Workflows** | 9 | Slash command procedures |
54
- | **Scripts** | 2 | Validation and automation tools |
73
+ | Component | Count | Description |
74
+ | ------------- | ----- | --------------------------------- |
75
+ | **Agents** | 9 | Specialist AI personas |
76
+ | **Skills** | 5+ | Domain-specific knowledge modules |
77
+ | **Workflows** | 9 | Slash command procedures |
78
+ | **Scripts** | 2 | Validation and automation tools |
55
79
 
56
80
  ### Agents
57
81
 
@@ -83,6 +107,7 @@ AI: 🤖 Using @debugger for systematic analysis...
83
107
  ```
84
108
 
85
109
  **How it works:**
110
+
86
111
  - Analyzes your request silently
87
112
  - Detects domain(s) automatically (frontend, backend, security, etc.)
88
113
  - Selects the best specialist(s)
@@ -90,6 +115,7 @@ AI: 🤖 Using @debugger for systematic analysis...
90
115
  - You get specialist-level responses without needing to know the system architecture
91
116
 
92
117
  **Benefits:**
118
+
93
119
  - ✅ Zero learning curve - just describe what you need
94
120
  - ✅ Always get expert responses
95
121
  - ✅ Transparent - shows which agent is being used
@@ -99,16 +125,17 @@ AI: 🤖 Using @debugger for systematic analysis...
99
125
 
100
126
  Invoke workflows with slash commands:
101
127
 
102
- | Command | Description |
103
- |---------|-------------|
104
- | `/plan` | Create task breakdown and implementation plan |
105
- | `/create` | Create new features or apps |
106
- | `/debug` | Systematic debugging |
107
- | `/test` | Generate and run tests |
108
- | `/deploy` | Deploy application |
109
- | `/security` | Security audit and fixes |
128
+ | Command | Description |
129
+ | ----------- | --------------------------------------------- |
130
+ | `/plan` | Create task breakdown and implementation plan |
131
+ | `/create` | Create new features or apps |
132
+ | `/debug` | Systematic debugging |
133
+ | `/test` | Generate and run tests |
134
+ | `/deploy` | Deploy application |
135
+ | `/security` | Security audit and fixes |
110
136
 
111
137
  Example:
138
+
112
139
  ```
113
140
  /plan user authentication system
114
141
  /create login form component
@@ -122,6 +149,7 @@ Example:
122
149
  Skills are loaded automatically based on task context. The AI reads skill descriptions and applies relevant knowledge.
123
150
 
124
151
  **Available Skills:**
152
+
125
153
  - **react-best-practices** - React hooks, patterns, performance
126
154
  - **api-patterns** - REST API design, authentication, best practices
127
155
  - **testing-patterns** - Unit, integration, E2E testing strategies
@@ -132,21 +160,30 @@ Skills are loaded automatically based on task context. The AI reads skill descri
132
160
 
133
161
  ### Commands
134
162
 
135
- | Command | Description |
136
- |---------|-------------|
137
- | `ai-devx init` | Install `.agent` folder into your project |
138
- | `ai-devx update` | Update to the latest version |
139
- | `ai-devx status` | Check installation status |
163
+ | Command | Description |
164
+ | --------------------------------- | ------------------------------------------- |
165
+ | `ai-devx init` | Install `.agent` folder into your project |
166
+ | `ai-devx init --assistant claude` | Install `.claude` folder (Claude-specific) |
167
+ | `ai-devx init --assistant gemini` | Install `.gemini` folder (Gemini-specific) |
168
+ | `ai-devx shell` | Start interactive shell to browse resources |
169
+ | `ai-devx update` | Update to the latest version |
170
+ | `ai-devx status` | Check installation status |
140
171
 
141
172
  ### Options
142
173
 
143
174
  ```bash
144
- ai-devx init --force # Overwrite existing .agent folder
145
- ai-devx init --path ./myapp # Install in specific directory
146
- ai-devx init --branch dev # Use specific branch
147
- ai-devx init --quiet # Suppress output (for CI/CD)
148
- ai-devx init --dry-run # Preview actions without executing
149
- ai-devx update --backup # Create backup before updating
175
+ # Installation options
176
+ ai-devx init # Install to .agent/ (universal)
177
+ ai-devx init --assistant claude # Install to .claude/ (Claude-specific)
178
+ ai-devx init --assistant gemini # Install to .gemini/ (Gemini-specific)
179
+ ai-devx init --force # Overwrite existing folder
180
+ ai-devx init --path ./myapp # Install in specific directory
181
+ ai-devx init --branch dev # Use specific branch
182
+ ai-devx init --quiet # Suppress output (for CI/CD)
183
+ ai-devx init --dry-run # Preview actions without executing
184
+
185
+ # Update options
186
+ ai-devx update --backup # Create backup before updating
150
187
  ```
151
188
 
152
189
  ### Validation Scripts
@@ -163,30 +200,49 @@ node .agent/scripts/security_scan.js
163
200
 
164
201
  ## 📁 Project Structure
165
202
 
203
+ AI-DEVX can be installed to different folders depending on your assistant preference:
204
+
205
+ ### Universal Installation (`.agent/`)
206
+
166
207
  ```
167
208
  .agent/
168
209
  ├── agents/ # Agent definitions
169
- │ ├── frontend-specialist.md
170
- │ ├── backend-specialist.md
171
- │ ├── security-auditor.md
172
- │ └── ...
173
210
  ├── skills/ # Skill modules
174
- │ ├── react-best-practices/
175
- │ ├── api-patterns/
176
- │ ├── testing-patterns/
177
- │ └── ...
178
211
  ├── workflows/ # Workflow definitions
179
- │ ├── plan.md
180
- │ ├── create.md
181
- │ ├── debug.md
182
- │ └── ...
183
212
  ├── scripts/ # Validation scripts
184
- ├── checklist.js
185
- └── security_scan.js
213
+ ├── rules/ # Assistant rules
214
+ ├── CLAUDE.md
215
+ │ └── GEMINI.md
186
216
  ├── VERSION # Current version
187
217
  └── config.json # Installation config
188
218
  ```
189
219
 
220
+ ### Claude-Specific Installation (`.claude/`)
221
+
222
+ ```
223
+ .claude/
224
+ ├── agents/ # Agent definitions
225
+ ├── skills/ # Skill modules
226
+ ├── workflows/ # Workflow definitions
227
+ ├── scripts/ # Validation scripts
228
+ ├── rules/
229
+ │ └── CLAUDE.md # Only Claude rules
230
+ └── config.json
231
+ ```
232
+
233
+ ### Gemini-Specific Installation (`.gemini/`)
234
+
235
+ ```
236
+ .gemini/
237
+ ├── agents/ # Agent definitions
238
+ ├── skills/ # Skill modules
239
+ ├── workflows/ # Workflow definitions
240
+ ├── scripts/ # Validation scripts
241
+ ├── rules/
242
+ │ └── GEMINI.md # Only Gemini rules
243
+ └── config.json
244
+ ```
245
+
190
246
  ## 🔄 How It Works
191
247
 
192
248
  ```
@@ -238,7 +294,7 @@ Next steps:
238
294
 
239
295
  ### Debugging
240
296
 
241
- ```
297
+ ````
242
298
  User: /debug Login button not working
243
299
 
244
300
  AI: 🤖 Applying @debugger...
@@ -253,17 +309,20 @@ Event handler not bound correctly in React component.
253
309
  // Before
254
310
  <button onClick={handleLogin}>Login</button>
255
311
 
256
- // After
312
+ // After
257
313
  <button onClick={() => handleLogin()}>Login</button>
258
- ```
314
+ ````
259
315
 
260
316
  ### Verification
317
+
261
318
  ✅ Button now triggers login function
319
+
262
320
  ```
263
321
 
264
322
  ### Security Audit
265
323
 
266
324
  ```
325
+
267
326
  User: /security
268
327
 
269
328
  AI: 🤖 Applying @security-auditor...
@@ -275,9 +334,11 @@ AI: 🤖 Applying @security-auditor...
275
334
  🟡 Medium: 2
276
335
 
277
336
  ### Critical Issue
337
+
278
338
  Hardcoded API key in src/config.ts:15
279
339
 
280
340
  Fix: Move to environment variables
341
+
281
342
  ```
282
343
 
283
344
  ## 🛡️ Security
@@ -311,10 +372,6 @@ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md)
311
372
 
312
373
  MIT © [kmamtora](https://github.com/kmamtora)
313
374
 
314
- ## 🙏 Acknowledgments
315
-
316
- Inspired by [antigravity-kit](https://github.com/vudovn/antigravity-kit) - An amazing AI agent toolkit.
317
-
318
375
  ## 📞 Support
319
376
 
320
377
  - GitHub Issues: [Report a bug](https://github.com/kmamtora/ai-devx/issues)
@@ -323,3 +380,4 @@ Inspired by [antigravity-kit](https://github.com/vudovn/antigravity-kit) - An am
323
380
  ---
324
381
 
325
382
  **Happy Coding!** 🤖✨
383
+ ```
package/bin/cli.js CHANGED
@@ -41,8 +41,7 @@ program
41
41
  )
42
42
  .option(
43
43
  "-a, --assistant <assistants>",
44
- "Comma-separated list of assistants (claude,gemini,all)",
45
- "all",
44
+ "Comma-separated list of assistants (claude,gemini) - installs to .claude/.gemini folder",
46
45
  )
47
46
  .action(initCommand);
48
47
 
@@ -71,19 +70,19 @@ program.on("--help", () => {
71
70
  console.log("");
72
71
  console.log(chalk.bold("Examples:"));
73
72
  console.log(
74
- " $ ai-devx init # Install in current directory",
73
+ " $ ai-devx init # Install to .agent/ folder",
75
74
  );
76
75
  console.log(
77
- " $ ai-devx init --path ./my-project # Install in specific directory",
76
+ " $ ai-devx init --assistant claude # Install to .claude/ folder",
78
77
  );
79
78
  console.log(
80
- " $ ai-devx init --force # Overwrite existing installation",
79
+ " $ ai-devx init --assistant gemini # Install to .gemini/ folder",
81
80
  );
82
81
  console.log(
83
- " $ ai-devx init --assistant claude # Install with only Claude rules",
82
+ " $ ai-devx init --path ./my-project # Install in specific directory",
84
83
  );
85
84
  console.log(
86
- " $ ai-devx init --assistant claude,gemini # Install with both assistants",
85
+ " $ ai-devx init --force # Overwrite existing installation",
87
86
  );
88
87
  console.log(
89
88
  " $ ai-devx shell # Start interactive shell",
@@ -93,8 +92,16 @@ program.on("--help", () => {
93
92
  " $ ai-devx status # Check installation status",
94
93
  );
95
94
  console.log("");
95
+ console.log(chalk.bold("Folder Structure:"));
96
+ console.log(
97
+ " Without --assistant: .agent/ (universal, all assistants)",
98
+ );
99
+ console.log(" --assistant claude: .claude/ (Claude-specific)");
100
+ console.log(" --assistant gemini: .gemini/ (Gemini-specific)");
101
+ console.log("");
96
102
  console.log(chalk.bold("Quick Start:"));
97
- console.log(" $ npx ai-devx init");
103
+ console.log(" $ npx ai-devx init --assistant claude");
104
+ console.log(" $ npx ai-devx init --assistant gemini");
98
105
  console.log(" $ npx ai-devx shell");
99
106
  console.log("");
100
107
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-devx",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "AI Agent templates with Skills, Agents, and Workflows for enhanced coding assistance",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -20,20 +20,45 @@ async function initCommand(options) {
20
20
 
21
21
  try {
22
22
  const absolutePath = path.resolve(targetPath);
23
- const agentPath = path.join(absolutePath, config.AGENT_FOLDER);
23
+
24
+ // Parse assistant selection
25
+ let selectedAssistants;
26
+ let targetFolder;
27
+
28
+ if (!assistant || assistant === "all") {
29
+ // No assistant specified or 'all' - use .agent folder with all assistants
30
+ selectedAssistants = ["claude", "gemini"];
31
+ targetFolder = config.AGENT_FOLDER;
32
+ } else {
33
+ // Parse assistant list
34
+ selectedAssistants = assistant
35
+ .toLowerCase()
36
+ .split(",")
37
+ .map((a) => a.trim())
38
+ .filter((a) => ["claude", "gemini"].includes(a));
39
+
40
+ // Determine folder based on selection
41
+ targetFolder = config.getFolderForAssistant(selectedAssistants);
42
+ }
43
+
44
+ const agentPath = path.join(absolutePath, targetFolder);
24
45
 
25
46
  // Check if already installed
26
- const isInstalled = await fileUtils.isInstalled(absolutePath);
47
+ const isInstalled = await fileUtils.isInstalled(absolutePath, targetFolder);
27
48
 
28
49
  if (isInstalled && !force && !dryRun) {
29
50
  if (spinner) spinner.stop();
30
- logger.warning("AI-DEVX is already installed in this directory.");
51
+ logger.warning(
52
+ `AI-DEVX is already installed in this directory (${targetFolder}).`,
53
+ );
31
54
  logger.info(
32
55
  'Use --force to overwrite or run "ai-devx update" to update.',
33
56
  );
34
57
  logger.blank();
35
- logger.info("To keep .agent/ local without git tracking:");
36
- logger.step('Add ".agent/" to .git/info/exclude (not .gitignore)');
58
+ logger.info(`To keep ${targetFolder}/ local without git tracking:`);
59
+ logger.step(
60
+ `Add "${targetFolder}/" to .git/info/exclude (not .gitignore)`,
61
+ );
37
62
  return;
38
63
  }
39
64
 
@@ -41,6 +66,8 @@ async function initCommand(options) {
41
66
  if (spinner) spinner.stop();
42
67
  logger.info("DRY RUN - Actions that would be taken:");
43
68
  logger.step(`Install templates to: ${agentPath}`);
69
+ logger.step(`Assistants: ${selectedAssistants.join(", ")}`);
70
+ logger.step(`Target folder: ${targetFolder}`);
44
71
  if (isInstalled) logger.step("Overwrite existing installation");
45
72
  return;
46
73
  }
@@ -54,13 +81,6 @@ async function initCommand(options) {
54
81
 
55
82
  // Handle assistant selection
56
83
  if (spinner) spinner.text = "Configuring assistants...";
57
- const selectedAssistants =
58
- assistant === "all"
59
- ? ["claude", "gemini"]
60
- : assistant
61
- .toLowerCase()
62
- .split(",")
63
- .map((a) => a.trim());
64
84
 
65
85
  const rulesPath = path.join(agentPath, "rules");
66
86
  const validAssistants = ["claude", "gemini"];
@@ -88,6 +108,7 @@ async function initCommand(options) {
88
108
  installedAt: new Date().toISOString(),
89
109
  source: source,
90
110
  assistants: selectedAssistants,
111
+ folder: targetFolder,
91
112
  });
92
113
 
93
114
  if (spinner) spinner.succeed("AI-DEVX templates installed successfully!");
@@ -97,10 +118,12 @@ async function initCommand(options) {
97
118
  logger.success(`Installed in: ${agentPath}`);
98
119
  logger.blank();
99
120
  logger.info("What's included:");
100
- logger.step(`Agents: 9 specialist personas`);
101
- logger.step(`Skills: Domain-specific knowledge modules`);
102
- logger.step(`Workflows: Slash commands (/plan, /create, /debug, etc.)`);
103
- logger.step(`Scripts: Validation and automation tools`);
121
+ logger.step(`Agents: 22 specialist personas`);
122
+ logger.step(`Skills: 37 domain-specific knowledge modules`);
123
+ logger.step(
124
+ `Workflows: 11 slash commands (/plan, /create, /debug, etc.)`,
125
+ );
126
+ logger.step(`Scripts: 4 validation and automation tools`);
104
127
  logger.step(`Assistants: ${selectedAssistants.join(", ")}`);
105
128
  logger.blank();
106
129
  logger.info("Quick Start:");
@@ -108,8 +131,10 @@ async function initCommand(options) {
108
131
  logger.step("Type /create to build new features");
109
132
  logger.step("Type /debug for systematic debugging");
110
133
  logger.blank();
111
- logger.warning("Important: For Cursor/Windsurf compatibility");
112
- logger.step('Add ".agent/" to .git/info/exclude (NOT .gitignore)');
134
+ logger.warning(`Important: For Cursor/Windsurf compatibility`);
135
+ logger.step(
136
+ `Add "${targetFolder}/" to .git/info/exclude (NOT .gitignore)`,
137
+ );
113
138
  logger.step("This keeps templates local while allowing AI indexing");
114
139
  }
115
140
  } catch (error) {
@@ -2,6 +2,8 @@ const path = require("path");
2
2
  const fs = require("fs-extra");
3
3
  const chalk = require("chalk");
4
4
  const readline = require("readline");
5
+ const config = require("../config");
6
+ const fileUtils = require("../utils/fileSystem");
5
7
 
6
8
  class InteractiveCLI {
7
9
  constructor(agentPath) {
@@ -334,14 +336,21 @@ class InteractiveCLI {
334
336
 
335
337
  async function shellCommand(targetPath) {
336
338
  const cwd = targetPath || process.cwd();
337
- const agentPath = path.join(path.resolve(cwd), ".agent");
338
339
 
339
- if (!(await fs.pathExists(agentPath))) {
340
+ // Find installed folder
341
+ const installedFolder = await fileUtils.findInstalledFolder(cwd);
342
+
343
+ if (!installedFolder) {
340
344
  console.log(chalk.red(`❌ AI-DEVX not installed in ${cwd}`));
341
- console.log(chalk.yellow("Run: npx ai-devx init"));
345
+ console.log(chalk.yellow("Run one of the following:"));
346
+ console.log(chalk.yellow(" npx ai-devx init"));
347
+ console.log(chalk.yellow(" npx ai-devx init --assistant claude"));
348
+ console.log(chalk.yellow(" npx ai-devx init --assistant gemini"));
342
349
  process.exit(1);
343
350
  }
344
351
 
352
+ const agentPath = path.join(path.resolve(cwd), installedFolder);
353
+
345
354
  const cli = new InteractiveCLI(agentPath);
346
355
  await cli.start();
347
356
  }
@@ -1,59 +1,96 @@
1
- const path = require('path');
2
- const chalk = require('chalk');
3
- const logger = require('../utils/logger');
4
- const fileUtils = require('../utils/fileSystem');
5
- const config = require('../config');
1
+ const path = require("path");
2
+ const chalk = require("chalk");
3
+ const logger = require("../utils/logger");
4
+ const fileUtils = require("../utils/fileSystem");
5
+ const config = require("../config");
6
6
 
7
7
  async function statusCommand(options) {
8
8
  const { path: targetPath } = options;
9
9
  const absolutePath = path.resolve(targetPath);
10
- const agentPath = path.join(absolutePath, config.AGENT_FOLDER);
11
-
10
+
12
11
  logger.blank();
13
- logger.info('AI-DEVX Status');
12
+ logger.info("AI-DEVX Status");
14
13
  logger.blank();
15
-
16
- const isInstalled = await fileUtils.isInstalled(absolutePath);
17
-
18
- if (!isInstalled) {
19
- logger.error('Not installed');
14
+
15
+ // Check all possible installations
16
+ const folderNames = config.getAllFolderNames();
17
+ const installations = [];
18
+
19
+ for (const folder of folderNames) {
20
+ const isInstalled = await fileUtils.isInstalled(absolutePath, folder);
21
+ if (isInstalled) {
22
+ const folderPath = path.join(absolutePath, folder);
23
+ const version = await fileUtils.getVersion(folderPath);
24
+ const configData = await fileUtils.readJson(
25
+ path.join(folderPath, "config.json"),
26
+ );
27
+
28
+ installations.push({
29
+ folder,
30
+ path: folderPath,
31
+ version: version || "unknown",
32
+ config: configData,
33
+ assistants: configData?.assistants || [],
34
+ });
35
+ }
36
+ }
37
+
38
+ if (installations.length === 0) {
39
+ logger.error("Not installed");
20
40
  logger.info(`Directory: ${absolutePath}`);
21
41
  logger.blank();
22
- logger.info('Run "ai-devx init" to install');
42
+ logger.info("Run one of the following:");
43
+ logger.step("npx ai-devx init # Install to .agent/");
44
+ logger.step("npx ai-devx init --assistant claude # Install to .claude/");
45
+ logger.step("npx ai-devx init --assistant gemini # Install to .gemini/");
46
+ logger.blank();
23
47
  return;
24
48
  }
25
-
26
- // Get version
27
- const version = await fileUtils.getVersion(agentPath);
28
- const configData = await fileUtils.readJson(path.join(agentPath, 'config.json'));
29
-
30
- logger.success('Installed');
49
+
50
+ logger.success(
51
+ `Installed (${installations.length} installation${installations.length > 1 ? "s" : ""})`,
52
+ );
31
53
  logger.blank();
32
- logger.info(`Directory: ${agentPath}`);
33
- logger.info(`Version: ${chalk.green(version || 'unknown')}`);
34
-
35
- if (configData) {
36
- if (configData.installedAt) {
37
- logger.info(`Installed: ${new Date(configData.installedAt).toLocaleDateString()}`);
54
+
55
+ installations.forEach((inst, index) => {
56
+ if (index > 0) logger.blank();
57
+
58
+ logger.info(`Installation ${index + 1}:`);
59
+ logger.step(`Folder: ${chalk.cyan(inst.folder)}`);
60
+ logger.step(`Path: ${inst.path}`);
61
+ logger.step(`Version: ${chalk.green(inst.version)}`);
62
+
63
+ if (inst.assistants.length > 0) {
64
+ logger.step(`Assistants: ${inst.assistants.join(", ")}`);
38
65
  }
39
- if (configData.updatedAt) {
40
- logger.info(`Last updated: ${new Date(configData.updatedAt).toLocaleDateString()}`);
66
+
67
+ if (inst.config) {
68
+ if (inst.config.installedAt) {
69
+ logger.step(
70
+ `Installed: ${new Date(inst.config.installedAt).toLocaleDateString()}`,
71
+ );
72
+ }
73
+ if (inst.config.updatedAt) {
74
+ logger.step(
75
+ `Last updated: ${new Date(inst.config.updatedAt).toLocaleDateString()}`,
76
+ );
77
+ }
41
78
  }
42
- }
43
-
79
+ });
80
+
44
81
  logger.blank();
45
- logger.info('Available Components:');
46
- logger.step(`Agents: 9 specialist personas`);
47
- logger.step(`Skills: Multiple domain knowledge modules`);
48
- logger.step(`Workflows: 9 slash commands`);
49
- logger.step(`Scripts: Validation and automation tools`);
50
-
82
+ logger.info("Available Components:");
83
+ logger.step(`Agents: 22 specialist personas`);
84
+ logger.step(`Skills: 37 domain knowledge modules`);
85
+ logger.step(`Workflows: 11 slash commands`);
86
+ logger.step(`Scripts: 4 validation and automation tools`);
87
+
51
88
  logger.blank();
52
- logger.info('Quick Commands:');
53
- config.WORKFLOWS.slice(0, 5).forEach(wf => {
89
+ logger.info("Quick Commands:");
90
+ config.WORKFLOWS.slice(0, 5).forEach((wf) => {
54
91
  logger.step(`${chalk.cyan(wf.command)} - ${wf.description}`);
55
92
  });
56
-
93
+
57
94
  logger.blank();
58
95
  }
59
96
 
@@ -1,74 +1,102 @@
1
- const path = require('path');
2
- const fs = require('fs-extra');
3
- const ora = require('ora');
4
- const logger = require('../utils/logger');
5
- const fileUtils = require('../utils/fileSystem');
6
- const config = require('../config');
1
+ const path = require("path");
2
+ const fs = require("fs-extra");
3
+ const ora = require("ora");
4
+ const logger = require("../utils/logger");
5
+ const fileUtils = require("../utils/fileSystem");
6
+ const config = require("../config");
7
7
 
8
8
  async function updateCommand(options) {
9
9
  const { force, backup, quiet } = options;
10
-
11
- const spinner = quiet ? null : ora('Checking for updates...').start();
12
-
10
+
11
+ const spinner = quiet ? null : ora("Checking for updates...").start();
12
+
13
13
  try {
14
14
  const cwd = process.cwd();
15
- const isInstalled = await fileUtils.isInstalled(cwd);
16
-
17
- if (!isInstalled) {
18
- if (spinner) spinner.stop();
19
- logger.error('AI-DEVX is not installed in this directory.');
20
- logger.info('Run "ai-devx init" first.');
21
- return;
15
+
16
+ // Find all installed folders
17
+ const folderNames = config.getAllFolderNames();
18
+ const installations = [];
19
+
20
+ for (const folder of folderNames) {
21
+ const isInstalled = await fileUtils.isInstalled(cwd, folder);
22
+ if (isInstalled) {
23
+ installations.push(folder);
24
+ }
22
25
  }
23
-
24
- const agentPath = path.join(cwd, config.AGENT_FOLDER);
25
- const currentVersion = await fileUtils.getVersion(agentPath);
26
- const latestVersion = '1.0.0'; // In real implementation, fetch from GitHub
27
-
28
- if (currentVersion === latestVersion && !force) {
26
+
27
+ if (installations.length === 0) {
29
28
  if (spinner) spinner.stop();
30
- logger.success('AI-DEVX is already up to date!');
31
- logger.info(`Version: ${currentVersion}`);
29
+ logger.error("AI-DEVX is not installed in this directory.");
30
+ logger.info('Run "ai-devx init" first.');
32
31
  return;
33
32
  }
34
-
35
- if (spinner) spinner.text = 'Updating templates...';
36
-
37
- // Create backup if requested
38
- if (backup) {
39
- const backupPath = await fileUtils.backup(cwd);
40
- if (backupPath && !quiet) {
41
- logger.info(`Backup created: ${backupPath}`);
33
+
34
+ const latestVersion = "1.0.0"; // In real implementation, fetch from GitHub
35
+ const sourcePath = path.join(__dirname, "../../templates/.agent");
36
+
37
+ // Update each installation
38
+ for (const folder of installations) {
39
+ const agentPath = path.join(cwd, folder);
40
+ const currentVersion = await fileUtils.getVersion(agentPath);
41
+
42
+ if (spinner) spinner.text = `Updating ${folder}...`;
43
+
44
+ // Create backup if requested
45
+ if (backup) {
46
+ const backupPath = path.join(cwd, `${folder}.backup.${Date.now()}`);
47
+ await fs.copy(agentPath, backupPath);
48
+ if (!quiet) {
49
+ logger.info(`Backup created: ${backupPath}`);
50
+ }
51
+ }
52
+
53
+ // Read existing config to preserve assistant settings
54
+ const configFile = path.join(agentPath, "config.json");
55
+ const existingConfig = (await fileUtils.readJson(configFile)) || {};
56
+ const assistants = existingConfig.assistants || ["claude", "gemini"];
57
+
58
+ // Copy updated templates
59
+ await fileUtils.copyDir(sourcePath, agentPath, { force: true });
60
+
61
+ // Re-apply assistant filtering
62
+ const rulesPath = path.join(agentPath, "rules");
63
+ const validAssistants = ["claude", "gemini"];
64
+
65
+ for (const ast of validAssistants) {
66
+ if (!assistants.includes(ast)) {
67
+ const ruleFile = path.join(rulesPath, `${ast.toUpperCase()}.md`);
68
+ try {
69
+ await fs.remove(ruleFile);
70
+ } catch (e) {
71
+ // File might not exist, ignore
72
+ }
73
+ }
42
74
  }
75
+
76
+ // Update version file
77
+ const versionFile = path.join(agentPath, "VERSION");
78
+ await fs.writeFile(versionFile, latestVersion);
79
+
80
+ // Update config
81
+ existingConfig.version = latestVersion;
82
+ existingConfig.updatedAt = new Date().toISOString();
83
+ existingConfig.assistants = assistants;
84
+ await fileUtils.writeJson(configFile, existingConfig);
43
85
  }
44
-
45
- // Copy updated templates
46
- const sourcePath = path.join(__dirname, '../../templates/.agent');
47
- await fileUtils.copyDir(sourcePath, agentPath, { force: true });
48
-
49
- // Update version file
50
- const versionFile = path.join(agentPath, 'VERSION');
51
- await fs.writeFile(versionFile, latestVersion);
52
-
53
- // Update config
54
- const configFile = path.join(agentPath, 'config.json');
55
- const existingConfig = await fileUtils.readJson(configFile) || {};
56
- existingConfig.version = latestVersion;
57
- existingConfig.updatedAt = new Date().toISOString();
58
- await fileUtils.writeJson(configFile, existingConfig);
59
-
60
- if (spinner) spinner.succeed('AI-DEVX updated successfully!');
61
-
86
+
87
+ if (spinner) spinner.succeed("AI-DEVX updated successfully!");
88
+
62
89
  if (!quiet) {
63
90
  logger.blank();
64
- logger.success(`Updated to version: ${latestVersion}`);
65
- if (currentVersion) {
66
- logger.info(`Previous version: ${currentVersion}`);
67
- }
91
+ logger.success(
92
+ `Updated ${installations.length} installation${installations.length > 1 ? "s" : ""} to version: ${latestVersion}`,
93
+ );
94
+ installations.forEach((folder) => {
95
+ logger.info(` - ${folder}/`);
96
+ });
68
97
  }
69
-
70
98
  } catch (error) {
71
- if (spinner) spinner.fail('Update failed');
99
+ if (spinner) spinner.fail("Update failed");
72
100
  logger.error(error.message);
73
101
  process.exit(1);
74
102
  }
package/src/config.js CHANGED
@@ -1,72 +1,139 @@
1
- const path = require('path');
1
+ const path = require("path");
2
2
 
3
3
  module.exports = {
4
- AGENT_FOLDER: '.agent',
5
- VERSION_FILE: '.agent/VERSION',
6
- CONFIG_FILE: '.agent/config.json',
7
- DEFAULT_REPO: 'kmamtora/ai-devx',
8
- DEFAULT_BRANCH: 'main',
9
- TEMPLATES_PATH: 'templates/.agent',
10
- GITHUB_RAW_URL: 'https://raw.githubusercontent.com',
11
- GITHUB_API_URL: 'https://api.github.com',
12
-
4
+ AGENT_FOLDER: ".agent",
5
+ CLAUDE_FOLDER: ".claude",
6
+ GEMINI_FOLDER: ".gemini",
7
+ VERSION_FILE: ".agent/VERSION",
8
+ CONFIG_FILE: ".agent/config.json",
9
+ DEFAULT_REPO: "kmamtora/ai-devx",
10
+ DEFAULT_BRANCH: "main",
11
+ TEMPLATES_PATH: "templates/.agent",
12
+ GITHUB_RAW_URL: "https://raw.githubusercontent.com",
13
+ GITHUB_API_URL: "https://api.github.com",
14
+
15
+ // Helper to get folder name based on assistant selection
16
+ getFolderForAssistant(assistants) {
17
+ if (!assistants || assistants.length === 0) {
18
+ return this.AGENT_FOLDER;
19
+ }
20
+
21
+ // Single assistant - use specific folder
22
+ if (assistants.length === 1) {
23
+ const assistant = assistants[0].toLowerCase();
24
+ if (assistant === "claude") return this.CLAUDE_FOLDER;
25
+ if (assistant === "gemini") return this.GEMINI_FOLDER;
26
+ }
27
+
28
+ // Multiple assistants or 'all' - use default .agent folder
29
+ return this.AGENT_FOLDER;
30
+ },
31
+
32
+ // Get all possible agent folder names
33
+ getAllFolderNames() {
34
+ return [this.AGENT_FOLDER, this.CLAUDE_FOLDER, this.GEMINI_FOLDER];
35
+ },
36
+
13
37
  AGENTS: {
14
38
  frontend: {
15
- name: 'frontend-specialist',
16
- description: 'Expert in React, Vue, Angular and modern frontend development',
17
- skills: ['react-best-practices', 'vue-expert', 'tailwind-patterns', 'frontend-design']
39
+ name: "frontend-specialist",
40
+ description:
41
+ "Expert in React, Vue, Angular and modern frontend development",
42
+ skills: [
43
+ "react-best-practices",
44
+ "vue-expert",
45
+ "tailwind-patterns",
46
+ "frontend-design",
47
+ ],
18
48
  },
19
49
  backend: {
20
- name: 'backend-specialist',
21
- description: 'Expert in Node.js, Python, Go backend development',
22
- skills: ['api-patterns', 'nodejs-best-practices', 'database-design']
50
+ name: "backend-specialist",
51
+ description: "Expert in Node.js, Python, Go backend development",
52
+ skills: ["api-patterns", "nodejs-best-practices", "database-design"],
23
53
  },
24
54
  security: {
25
- name: 'security-auditor',
26
- description: 'Security expert for vulnerability scanning and best practices',
27
- skills: ['vulnerability-scanner', 'security-best-practices']
55
+ name: "security-auditor",
56
+ description:
57
+ "Security expert for vulnerability scanning and best practices",
58
+ skills: ["vulnerability-scanner", "security-best-practices"],
28
59
  },
29
60
  database: {
30
- name: 'database-architect',
31
- description: 'Database design and optimization expert',
32
- skills: ['database-design', 'prisma-expert', 'sql-optimization']
61
+ name: "database-architect",
62
+ description: "Database design and optimization expert",
63
+ skills: ["database-design", "prisma-expert", "sql-optimization"],
33
64
  },
34
65
  devops: {
35
- name: 'devops-engineer',
36
- description: 'DevOps and deployment expert',
37
- skills: ['docker-expert', 'deployment-procedures', 'ci-cd']
66
+ name: "devops-engineer",
67
+ description: "DevOps and deployment expert",
68
+ skills: ["docker-expert", "deployment-procedures", "ci-cd"],
38
69
  },
39
70
  testing: {
40
- name: 'test-engineer',
41
- description: 'Testing and QA expert',
42
- skills: ['testing-patterns', 'webapp-testing', 'tdd-workflow']
71
+ name: "test-engineer",
72
+ description: "Testing and QA expert",
73
+ skills: ["testing-patterns", "webapp-testing", "tdd-workflow"],
43
74
  },
44
75
  debugger: {
45
- name: 'debugger',
46
- description: 'Systematic debugging expert',
47
- skills: ['systematic-debugging', 'performance-profiling']
76
+ name: "debugger",
77
+ description: "Systematic debugging expert",
78
+ skills: ["systematic-debugging", "performance-profiling"],
48
79
  },
49
80
  planner: {
50
- name: 'project-planner',
51
- description: 'Project planning and architecture expert',
52
- skills: ['brainstorming', 'plan-writing', 'architecture']
81
+ name: "project-planner",
82
+ description: "Project planning and architecture expert",
83
+ skills: ["brainstorming", "plan-writing", "architecture"],
53
84
  },
54
85
  orchestrator: {
55
- name: 'orchestrator',
56
- description: 'Multi-agent coordination specialist',
57
- skills: ['parallel-agents', 'behavioral-modes']
58
- }
86
+ name: "orchestrator",
87
+ description: "Multi-agent coordination specialist",
88
+ skills: ["parallel-agents", "behavioral-modes"],
89
+ },
59
90
  },
60
-
91
+
61
92
  WORKFLOWS: [
62
- { command: '/brainstorm', description: 'Explore options before implementation', agent: 'project-planner' },
63
- { command: '/create', description: 'Create new features or apps', agent: 'orchestrator' },
64
- { command: '/debug', description: 'Systematic debugging', agent: 'debugger' },
65
- { command: '/deploy', description: 'Deploy application', agent: 'devops-engineer' },
66
- { command: '/enhance', description: 'Improve existing code', agent: 'frontend' },
67
- { command: '/orchestrate', description: 'Multi-agent coordination', agent: 'orchestrator' },
68
- { command: '/plan', description: 'Create task breakdown', agent: 'project-planner' },
69
- { command: '/test', description: 'Generate and run tests', agent: 'test-engineer' },
70
- { command: '/security', description: 'Security audit and fixes', agent: 'security-auditor' }
71
- ]
93
+ {
94
+ command: "/brainstorm",
95
+ description: "Explore options before implementation",
96
+ agent: "project-planner",
97
+ },
98
+ {
99
+ command: "/create",
100
+ description: "Create new features or apps",
101
+ agent: "orchestrator",
102
+ },
103
+ {
104
+ command: "/debug",
105
+ description: "Systematic debugging",
106
+ agent: "debugger",
107
+ },
108
+ {
109
+ command: "/deploy",
110
+ description: "Deploy application",
111
+ agent: "devops-engineer",
112
+ },
113
+ {
114
+ command: "/enhance",
115
+ description: "Improve existing code",
116
+ agent: "frontend",
117
+ },
118
+ {
119
+ command: "/orchestrate",
120
+ description: "Multi-agent coordination",
121
+ agent: "orchestrator",
122
+ },
123
+ {
124
+ command: "/plan",
125
+ description: "Create task breakdown",
126
+ agent: "project-planner",
127
+ },
128
+ {
129
+ command: "/test",
130
+ description: "Generate and run tests",
131
+ agent: "test-engineer",
132
+ },
133
+ {
134
+ command: "/security",
135
+ description: "Security audit and fixes",
136
+ agent: "security-auditor",
137
+ },
138
+ ],
72
139
  };
@@ -1,5 +1,5 @@
1
- const fs = require('fs-extra');
2
- const path = require('path');
1
+ const fs = require("fs-extra");
2
+ const path = require("path");
3
3
 
4
4
  const fileUtils = {
5
5
  async ensureDir(dirPath) {
@@ -8,12 +8,12 @@ const fileUtils = {
8
8
 
9
9
  async copyDir(src, dest, options = {}) {
10
10
  const { force = false, dryRun = false } = options;
11
-
11
+
12
12
  if (dryRun) {
13
13
  return { success: true, message: `Would copy ${src} to ${dest}` };
14
14
  }
15
15
 
16
- if (await fs.pathExists(dest) && !force) {
16
+ if ((await fs.pathExists(dest)) && !force) {
17
17
  throw new Error(`Directory already exists: ${dest}`);
18
18
  }
19
19
 
@@ -23,7 +23,7 @@ const fileUtils = {
23
23
 
24
24
  async readJson(filePath) {
25
25
  try {
26
- const content = await fs.readFile(filePath, 'utf-8');
26
+ const content = await fs.readFile(filePath, "utf-8");
27
27
  return JSON.parse(content);
28
28
  } catch (error) {
29
29
  return null;
@@ -35,30 +35,41 @@ const fileUtils = {
35
35
  },
36
36
 
37
37
  async getVersion(agentPath) {
38
- const versionFile = path.join(agentPath, 'VERSION');
38
+ const versionFile = path.join(agentPath, "VERSION");
39
39
  try {
40
- const version = await fs.readFile(versionFile, 'utf-8');
40
+ const version = await fs.readFile(versionFile, "utf-8");
41
41
  return version.trim();
42
42
  } catch (error) {
43
43
  return null;
44
44
  }
45
45
  },
46
46
 
47
- async isInstalled(targetPath) {
48
- const agentPath = path.join(targetPath, '.agent');
47
+ async isInstalled(targetPath, folderName = ".agent") {
48
+ const agentPath = path.join(targetPath, folderName);
49
49
  return await fs.pathExists(agentPath);
50
50
  },
51
51
 
52
+ async findInstalledFolder(targetPath) {
53
+ const folders = [".agent", ".claude", ".gemini"];
54
+ for (const folder of folders) {
55
+ const folderPath = path.join(targetPath, folder);
56
+ if (await fs.pathExists(folderPath)) {
57
+ return folder;
58
+ }
59
+ }
60
+ return null;
61
+ },
62
+
52
63
  async backup(targetPath) {
53
- const agentPath = path.join(targetPath, '.agent');
64
+ const agentPath = path.join(targetPath, ".agent");
54
65
  const backupPath = path.join(targetPath, `.agent.backup.${Date.now()}`);
55
-
66
+
56
67
  if (await fs.pathExists(agentPath)) {
57
68
  await fs.copy(agentPath, backupPath);
58
69
  return backupPath;
59
70
  }
60
71
  return null;
61
- }
72
+ },
62
73
  };
63
74
 
64
75
  module.exports = fileUtils;