#!/usr/bin/env node /** * Coolify MCP CLI - Entry point. * * Command-line interface for Coolify deployment management. * * @module */ import { Command } from "commander"; import chalk from "chalk"; import { setVerbosity } from "@mks2508/better-logger"; // Silence SDK logger in CLI mode — all progress goes through spinners/prompts setVerbosity("silent"); import { createCommand } from "./commands/create.js"; import { deployCommand } from "./commands/deploy.js"; import { listCommand } from "./commands/list.js"; import { logsCommand } from "./commands/logs.js"; import { serversCommand } from "./commands/servers.js"; import { projectsCommand } from "./commands/projects.js"; import { statusCommand } from "./commands/status.js"; import { environmentsCommand } from "./commands/environments.js"; import { configCommand } from "./commands/config.js"; import { envCommand } from "./commands/env.js"; import { updateCommand } from "./commands/update.js"; import { deleteCommand } from "./commands/delete.js"; import { destinationsCommand } from "./commands/destinations.js"; import { showCommand } from "./commands/show.js"; import { deploymentsCommand } from "./commands/deployments.js"; import { startCommand } from "./commands/start.js"; import { stopCommand } from "./commands/stop.js"; import { restartCommand } from "./commands/restart.js"; import { buildLogsCommand } from "./commands/build-logs.js"; import { serviceLogsCommand } from "./commands/service-logs.js"; import { initCommand } from "./commands/init.js"; import { versionCommand } from "./commands/version.js"; import { databasesCommand } from "./commands/databases.js"; import { servicesCommand as servicesListCommand } from "./commands/services.js"; import { cancelDeployCommand } from "./commands/cancel-deploy.js"; import { serverResourcesCommand } from "./commands/server-resources.js"; import { dbListCommand, dbGetCommand, dbCreateCommand, dbUpdateCommand, dbStartCommand, dbStopCommand, dbRestartCommand, dbDeleteCommand, dbBackupsCommand, } from "./commands/db.js"; import { svcListCommand, svcGetCommand, svcStartCommand, svcStopCommand, svcRestartCommand, svcDeleteCommand, svcEnvCommand, svcSetEnvCommand, } from "./commands/svc.js"; import { keysListCommand, keysGetCommand, keysCreateCommand, keysDeleteCommand, } from "./commands/keys.js"; import { teamsListCommand, teamsCurrentCommand, teamsMembersCommand, } from "./commands/teams.js"; import { diagnoseAppCommand, diagnoseServerCommand, scanIssuesCommand, } from "./commands/diagnose.js"; import { execCommand } from "./commands/exec.js"; import { activeDeploymentsCommand } from "./commands/active-deployments.js"; import { networkInspectCommand, analyzeDeployCommand, } from "./commands/network.js"; import { volumesListCommand, volumesAddCommand, volumesRemoveCommand, } from "./commands/volumes.js"; const program = new Command(); // Detect binary name to show correct help const binaryName = process.argv[1]?.includes("coolify-cli") ? "coolify-cli" : "coolify-mcp"; program .name(binaryName) .description( `${chalk.bold.hex("#8c52ff")("Coolify CLI")} — Manage deployments, env vars, and resources\n` + ` Global: ${chalk.gray("bun install -g @mks2508/coolify-mks-cli-mcp")}`, ) .version("0.9.0") .addHelpText("beforeAll", () => { // Show banner before help output const { showAutoBanner } = require("./ui/banner.js"); showAutoBanner("0.9.0"); return ""; }); // Create application program .command("create") .description("Create a new application") .option("--name ", "Application name") .option("--description ", "Application description") .option("--server ", "Server UUID") .option("--project ", "Project UUID") .option( "--environment ", "Environment UUID (auto-fetched if not provided)", ) .option("--repo ", "Git repository URL") .option("--branch ", "Git branch", "main") .option( "--type ", "Application type (public, private-github-app, private-deploy-key, dockerfile, docker-image, docker-compose)", "public", ) .option( "--build-pack ", "Build pack (dockerfile, nixpacks, static, dockercompose)", "dockerfile", ) .option("--ports ", "Ports to expose (default: 3000)", "3000") .option("--docker-image ", "Docker image (for docker-image type)") .option( "--docker-compose ", "Docker Compose content (for docker-compose type)", ) .option( "--docker-compose-location ", 'Docker Compose file path (for dockercompose buildPack, e.g., "docker-compose.yml")', ) .option( "--dockerfile-location ", 'Dockerfile location (e.g., "apps/haidodocs/Dockerfile")', ) .option( "--base-directory ", 'Base directory for build context (default: "/")', "/", ) .option( "--github-app-uuid ", "GitHub App UUID (auto-detected if not provided)", ) .option( "--private-key-uuid ", "Private key UUID (required for private-deploy-key type)", ) .option( "--domain ", "Domain to set after creation (e.g., app.example.com or https://app.example.com)", ) .action(createCommand); // Config command program .command("config") .description("Manage configuration") .argument("[action]", "Action to perform (set, get, path)") .option("--key ", 'Configuration key (for "set" action)') .option("--value ", 'Configuration value (for "set" action)') .action(configCommand); // Init application (link existing or create new) program .command("init") .description("Initialize Coolify deployment (link existing or create new)") .option("--yes", "Auto-mode with defaults") .option("--force", "Ignore existing .coolify.json") .option("--name ", "App name") .option("--link", "Link-only mode (don't create new apps)") .action(initCommand); // List applications program .command("list") .description("List all applications") .option("-t, --team ", "Filter by team ID") .option("-p, --project ", "Filter by project ID") .action(listCommand); // Deploy application program .command("deploy [uuid]") .description("Deploy an application (reads .coolify.json if no UUID)") .option("-f, --force", "Force rebuild without cache") .option("-t, --tag ", "Deploy specific tag/version") .option("--all", "Deploy all apps from .coolify.json in parallel") .option("--service ", "Deploy specific service from .coolify.json") .action(deployCommand); // Logs command program .command("logs [uuid]") .description("Get application logs (reads .coolify.json if no UUID)") .option("-n, --lines ", "Number of lines to retrieve", "50") .option("-f, --follow", "Follow logs in real-time (polls every 2s)") .option("--errors", "Show errors only") .option("--since ", "Show logs since duration (e.g. 1h, 30m, 2d)") .action((uuid, options) => { const lines = parseInt(options.lines, 10); logsCommand(uuid, { lines, follow: options.follow, errors: options.errors, since: options.since, }); }); // Servers command program .command("servers") .description("List available servers") .action((options) => serversCommand(options)); // Status dashboard program .command("status") .description("Show status dashboard") .option("-w, --watch", "Auto-refresh every 5s") .action((options) => statusCommand(options)); // Projects command program .command("projects") .description("List or create projects") .option("--create ", "Create a new project with this name") .option("--description ", "Project description (use with --create)") .option("--show ", "Show project details with environments, apps, and databases") .option("--apps ", "Show all applications in a project") .action((options) => projectsCommand(options)); // Environments command program .command("environments ") .description("List environments for a project") .action((projectUuid, options) => environmentsCommand(projectUuid, options)); // Env vars command program .command("env [uuid]") .description("Manage env vars (reads .coolify.json if no UUID)") .option( "--set ", "Set an environment variable (can be repeated: --set A=1 --set B=2)", (value: string, prev: string[] | undefined) => (prev ?? []).concat(value), [] as string[], ) .option("--delete ", "Delete an environment variable") .option("--get ", "Get a single environment variable value (prints value, no colors)") .option("--buildtime", "Mark variable as build-time only (use with --set)") .option("--runtime-only", "Mark variable as runtime only, not build-time (use with --set)") .option("--sync [file]", "Sync env vars from .env file (default: .env, or stdin with -)") .option("--dry-run", "Preview changes without applying (use with --sync)") .option("--prune", "Delete vars not in file (use with --sync)") .option("--table", "Show env vars in table format") .option("--json", "Output machine-parseable JSON (ICoolifyEnvVar[])") .action((uuid, options) => envCommand(uuid, options)); // Update application program .command("update [uuid]") .description("Update app config (reads .coolify.json if no UUID)") .option("--name ", "Application name") .option("--description ", "Application description") .option("--build-pack ", "Build pack (dockerfile, nixpacks, static)") .option("--git-branch ", "Git branch") .option("--ports ", "Ports to expose (e.g., 3000)") .option("--install-command ", "Install command (nixpacks)") .option("--build-command ", "Build command") .option("--start-command ", "Start command") .option( "--dockerfile-location ", 'Dockerfile location (e.g., "apps/haidodocs/Dockerfile")', ) .option( "--base-directory ", 'Base directory for build context (e.g., "/")', ) .option( "--domains ", 'Domains (comma-separated with protocol, e.g., "https://app.example.com")', ) .option("--auto-deploy", "Enable auto-deploy on git push") .option("--no-auto-deploy", "Disable auto-deploy on git push") .option( "--watch-paths ", 'Watch paths for selective auto-deploy (newline-separated globs, e.g. "src/**\\npackages/**")', ) .option("--clear-watch-paths", "Clear watch paths (deploy on all changes)") .option("--force-https", "Enable forced HTTPS redirect") .option("--health-check-enabled", "Enable health check") .option("--no-health-check-enabled", "Disable health check") .option("--health-check-path ", "Health check path (e.g., /health)") .option("--health-check-port ", "Health check port") .option("--health-check-interval ", "Health check interval in seconds") .option("--health-check-timeout ", "Health check timeout in seconds") .option("--health-check-retries ", "Health check retries") .option("--health-check-start-period ", "Health check start period in seconds") .action((uuid, options) => updateCommand({ uuid, ...options })); // Delete application program .command("delete [uuid]") .description("Delete application (reads .coolify.json if no UUID)") .option("-f, --force", "Skip confirmation prompt") .option("-y, --yes", "Skip confirmation prompt (alias for --force)") .action((uuid, options) => deleteCommand(uuid, options)); // Destinations command program .command("destinations ") .description("List available destinations for a server") .action(destinationsCommand); // Show application details program .command("show [uuid]") .description("Show app details (reads .coolify.json if no UUID)") .action(showCommand); // Deployments history program .command("deployments [uuid]") .description("Show deployment history (reads .coolify.json if no UUID)") .option("-n, --limit ", "Limit number of deployments shown", "10") .action((uuid, options) => { const limit = parseInt(options.limit, 10); deploymentsCommand(uuid, { full: options.full, limit }); }); // Start application program .command("start [uuid]") .description("Start application (reads .coolify.json if no UUID)") .action(startCommand); // Stop application program .command("stop [uuid]") .description("Stop application (reads .coolify.json if no UUID)") .action(stopCommand); // Restart application program .command("restart [uuid]") .description("Restart application (reads .coolify.json if no UUID)") .action(restartCommand); // Build/deployment logs program .command("build-logs ") .description("View build/deployment logs for a specific deployment") .option("-n, --lines ", "Number of lines to show (tail)") .action((deploymentUuid, options) => { const lines = options.lines ? parseInt(options.lines, 10) : undefined; buildLogsCommand(deploymentUuid, { lines }); }); // Service logs (docker-compose) program .command("service-logs ") .description("View logs for a specific docker-compose service") .option("-n, --lines ", "Number of lines to retrieve", "50") .action((uuid, serviceName, options) => { const lines = parseInt(options.lines, 10); serviceLogsCommand(uuid, serviceName, { lines }); }); // Coolify server version program .command("version") .description("Show Coolify server version") .action(versionCommand); // List databases program .command("databases") .description("List all databases") .action((options) => databasesCommand(options)); // List services program .command("services") .description("List all services") .action((options) => servicesListCommand(options)); // Cancel deployment program .command("cancel-deploy ") .description("Cancel an in-progress deployment") .action(cancelDeployCommand); // Server resources program .command("server-resources ") .description("List resources deployed on a server") .action((serverUuid, options) => serverResourcesCommand(serverUuid, options)); // ─── Database subcommands ──────────────────────────────────────────────────── const db = program.command("db").description("Manage databases"); db.command("list").description("List all databases").action(dbListCommand); db.command("get ") .description("Get database details") .action(dbGetCommand); db.command("update ") .description("Update database configuration") .option("--public-port ", "Publish port (e.g., 127.0.0.1:5432 or 5432)") .option("--is-public", "Make database publicly accessible") .option("--no-is-public", "Make database private") .action((uuid, options) => dbUpdateCommand(uuid, options)); db.command("create ") .description( "Create database (postgresql, mysql, mariadb, mongodb, redis, keydb, clickhouse, dragonfly)", ) .requiredOption("--server ", "Server UUID") .requiredOption("--project ", "Project UUID") .option("--environment ", "Environment name (default: production)") .option("--name ", "Database name") .action(dbCreateCommand); db.command("start ") .description("Start a database") .action(dbStartCommand); db.command("stop ").description("Stop a database").action(dbStopCommand); db.command("restart ") .description("Restart a database") .action(dbRestartCommand); db.command("delete ") .description("Delete a database") .action(dbDeleteCommand); db.command("backups ") .description("List backups for a database") .action(dbBackupsCommand); db.action(() => db.help()); // ─── Service subcommands ───────────────────────────────────────────────────── const svc = program.command("svc").description("Manage services"); svc.command("list").description("List all services").action(svcListCommand); svc .command("get ") .description("Get service details") .action(svcGetCommand); svc .command("start ") .description("Start a service") .action(svcStartCommand); svc.command("stop ").description("Stop a service").action(svcStopCommand); svc .command("restart ") .description("Restart a service") .action(svcRestartCommand); svc .command("delete ") .description("Delete a service") .action(svcDeleteCommand); svc .command("env ") .description("List env vars for a service") .action(svcEnvCommand); svc .command("set-env ") .description("Set env var for a service") .action(svcSetEnvCommand); svc.action(() => svc.help()); // ─── SSH Key subcommands ───────────────────────────────────────────────────── const keys = program.command("keys").description("Manage SSH private keys"); keys .command("list") .description("List all private keys") .action(keysListCommand); keys .command("get ") .description("Get private key details") .action(keysGetCommand); keys .command("create ") .description("Create a private key") .option("--key ", "Private key content") .option("--file ", "Path to private key file") .option("--description ", "Description") .action(keysCreateCommand); keys .command("delete ") .description("Delete a private key") .action(keysDeleteCommand); keys.action(() => keys.help()); // ─── Team subcommands ──────────────────────────────────────────────────────── const team = program.command("team").description("Manage teams"); team.command("list").description("List all teams").action(teamsListCommand); team .command("current") .description("Show current team") .action(teamsCurrentCommand); team .command("members ") .description("Show team members") .action(teamsMembersCommand); team.action(() => team.help()); // ─── Diagnostics ───────────────────────────────────────────────────────────── program .command("diagnose [query]") .description("Diagnose application (reads .coolify.json if no query)") .action(diagnoseAppCommand); program .command("diagnose-server ") .description("Diagnose a server (name, IP, or UUID)") .action(diagnoseServerCommand); program .command("scan") .description("Scan all infrastructure for issues") .action(scanIssuesCommand); // ─── Execute command ───────────────────────────────────────────────────────── program .command("exec [uuid] ") .description("Execute command on app container (reads .coolify.json)") .action(execCommand); // ─── Active deployments ────────────────────────────────────────────────────── program .command("active-deployments") .description("List all active/queued deployments") .action(activeDeploymentsCommand); // ─── Network diagnostics ───────────────────────────────────────────────────── const net = program.command("network").description("Network diagnostics"); net .command("inspect [uuid]") .description("Inspect container network (DNS, hosts, connectivity)") .option( "--services ", "Comma-separated service names to test (e.g., db,redis)", ) .action((uuid, options) => networkInspectCommand(uuid, options)); net.action(() => net.help()); // ─── Deploy failure analysis ───────────────────────────────────────────────── program .command("analyze-deploy ") .description("Analyze a failed deployment (extract errors, suggest fixes)") .action(analyzeDeployCommand); // ─── Volumes subcommands ────────────────────────────────────────────────────── const volumes = program.command("volumes").description("Manage volumes for docker-compose apps"); volumes .command("list ") .description("List volumes for an application") .option("--service ", "Service name (for multi-service compose)") .action((uuid, options) => volumesListCommand(uuid, options)); volumes .command("add ") .description("Add a bind mount volume") .requiredOption("--source ", "Source path on host") .requiredOption("--target ", "Target path in container") .option("--service ", "Service name (required for multi-service compose)") .option("--no-restart", "Skip automatic redeploy after adding volume") .action((uuid, options) => volumesAddCommand(uuid, options)); volumes .command("remove ") .description("Remove a volume by target path") .requiredOption("--target ", "Target path in container to remove") .option("--service ", "Service name (required for multi-service compose)") .option("--no-restart", "Skip automatic redeploy after removing volume") .action((uuid, options) => volumesRemoveCommand(uuid, options)); volumes.action(() => volumes.help()); // Show help by default (or interactive menu if no args) program.action(async () => { // If called without arguments, show interactive menu if (process.argv.length <= 2) { const { mainMenu } = await import("./commands/main-menu.js"); await mainMenu(); } else { // Show help if called with unknown command console.log(chalk.cyan("Coolify MCP CLI v0.8.0")); console.log(chalk.gray("Manage Coolify deployments from the command line\n")); program.help(); } }); program.parse();