@mks2508/coolify-mks-cli-mcp 0.1.0 → 0.2.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.
@@ -17148,7 +17148,8 @@ class CoolifyService {
17148
17148
  return { error: "Coolify not configured", status: 0, durationMs: Date.now() - startTime };
17149
17149
  }
17150
17150
  try {
17151
- const url = `${this.baseUrl}/api/v1${endpoint}`;
17151
+ const baseUrl = this.baseUrl.replace(/\/+$/, "");
17152
+ const url = `${baseUrl}/api/v1${endpoint}`;
17152
17153
  const response = await fetch(url, {
17153
17154
  ...options,
17154
17155
  headers: {
@@ -17187,47 +17188,81 @@ class CoolifyService {
17187
17188
  log.info(`Deploying application ${options.uuid || options.tag}`);
17188
17189
  onProgress?.(25, "Validating deployment configuration");
17189
17190
  onProgress?.(50, "Triggering build pipeline...");
17190
- const result = await this.request("/deploy", {
17191
- method: "POST",
17192
- body: JSON.stringify({
17193
- uuid: options.uuid,
17194
- tag: options.tag,
17195
- force: options.force ?? false
17196
- })
17191
+ const params = new URLSearchParams;
17192
+ if (options.uuid)
17193
+ params.set("uuid", options.uuid);
17194
+ if (options.tag)
17195
+ params.set("tag", options.tag);
17196
+ if (options.force)
17197
+ params.set("force", "true");
17198
+ const endpoint = `/deploy${params.toString() ? `?${params.toString()}` : ""}`;
17199
+ const result = await this.request(endpoint, {
17200
+ method: "POST"
17197
17201
  });
17198
17202
  if (result.error) {
17199
17203
  log.error(`Deployment failed: ${result.error}`);
17200
17204
  return err(new Error(result.error));
17201
17205
  }
17206
+ const deployments = result.data?.deployments || [];
17207
+ if (deployments.length === 0) {
17208
+ log.error("No deployments started");
17209
+ return err(new Error("No deployments started - check application configuration"));
17210
+ }
17211
+ const deployment = deployments[0];
17202
17212
  onProgress?.(90, "Build started on Coolify server");
17203
17213
  onProgress?.(100, "Deployment triggered");
17204
- log.success(`Deployment started: ${result.data?.deployment_uuid}`);
17214
+ log.success(`Deployment started: ${deployment.deployment_uuid}`);
17205
17215
  return ok({
17206
17216
  success: true,
17207
- deploymentUuid: result.data?.deployment_uuid,
17208
- resourceUuid: result.data?.resource_uuid
17217
+ deploymentUuid: deployment.deployment_uuid,
17218
+ resourceUuid: deployment.resource_uuid
17209
17219
  });
17210
17220
  }
17211
17221
  async createApplication(options, onProgress) {
17212
17222
  onProgress?.(5, `Preparing app "${options.name}"`);
17213
- log.info(`Creating application ${options.name}`);
17223
+ const appType = options.type || "public";
17224
+ log.info(`Creating application ${options.name} (type: ${appType})`);
17214
17225
  onProgress?.(25, `Validating server ${options.serverUuid.slice(0, 8)}...`);
17215
17226
  onProgress?.(50, "Sending creation request to Coolify API...");
17216
- const result = await this.request("/applications", {
17227
+ const endpointMap = {
17228
+ public: "/applications/public",
17229
+ "private-github-app": "/applications/private-github-app",
17230
+ "private-deploy-key": "/applications/private-deploy-key",
17231
+ dockerfile: "/applications/dockerfile",
17232
+ "docker-image": "/applications/docker-image",
17233
+ "docker-compose": "/applications/docker-compose"
17234
+ };
17235
+ const endpoint = endpointMap[appType] || "/applications/public";
17236
+ const body = {
17237
+ name: options.name,
17238
+ description: options.description,
17239
+ project_uuid: options.projectUuid,
17240
+ environment_uuid: options.environmentUuid,
17241
+ server_uuid: options.serverUuid
17242
+ };
17243
+ if (appType === "public" || appType === "private-github-app" || appType === "private-deploy-key") {
17244
+ if (options.githubRepoUrl) {
17245
+ body.git_repository = options.githubRepoUrl;
17246
+ }
17247
+ body.git_branch = options.branch || "main";
17248
+ body.build_pack = options.buildPack || "dockerfile";
17249
+ if (options.portsExposes) {
17250
+ body.ports_exposes = options.portsExposes;
17251
+ }
17252
+ if (options.dockerfileLocation) {
17253
+ body.dockerfile_location = options.dockerfileLocation;
17254
+ }
17255
+ if (options.baseDirectory) {
17256
+ body.base_directory = options.baseDirectory;
17257
+ }
17258
+ } else if (appType === "docker-image" && options.dockerImage) {
17259
+ body.docker_image = options.dockerImage;
17260
+ } else if (appType === "docker-compose" && options.dockerCompose) {
17261
+ body.docker_compose = options.dockerCompose;
17262
+ }
17263
+ const result = await this.request(endpoint, {
17217
17264
  method: "POST",
17218
- body: JSON.stringify({
17219
- name: options.name,
17220
- description: options.description,
17221
- server_uuid: options.serverUuid,
17222
- destination_uuid: options.destinationUuid,
17223
- project_uuid: options.serverUuid,
17224
- environment_name: "production",
17225
- git_repository: options.githubRepoUrl,
17226
- git_branch: options.branch || "main",
17227
- build_pack: options.buildPack || "nixpacks",
17228
- ports_exposes: "3000",
17229
- instant_deploy: false
17230
- })
17265
+ body: JSON.stringify(body)
17231
17266
  });
17232
17267
  if (result.error) {
17233
17268
  log.error(`Failed to create application: ${result.error}`);
@@ -17299,6 +17334,16 @@ class CoolifyService {
17299
17334
  }
17300
17335
  return ok(result.data || []);
17301
17336
  }
17337
+ async getProjectEnvironments(projectUuid) {
17338
+ log.info(`Getting environments for project ${projectUuid}`);
17339
+ const result = await this.request(`/projects/${projectUuid}`);
17340
+ if (result.error) {
17341
+ log.error(`Failed to get environments: ${result.error}`);
17342
+ return err(new Error(result.error));
17343
+ }
17344
+ log.success(`Environments retrieved for project ${projectUuid}`);
17345
+ return ok(result.data?.environments || []);
17346
+ }
17302
17347
  async listTeams() {
17303
17348
  const result = await this.request("/teams");
17304
17349
  if (result.error) {
@@ -17363,6 +17408,10 @@ class CoolifyService {
17363
17408
  body.build_command = options.buildCommand;
17364
17409
  if (options.startCommand)
17365
17410
  body.start_command = options.startCommand;
17411
+ if (options.dockerfileLocation)
17412
+ body.dockerfile_location = options.dockerfileLocation;
17413
+ if (options.baseDirectory)
17414
+ body.base_directory = options.baseDirectory;
17366
17415
  const result = await this.request(`/applications/${appUuid}`, {
17367
17416
  method: "PATCH",
17368
17417
  body: JSON.stringify(body)
@@ -17401,7 +17450,7 @@ class CoolifyService {
17401
17450
  return err(new Error(result.error));
17402
17451
  }
17403
17452
  log.success(`Deployment history retrieved for ${appUuid}`);
17404
- return ok(result.data || []);
17453
+ return ok(result.data?.deployments || []);
17405
17454
  }
17406
17455
  async startApplication(appUuid) {
17407
17456
  log.info(`Starting application ${appUuid}`);
@@ -18225,8 +18274,10 @@ async function handleCreateApplication(coolify, args) {
18225
18274
  const result = await coolify.createApplication({
18226
18275
  name: args.name,
18227
18276
  description: args.description,
18277
+ projectUuid: args.projectUuid,
18278
+ environmentUuid: args.environmentUuid,
18228
18279
  serverUuid: args.serverUuid,
18229
- destinationUuid: args.destinationUuid,
18280
+ type: "public",
18230
18281
  githubRepoUrl: args.githubRepoUrl,
18231
18282
  branch: args.branch,
18232
18283
  buildPack: args.buildPack
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mks2508/coolify-mks-cli-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server and CLI for Coolify deployment management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Create command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isOk, isErr } from '@mks2508/no-throw'
8
+ import ora from 'ora'
9
+ import chalk from 'chalk'
10
+ import { getCoolifyService } from '../../coolify/index.js'
11
+
12
+ /**
13
+ * Create command options.
14
+ */
15
+ interface ICreateOptions {
16
+ name: string
17
+ description?: string
18
+ server: string
19
+ project: string
20
+ environment?: string
21
+ repo?: string
22
+ branch?: string
23
+ type?: 'public' | 'private-github-app' | 'private-deploy-key' | 'dockerfile' | 'docker-image' | 'docker-compose'
24
+ buildPack?: 'dockerfile' | 'nixpacks' | 'static'
25
+ ports?: string
26
+ dockerImage?: string
27
+ dockerCompose?: string
28
+ dockerfileLocation?: string
29
+ baseDirectory?: string
30
+ }
31
+
32
+ /**
33
+ * Create command handler.
34
+ *
35
+ * @param options - Create options
36
+ */
37
+ export async function createCommand(options: ICreateOptions) {
38
+ const spinner = ora('Initializing Coolify connection...').start()
39
+
40
+ try {
41
+ const coolify = getCoolifyService()
42
+ const initResult = await coolify.init()
43
+
44
+ if (isErr(initResult)) {
45
+ spinner.fail(chalk.red(`Failed to initialize: ${initResult.error.message}`))
46
+ return
47
+ }
48
+
49
+ // Auto-fetch environment UUID if not provided
50
+ let environmentUuid: string | undefined = options.environment
51
+
52
+ if (!environmentUuid) {
53
+ spinner.text = 'Fetching project environments...'
54
+
55
+ const envResult = await coolify.getProjectEnvironments(options.project)
56
+
57
+ if (isOk(envResult) && envResult.value.length > 0) {
58
+ // Use the first environment (usually "production")
59
+ environmentUuid = envResult.value[0].uuid
60
+ const envName = envResult.value[0].name
61
+ spinner.info(chalk.cyan(`Using environment: ${envName} (${environmentUuid.slice(0, 8)}...)`))
62
+ } else {
63
+ spinner.fail(chalk.red('No environments found for project. Please specify --environment <uuid>'))
64
+ return
65
+ }
66
+ }
67
+
68
+ // Ensure environmentUuid is defined before creating application
69
+ if (!environmentUuid) {
70
+ spinner.fail(chalk.red('Environment UUID is required'))
71
+ return
72
+ }
73
+
74
+ spinner.text = 'Creating application...'
75
+
76
+ const result = await coolify.createApplication(
77
+ {
78
+ name: options.name,
79
+ description: options.description,
80
+ projectUuid: options.project,
81
+ environmentUuid,
82
+ serverUuid: options.server,
83
+ type: options.type || 'public',
84
+ githubRepoUrl: options.repo,
85
+ branch: options.branch || 'main',
86
+ buildPack: options.buildPack || 'dockerfile',
87
+ portsExposes: options.ports || '3000',
88
+ dockerImage: options.dockerImage,
89
+ dockerCompose: options.dockerCompose,
90
+ dockerfileLocation: options.dockerfileLocation,
91
+ baseDirectory: options.baseDirectory,
92
+ },
93
+ (percent, message) => {
94
+ spinner.text = `${chalk.bold(`[${percent}%]`)} ${message}`
95
+ }
96
+ )
97
+
98
+ if (isOk(result)) {
99
+ spinner.succeed(
100
+ chalk.green(`Application created! UUID: ${chalk.cyan(result.value.uuid?.slice(0, 8))}`)
101
+ )
102
+ console.log(` Full UUID: ${chalk.cyan(result.value.uuid)}`)
103
+ console.log(` Name: ${chalk.cyan(options.name)}`)
104
+ console.log(` Type: ${chalk.cyan(options.type || 'public')}`)
105
+ console.log(` Next steps:`)
106
+ console.log(` 1. Set environment variables: ${chalk.yellow('coolify-mcp env ' + result.value.uuid?.slice(0, 8))}`)
107
+ console.log(` 2. Deploy application: ${chalk.yellow('coolify-mcp deploy ' + result.value.uuid?.slice(0, 8))}`)
108
+ } else {
109
+ spinner.fail(chalk.red(`Creation failed: ${result.error.message}`))
110
+ }
111
+ } catch (error) {
112
+ spinner.fail(
113
+ chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`)
114
+ )
115
+ }
116
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Delete application command.
3
+ *
4
+ * Deletes an existing Coolify application.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { isErr } from '@mks2508/no-throw'
10
+ import chalk from 'chalk'
11
+ import { getCoolifyService } from '../../coolify/index.js'
12
+
13
+ /**
14
+ * Executes the delete command.
15
+ *
16
+ * @param uuid - Application UUID
17
+ * @param options - Command options
18
+ */
19
+ export async function deleteCommand(
20
+ uuid: string,
21
+ options: { force?: boolean; yes?: boolean } = {}
22
+ ): Promise<void> {
23
+ const service = getCoolifyService()
24
+ const initResult = await service.init()
25
+
26
+ if (isErr(initResult)) {
27
+ console.error(chalk.red('Failed to initialize Coolify service'))
28
+ console.error(chalk.gray(initResult.error.message))
29
+ process.exit(1)
30
+ }
31
+
32
+ if (!options.force && !options.yes) {
33
+ const readline = await import('readline')
34
+ const rl = readline.createInterface({
35
+ input: process.stdin,
36
+ output: process.stdout,
37
+ })
38
+
39
+ const answer = await new Promise<string>((resolve) => {
40
+ rl.question(
41
+ chalk.yellow(`Are you sure you want to delete application ${chalk.bold(uuid)}? (yes/no): `),
42
+ (ans) => {
43
+ rl.close()
44
+ resolve(ans.toLowerCase())
45
+ }
46
+ )
47
+ })
48
+
49
+ if (answer !== 'yes' && answer !== 'y') {
50
+ console.log(chalk.gray('Operation cancelled'))
51
+ process.exit(0)
52
+ }
53
+ }
54
+
55
+ console.log(chalk.cyan(`Deleting application ${chalk.bold(uuid)}...`))
56
+
57
+ const result = await service.deleteApplication(uuid)
58
+
59
+ if (isErr(result)) {
60
+ console.error(chalk.red('Failed to delete application'))
61
+ console.error(chalk.gray(result.error.message))
62
+ process.exit(1)
63
+ }
64
+
65
+ console.log(chalk.green('Application deleted successfully'))
66
+ if (result.value.message) {
67
+ console.log(chalk.gray(result.value.message))
68
+ }
69
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Deployments command for CLI.
3
+ *
4
+ * Shows deployment history for an application.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { isErr } from '@mks2508/no-throw'
10
+ import chalk from 'chalk'
11
+ import Table from 'cli-table3'
12
+ import { getCoolifyService } from '../../coolify/index.js'
13
+ import { formatStatus } from '../../utils/format.js'
14
+
15
+ /**
16
+ * Deployments command handler.
17
+ *
18
+ * @param uuid - Application UUID
19
+ * @param options - Command options
20
+ */
21
+ export async function deploymentsCommand(
22
+ uuid: string,
23
+ options: { full?: boolean; limit?: number } = {}
24
+ ) {
25
+ const coolify = getCoolifyService()
26
+ const initResult = await coolify.init()
27
+
28
+ if (isErr(initResult)) {
29
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
30
+ return
31
+ }
32
+
33
+ const result = await coolify.getApplicationDeploymentHistory(uuid)
34
+
35
+ if (isErr(result)) {
36
+ console.error(chalk.red(`Error: ${result.error.message}`))
37
+ return
38
+ }
39
+
40
+ let deployments = result.value
41
+
42
+ // Show most recent first
43
+ deployments = deployments.reverse()
44
+
45
+ if (options.limit) {
46
+ deployments = deployments.slice(0, options.limit)
47
+ }
48
+
49
+ if (deployments.length === 0) {
50
+ console.log(chalk.yellow('No deployments found'))
51
+ return
52
+ }
53
+
54
+ const table = new Table({
55
+ head: [
56
+ chalk.cyan('ID'),
57
+ chalk.cyan('UUID'),
58
+ chalk.cyan('Status'),
59
+ chalk.cyan('Commit'),
60
+ chalk.cyan('Created'),
61
+ ],
62
+ ...(options.full ? { colWidths: [8, 36, 20, 10, 20] } : {}),
63
+ })
64
+
65
+ for (const dep of deployments) {
66
+ table.push([
67
+ String(dep.id),
68
+ options.full ? dep.uuid : dep.uuid.slice(0, 8),
69
+ formatStatus(dep.status),
70
+ dep.commit?.slice(0, 7) || '-',
71
+ new Date(dep.created_at).toLocaleString(),
72
+ ])
73
+ }
74
+
75
+ console.log(table.toString())
76
+ console.log(chalk.gray(`Total: ${deployments.length} deployment(s)`))
77
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Destinations command for CLI.
3
+ *
4
+ * Lists available destinations for a server.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { isErr } from '@mks2508/no-throw'
10
+ import chalk from 'chalk'
11
+ import Table from 'cli-table3'
12
+ import { getCoolifyService } from '../../coolify/index.js'
13
+
14
+ /**
15
+ * Destinations command handler.
16
+ *
17
+ * @param serverUuid - Server UUID
18
+ */
19
+ export async function destinationsCommand(serverUuid: string) {
20
+ const coolify = getCoolifyService()
21
+ const initResult = await coolify.init()
22
+
23
+ if (isErr(initResult)) {
24
+ console.error(chalk.red(`Error: ${initResult.error.message}`))
25
+ return
26
+ }
27
+
28
+ const result = await coolify.getServerDestinations(serverUuid)
29
+
30
+ if (isErr(result)) {
31
+ console.error(chalk.red(`Error: ${result.error.message}`))
32
+ return
33
+ }
34
+
35
+ const destinations = result.value
36
+
37
+ if (destinations.length === 0) {
38
+ console.log(chalk.yellow('No destinations found'))
39
+ return
40
+ }
41
+
42
+ const table = new Table({
43
+ head: [
44
+ chalk.cyan('UUID'),
45
+ chalk.cyan('Name'),
46
+ chalk.cyan('Network'),
47
+ ],
48
+ })
49
+
50
+ for (const dest of destinations) {
51
+ table.push([
52
+ dest.uuid,
53
+ dest.name,
54
+ dest.network || 'N/A',
55
+ ])
56
+ }
57
+
58
+ console.log(table.toString())
59
+ console.log(chalk.gray(`Total: ${destinations.length} destination(s)`))
60
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Environments command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isOk, isErr } from '@mks2508/no-throw'
8
+ import ora from 'ora'
9
+ import chalk from 'chalk'
10
+ import Table from 'cli-table3'
11
+ import { getCoolifyService } from '../../coolify/index.js'
12
+
13
+ /**
14
+ * Environments command handler.
15
+ *
16
+ * @param projectUuid - Project UUID to get environments for
17
+ * @param options - Command options
18
+ */
19
+ export async function environmentsCommand(projectUuid: string, options: { full?: boolean } = {}) {
20
+ const spinner = ora('Connecting to Coolify...').start()
21
+
22
+ try {
23
+ const coolify = getCoolifyService()
24
+ const initResult = await coolify.init()
25
+
26
+ if (isErr(initResult)) {
27
+ spinner.fail(chalk.red(`Failed to initialize: ${initResult.error.message}`))
28
+ return
29
+ }
30
+
31
+ spinner.text = `Fetching environments for project ${projectUuid.slice(0, 8)}...`
32
+
33
+ const result = await coolify.getProjectEnvironments(projectUuid)
34
+
35
+ if (isOk(result)) {
36
+ spinner.succeed(chalk.green('Environments retrieved'))
37
+
38
+ const environments = result.value
39
+
40
+ if (environments.length === 0) {
41
+ console.log(chalk.yellow('No environments found for this project'))
42
+ return
43
+ }
44
+
45
+ const table = new Table({
46
+ head: [
47
+ chalk.cyan('UUID'),
48
+ chalk.cyan('Name'),
49
+ chalk.cyan('Description'),
50
+ ],
51
+ ...(options.full ? { colWidths: [36, 25, 40] } : {}),
52
+ })
53
+
54
+ for (const env of environments) {
55
+ table.push([
56
+ options.full ? env.uuid : env.uuid.slice(0, 8),
57
+ env.name,
58
+ env.description || '-',
59
+ ])
60
+ }
61
+
62
+ console.log(table.toString())
63
+ console.log(chalk.gray(`Total: ${environments.length} environment(s)`))
64
+ } else {
65
+ spinner.fail(chalk.red(`Failed to fetch environments: ${result.error.message}`))
66
+ }
67
+ } catch (error) {
68
+ spinner.fail(
69
+ chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`)
70
+ )
71
+ }
72
+ }
@@ -15,7 +15,7 @@ import { formatStatus } from '../../utils/format.js'
15
15
  *
16
16
  * @param options - List options
17
17
  */
18
- export async function listCommand(options: { team?: string; project?: string }) {
18
+ export async function listCommand(options: { team?: string; project?: string; full?: boolean }) {
19
19
  const coolify = getCoolifyService()
20
20
  const initResult = await coolify.init()
21
21
 
@@ -46,12 +46,12 @@ export async function listCommand(options: { team?: string; project?: string })
46
46
  chalk.cyan('Status'),
47
47
  chalk.cyan('Server')
48
48
  ],
49
- // Sin anchos fijos, dejar que cli-table3 auto-ajuste
49
+ ...(options.full ? { colWidths: [36, 30, 20, 10] } : {}),
50
50
  })
51
51
 
52
52
  for (const app of apps) {
53
53
  table.push([
54
- app.uuid,
54
+ options.full ? app.uuid : app.uuid.slice(0, 8),
55
55
  app.name,
56
56
  formatStatus(app.status),
57
57
  app.destination?.server?.name || 'N/A',
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Projects command for CLI.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { isOk, isErr } from '@mks2508/no-throw'
8
+ import ora from 'ora'
9
+ import chalk from 'chalk'
10
+ import Table from 'cli-table3'
11
+ import { getCoolifyService } from '../../coolify/index.js'
12
+
13
+ /**
14
+ * Projects command handler.
15
+ */
16
+ export async function projectsCommand(options: { full?: boolean } = {}) {
17
+ const spinner = ora('Connecting to Coolify...').start()
18
+
19
+ try {
20
+ const coolify = getCoolifyService()
21
+ const initResult = await coolify.init()
22
+
23
+ if (isErr(initResult)) {
24
+ spinner.fail(chalk.red(`Failed to initialize: ${initResult.error.message}`))
25
+ return
26
+ }
27
+
28
+ spinner.text = 'Fetching projects...'
29
+
30
+ const result = await coolify.listProjects()
31
+
32
+ if (isOk(result)) {
33
+ spinner.succeed(chalk.green('Projects retrieved'))
34
+
35
+ const projects = result.value
36
+
37
+ if (projects.length === 0) {
38
+ console.log(chalk.yellow('No projects found'))
39
+ return
40
+ }
41
+
42
+ const table = new Table({
43
+ head: [
44
+ chalk.cyan('UUID'),
45
+ chalk.cyan('Name'),
46
+ chalk.cyan('Description'),
47
+ ],
48
+ ...(options.full ? { colWidths: [36, 30, 40] } : {}),
49
+ })
50
+
51
+ for (const project of projects) {
52
+ table.push([
53
+ options.full ? project.uuid : project.uuid.slice(0, 8),
54
+ project.name,
55
+ project.description || '-',
56
+ ])
57
+ }
58
+
59
+ console.log(table.toString())
60
+ console.log(chalk.gray(`Total: ${projects.length} project(s)`))
61
+ } else {
62
+ spinner.fail(chalk.red(`Failed to fetch projects: ${result.error.message}`))
63
+ }
64
+ } catch (error) {
65
+ spinner.fail(
66
+ chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`)
67
+ )
68
+ }
69
+ }
@@ -12,7 +12,7 @@ import { createTable } from '../../utils/format.js'
12
12
  /**
13
13
  * Servers command handler.
14
14
  */
15
- export async function serversCommand() {
15
+ export async function serversCommand(options: { full?: boolean } = {}) {
16
16
  const coolify = getCoolifyService()
17
17
  const initResult = await coolify.init()
18
18
 
@@ -35,12 +35,12 @@ export async function serversCommand() {
35
35
  return
36
36
  }
37
37
 
38
- const table = createTable(['UUID', 'Name', 'IP', 'Status'], [36, 25, 20, 15])
38
+ const table = createTable(['UUID', 'Name', 'IP', 'Status'], [options.full ? 36 : 8, 25, 20, 15])
39
39
 
40
40
  for (const server of servers) {
41
41
  const statusColor = server.is_usable ? chalk.green : chalk.red
42
42
  table.push([
43
- server.uuid.slice(0, 8),
43
+ options.full ? server.uuid : server.uuid.slice(0, 8),
44
44
  server.name,
45
45
  server.ip || 'N/A',
46
46
  statusColor(server.is_usable ? '● Usable' : '○ Unusable'),