clavix 3.3.2 → 3.5.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/README.md CHANGED
@@ -12,10 +12,10 @@
12
12
 
13
13
  | Version | Highlights | Details |
14
14
  | --- | --- | --- |
15
- | **v3.1.0** (Latest) | Clavix Intelligence™ brand evolution | [Changelog](CHANGELOG.md#310---2025-11-23) |
16
- | **v3.0.1** | Enhanced intent detection (95%+ accuracy) | [Changelog](CHANGELOG.md#301---2025-11-22) |
17
- | **v2.8.0** | Pure ESM package (breaking change) | [Changelog](CHANGELOG.md#280---2025-11-17) |
18
- | **v2.7.0** | Prompt lifecycle management | [Changelog](CHANGELOG.md#270---2025-11-15) |
15
+ | **v3.4.0** (Latest) | Provider categorization fixes | [Changelog](CHANGELOG.md#340---2025-11-24) |
16
+ | **v3.3.1** | JSON5/JSON config bug fix | [Changelog](CHANGELOG.md#331---2025-11-23) |
17
+ | **v3.3.0** | Provider management & interactive config | [Changelog](CHANGELOG.md#330---2025-11-23) |
18
+ | **v3.1.0** | Clavix Intelligence™ brand evolution | [Changelog](CHANGELOG.md#310---2025-11-23) |
19
19
 
20
20
  **Requirements:** Node.js ≥ 16.0.0 (ESM support required)
21
21
 
@@ -44,10 +44,10 @@ Clavix uses **Clavix Intelligence™** (v3.0+) to automatically:
44
44
  | Category | Providers |
45
45
  | --- | --- |
46
46
  | IDE & editor extensions | Cursor · Windsurf · Kilocode · Roocode · Cline |
47
- | CLI agents | Claude Code · Droid CLI · CodeBuddy CLI · OpenCode · Gemini CLI · Qwen Code · Amp · Crush CLI · Codex CLI · Augment CLI |
47
+ | CLI agents | Claude Code · Droid CLI · CodeBuddy CLI · OpenCode · Gemini CLI · Qwen Code · LLXPRT · Amp · Crush CLI · Codex CLI · Augment CLI |
48
48
  | Universal adapters | AGENTS.md · GitHub Copilot · OCTO.md · WARP.md |
49
49
 
50
- Provider paths and argument placeholders are listed in [docs/providers.md](docs/providers.md).
50
+ Provider paths and argument placeholders are listed in [docs/integrations.md](docs/integrations.md).
51
51
 
52
52
  ## Quickstart
53
53
 
@@ -81,7 +81,7 @@ clavix implement # Start implementation workflow
81
81
  clavix task-complete <taskId> # Mark tasks done with auto-commit
82
82
  ```
83
83
 
84
- **Supported agents**: Claude Code, Cursor, Windsurf, and [15+ more providers](docs/providers.md)
84
+ **Supported agents**: Claude Code, Cursor, Windsurf, and [17+ more providers](docs/integrations.md)
85
85
 
86
86
  Learn more: [Complete prompt lifecycle documentation](docs/commands/execute.md)
87
87
 
@@ -99,7 +99,7 @@ clavix prd
99
99
  ## Full documentation
100
100
  - Overview & navigation: [docs/README.md](docs/README.md)
101
101
  - Command reference: [docs/commands/](docs/commands/README.md)
102
- - Providers: [docs/providers.md](docs/providers.md)
102
+ - Providers: [docs/integrations.md](docs/integrations.md)
103
103
  - Clavix Intelligence: [docs/clavix-intelligence.md](docs/clavix-intelligence.md)
104
104
  - Guides: [docs/guides/](docs/guides/workflows.md)
105
105
 
@@ -12,10 +12,10 @@ export default class Config extends Command {
12
12
  };
13
13
  run(): Promise<void>;
14
14
  private showInteractiveMenu;
15
- private manageProviders;
16
- private addProviders;
17
- private removeProviders;
18
- private replaceProviders;
15
+ private manageIntegrations;
16
+ private addIntegrations;
17
+ private removeIntegrations;
18
+ private replaceIntegrations;
19
19
  private getConfig;
20
20
  private setConfig;
21
21
  private editConfig;
@@ -10,7 +10,7 @@ export default class Config extends Command {
10
10
  static description = 'Manage Clavix configuration';
11
11
  static examples = [
12
12
  '<%= config.bin %> <%= command.id %>',
13
- '<%= config.bin %> <%= command.id %> get providers',
13
+ '<%= config.bin %> <%= command.id %> get integrations',
14
14
  '<%= config.bin %> <%= command.id %> set preferences.verboseLogging true',
15
15
  ];
16
16
  static args = {
@@ -84,7 +84,7 @@ export default class Config extends Command {
84
84
  message: 'What would you like to do?',
85
85
  choices: [
86
86
  { name: 'View current configuration', value: 'view' },
87
- { name: 'Manage providers (add/remove)', value: 'providers' },
87
+ { name: 'Manage integrations (add/remove)', value: 'integrations' },
88
88
  { name: 'Edit preferences', value: 'edit-preferences' },
89
89
  { name: 'Reset to defaults', value: 'reset' },
90
90
  { name: 'Exit', value: 'exit' },
@@ -95,8 +95,8 @@ export default class Config extends Command {
95
95
  case 'view':
96
96
  // Already displayed above
97
97
  break;
98
- case 'providers':
99
- await this.manageProviders(config, configPath);
98
+ case 'integrations':
99
+ await this.manageIntegrations(config, configPath);
100
100
  break;
101
101
  case 'edit-preferences':
102
102
  await this.editPreferences(configPath, config);
@@ -110,18 +110,18 @@ export default class Config extends Command {
110
110
  }
111
111
  }
112
112
  }
113
- async manageProviders(config, configPath) {
113
+ async manageIntegrations(config, configPath) {
114
114
  const agentManager = new AgentManager();
115
115
  while (true) {
116
- // Show current providers
117
- this.log(chalk.cyan('\n📦 Current Providers:'));
118
- if (config.providers.length === 0) {
116
+ // Show current integrations
117
+ this.log(chalk.cyan('\n📦 Current Integrations:'));
118
+ if (config.integrations.length === 0) {
119
119
  this.log(chalk.gray(' (none configured)'));
120
120
  }
121
121
  else {
122
- for (const providerName of config.providers) {
123
- const adapter = agentManager.getAdapter(providerName);
124
- const displayName = adapter?.displayName || providerName;
122
+ for (const integrationName of config.integrations) {
123
+ const adapter = agentManager.getAdapter(integrationName);
124
+ const displayName = adapter?.displayName || integrationName;
125
125
  this.log(chalk.gray(` • ${displayName}`));
126
126
  }
127
127
  }
@@ -132,9 +132,9 @@ export default class Config extends Command {
132
132
  name: 'action',
133
133
  message: 'What would you like to do?',
134
134
  choices: [
135
- { name: 'Add provider', value: 'add' },
136
- { name: 'Remove provider', value: 'remove' },
137
- { name: 'Replace all providers', value: 'replace' },
135
+ { name: 'Add integration', value: 'add' },
136
+ { name: 'Remove integration', value: 'remove' },
137
+ { name: 'Replace all integrations', value: 'replace' },
138
138
  { name: 'Back to main menu', value: 'back' },
139
139
  ],
140
140
  },
@@ -143,33 +143,33 @@ export default class Config extends Command {
143
143
  break;
144
144
  switch (action) {
145
145
  case 'add':
146
- await this.addProviders(config, configPath);
146
+ await this.addIntegrations(config, configPath);
147
147
  break;
148
148
  case 'remove':
149
- await this.removeProviders(config, configPath);
149
+ await this.removeIntegrations(config, configPath);
150
150
  break;
151
151
  case 'replace':
152
- await this.replaceProviders(config, configPath);
152
+ await this.replaceIntegrations(config, configPath);
153
153
  break;
154
154
  }
155
155
  // Reload config after modifications
156
156
  config = this.loadConfig(configPath);
157
157
  }
158
158
  }
159
- async addProviders(config, configPath) {
159
+ async addIntegrations(config, configPath) {
160
160
  const agentManager = new AgentManager();
161
- const allProviders = agentManager.getAdapters();
161
+ const allIntegrations = agentManager.getAdapters();
162
162
  // Show only non-selected providers
163
- const availableToAdd = allProviders.filter((a) => !config.providers.includes(a.name));
163
+ const availableToAdd = allIntegrations.filter((a) => !config.integrations.includes(a.name));
164
164
  if (availableToAdd.length === 0) {
165
- this.log(chalk.yellow('\n✓ All providers already added!'));
165
+ this.log(chalk.yellow('\n✓ All integrations already added!'));
166
166
  return;
167
167
  }
168
168
  // Multi-select checkbox
169
- const { newProviders } = await inquirer.prompt([
169
+ const { newIntegrations } = await inquirer.prompt([
170
170
  {
171
171
  type: 'checkbox',
172
- name: 'newProviders',
172
+ name: 'newIntegrations',
173
173
  message: 'Select providers to add:',
174
174
  choices: availableToAdd.map((adapter) => ({
175
175
  name: `${adapter.displayName} (${adapter.directory})`,
@@ -177,38 +177,38 @@ export default class Config extends Command {
177
177
  })),
178
178
  },
179
179
  ]);
180
- if (newProviders.length === 0) {
181
- this.log(chalk.gray('No providers selected'));
180
+ if (newIntegrations.length === 0) {
181
+ this.log(chalk.gray('No integrations selected'));
182
182
  return;
183
183
  }
184
184
  // Add to config
185
- config.providers.push(...newProviders);
185
+ config.integrations.push(...newIntegrations);
186
186
  this.saveConfig(configPath, config);
187
- this.log(chalk.gray('\n🔧 Generating commands for new providers...'));
188
- // Generate commands for new providers
189
- for (const providerName of newProviders) {
190
- const adapter = agentManager.getAdapter(providerName);
187
+ this.log(chalk.gray('\n🔧 Generating commands for new integrations...'));
188
+ // Generate commands for new integrations
189
+ for (const integrationName of newIntegrations) {
190
+ const adapter = agentManager.getAdapter(integrationName);
191
191
  if (!adapter)
192
192
  continue;
193
193
  const templates = await loadCommandTemplates(adapter);
194
194
  await adapter.generateCommands(templates);
195
195
  this.log(chalk.green(` ✓ Generated ${templates.length} command(s) for ${adapter.displayName}`));
196
196
  }
197
- this.log(chalk.green('\n✅ Providers added successfully!'));
197
+ this.log(chalk.green('\n✅ Integrations added successfully!'));
198
198
  }
199
- async removeProviders(config, configPath) {
200
- if (config.providers.length === 0) {
201
- this.log(chalk.yellow('\n⚠ No providers configured!'));
199
+ async removeIntegrations(config, configPath) {
200
+ if (config.integrations.length === 0) {
201
+ this.log(chalk.yellow('\n⚠ No integrations configured!'));
202
202
  return;
203
203
  }
204
204
  const agentManager = new AgentManager();
205
- // Multi-select from current providers
206
- const { providersToRemove } = await inquirer.prompt([
205
+ // Multi-select from current integrations
206
+ const { integrationsToRemove } = await inquirer.prompt([
207
207
  {
208
208
  type: 'checkbox',
209
- name: 'providersToRemove',
209
+ name: 'integrationsToRemove',
210
210
  message: 'Select providers to remove:',
211
- choices: config.providers.map((name) => {
211
+ choices: config.integrations.map((name) => {
212
212
  const adapter = agentManager.getAdapter(name);
213
213
  return {
214
214
  name: `${adapter?.displayName || name} (${adapter?.directory || 'unknown'})`,
@@ -216,15 +216,15 @@ export default class Config extends Command {
216
216
  };
217
217
  }),
218
218
  validate: (answer) => {
219
- if (answer.length === config.providers.length) {
220
- return 'You must keep at least one provider. Use "Reset to defaults" to reconfigure completely.';
219
+ if (answer.length === config.integrations.length) {
220
+ return 'You must keep at least one integration. Use "Reset to defaults" to reconfigure completely.';
221
221
  }
222
222
  return true;
223
223
  },
224
224
  },
225
225
  ]);
226
- if (providersToRemove.length === 0) {
227
- this.log(chalk.gray('No providers selected'));
226
+ if (integrationsToRemove.length === 0) {
227
+ this.log(chalk.gray('No integrations selected'));
228
228
  return;
229
229
  }
230
230
  // Confirm cleanup
@@ -232,43 +232,43 @@ export default class Config extends Command {
232
232
  {
233
233
  type: 'confirm',
234
234
  name: 'cleanup',
235
- message: 'Remove command files for these providers?',
235
+ message: 'Remove command files for these integrations?',
236
236
  default: true,
237
237
  },
238
238
  ]);
239
239
  // Remove from config
240
- config.providers = config.providers.filter((p) => !providersToRemove.includes(p));
240
+ config.integrations = config.integrations.filter((p) => !integrationsToRemove.includes(p));
241
241
  this.saveConfig(configPath, config);
242
242
  // Clean up command files
243
243
  if (cleanup) {
244
244
  this.log(chalk.gray('\n🗑️ Cleaning up command files...'));
245
- for (const providerName of providersToRemove) {
246
- const adapter = agentManager.getAdapter(providerName);
245
+ for (const integrationName of integrationsToRemove) {
246
+ const adapter = agentManager.getAdapter(integrationName);
247
247
  if (adapter) {
248
248
  const removed = await adapter.removeAllCommands();
249
249
  this.log(chalk.gray(` ✓ Removed ${removed} command(s) from ${adapter.displayName}`));
250
250
  }
251
251
  }
252
252
  }
253
- this.log(chalk.green('\n✅ Providers removed successfully!'));
253
+ this.log(chalk.green('\n✅ Integrations removed successfully!'));
254
254
  }
255
- async replaceProviders(config, configPath) {
255
+ async replaceIntegrations(config, configPath) {
256
256
  const agentManager = new AgentManager();
257
257
  // Use shared provider selector
258
- const { selectProviders } = await import('../../utils/provider-selector.js');
259
- const newProviders = await selectProviders(agentManager, config.providers);
260
- if (newProviders.length === 0) {
261
- this.log(chalk.gray('No providers selected'));
258
+ const { selectIntegrations } = await import('../../utils/integration-selector.js');
259
+ const newIntegrations = await selectIntegrations(agentManager, config.integrations);
260
+ if (newIntegrations.length === 0) {
261
+ this.log(chalk.gray('No integrations selected'));
262
262
  return;
263
263
  }
264
- // Find deselected providers
265
- const deselected = config.providers.filter((p) => !newProviders.includes(p));
264
+ // Find deselected integrations
265
+ const deselected = config.integrations.filter((p) => !newIntegrations.includes(p));
266
266
  // Handle cleanup if providers were deselected
267
267
  if (deselected.length > 0) {
268
268
  this.log(chalk.yellow('\n⚠ Previously configured but not selected:'));
269
- for (const providerName of deselected) {
270
- const adapter = agentManager.getAdapter(providerName);
271
- const displayName = adapter?.displayName || providerName;
269
+ for (const integrationName of deselected) {
270
+ const adapter = agentManager.getAdapter(integrationName);
271
+ const displayName = adapter?.displayName || integrationName;
272
272
  const directory = adapter?.directory || 'unknown';
273
273
  this.log(chalk.gray(` • ${displayName} (${directory})`));
274
274
  }
@@ -276,7 +276,7 @@ export default class Config extends Command {
276
276
  {
277
277
  type: 'list',
278
278
  name: 'cleanupAction',
279
- message: 'What would you like to do with these providers?',
279
+ message: 'What would you like to do with these integrations?',
280
280
  choices: [
281
281
  { name: 'Clean up (remove all command files)', value: 'cleanup' },
282
282
  { name: 'Skip (leave as-is)', value: 'skip' },
@@ -284,9 +284,9 @@ export default class Config extends Command {
284
284
  },
285
285
  ]);
286
286
  if (cleanupAction === 'cleanup') {
287
- this.log(chalk.gray('\n🗑️ Cleaning up deselected providers...'));
288
- for (const providerName of deselected) {
289
- const adapter = agentManager.getAdapter(providerName);
287
+ this.log(chalk.gray('\n🗑️ Cleaning up deselected integrations...'));
288
+ for (const integrationName of deselected) {
289
+ const adapter = agentManager.getAdapter(integrationName);
290
290
  if (adapter) {
291
291
  const removed = await adapter.removeAllCommands();
292
292
  this.log(chalk.gray(` ✓ Removed ${removed} command(s) from ${adapter.displayName}`));
@@ -295,7 +295,7 @@ export default class Config extends Command {
295
295
  }
296
296
  }
297
297
  // Update config
298
- config.providers = newProviders;
298
+ config.integrations = newIntegrations;
299
299
  this.saveConfig(configPath, config);
300
300
  // Prompt to run update
301
301
  const { runUpdate } = await inquirer.prompt([
@@ -307,11 +307,11 @@ export default class Config extends Command {
307
307
  },
308
308
  ]);
309
309
  if (runUpdate) {
310
- this.log(chalk.gray('\n🔧 Regenerating commands for all providers...\n'));
310
+ this.log(chalk.gray('\n🔧 Regenerating commands for all integrations...\n'));
311
311
  const Update = (await import('./update.js')).default;
312
312
  await Update.run([]);
313
313
  }
314
- this.log(chalk.green('\n✅ Providers replaced successfully!'));
314
+ this.log(chalk.green('\n✅ Integrations replaced successfully!'));
315
315
  }
316
316
  async getConfig(configPath, key) {
317
317
  const config = this.loadConfig(configPath);
@@ -363,10 +363,10 @@ export default class Config extends Command {
363
363
  const config = this.loadConfig(configPath);
364
364
  const defaultConfig = {
365
365
  ...DEFAULT_CONFIG,
366
- providers: config.providers, // Keep existing providers
366
+ providers: config.integrations, // Keep existing integrations
367
367
  };
368
368
  this.saveConfig(configPath, defaultConfig);
369
- this.log(chalk.green('✅ Configuration reset to defaults (providers preserved)'));
369
+ this.log(chalk.green('✅ Configuration reset to defaults (integrations preserved)'));
370
370
  }
371
371
  async editPreferences(configPath, config) {
372
372
  const preferences = config.preferences || DEFAULT_CONFIG.preferences;
@@ -420,7 +420,7 @@ export default class Config extends Command {
420
420
  }
421
421
  displayConfig(config) {
422
422
  this.log(` ${chalk.gray('Version:')} ${config.version}`);
423
- this.log(` ${chalk.gray('Providers:')} ${config.providers.map(p => chalk.cyan(p)).join(', ') || chalk.gray('(none)')}`);
423
+ this.log(` ${chalk.gray('Integrations:')} ${config.integrations.map(p => chalk.cyan(p)).join(', ') || chalk.gray('(none)')}`);
424
424
  if (config.preferences) {
425
425
  this.log(`\n ${chalk.bold('Preferences:')}`);
426
426
  this.log(` ${chalk.gray('Auto-open outputs:')} ${config.preferences.autoOpenOutputs ? chalk.green('yes') : chalk.gray('no')}`);
@@ -39,33 +39,33 @@ export default class Init extends Command {
39
39
  }
40
40
  // Load existing config if re-initializing
41
41
  const agentManager = new AgentManager();
42
- let existingProviders = [];
42
+ let existingIntegrations = [];
43
43
  if (await FileSystem.exists('.clavix/config.json')) {
44
44
  try {
45
45
  const configContent = await FileSystem.readFile('.clavix/config.json');
46
46
  const config = JSON.parse(configContent);
47
- existingProviders = config.providers || [];
47
+ existingIntegrations = config.integrations || config.providers || [];
48
48
  }
49
49
  catch (error) {
50
50
  // Ignore parse errors, will use empty array
51
51
  }
52
52
  }
53
- // Select providers using shared utility
53
+ // Select integrations using shared utility
54
54
  console.log(chalk.gray('Select AI development tools to support:\n'));
55
55
  console.log(chalk.gray('(Space to select, Enter to confirm)\n'));
56
- const { selectProviders } = await import('../../utils/provider-selector.js');
57
- const selectedProviders = await selectProviders(agentManager, existingProviders);
58
- if (!selectedProviders || selectedProviders.length === 0) {
59
- console.log(chalk.red('\n✗ No providers selected\n'));
56
+ const { selectIntegrations } = await import('../../utils/integration-selector.js');
57
+ const selectedIntegrations = await selectIntegrations(agentManager, existingIntegrations);
58
+ if (!selectedIntegrations || selectedIntegrations.length === 0) {
59
+ console.log(chalk.red('\n✗ No integrations selected\n'));
60
60
  return;
61
61
  }
62
- // Handle deselected providers (cleanup prompt)
63
- const deselectedProviders = existingProviders.filter((p) => !selectedProviders.includes(p));
64
- if (deselectedProviders.length > 0) {
62
+ // Handle deselected integrations (cleanup prompt)
63
+ const deselectedIntegrations = existingIntegrations.filter((p) => !selectedIntegrations.includes(p));
64
+ if (deselectedIntegrations.length > 0) {
65
65
  console.log(chalk.yellow('\n⚠ Previously configured but not selected:'));
66
- for (const providerName of deselectedProviders) {
67
- const adapter = agentManager.getAdapter(providerName);
68
- const displayName = adapter?.displayName || providerName;
66
+ for (const integrationName of deselectedIntegrations) {
67
+ const adapter = agentManager.getAdapter(integrationName);
68
+ const displayName = adapter?.displayName || integrationName;
69
69
  const directory = adapter?.directory || 'unknown';
70
70
  console.log(chalk.gray(` • ${displayName} (${directory})`));
71
71
  }
@@ -73,7 +73,7 @@ export default class Init extends Command {
73
73
  {
74
74
  type: 'list',
75
75
  name: 'cleanupAction',
76
- message: 'What would you like to do with these providers?',
76
+ message: 'What would you like to do with these integrations?',
77
77
  choices: [
78
78
  { name: 'Clean up (remove all command files)', value: 'cleanup' },
79
79
  { name: 'Keep (also update their commands)', value: 'update' },
@@ -82,9 +82,9 @@ export default class Init extends Command {
82
82
  },
83
83
  ]);
84
84
  if (cleanupAction === 'cleanup') {
85
- console.log(chalk.gray('\n🗑️ Cleaning up deselected providers...'));
86
- for (const providerName of deselectedProviders) {
87
- const adapter = agentManager.getAdapter(providerName);
85
+ console.log(chalk.gray('\n🗑️ Cleaning up deselected integrations...'));
86
+ for (const integrationName of deselectedIntegrations) {
87
+ const adapter = agentManager.getAdapter(integrationName);
88
88
  if (adapter) {
89
89
  const removed = await adapter.removeAllCommands();
90
90
  console.log(chalk.gray(` ✓ Removed ${removed} command(s) from ${adapter.displayName}`));
@@ -93,8 +93,8 @@ export default class Init extends Command {
93
93
  }
94
94
  else if (cleanupAction === 'update') {
95
95
  // Add them back to selection
96
- selectedProviders.push(...deselectedProviders);
97
- console.log(chalk.gray('\n✓ Keeping all providers\n'));
96
+ selectedIntegrations.push(...deselectedIntegrations);
97
+ console.log(chalk.gray('\n✓ Keeping all integrations\n'));
98
98
  }
99
99
  // If 'skip': do nothing
100
100
  }
@@ -103,36 +103,36 @@ export default class Init extends Command {
103
103
  await this.createDirectoryStructure();
104
104
  // Generate config
105
105
  console.log(chalk.cyan('⚙️ Generating configuration...'));
106
- await this.generateConfig(selectedProviders);
106
+ await this.generateConfig(selectedIntegrations);
107
107
  // Generate INSTRUCTIONS.md
108
108
  await this.generateInstructions();
109
- // Generate commands for each selected provider
110
- console.log(chalk.cyan(`\n📝 Generating commands for ${selectedProviders.length} provider(s)...\n`));
111
- for (const providerName of selectedProviders) {
109
+ // Generate commands for each selected integration
110
+ console.log(chalk.cyan(`\n📝 Generating commands for ${selectedIntegrations.length} integration(s)...\n`));
111
+ for (const integrationName of selectedIntegrations) {
112
112
  // Handle agents-md separately (it's not an adapter)
113
- if (providerName === 'agents-md') {
113
+ if (integrationName === 'agents-md') {
114
114
  console.log(chalk.gray(' ✓ Generating AGENTS.md...'));
115
115
  await AgentsMdGenerator.generate();
116
116
  continue;
117
117
  }
118
118
  // Handle copilot-instructions separately (it's not an adapter)
119
- if (providerName === 'copilot-instructions') {
119
+ if (integrationName === 'copilot-instructions') {
120
120
  console.log(chalk.gray(' ✓ Generating .github/copilot-instructions.md...'));
121
121
  await CopilotInstructionsGenerator.generate();
122
122
  continue;
123
123
  }
124
124
  // Handle octo-md separately (it's not an adapter)
125
- if (providerName === 'octo-md') {
125
+ if (integrationName === 'octo-md') {
126
126
  console.log(chalk.gray(' ✓ Generating OCTO.md...'));
127
127
  await OctoMdGenerator.generate();
128
128
  continue;
129
129
  }
130
- if (providerName === 'warp-md') {
130
+ if (integrationName === 'warp-md') {
131
131
  console.log(chalk.gray(' ✓ Generating WARP.md...'));
132
132
  await WarpMdGenerator.generate();
133
133
  continue;
134
134
  }
135
- let adapter = agentManager.requireAdapter(providerName);
135
+ let adapter = agentManager.requireAdapter(integrationName);
136
136
  console.log(chalk.gray(` ✓ Generating ${adapter.displayName} commands...`));
137
137
  if (adapter.name === 'codex') {
138
138
  const codexPath = adapter.getCommandPath();
@@ -211,7 +211,7 @@ export default class Init extends Command {
211
211
  console.log(chalk.gray(' Tip: reopen the CLI or run /help to refresh the command list.'));
212
212
  }
213
213
  // Inject documentation blocks (Claude Code only)
214
- if (providerName === 'claude-code') {
214
+ if (integrationName === 'claude-code') {
215
215
  console.log(chalk.gray(' ✓ Injecting CLAUDE.md documentation...'));
216
216
  await this.injectDocumentation(adapter);
217
217
  }
@@ -245,10 +245,10 @@ export default class Init extends Command {
245
245
  await FileSystem.ensureDir(dir);
246
246
  }
247
247
  }
248
- async generateConfig(providers) {
248
+ async generateConfig(integrations) {
249
249
  const config = {
250
250
  ...DEFAULT_CONFIG,
251
- providers,
251
+ integrations,
252
252
  };
253
253
  const configPath = '.clavix/config.json';
254
254
  const configContent = JSON.stringify(config, null, 2);
@@ -47,44 +47,44 @@ export default class Update extends Command {
47
47
  chalk.yellow(' to initialize Clavix in this project.'));
48
48
  }
49
49
  this.log(chalk.bold.cyan('🔄 Updating Clavix integration...\n'));
50
- // Load config to determine providers
50
+ // Load config to determine integrations
51
51
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
52
- const providers = config.providers || ['claude-code'];
52
+ const integrations = config.integrations || config.providers || ['claude-code'];
53
53
  const agentManager = new AgentManager();
54
54
  const updateDocs = flags['docs-only'] || (!flags['docs-only'] && !flags['commands-only']);
55
55
  const updateCommands = flags['commands-only'] || (!flags['docs-only'] && !flags['commands-only']);
56
56
  let updatedCount = 0;
57
57
  // Update for each provider
58
- for (const providerName of providers) {
58
+ for (const integrationName of integrations) {
59
59
  // Handle AGENTS.md separately
60
- if (providerName === 'agents-md') {
60
+ if (integrationName === 'agents-md') {
61
61
  if (updateDocs) {
62
62
  updatedCount += await this.updateAgentsMd(flags.force);
63
63
  }
64
64
  continue;
65
65
  }
66
66
  // Handle Warp separately
67
- if (providerName === 'warp-md') {
67
+ if (integrationName === 'warp-md') {
68
68
  if (updateDocs) {
69
69
  updatedCount += await this.updateWarpMd(flags.force);
70
70
  }
71
71
  continue;
72
72
  }
73
73
  // Handle Octofriend separately
74
- if (providerName === 'octo-md') {
74
+ if (integrationName === 'octo-md') {
75
75
  if (updateDocs) {
76
76
  updatedCount += await this.updateOctoMd(flags.force);
77
77
  }
78
78
  continue;
79
79
  }
80
- const adapter = agentManager.getAdapter(providerName);
80
+ const adapter = agentManager.getAdapter(integrationName);
81
81
  if (!adapter) {
82
- this.log(chalk.yellow(` ⚠ Unknown provider: ${providerName}, skipping...`));
82
+ this.log(chalk.yellow(` ⚠ Unknown integration: ${integrationName}, skipping...`));
83
83
  continue;
84
84
  }
85
85
  // Update documentation blocks (Claude Code only)
86
- if (updateDocs && providerName === 'claude-code') {
87
- updatedCount += await this.updateDocumentation(adapter, providerName, flags.force);
86
+ if (updateDocs && integrationName === 'claude-code') {
87
+ updatedCount += await this.updateDocumentation(adapter, integrationName, flags.force);
88
88
  }
89
89
  // Update slash commands
90
90
  if (updateCommands) {
@@ -1,6 +1,6 @@
1
- import { AgentAdapter, CommandTemplate, ManagedBlock, ProviderFeatures, ValidationResult } from '../../types/agent.js';
1
+ import { AgentAdapter, CommandTemplate, ManagedBlock, IntegrationFeatures, ValidationResult } from '../../types/agent.js';
2
2
  /**
3
- * Base adapter class with shared logic for all providers
3
+ * Base adapter class with shared logic for all integrations
4
4
  * Ensures consistency and reduces code duplication
5
5
  */
6
6
  export declare abstract class BaseAdapter implements AgentAdapter {
@@ -8,12 +8,12 @@ export declare abstract class BaseAdapter implements AgentAdapter {
8
8
  abstract readonly displayName: string;
9
9
  abstract readonly directory: string;
10
10
  abstract readonly fileExtension: string;
11
- readonly features?: ProviderFeatures;
11
+ readonly features?: IntegrationFeatures;
12
12
  abstract detectProject(): Promise<boolean>;
13
13
  abstract getCommandPath(): string;
14
14
  /**
15
15
  * Determine the target filename for a generated command
16
- * Providers can override to customize filename conventions
16
+ * Integrations can override to customize filename conventions
17
17
  */
18
18
  getTargetFilename(name: string): string;
19
19
  /**
@@ -29,25 +29,25 @@ export declare abstract class BaseAdapter implements AgentAdapter {
29
29
  removeAllCommands(): Promise<number>;
30
30
  /**
31
31
  * Determine if a file is a Clavix-generated command
32
- * Override in adapters for provider-specific patterns
32
+ * Override in adapters for integration-specific patterns
33
33
  * @param filename The filename to check
34
34
  * @returns true if this is a Clavix-generated command file
35
35
  */
36
36
  protected isClavixGeneratedCommand(filename: string): boolean;
37
37
  /**
38
38
  * Generate commands - default implementation
39
- * Creates command files in the provider's directory
39
+ * Creates command files in the integration's directory
40
40
  */
41
41
  generateCommands(templates: CommandTemplate[]): Promise<void>;
42
42
  /**
43
- * Format command content for this provider
43
+ * Format command content for this integration
44
44
  * Default: return content as-is
45
- * Override for provider-specific formatting (frontmatter, placeholders, etc.)
45
+ * Override for integration-specific formatting (frontmatter, placeholders, etc.)
46
46
  */
47
47
  protected formatCommand(template: CommandTemplate): string;
48
48
  /**
49
49
  * Default documentation injection - no-op
50
- * Override if provider needs doc injection (like Claude Code)
50
+ * Override if integration needs doc injection (like Claude Code)
51
51
  */
52
52
  injectDocumentation(_blocks: ManagedBlock[]): Promise<void>;
53
53
  /**
@@ -2,14 +2,14 @@ import * as path from 'path';
2
2
  import { FileSystem } from '../../utils/file-system.js';
3
3
  import { IntegrationError } from '../../types/errors.js';
4
4
  /**
5
- * Base adapter class with shared logic for all providers
5
+ * Base adapter class with shared logic for all integrations
6
6
  * Ensures consistency and reduces code duplication
7
7
  */
8
8
  export class BaseAdapter {
9
9
  features;
10
10
  /**
11
11
  * Determine the target filename for a generated command
12
- * Providers can override to customize filename conventions
12
+ * Integrations can override to customize filename conventions
13
13
  */
14
14
  getTargetFilename(name) {
15
15
  return `${name}${this.fileExtension}`;
@@ -88,7 +88,7 @@ export class BaseAdapter {
88
88
  }
89
89
  /**
90
90
  * Determine if a file is a Clavix-generated command
91
- * Override in adapters for provider-specific patterns
91
+ * Override in adapters for integration-specific patterns
92
92
  * @param filename The filename to check
93
93
  * @returns true if this is a Clavix-generated command file
94
94
  */
@@ -98,7 +98,7 @@ export class BaseAdapter {
98
98
  }
99
99
  /**
100
100
  * Generate commands - default implementation
101
- * Creates command files in the provider's directory
101
+ * Creates command files in the integration's directory
102
102
  */
103
103
  async generateCommands(templates) {
104
104
  const commandPath = this.getCommandPath();
@@ -118,16 +118,16 @@ export class BaseAdapter {
118
118
  }
119
119
  }
120
120
  /**
121
- * Format command content for this provider
121
+ * Format command content for this integration
122
122
  * Default: return content as-is
123
- * Override for provider-specific formatting (frontmatter, placeholders, etc.)
123
+ * Override for integration-specific formatting (frontmatter, placeholders, etc.)
124
124
  */
125
125
  formatCommand(template) {
126
126
  return template.content;
127
127
  }
128
128
  /**
129
129
  * Default documentation injection - no-op
130
- * Override if provider needs doc injection (like Claude Code)
130
+ * Override if integration needs doc injection (like Claude Code)
131
131
  */
132
132
  async injectDocumentation(_blocks) {
133
133
  // Default: no documentation injection
@@ -11,7 +11,7 @@ Use these instructions when your agent can only read documentation (no slash-com
11
11
 
12
12
  | Command | Purpose |
13
13
  | --- | --- |
14
- | `clavix init` | Interactive setup. Select providers and generate documentation/command files. |
14
+ | `clavix init` | Interactive setup. Select integrations and generate documentation/command files. |
15
15
  | `clavix fast "<prompt>"` | Quick prompt optimization with quality assessment (Clarity, Efficiency, Structure, Completeness, Actionability). CLI auto-saves to `.clavix/outputs/prompts/fast/`. When using slash commands, agent must save manually per template instructions. |
16
16
  | `clavix deep "<prompt>"` | Comprehensive analysis with alternatives, edge cases, and validation checklists. CLI auto-saves to `.clavix/outputs/prompts/deep/`. When using slash commands, agent must save manually per template instructions. |
17
17
  | `clavix execute [--latest]` | Execute saved prompts from fast/deep optimization. Interactive selection or `--latest` for most recent. |
@@ -267,7 +267,7 @@ When starting implementation with `clavix implement`:
267
267
 
268
268
  | Command | Use it for |
269
269
  | --- | --- |
270
- | `clavix init` | Rebuild `.clavix` structure and regenerate provider assets. |
270
+ | `clavix init` | Rebuild `.clavix` structure and regenerate integration assets. |
271
271
  | `clavix fast` / `clavix deep` | Quality-based prompt improvement (quick vs. comprehensive). CLI auto-saves prompts. Slash commands require manual saving per template instructions. |
272
272
  | `clavix execute` | Execute saved prompts (interactive selection or `--latest` for most recent). |
273
273
  | `clavix prompts list` | View saved prompts with lifecycle status (NEW, EXECUTED, OLD, STALE). |
@@ -8,7 +8,7 @@ Clavix helps Warp developers turn rough ideas into quality, AI-ready prompts and
8
8
  - Verify setup: `clavix version`
9
9
 
10
10
  ### Common commands
11
- - `clavix init` – interactive provider setup (regenerates docs & commands)
11
+ - `clavix init` – interactive integration setup (regenerates docs & commands)
12
12
  - `clavix fast "<prompt>"` – quick quality assessment (5 dimensions) and improved prompt. CLI auto-saves; slash commands need manual saving per template instructions.
13
13
  - `clavix deep "<prompt>"` – comprehensive analysis with alternatives, edge cases, and validation checklists. CLI auto-saves; slash commands need manual saving per template instructions.
14
14
  - `clavix execute [--latest]` – execute saved prompts from fast/deep. Interactive selection or `--latest` for most recent.
@@ -6,7 +6,7 @@ export interface AgentAdapter {
6
6
  displayName: string;
7
7
  directory: string;
8
8
  fileExtension: string;
9
- features?: ProviderFeatures;
9
+ features?: IntegrationFeatures;
10
10
  detectProject(): Promise<boolean>;
11
11
  generateCommands(templates: CommandTemplate[]): Promise<void>;
12
12
  removeAllCommands(): Promise<number>;
@@ -15,13 +15,17 @@ export interface AgentAdapter {
15
15
  getTargetFilename(name: string): string;
16
16
  validate?(): Promise<ValidationResult>;
17
17
  }
18
- export interface ProviderFeatures {
18
+ export interface IntegrationFeatures {
19
19
  supportsFrontmatter?: boolean;
20
20
  supportsExecutableCommands?: boolean;
21
21
  supportsSubdirectories?: boolean;
22
22
  argumentPlaceholder?: string;
23
23
  frontmatterFields?: string[];
24
24
  }
25
+ /**
26
+ * @deprecated Use IntegrationFeatures instead. Will be removed in v4.0.0
27
+ */
28
+ export type ProviderFeatures = IntegrationFeatures;
25
29
  export interface ValidationResult {
26
30
  valid: boolean;
27
31
  errors?: string[];
@@ -3,18 +3,22 @@
3
3
  */
4
4
  export interface ClavixConfig {
5
5
  version: string;
6
- providers: string[];
6
+ integrations: string[];
7
7
  templates: TemplateConfig;
8
8
  outputs: OutputConfig;
9
9
  preferences: PreferencesConfig;
10
10
  experimental?: Record<string, unknown>;
11
11
  }
12
12
  /**
13
- * Legacy config format from v1.3.0 and earlier
13
+ * Legacy config format (pre-v3.5.0)
14
+ * Supports migration from:
15
+ * - v1.3.0 and earlier (single 'agent')
16
+ * - v1.4.0 to v3.4.x ('providers')
14
17
  */
15
18
  export interface LegacyConfig {
16
19
  version: string;
17
- agent: string;
20
+ agent?: string;
21
+ providers?: string[];
18
22
  templates: TemplateConfig;
19
23
  outputs: OutputConfig;
20
24
  preferences: PreferencesConfig;
@@ -36,11 +40,14 @@ export interface PreferencesConfig {
36
40
  }
37
41
  export declare const DEFAULT_CONFIG: ClavixConfig;
38
42
  /**
39
- * Migrate legacy config (v1.3.0 and earlier) to new format
43
+ * Migrate legacy config to current format (v3.5.0+)
44
+ * Handles migration from:
45
+ * - v1.3.0 and earlier (single 'agent' field)
46
+ * - v1.4.0 to v3.4.x ('providers' field)
40
47
  */
41
48
  export declare function migrateConfig(legacy: LegacyConfig): ClavixConfig;
42
49
  /**
43
- * Check if config is legacy format
50
+ * Check if config is legacy format (pre-v3.5.0)
44
51
  */
45
52
  export declare function isLegacyConfig(config: unknown): config is LegacyConfig;
46
53
  //# sourceMappingURL=config.d.ts.map
@@ -2,8 +2,8 @@
2
2
  * Configuration types for Clavix
3
3
  */
4
4
  export const DEFAULT_CONFIG = {
5
- version: '1.4.0',
6
- providers: [],
5
+ version: '3.5.0',
6
+ integrations: [],
7
7
  templates: {
8
8
  prdQuestions: 'default',
9
9
  fullPrd: 'default',
@@ -20,12 +20,29 @@ export const DEFAULT_CONFIG = {
20
20
  },
21
21
  };
22
22
  /**
23
- * Migrate legacy config (v1.3.0 and earlier) to new format
23
+ * Migrate legacy config to current format (v3.5.0+)
24
+ * Handles migration from:
25
+ * - v1.3.0 and earlier (single 'agent' field)
26
+ * - v1.4.0 to v3.4.x ('providers' field)
24
27
  */
25
28
  export function migrateConfig(legacy) {
29
+ // Determine which legacy format we're migrating from
30
+ let integrations;
31
+ if (legacy.providers) {
32
+ // Migration from v1.4.0-v3.4.x (providers → integrations)
33
+ integrations = legacy.providers;
34
+ }
35
+ else if (legacy.agent) {
36
+ // Migration from v1.3.0 and earlier (agent → integrations)
37
+ integrations = [legacy.agent];
38
+ }
39
+ else {
40
+ // Fallback: empty integrations
41
+ integrations = [];
42
+ }
26
43
  return {
27
- version: '1.4.0',
28
- providers: [legacy.agent],
44
+ version: '3.5.0',
45
+ integrations,
29
46
  templates: legacy.templates,
30
47
  outputs: legacy.outputs,
31
48
  preferences: legacy.preferences,
@@ -33,14 +50,14 @@ export function migrateConfig(legacy) {
33
50
  };
34
51
  }
35
52
  /**
36
- * Check if config is legacy format
53
+ * Check if config is legacy format (pre-v3.5.0)
37
54
  */
38
55
  export function isLegacyConfig(config) {
39
56
  return (config !== null &&
40
57
  config !== undefined &&
41
58
  typeof config === 'object' &&
42
- 'agent' in config &&
43
- typeof config.agent === 'string' &&
44
- !('providers' in config));
59
+ (('agent' in config && typeof config.agent === 'string') ||
60
+ ('providers' in config && Array.isArray(config.providers))) &&
61
+ !('integrations' in config));
45
62
  }
46
63
  //# sourceMappingURL=config.js.map
@@ -0,0 +1,8 @@
1
+ import { AgentManager } from '../core/agent-manager.js';
2
+ /**
3
+ * Interactive integration selection utility
4
+ * Displays multi-select checkbox for all available integrations
5
+ * Used by both init and config commands
6
+ */
7
+ export declare function selectIntegrations(agentManager: AgentManager, preSelected?: string[]): Promise<string[]>;
8
+ //# sourceMappingURL=integration-selector.d.ts.map
@@ -0,0 +1,60 @@
1
+ import inquirer from 'inquirer';
2
+ /**
3
+ * Interactive integration selection utility
4
+ * Displays multi-select checkbox for all available integrations
5
+ * Used by both init and config commands
6
+ */
7
+ export async function selectIntegrations(agentManager, preSelected = []) {
8
+ const { selectedIntegrations } = await inquirer.prompt([
9
+ {
10
+ type: 'checkbox',
11
+ name: 'selectedIntegrations',
12
+ message: 'Which AI tools are you using?',
13
+ choices: [
14
+ new inquirer.Separator('=== CLI Tools ==='),
15
+ { name: 'Amp (.agents/commands/)', value: 'amp' },
16
+ { name: 'Augment CLI (.augment/commands/clavix/)', value: 'augment' },
17
+ { name: 'Claude Code (.claude/commands/clavix/)', value: 'claude-code' },
18
+ { name: 'CodeBuddy CLI (.codebuddy/prompts/)', value: 'codebuddy' },
19
+ { name: 'Codex CLI (~/.codex/prompts)', value: 'codex' },
20
+ { name: 'Crush CLI (crush://prompts)', value: 'crush' },
21
+ { name: 'Droid CLI (.droid/clavix/)', value: 'droid' },
22
+ { name: 'Gemini CLI (.gemini/commands/clavix/)', value: 'gemini' },
23
+ { name: 'LLXPRT (~/.llxprt/clavix/)', value: 'llxprt' },
24
+ { name: 'OpenCode (.opencode/clavix/)', value: 'opencode' },
25
+ { name: 'Qwen Code (~/.qwen/commands/clavix/)', value: 'qwen' },
26
+ new inquirer.Separator(),
27
+ new inquirer.Separator('=== IDE & IDE Extensions ==='),
28
+ { name: 'Cline (.cline/workflows/)', value: 'cline' },
29
+ { name: 'Cursor (.cursor/commands/)', value: 'cursor' },
30
+ { name: 'Kilocode (.kilo/clavix/)', value: 'kilocode' },
31
+ { name: 'Roocode (.roo/clavix/)', value: 'roocode' },
32
+ { name: 'Windsurf (.windsurf/rules/)', value: 'windsurf' },
33
+ new inquirer.Separator(),
34
+ new inquirer.Separator('=== Universal Adapters ==='),
35
+ { name: 'AGENTS.md (Universal)', value: 'agents-md' },
36
+ { name: 'GitHub Copilot (.github/copilot-instructions.md)', value: 'copilot-instructions' },
37
+ { name: 'OCTO.md (Universal)', value: 'octo-md' },
38
+ { name: 'WARP.md (Universal)', value: 'warp-md' },
39
+ ].map((choice) => {
40
+ // Keep separators as-is
41
+ if (choice instanceof inquirer.Separator) {
42
+ return choice;
43
+ }
44
+ // Add 'checked' property based on preSelected
45
+ return {
46
+ ...choice,
47
+ checked: preSelected.includes(choice.value),
48
+ };
49
+ }),
50
+ validate: (answer) => {
51
+ if (answer.length === 0) {
52
+ return 'You must select at least one integration.';
53
+ }
54
+ return true;
55
+ },
56
+ },
57
+ ]);
58
+ return selectedIntegrations;
59
+ }
60
+ //# sourceMappingURL=integration-selector.js.map
@@ -14,28 +14,28 @@ export async function selectProviders(agentManager, preSelected = []) {
14
14
  new inquirer.Separator('=== CLI Tools ==='),
15
15
  { name: 'Amp (.agents/commands/)', value: 'amp' },
16
16
  { name: 'Augment CLI (.augment/commands/clavix/)', value: 'augment' },
17
+ { name: 'Claude Code (.claude/commands/clavix/)', value: 'claude-code' },
18
+ { name: 'CodeBuddy CLI (.codebuddy/prompts/)', value: 'codebuddy' },
17
19
  { name: 'Codex CLI (~/.codex/prompts)', value: 'codex' },
18
- { name: 'Droid (.droid/clavix/)', value: 'droid' },
20
+ { name: 'Crush CLI (crush://prompts)', value: 'crush' },
21
+ { name: 'Droid CLI (.droid/clavix/)', value: 'droid' },
19
22
  { name: 'Gemini CLI (.gemini/commands/clavix/)', value: 'gemini' },
20
- { name: 'Kilocode (.kilo/clavix/)', value: 'kilocode' },
21
- { name: 'LLXPRT CLI (.llxprt/clavix/)', value: 'llxprt' },
23
+ { name: 'LLXPRT (~/.llxprt/clavix/)', value: 'llxprt' },
22
24
  { name: 'OpenCode (.opencode/clavix/)', value: 'opencode' },
23
- { name: 'Qwen (通义灵码) (~/.qwen/commands/clavix/)', value: 'qwen' },
24
- { name: 'RooCode (.roo/clavix/)', value: 'roocode' },
25
+ { name: 'Qwen Code (~/.qwen/commands/clavix/)', value: 'qwen' },
25
26
  new inquirer.Separator(),
26
27
  new inquirer.Separator('=== IDE & IDE Extensions ==='),
27
- { name: 'Claude Code (.claude/commands/clavix/)', value: 'claude-code' },
28
28
  { name: 'Cline (.cline/workflows/)', value: 'cline' },
29
- { name: 'CodeBuddy (.codebuddy/prompts/)', value: 'codebuddy' },
30
- { name: 'Copilot Instructions (.github/copilot-instructions.md)', value: 'copilot-instructions' },
31
- { name: 'Crush (crush://prompts)', value: 'crush' },
32
29
  { name: 'Cursor (.cursor/commands/)', value: 'cursor' },
30
+ { name: 'Kilocode (.kilo/clavix/)', value: 'kilocode' },
31
+ { name: 'Roocode (.roo/clavix/)', value: 'roocode' },
33
32
  { name: 'Windsurf (.windsurf/rules/)', value: 'windsurf' },
34
33
  new inquirer.Separator(),
35
34
  new inquirer.Separator('=== Universal Adapters ==='),
36
- { name: 'Agents (AGENTS.md - Universal)', value: 'agents-md' },
37
- { name: 'Octo (OCTO.md - Universal)', value: 'octo-md' },
38
- { name: 'Custom (custom/ directory)', value: 'custom' },
35
+ { name: 'AGENTS.md (Universal)', value: 'agents-md' },
36
+ { name: 'GitHub Copilot (.github/copilot-instructions.md)', value: 'copilot-instructions' },
37
+ { name: 'OCTO.md (Universal)', value: 'octo-md' },
38
+ { name: 'WARP.md (Universal)', value: 'warp-md' },
39
39
  ].map((choice) => {
40
40
  // Keep separators as-is
41
41
  if (choice instanceof inquirer.Separator) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clavix",
3
- "version": "3.3.2",
3
+ "version": "3.5.0",
4
4
  "description": "Clavix Intelligence™ for AI coding. Automatically optimizes prompts with intent detection, quality assessment, and adaptive patterns—no framework to learn. Works with Claude Code, Cursor, Windsurf, and 19+ other AI coding tools.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",