#!/usr/bin/env node import { Command } from "commander" import chalk from "chalk" import { loadConfig, isLoggedIn } from "./auth/config" import { createClient } from "./auth/client" import { startRepl } from "./repl/repl" const program = new Command() program .name("llmtune") .description("LLMTune CLI - AI coding agent powered by api.llmtune.io") .version("0.1.0") program .command("login") .description("Configure API key and settings") .action(async () => { const { loginCommand } = await import("./commands/login") await loginCommand() }) program .command("chat") .description("Start interactive coding session") .option("-m, --model ", "Model to use") .option("--no-stream", "Disable streaming") .action(async (options: { model?: string; stream?: boolean }) => { if (!isLoggedIn()) { console.log(chalk.red('Not logged in. Run "llmtune login" first.')) process.exit(1) } const config = loadConfig() const client = createClient() const model = options.model ?? (config.defaultModel as string) ?? "z-ai/GLM-5.1" const apiBase = (config.apiBase as string) ?? "https://api.llmtune.io/api/agent/v1" console.log(chalk.cyan("\nLLMTune CLI")) console.log(chalk.dim(`Connected to ${apiBase}`)) console.log(chalk.dim(`Model: ${model}`)) console.log(chalk.dim("Type /help for commands, /exit to quit\n")) await startRepl({ client, model, stream: options.stream !== false }) }) program .command("models") .description("List available models") .action(async () => { const { modelsCommand } = await import("./commands/models") await modelsCommand() }) program .command("config") .description("Show current configuration") .action(async () => { const { showConfig } = await import("./commands/config") showConfig() }) // Skills marketplace commands const skillsCmd = program.command("skills").description("Manage skills (list, install, publish, sign)") skillsCmd .command("list") .description("List available skills from marketplace") .action(async () => { const { listSkillsCommand } = await import("./commands/marketplace") await listSkillsCommand() }) skillsCmd .command("install") .description("Install a skill from the marketplace") .argument("", "Skill name to install") .action(async (name: string) => { const { installSkillCommand } = await import("./commands/marketplace") await installSkillCommand(name) }) skillsCmd .command("publish") .description("Publish a local skill to the marketplace") .argument("", "Path to skill directory") .action(async (skillPath: string) => { const { publishSkillCommand } = await import("./commands/marketplace") await publishSkillCommand(skillPath) }) skillsCmd .command("sign") .description("Cryptographically sign a skill") .argument("", "Path to skill directory") .action(async (skillPath: string) => { const { signSkillCommand } = await import("./commands/marketplace") await signSkillCommand(skillPath) }) program.parse()