#!/usr/bin/env node /** * Multica CLI - Unified command-line interface * * Usage: * multica Interactive mode (default) * multica run Run a single prompt * multica chat Interactive mode (explicit) * multica session Session management * multica profile Profile management * multica skills Skills management * multica tools Tool policy inspection * multica credentials Credentials management * multica cron Scheduled task management * multica dev [service] Development servers * multica help Show help */ import { cyan, yellow, green, dim, brightCyan } from "./colors.js"; // Subcommand handlers (lazy imports for faster startup) type SubcommandHandler = (args: string[]) => Promise; const subcommands: Record Promise> = { run: async () => (await import("./commands/run.js")).runCommand, chat: async () => (await import("./commands/chat.js")).chatCommand, session: async () => (await import("./commands/session.js")).sessionCommand, profile: async () => (await import("./commands/profile.js")).profileCommand, skills: async () => (await import("./commands/skills.js")).skillsCommand, tools: async () => (await import("./commands/tools.js")).toolsCommand, credentials: async () => (await import("./commands/credentials.js")).credentialsCommand, dev: async () => (await import("./commands/dev.js")).devCommand, cron: async () => (await import("./commands/cron.js")).cronCommand, }; function printHelp() { console.log(` ${brightCyan("Multica CLI")} - AI Agent Framework ${cyan("Usage:")} ${yellow("multica")} Start interactive mode (default) ${yellow("multica run")} Run a single prompt ${yellow("multica chat")} [options] Start interactive mode ${yellow("multica session")} Manage sessions ${yellow("multica profile")} Manage agent profiles ${yellow("multica skills")} Manage skills ${yellow("multica tools")} Inspect tool policies ${yellow("multica credentials")} Manage credentials ${yellow("multica cron")} Manage scheduled tasks ${yellow("multica dev")} [service] Start development servers ${yellow("multica help")} Show this help ${cyan("Agent Options:")} ${dim("(for run/chat)")} ${yellow("--profile")} ID Load agent profile ${yellow("--provider")} NAME LLM provider (openai, anthropic, kimi, etc.) ${yellow("--model")} NAME Model name ${yellow("--system")} TEXT System prompt ${yellow("--session")} ID Resume session ${yellow("--cwd")} DIR Working directory ${cyan("Commands:")} ${green("session")} list List all sessions show Show session details delete Delete a session ${green("profile")} list List all profiles new Create a new profile show Show profile contents edit Open profile in file manager delete Delete a profile ${green("skills")} list List all skills status [id] Show skill status install Install skill dependencies add Add skill from GitHub remove Remove a skill ${green("tools")} list [--profile P] List tools (with optional filter) groups Show tool groups profiles Show tool profiles ${green("credentials")} init [--force] Create credential files show Show credential paths edit Open credentials in editor ${green("cron")} status Show cron service status list List all scheduled jobs add [options] Create a new scheduled job run Run a job immediately enable Enable a job disable Disable a job remove Delete a job logs Show job run logs ${green("dev")} ${dim("(default)")} Start all services (gateway + console + web) gateway Start gateway only (:3000) console Start console only (:4000) web Start web app only (:3001) desktop Start desktop app ${cyan("Examples:")} ${dim("# Start interactive mode")} multica ${dim("# Run a single prompt")} multica run "What files are in this directory?" ${dim("# Use a specific profile")} multica chat --profile coder ${dim("# Resume a session")} multica --session abc123 ${dim("# Start development servers")} multica dev multica dev gateway `); } function printVersion() { // Read version from package.json would be ideal, but for now just print a placeholder console.log("multica 1.0.0"); } async function main() { // Filter out standalone "--" (used by pnpm to pass args) const args = process.argv.slice(2).filter((arg) => arg !== "--"); // Handle global flags if (args.includes("--help") || args.includes("-h")) { // If help is requested with a subcommand, delegate to that subcommand const firstArg = args[0]; if (firstArg && !firstArg.startsWith("-") && subcommands[firstArg]) { const handler = await subcommands[firstArg](); await handler(["--help"]); return; } printHelp(); return; } if (args.includes("--version") || args.includes("-V")) { printVersion(); return; } // Determine command const firstArg = args[0]; // No args or starts with -- means interactive mode if (!firstArg || firstArg.startsWith("-")) { const chatHandler = await subcommands.chat!(); await chatHandler(args); return; } // Check if it's "help" command if (firstArg === "help") { const subcommand = args[1]; if (subcommand && subcommands[subcommand]) { const handler = await subcommands[subcommand](); await handler(["--help"]); return; } printHelp(); return; } // Check if it's a known subcommand if (subcommands[firstArg]) { const handler = await subcommands[firstArg](); await handler(args.slice(1)); return; } // Unknown command - show error and help console.error(`Unknown command: ${firstArg}`); console.error(`Run 'multica help' for usage information.`); process.exit(1); } main().catch((err) => { console.error(err?.stack || String(err)); process.exit(1); });