zouroboros-cli 2.0.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.
@@ -0,0 +1,112 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { Database } from 'bun:sqlite';
4
+ import { existsSync } from 'fs';
5
+ import { loadConfig, createMigrationRunner, MIGRATIONS } from 'zouroboros-core';
6
+ function openDb() {
7
+ const config = loadConfig();
8
+ if (!existsSync(config.memory.dbPath)) {
9
+ console.error(chalk.red(`\n❌ Database not found at ${config.memory.dbPath}`));
10
+ console.error(chalk.gray(' Run "zouroboros init" first to create the database.\n'));
11
+ process.exit(1);
12
+ }
13
+ return new Database(config.memory.dbPath);
14
+ }
15
+ export const migrateCommand = new Command('migrate')
16
+ .description('Manage database schema migrations')
17
+ .addCommand(new Command('up')
18
+ .description('Apply pending migrations')
19
+ .option('--to <id>', 'Migrate up to a specific migration ID')
20
+ .action((opts) => {
21
+ const db = openDb();
22
+ try {
23
+ const runner = createMigrationRunner(db);
24
+ const targetId = opts.to ? parseInt(opts.to, 10) : undefined;
25
+ const result = runner.migrate(targetId);
26
+ if (result.applied.length === 0 && result.errors.length === 0) {
27
+ console.log(chalk.green('\n✅ Database is up to date — no pending migrations\n'));
28
+ return;
29
+ }
30
+ if (result.applied.length > 0) {
31
+ console.log(chalk.green(`\n✅ Applied ${result.applied.length} migration(s):\n`));
32
+ for (const name of result.applied) {
33
+ console.log(` ${chalk.gray('↑')} ${name}`);
34
+ }
35
+ }
36
+ if (result.errors.length > 0) {
37
+ console.log(chalk.red(`\n❌ ${result.errors.length} migration(s) failed:\n`));
38
+ for (const { name, error } of result.errors) {
39
+ console.log(` ${chalk.red('✗')} ${name}: ${error}`);
40
+ }
41
+ process.exit(1);
42
+ }
43
+ console.log();
44
+ }
45
+ finally {
46
+ db.close();
47
+ }
48
+ }))
49
+ .addCommand(new Command('down')
50
+ .description('Rollback migrations to a specific point')
51
+ .argument('<target-id>', 'Roll back to this migration ID (0 to rollback all)')
52
+ .action((targetId) => {
53
+ const id = parseInt(targetId, 10);
54
+ if (isNaN(id) || id < 0) {
55
+ console.error(chalk.red('Target ID must be a non-negative integer'));
56
+ process.exit(1);
57
+ }
58
+ const db = openDb();
59
+ try {
60
+ const runner = createMigrationRunner(db);
61
+ const result = runner.rollback(id);
62
+ if (result.applied.length === 0) {
63
+ console.log(chalk.yellow('\nNo migrations to rollback\n'));
64
+ return;
65
+ }
66
+ console.log(chalk.green(`\n✅ Rolled back ${result.applied.length} migration(s):\n`));
67
+ for (const name of result.applied) {
68
+ console.log(` ${chalk.gray('↓')} ${name}`);
69
+ }
70
+ if (result.errors.length > 0) {
71
+ console.log(chalk.red(`\n❌ ${result.errors.length} rollback(s) failed:\n`));
72
+ for (const { name, error } of result.errors) {
73
+ console.log(` ${chalk.red('✗')} ${name}: ${error}`);
74
+ }
75
+ }
76
+ console.log();
77
+ }
78
+ finally {
79
+ db.close();
80
+ }
81
+ }))
82
+ .addCommand(new Command('status')
83
+ .description('Show migration status')
84
+ .action(() => {
85
+ const db = openDb();
86
+ try {
87
+ const runner = createMigrationRunner(db);
88
+ const status = runner.getStatus();
89
+ console.log(chalk.cyan('\nMigration Status:\n'));
90
+ console.log(` Current version: ${status.current || chalk.gray('(none)')}`);
91
+ console.log(` Applied: ${status.applied.length}`);
92
+ console.log(` Pending: ${status.pending.length}`);
93
+ console.log(` Total available: ${MIGRATIONS.length}\n`);
94
+ if (status.applied.length > 0) {
95
+ console.log(chalk.gray(' Applied:'));
96
+ for (const m of status.applied) {
97
+ const date = new Date(m.applied_at * 1000).toLocaleString();
98
+ console.log(` ${chalk.green('✓')} ${m.name} ${chalk.gray(`(${date})`)}`);
99
+ }
100
+ }
101
+ if (status.pending.length > 0) {
102
+ console.log(chalk.gray(' Pending:'));
103
+ for (const m of status.pending) {
104
+ console.log(` ${chalk.yellow('○')} ${m.name}`);
105
+ }
106
+ }
107
+ console.log();
108
+ }
109
+ finally {
110
+ db.close();
111
+ }
112
+ }));
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const personaCommand: Command;
@@ -0,0 +1,45 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ export const personaCommand = new Command('persona')
4
+ .description('Persona management commands')
5
+ .addCommand(new Command('create')
6
+ .description('Create a new persona')
7
+ .argument('<name>', 'Persona name')
8
+ .option('--domain <domain>', 'Domain', 'general')
9
+ .option('--interactive', 'Interactive mode', false)
10
+ .action(async (name, options) => {
11
+ const { generatePersona } = await import('zouroboros-personas');
12
+ if (options.interactive) {
13
+ console.log(chalk.cyan(`\n🎭 Creating persona: ${name}\n`));
14
+ // Interactive mode would go here
15
+ }
16
+ else {
17
+ const slug = name.toLowerCase().replace(/\s+/g, '-');
18
+ const config = {
19
+ name,
20
+ slug,
21
+ domain: options.domain,
22
+ description: `${name} persona for ${options.domain} domain`,
23
+ expertise: [],
24
+ requiresApiKey: false,
25
+ safetyRules: [],
26
+ capabilities: [],
27
+ };
28
+ const genOptions = {
29
+ outputDir: process.cwd(),
30
+ };
31
+ const result = await generatePersona(config, genOptions);
32
+ const files = result.filter((r) => r.output).map((r) => r.output);
33
+ console.log(chalk.green(`✅ Persona '${name}' created`));
34
+ console.log(chalk.gray(` Phases: ${result.length} completed`));
35
+ if (files.length > 0) {
36
+ console.log(chalk.gray(` Output: ${files.join(', ')}`));
37
+ }
38
+ }
39
+ }))
40
+ .addCommand(new Command('list')
41
+ .description('List all personas')
42
+ .action(() => {
43
+ console.log(chalk.cyan('\nAvailable Personas:\n'));
44
+ console.log('Run with --interactive to create one.\n');
45
+ }));
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const skillsCommand: Command;
@@ -0,0 +1,48 @@
1
+ import { Command } from 'commander';
2
+ import { spawn } from 'child_process';
3
+ import { resolve } from 'path';
4
+ const REPO_ROOT = resolve(import.meta.dirname || __dirname, '../../..');
5
+ export const skillsCommand = new Command('skills')
6
+ .description('Manage Zouroboros skills')
7
+ .addCommand(new Command('install')
8
+ .description('Export skills to ~/Skills/ (or custom directory)')
9
+ .option('--dest <dir>', 'Target directory (default: ~/Skills)')
10
+ .option('--skill <name>', 'Install a single skill by name')
11
+ .action((options) => {
12
+ const args = [];
13
+ if (options.dest)
14
+ args.push('--dest', options.dest);
15
+ if (options.skill)
16
+ args.push('--skill', options.skill);
17
+ spawn('bash', [resolve(REPO_ROOT, 'scripts/export-skills.sh'), ...args], {
18
+ stdio: 'inherit',
19
+ });
20
+ }))
21
+ .addCommand(new Command('list')
22
+ .description('List available skills')
23
+ .action(() => {
24
+ console.log(`
25
+ Zouroboros Skills
26
+ ═════════════════
27
+
28
+ Workflow Skills (packages/workflow):
29
+ spec-first-interview Socratic interview & seed specification generator
30
+ three-stage-eval Mechanical/semantic/consensus evaluation pipeline
31
+ autoloop Single-metric optimization loop (inspired by autoresearch)
32
+ unstuck-lateral 5 lateral-thinking personas for creative problem solving
33
+
34
+ Self-Enhancement Skills (packages/selfheal):
35
+ zouroboros-introspect 7-metric health scorecard for Zo ecosystem
36
+ zouroboros-prescribe Auto-generate improvement prescriptions from scorecard
37
+ zouroboros-evolve Execute prescriptions with regression detection
38
+
39
+ Core System Skills:
40
+ zo-swarm-orchestrator Multi-agent swarm orchestration with DAG execution
41
+ zo-memory-system Hybrid SQLite + vector memory engine
42
+
43
+ Install:
44
+ zouroboros skills install # Export all to ~/Skills/
45
+ zouroboros skills install --skill autoloop # Export one skill
46
+ zouroboros skills install --dest ./my-skills # Custom directory
47
+ `);
48
+ }));
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const swarmCommand: Command;
@@ -0,0 +1,32 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { existsSync } from 'fs';
4
+ export const swarmCommand = new Command('swarm')
5
+ .description('Swarm orchestration commands')
6
+ .addCommand(new Command('run')
7
+ .description('Run a swarm campaign')
8
+ .argument('<tasks-file>', 'JSON file with tasks')
9
+ .option('--strategy <strategy>', 'Routing strategy', 'balanced')
10
+ .option('--max-concurrent <n>', 'Max concurrent tasks', '8')
11
+ .action(async (tasksFile, options) => {
12
+ if (!existsSync(tasksFile)) {
13
+ console.log(chalk.red(`Error: Tasks file not found: ${tasksFile}`));
14
+ process.exit(1);
15
+ }
16
+ // Import and run orchestrator
17
+ const { SwarmOrchestrator } = await import('zouroboros-swarm');
18
+ const orchestrator = new SwarmOrchestrator({
19
+ routingStrategy: options.strategy,
20
+ localConcurrency: parseInt(options.maxConcurrent),
21
+ });
22
+ const { readFileSync } = await import('fs');
23
+ const tasks = JSON.parse(readFileSync(tasksFile, 'utf-8'));
24
+ const results = await orchestrator.run(tasks);
25
+ const successCount = results.filter((r) => r.success).length;
26
+ console.log(chalk.green(`\n✅ Campaign complete: ${successCount}/${results.length} tasks succeeded`));
27
+ }))
28
+ .addCommand(new Command('status')
29
+ .description('Check swarm status')
30
+ .action(() => {
31
+ console.log(chalk.cyan('Swarm status: Ready'));
32
+ }));
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const tuiCommand: Command;
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ import { spawn } from 'child_process';
3
+ import { join } from 'path';
4
+ export const tuiCommand = new Command('tui')
5
+ .description('Launch Terminal User Interface dashboard')
6
+ .action(() => {
7
+ // Launch the TUI from the separate tui package
8
+ spawn('bun', [join(__dirname, '../../../tui/src/index.ts')], {
9
+ stdio: 'inherit'
10
+ });
11
+ });
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const workflowCommand: Command;
3
+ export declare const selfhealCommand: Command;
@@ -0,0 +1,87 @@
1
+ import { Command } from 'commander';
2
+ import { spawn } from 'child_process';
3
+ import { join, resolve } from 'path';
4
+ const PACKAGES = resolve(import.meta.dirname || __dirname, '../../../packages');
5
+ function runCli(pkg, cli, args = []) {
6
+ spawn('bun', [join(PACKAGES, pkg, 'src/cli', `${cli}.ts`), ...args], {
7
+ stdio: 'inherit',
8
+ });
9
+ }
10
+ export const workflowCommand = new Command('workflow')
11
+ .description('Workflow tools (interview, evaluate, unstuck, autoloop)')
12
+ .addCommand(new Command('interview')
13
+ .description('Run spec-first interview')
14
+ .option('--topic <topic>', 'Interview topic')
15
+ .action((options) => {
16
+ const args = options.topic ? ['--topic', options.topic] : [];
17
+ runCli('workflow', 'interview', args);
18
+ }))
19
+ .addCommand(new Command('evaluate')
20
+ .description('Run three-stage evaluation')
21
+ .requiredOption('--seed <path>', 'Seed specification file')
22
+ .requiredOption('--artifact <path>', 'Artifact to evaluate')
23
+ .action((options) => {
24
+ runCli('workflow', 'evaluate', ['--seed', options.seed, '--artifact', options.artifact]);
25
+ }))
26
+ .addCommand(new Command('unstuck')
27
+ .description('Run unstuck lateral thinking')
28
+ .argument('<problem>', 'Description of what you are stuck on')
29
+ .action((problem) => {
30
+ runCli('workflow', 'unstuck', [problem]);
31
+ }))
32
+ .addCommand(new Command('autoloop')
33
+ .description('Run autoloop optimization')
34
+ .requiredOption('--program <path>', 'Program.md file')
35
+ .action((options) => {
36
+ runCli('workflow', 'autoloop', ['--program', options.program]);
37
+ }));
38
+ export const selfhealCommand = new Command('selfheal')
39
+ .description('Self-enhancement tools (introspect, prescribe, evolve)')
40
+ .addCommand(new Command('introspect')
41
+ .description('Run 7-metric health scorecard')
42
+ .option('--json', 'Output raw JSON')
43
+ .option('--store', 'Persist scorecard')
44
+ .option('--verbose', 'Print formatted table')
45
+ .action((options) => {
46
+ const args = [];
47
+ if (options.json)
48
+ args.push('--json');
49
+ if (options.store)
50
+ args.push('--store');
51
+ if (options.verbose)
52
+ args.push('--verbose');
53
+ runCli('selfheal', 'introspect', args);
54
+ }))
55
+ .addCommand(new Command('prescribe')
56
+ .description('Generate improvement prescription')
57
+ .option('--scorecard <path>', 'Path to scorecard JSON')
58
+ .option('--target <metric>', 'Target metric name')
59
+ .option('--live', 'Run live introspection')
60
+ .option('--dry-run', 'Preview without writing')
61
+ .action((options) => {
62
+ const args = [];
63
+ if (options.scorecard)
64
+ args.push('--scorecard', options.scorecard);
65
+ if (options.target)
66
+ args.push('--target', options.target);
67
+ if (options.live)
68
+ args.push('--live');
69
+ if (options.dryRun)
70
+ args.push('--dry-run');
71
+ runCli('selfheal', 'prescribe', args);
72
+ }))
73
+ .addCommand(new Command('evolve')
74
+ .description('Execute prescription with regression detection')
75
+ .option('--prescription <path>', 'Path to prescription JSON')
76
+ .option('--dry-run', 'Preview without changes')
77
+ .option('--skip-governor', 'Bypass governor safety gate')
78
+ .action((options) => {
79
+ const args = [];
80
+ if (options.prescription)
81
+ args.push('--prescription', options.prescription);
82
+ if (options.dryRun)
83
+ args.push('--dry-run');
84
+ if (options.skipGovernor)
85
+ args.push('--skip-governor');
86
+ runCli('selfheal', 'evolve', args);
87
+ }));
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Zouroboros CLI
4
+ *
5
+ * Unified command-line interface for all Zouroboros packages.
6
+ *
7
+ * @module zouroboros-cli
8
+ */
9
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Zouroboros CLI
4
+ *
5
+ * Unified command-line interface for all Zouroboros packages.
6
+ *
7
+ * @module zouroboros-cli
8
+ */
9
+ import { Command } from 'commander';
10
+ import chalk from 'chalk';
11
+ import { VERSION } from 'zouroboros-core';
12
+ // Import commands
13
+ import { initCommand } from './commands/init.js';
14
+ import { doctorCommand } from './commands/doctor.js';
15
+ import { configCommand } from './commands/config.js';
16
+ import { memoryCommand } from './commands/memory.js';
17
+ import { swarmCommand } from './commands/swarm.js';
18
+ import { personaCommand } from './commands/persona.js';
19
+ import { workflowCommand, selfhealCommand } from './commands/workflow.js';
20
+ import { healCommand } from './commands/heal.js';
21
+ import { tuiCommand } from './commands/tui.js';
22
+ import { backupCommand } from './commands/backup.js';
23
+ import { migrateCommand } from './commands/migrate.js';
24
+ import { skillsCommand } from './commands/skills.js';
25
+ import { agentsCommand } from './commands/agents.js';
26
+ const program = new Command();
27
+ program
28
+ .name('zouroboros')
29
+ .description('🐍⭕ Zouroboros - Self-enhancing AI memory and orchestration system')
30
+ .version(VERSION, '-v, --version', 'Display version number')
31
+ .helpOption('-h, --help', 'Display help for command')
32
+ .configureOutput({
33
+ writeOut: (str) => process.stdout.write(str),
34
+ writeErr: (str) => process.stderr.write(str),
35
+ });
36
+ // Global options
37
+ program
38
+ .option('--config <path>', 'Path to config file')
39
+ .option('--verbose', 'Enable verbose output')
40
+ .option('--json', 'Output as JSON');
41
+ // Register commands
42
+ program.addCommand(initCommand);
43
+ program.addCommand(doctorCommand);
44
+ program.addCommand(configCommand);
45
+ program.addCommand(memoryCommand);
46
+ program.addCommand(swarmCommand);
47
+ program.addCommand(personaCommand);
48
+ program.addCommand(workflowCommand);
49
+ program.addCommand(selfhealCommand);
50
+ program.addCommand(healCommand);
51
+ program.addCommand(tuiCommand);
52
+ program.addCommand(backupCommand);
53
+ program.addCommand(migrateCommand);
54
+ program.addCommand(skillsCommand);
55
+ program.addCommand(agentsCommand);
56
+ // Default action (no command)
57
+ program.action(() => {
58
+ console.log(chalk.cyan('\n🐍⭕ Zouroboros'));
59
+ console.log(chalk.gray('Self-enhancing AI memory and orchestration system\n'));
60
+ console.log('Run ' + chalk.yellow('zouroboros --help') + ' for available commands\n');
61
+ });
62
+ // Error handling
63
+ program.exitOverride();
64
+ try {
65
+ await program.parseAsync();
66
+ }
67
+ catch (err) {
68
+ if (err.code === 'commander.help') {
69
+ process.exit(0);
70
+ }
71
+ if (err.code === 'commander.version') {
72
+ process.exit(0);
73
+ }
74
+ if (err.code === 'commander.unknownOption') {
75
+ console.error(chalk.red(`Error: ${err.message}`));
76
+ process.exit(1);
77
+ }
78
+ if (err.code === 'commander.missingArgument') {
79
+ console.error(chalk.red(`Error: ${err.message}`));
80
+ process.exit(1);
81
+ }
82
+ throw err;
83
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Doctor utility - Health check for Zouroboros components
3
+ */
4
+ export declare function runDoctor(options?: {
5
+ fix?: boolean;
6
+ }): Promise<boolean>;