claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
428 lines • 16.1 kB
JavaScript
/**
* V3 CLI Config Command
* Configuration management
*/
import { output } from '../output.js';
import { configManager, parseConfigValue } from '../services/config-file-manager.js';
import * as path from 'path';
// Init configuration
const initCommand = {
name: 'init',
description: 'Initialize configuration',
options: [
{
name: 'force',
short: 'f',
description: 'Overwrite existing configuration',
type: 'boolean',
default: false
},
{
name: 'sparc',
description: 'Initialize with SPARC methodology',
type: 'boolean',
default: false
},
{
name: 'v3',
description: 'Initialize V3 configuration',
type: 'boolean',
default: true
}
],
action: async (ctx) => {
try {
const configPath = configManager.create(ctx.cwd, undefined, ctx.flags.force);
output.writeln();
output.writeln(output.success(`Configuration created: ${configPath}`));
output.writeln();
const defaults = configManager.getDefaults();
output.writeln(output.bold('Key defaults:'));
output.writeln(` swarm.topology = ${defaults.swarm.topology}`);
output.writeln(` swarm.maxAgents = ${defaults.swarm.maxAgents}`);
output.writeln(` memory.backend = ${defaults.memory.backend}`);
output.writeln(` mcp.transportType = ${defaults.mcp.transportType}`);
return { success: true };
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(message);
return { success: false, exitCode: 1 };
}
}
};
// Get configuration
const getCommand = {
name: 'get',
description: 'Get configuration value',
options: [
{
name: 'key',
short: 'k',
description: 'Configuration key (dot notation)',
type: 'string'
}
],
examples: [
{ command: 'claude-flow config get swarm.topology', description: 'Get swarm topology' },
{ command: 'claude-flow config get -k memory.backend', description: 'Get memory backend' }
],
action: async (ctx) => {
const key = ctx.flags.key || ctx.args[0];
if (!key) {
// Show all config from actual config file (fall back to defaults)
const config = configManager.getConfig(ctx.cwd);
const flatEntries = {};
const flatten = (obj, prefix = '') => {
for (const [k, v] of Object.entries(obj)) {
const fullKey = prefix ? `${prefix}.${k}` : k;
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
flatten(v, fullKey);
}
else {
flatEntries[fullKey] = v;
}
}
};
flatten(config);
if (ctx.flags.format === 'json') {
output.printJson(flatEntries);
return { success: true, data: flatEntries };
}
output.writeln();
output.writeln(output.bold('Current Configuration'));
output.writeln();
output.printTable({
columns: [
{ key: 'key', header: 'Key', width: 25 },
{ key: 'value', header: 'Value', width: 30 }
],
data: Object.entries(flatEntries).map(([k, v]) => ({ key: k, value: String(v) }))
});
return { success: true, data: flatEntries };
}
const value = configManager.get(ctx.cwd, key);
if (value === undefined) {
output.printError(`Configuration key not found: ${key}`);
return { success: false, exitCode: 1 };
}
if (ctx.flags.format === 'json') {
output.printJson({ key, value });
}
else {
output.writeln(`${key} = ${value}`);
}
return { success: true, data: { key, value } };
}
};
// Set configuration
const setCommand = {
name: 'set',
description: 'Set configuration value',
options: [
{
name: 'key',
short: 'k',
description: 'Configuration key',
type: 'string',
required: true
},
{
name: 'value',
short: 'v',
description: 'Configuration value',
type: 'string',
required: true
}
],
examples: [
{ command: 'claude-flow config set swarm.maxAgents 20', description: 'Set max agents' },
{ command: 'claude-flow config set -k memory.backend -v agentdb', description: 'Set memory backend' }
],
action: async (ctx) => {
const key = ctx.flags.key || ctx.args[0];
const value = ctx.flags.value || ctx.args[1];
if (!key || value === undefined) {
output.printError('Both key and value are required');
return { success: false, exitCode: 1 };
}
try {
const parsedValue = parseConfigValue(value);
configManager.set(ctx.cwd, key, parsedValue);
output.writeln(`Set ${key} = ${value}`);
return { success: true };
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(message);
return { success: false, exitCode: 1 };
}
}
};
// List providers
const providersCommand = {
name: 'providers',
description: 'Manage AI providers',
options: [
{
name: 'add',
short: 'a',
description: 'Add provider',
type: 'string'
},
{
name: 'remove',
short: 'r',
description: 'Remove provider',
type: 'string'
},
{
name: 'enable',
description: 'Enable provider',
type: 'string'
},
{
name: 'disable',
description: 'Disable provider',
type: 'string'
}
],
action: async (ctx) => {
const defaultProviders = [
{ name: 'anthropic', model: 'claude-3-5-sonnet-20241022', priority: 1, enabled: true, status: 'Active' },
{ name: 'openrouter', model: 'claude-3.5-sonnet', priority: 2, enabled: false, status: 'Disabled' },
{ name: 'ollama', model: 'llama3.2', priority: 3, enabled: false, status: 'Disabled' },
{ name: 'gemini', model: 'gemini-2.0-flash', priority: 4, enabled: false, status: 'Disabled' }
];
// Handle mutation flags
const addProvider = ctx.flags.add;
const removeProvider = ctx.flags.remove;
const enableProvider = ctx.flags.enable;
const disableProvider = ctx.flags.disable;
if (addProvider || removeProvider || enableProvider || disableProvider) {
// Read current providers from config
let currentProviders = configManager.get(ctx.cwd, 'providers') || [];
if (!Array.isArray(currentProviders))
currentProviders = [];
if (addProvider) {
const exists = currentProviders.some((p) => p.name === addProvider);
if (exists) {
output.printError(`Provider '${addProvider}' already exists`);
return { success: false, exitCode: 1 };
}
currentProviders.push({ name: addProvider, enabled: true, priority: currentProviders.length + 1 });
output.writeln(output.success(`Added provider: ${addProvider}`));
}
if (removeProvider) {
const before = currentProviders.length;
currentProviders = currentProviders.filter((p) => p.name !== removeProvider);
if (currentProviders.length === before) {
output.printError(`Provider '${removeProvider}' not found`);
return { success: false, exitCode: 1 };
}
output.writeln(output.success(`Removed provider: ${removeProvider}`));
}
if (enableProvider) {
const p = currentProviders.find((p) => p.name === enableProvider);
if (p) {
p.enabled = true;
output.writeln(output.success(`Enabled provider: ${enableProvider}`));
}
else {
output.printError(`Provider '${enableProvider}' not found`);
return { success: false, exitCode: 1 };
}
}
if (disableProvider) {
const p = currentProviders.find((p) => p.name === disableProvider);
if (p) {
p.enabled = false;
output.writeln(output.success(`Disabled provider: ${disableProvider}`));
}
else {
output.printError(`Provider '${disableProvider}' not found`);
return { success: false, exitCode: 1 };
}
}
try {
configManager.set(ctx.cwd, 'providers', currentProviders);
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(`Failed to save providers: ${message}`);
return { success: false, exitCode: 1 };
}
return { success: true, data: currentProviders };
}
// Read providers from config, fall back to defaults
const configuredProviders = configManager.get(ctx.cwd, 'providers');
const providers = (Array.isArray(configuredProviders) && configuredProviders.length > 0)
? configuredProviders.map((p, i) => ({
name: String(p.name || ''),
model: String(p.model || ''),
priority: Number(p.priority || i + 1),
enabled: p.enabled !== false,
status: p.enabled !== false ? 'Active' : 'Disabled',
}))
: defaultProviders;
if (ctx.flags.format === 'json') {
output.printJson(providers);
return { success: true, data: providers };
}
output.writeln();
output.writeln(output.bold('AI Providers'));
output.writeln();
output.printTable({
columns: [
{ key: 'name', header: 'Provider', width: 12 },
{ key: 'model', header: 'Model', width: 25 },
{ key: 'priority', header: 'Priority', width: 10, align: 'right' },
{ key: 'status', header: 'Status', width: 10, format: (v) => {
if (v === 'Active')
return output.success(String(v));
return output.dim(String(v));
} }
],
data: providers
});
output.writeln();
output.writeln(output.dim('Use --add, --remove, --enable, --disable to manage providers'));
return { success: true, data: providers };
}
};
// Reset configuration
const resetCommand = {
name: 'reset',
description: 'Reset configuration to defaults',
options: [
{
name: 'force',
short: 'f',
description: 'Skip confirmation',
type: 'boolean',
default: false
},
{
name: 'section',
description: 'Reset specific section only',
type: 'string',
choices: ['agents', 'swarm', 'memory', 'mcp', 'providers', 'all']
}
],
action: async (ctx) => {
try {
const configPath = configManager.reset(ctx.cwd);
output.writeln(`Configuration reset to defaults: ${configPath}`);
return { success: true };
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(message);
return { success: false, exitCode: 1 };
}
}
};
// Export configuration
const exportCommand = {
name: 'export',
description: 'Export configuration',
options: [
{
name: 'output',
short: 'o',
description: 'Output file path',
type: 'string'
},
{
name: 'format',
short: 'f',
description: 'Export format (json, yaml)',
type: 'string',
default: 'json',
choices: ['json', 'yaml']
}
],
action: async (ctx) => {
try {
const exportPath = ctx.flags.output || ctx.args[0] || 'claude-flow.config.export.json';
configManager.exportTo(ctx.cwd, exportPath);
const resolved = path.resolve(ctx.cwd, exportPath);
output.writeln(`Configuration exported to: ${resolved}`);
return { success: true };
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(message);
return { success: false, exitCode: 1 };
}
}
};
// Import configuration
const importCommand = {
name: 'import',
description: 'Import configuration',
options: [
{
name: 'file',
short: 'f',
description: 'Configuration file path',
type: 'string',
required: true
},
{
name: 'merge',
description: 'Merge with existing configuration',
type: 'boolean',
default: false
}
],
action: async (ctx) => {
const file = ctx.flags.file || ctx.args[0];
if (!file) {
output.printError('File path is required');
return { success: false, exitCode: 1 };
}
try {
configManager.importFrom(ctx.cwd, file);
output.writeln(`Configuration imported from: ${path.resolve(ctx.cwd, file)}`);
return { success: true };
}
catch (err) {
const message = err instanceof Error ? err.message : String(err);
output.printError(message);
return { success: false, exitCode: 1 };
}
}
};
// Main config command
export const configCommand = {
name: 'config',
description: 'Configuration management',
subcommands: [initCommand, getCommand, setCommand, providersCommand, resetCommand, exportCommand, importCommand],
options: [],
examples: [
{ command: 'claude-flow config init --v3', description: 'Initialize V3 config' },
{ command: 'claude-flow config get swarm.topology', description: 'Get config value' },
{ command: 'claude-flow config set swarm.maxAgents 20', description: 'Set config value' }
],
action: async (ctx) => {
output.writeln();
output.writeln(output.bold('Configuration Management'));
output.writeln();
output.writeln('Usage: claude-flow config <subcommand> [options]');
output.writeln();
output.writeln('Subcommands:');
output.printList([
`${output.highlight('init')} - Initialize configuration`,
`${output.highlight('get')} - Get configuration value`,
`${output.highlight('set')} - Set configuration value`,
`${output.highlight('providers')} - Manage AI providers`,
`${output.highlight('reset')} - Reset to defaults`,
`${output.highlight('export')} - Export configuration`,
`${output.highlight('import')} - Import configuration`
]);
return { success: true };
}
};
export default configCommand;
//# sourceMappingURL=config.js.map