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 +8 -8
- package/dist/cli/commands/config.d.ts +4 -4
- package/dist/cli/commands/config.js +67 -67
- package/dist/cli/commands/init.js +31 -31
- package/dist/cli/commands/update.js +10 -10
- package/dist/core/adapters/base-adapter.d.ts +9 -9
- package/dist/core/adapters/base-adapter.js +7 -7
- package/dist/templates/agents/agents.md +1 -1
- package/dist/templates/agents/octo.md +1 -1
- package/dist/templates/agents/warp.md +1 -1
- package/dist/types/agent.d.ts +6 -2
- package/dist/types/config.d.ts +12 -5
- package/dist/types/config.js +26 -9
- package/dist/utils/integration-selector.d.ts +8 -0
- package/dist/utils/integration-selector.js +60 -0
- package/dist/utils/provider-selector.js +12 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
| Version | Highlights | Details |
|
|
14
14
|
| --- | --- | --- |
|
|
15
|
-
| **v3.
|
|
16
|
-
| **v3.
|
|
17
|
-
| **
|
|
18
|
-
| **
|
|
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/
|
|
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 [
|
|
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/
|
|
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
|
|
16
|
-
private
|
|
17
|
-
private
|
|
18
|
-
private
|
|
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
|
|
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
|
|
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 '
|
|
99
|
-
await this.
|
|
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
|
|
113
|
+
async manageIntegrations(config, configPath) {
|
|
114
114
|
const agentManager = new AgentManager();
|
|
115
115
|
while (true) {
|
|
116
|
-
// Show current
|
|
117
|
-
this.log(chalk.cyan('\n📦 Current
|
|
118
|
-
if (config.
|
|
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
|
|
123
|
-
const adapter = agentManager.getAdapter(
|
|
124
|
-
const displayName = adapter?.displayName ||
|
|
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
|
|
136
|
-
{ name: 'Remove
|
|
137
|
-
{ name: 'Replace all
|
|
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.
|
|
146
|
+
await this.addIntegrations(config, configPath);
|
|
147
147
|
break;
|
|
148
148
|
case 'remove':
|
|
149
|
-
await this.
|
|
149
|
+
await this.removeIntegrations(config, configPath);
|
|
150
150
|
break;
|
|
151
151
|
case 'replace':
|
|
152
|
-
await this.
|
|
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
|
|
159
|
+
async addIntegrations(config, configPath) {
|
|
160
160
|
const agentManager = new AgentManager();
|
|
161
|
-
const
|
|
161
|
+
const allIntegrations = agentManager.getAdapters();
|
|
162
162
|
// Show only non-selected providers
|
|
163
|
-
const availableToAdd =
|
|
163
|
+
const availableToAdd = allIntegrations.filter((a) => !config.integrations.includes(a.name));
|
|
164
164
|
if (availableToAdd.length === 0) {
|
|
165
|
-
this.log(chalk.yellow('\n✓ All
|
|
165
|
+
this.log(chalk.yellow('\n✓ All integrations already added!'));
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
// Multi-select checkbox
|
|
169
|
-
const {
|
|
169
|
+
const { newIntegrations } = await inquirer.prompt([
|
|
170
170
|
{
|
|
171
171
|
type: 'checkbox',
|
|
172
|
-
name: '
|
|
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 (
|
|
181
|
-
this.log(chalk.gray('No
|
|
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.
|
|
185
|
+
config.integrations.push(...newIntegrations);
|
|
186
186
|
this.saveConfig(configPath, config);
|
|
187
|
-
this.log(chalk.gray('\n🔧 Generating commands for new
|
|
188
|
-
// Generate commands for new
|
|
189
|
-
for (const
|
|
190
|
-
const adapter = agentManager.getAdapter(
|
|
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✅
|
|
197
|
+
this.log(chalk.green('\n✅ Integrations added successfully!'));
|
|
198
198
|
}
|
|
199
|
-
async
|
|
200
|
-
if (config.
|
|
201
|
-
this.log(chalk.yellow('\n⚠ No
|
|
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
|
|
206
|
-
const {
|
|
205
|
+
// Multi-select from current integrations
|
|
206
|
+
const { integrationsToRemove } = await inquirer.prompt([
|
|
207
207
|
{
|
|
208
208
|
type: 'checkbox',
|
|
209
|
-
name: '
|
|
209
|
+
name: 'integrationsToRemove',
|
|
210
210
|
message: 'Select providers to remove:',
|
|
211
|
-
choices: config.
|
|
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.
|
|
220
|
-
return 'You must keep at least one
|
|
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 (
|
|
227
|
-
this.log(chalk.gray('No
|
|
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
|
|
235
|
+
message: 'Remove command files for these integrations?',
|
|
236
236
|
default: true,
|
|
237
237
|
},
|
|
238
238
|
]);
|
|
239
239
|
// Remove from config
|
|
240
|
-
config.
|
|
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
|
|
246
|
-
const adapter = agentManager.getAdapter(
|
|
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✅
|
|
253
|
+
this.log(chalk.green('\n✅ Integrations removed successfully!'));
|
|
254
254
|
}
|
|
255
|
-
async
|
|
255
|
+
async replaceIntegrations(config, configPath) {
|
|
256
256
|
const agentManager = new AgentManager();
|
|
257
257
|
// Use shared provider selector
|
|
258
|
-
const {
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
this.log(chalk.gray('No
|
|
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
|
|
265
|
-
const deselected = config.
|
|
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
|
|
270
|
-
const adapter = agentManager.getAdapter(
|
|
271
|
-
const displayName = adapter?.displayName ||
|
|
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
|
|
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
|
|
288
|
-
for (const
|
|
289
|
-
const adapter = agentManager.getAdapter(
|
|
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.
|
|
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
|
|
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✅
|
|
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.
|
|
366
|
+
providers: config.integrations, // Keep existing integrations
|
|
367
367
|
};
|
|
368
368
|
this.saveConfig(configPath, defaultConfig);
|
|
369
|
-
this.log(chalk.green('✅ Configuration reset to defaults (
|
|
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('
|
|
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
|
|
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
|
-
|
|
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
|
|
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 {
|
|
57
|
-
const
|
|
58
|
-
if (!
|
|
59
|
-
console.log(chalk.red('\n✗ No
|
|
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
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
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
|
|
67
|
-
const adapter = agentManager.getAdapter(
|
|
68
|
-
const displayName = adapter?.displayName ||
|
|
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
|
|
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
|
|
86
|
-
for (const
|
|
87
|
-
const adapter = agentManager.getAdapter(
|
|
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
|
-
|
|
97
|
-
console.log(chalk.gray('\n✓ Keeping all
|
|
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(
|
|
106
|
+
await this.generateConfig(selectedIntegrations);
|
|
107
107
|
// Generate INSTRUCTIONS.md
|
|
108
108
|
await this.generateInstructions();
|
|
109
|
-
// Generate commands for each selected
|
|
110
|
-
console.log(chalk.cyan(`\n📝 Generating commands for ${
|
|
111
|
-
for (const
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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(
|
|
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 (
|
|
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(
|
|
248
|
+
async generateConfig(integrations) {
|
|
249
249
|
const config = {
|
|
250
250
|
...DEFAULT_CONFIG,
|
|
251
|
-
|
|
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
|
|
50
|
+
// Load config to determine integrations
|
|
51
51
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
52
|
-
const
|
|
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
|
|
58
|
+
for (const integrationName of integrations) {
|
|
59
59
|
// Handle AGENTS.md separately
|
|
60
|
-
if (
|
|
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 (
|
|
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 (
|
|
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(
|
|
80
|
+
const adapter = agentManager.getAdapter(integrationName);
|
|
81
81
|
if (!adapter) {
|
|
82
|
-
this.log(chalk.yellow(` ⚠ Unknown
|
|
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 &&
|
|
87
|
-
updatedCount += await this.updateDocumentation(adapter,
|
|
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,
|
|
1
|
+
import { AgentAdapter, CommandTemplate, ManagedBlock, IntegrationFeatures, ValidationResult } from '../../types/agent.js';
|
|
2
2
|
/**
|
|
3
|
-
* Base adapter class with shared logic for all
|
|
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?:
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
43
|
+
* Format command content for this integration
|
|
44
44
|
* Default: return content as-is
|
|
45
|
-
* Override for
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
121
|
+
* Format command content for this integration
|
|
122
122
|
* Default: return content as-is
|
|
123
|
-
* Override for
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface AgentAdapter {
|
|
|
6
6
|
displayName: string;
|
|
7
7
|
directory: string;
|
|
8
8
|
fileExtension: string;
|
|
9
|
-
features?:
|
|
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
|
|
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[];
|
package/dist/types/config.d.ts
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface ClavixConfig {
|
|
5
5
|
version: string;
|
|
6
|
-
|
|
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
|
|
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
|
|
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 (
|
|
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
|
package/dist/types/config.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Configuration types for Clavix
|
|
3
3
|
*/
|
|
4
4
|
export const DEFAULT_CONFIG = {
|
|
5
|
-
version: '
|
|
6
|
-
|
|
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 (
|
|
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: '
|
|
28
|
-
|
|
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
|
-
|
|
44
|
-
!('
|
|
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: '
|
|
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: '
|
|
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
|
|
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: '
|
|
37
|
-
{ name: '
|
|
38
|
-
{ name: '
|
|
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
|
+
"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",
|