@studiometa/forge-cli 0.2.5 → 0.4.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.
Files changed (59) hide show
  1. package/README.md +61 -58
  2. package/dist/cli.js +866 -597
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/backups/command.d.ts.map +1 -1
  5. package/dist/commands/backups/handlers.d.ts +1 -0
  6. package/dist/commands/backups/handlers.d.ts.map +1 -1
  7. package/dist/commands/backups/help.d.ts.map +1 -1
  8. package/dist/commands/certificates/command.d.ts.map +1 -1
  9. package/dist/commands/certificates/handlers.d.ts +0 -1
  10. package/dist/commands/certificates/handlers.d.ts.map +1 -1
  11. package/dist/commands/certificates/help.d.ts.map +1 -1
  12. package/dist/commands/commands/handlers.d.ts.map +1 -1
  13. package/dist/commands/completion.d.ts.map +1 -1
  14. package/dist/commands/config.d.ts +1 -1
  15. package/dist/commands/config.d.ts.map +1 -1
  16. package/dist/commands/daemons/command.d.ts.map +1 -1
  17. package/dist/commands/daemons/handlers.d.ts +1 -0
  18. package/dist/commands/daemons/handlers.d.ts.map +1 -1
  19. package/dist/commands/daemons/help.d.ts.map +1 -1
  20. package/dist/commands/database-users/command.d.ts.map +1 -1
  21. package/dist/commands/database-users/handlers.d.ts +1 -0
  22. package/dist/commands/database-users/handlers.d.ts.map +1 -1
  23. package/dist/commands/database-users/help.d.ts.map +1 -1
  24. package/dist/commands/deployments/handlers.d.ts.map +1 -1
  25. package/dist/commands/deployments/help.d.ts.map +1 -1
  26. package/dist/commands/monitors/handlers.d.ts.map +1 -1
  27. package/dist/commands/recipes/command.d.ts.map +1 -1
  28. package/dist/commands/recipes/handlers.d.ts +1 -0
  29. package/dist/commands/recipes/handlers.d.ts.map +1 -1
  30. package/dist/commands/recipes/help.d.ts.map +1 -1
  31. package/dist/commands/redirect-rules/handlers.d.ts.map +1 -1
  32. package/dist/commands/scheduled-jobs/handlers.d.ts.map +1 -1
  33. package/dist/commands/security-rules/command.d.ts.map +1 -1
  34. package/dist/commands/security-rules/handlers.d.ts +1 -0
  35. package/dist/commands/security-rules/handlers.d.ts.map +1 -1
  36. package/dist/commands/security-rules/help.d.ts.map +1 -1
  37. package/dist/commands/sites/command.d.ts.map +1 -1
  38. package/dist/commands/sites/handlers.d.ts +1 -0
  39. package/dist/commands/sites/handlers.d.ts.map +1 -1
  40. package/dist/commands/ssh-keys/handlers.d.ts.map +1 -1
  41. package/dist/config.d.ts +2 -2
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/context.d.ts.map +1 -1
  44. package/dist/{error-handler-BahHMt6t.js → error-handler-ByMitiOr.js} +24 -13
  45. package/dist/error-handler-ByMitiOr.js.map +1 -0
  46. package/dist/error-handler.d.ts +1 -1
  47. package/dist/error-handler.d.ts.map +1 -1
  48. package/dist/errors.d.ts +1 -1
  49. package/dist/errors.d.ts.map +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/output.d.ts.map +1 -1
  52. package/dist/types.d.ts +1 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/utils/args.d.ts +1 -0
  55. package/dist/utils/args.d.ts.map +1 -1
  56. package/dist/utils/command-router.d.ts.map +1 -1
  57. package/dist/utils/resolve.d.ts.map +1 -1
  58. package/package.json +4 -4
  59. package/dist/error-handler-BahHMt6t.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as createContext, c as colors, d as deleteToken, i as runCommand, l as setColorEnabled, m as setToken, n as exitWithValidationError, p as getToken, s as OutputFormatter, u as createConfigStore, v as ValidationError } from "./error-handler-BahHMt6t.js";
3
- import { activateCertificate, createAuditLogger, createBackupConfig, createCommand, createDatabaseUser, createMonitor, createNginxTemplate, createRedirectRule, createScheduledJob, createSecurityRule, deleteBackupConfig, deleteDatabaseUser, deleteMonitor, deleteNginxTemplate, deleteRedirectRule, deleteScheduledJob, deleteSecurityRule, deploySiteAndWait, getBackupConfig, getCertificate, getCommand, getDaemon, getDatabase, getDatabaseUser, getEnv, getFirewallRule, getMonitor, getNginxConfig, getNginxTemplate, getRecipe, getRedirectRule, getScheduledJob, getSecurityRule, getServer, getSite, getSshKey, getUser, listBackupConfigs, listCertificates, listCommands, listDaemons, listDatabaseUsers, listDatabases, listDeployments, listFirewallRules, listMonitors, listNginxTemplates, listRecipes, listRedirectRules, listScheduledJobs, listSecurityRules, listServers, listSites, listSshKeys, matchByName, rebootServer, restartDaemon, runRecipe, updateEnv, updateNginxConfig, updateNginxTemplate } from "@studiometa/forge-core";
2
+ import { S as isOutputFormat, a as createContext, b as ValidationError, c as colors, d as deleteToken, g as setToken, h as setOrganizationSlug, i as runCommand, l as setColorEnabled, m as getToken, n as exitWithValidationError, p as getOrganizationSlug, s as OutputFormatter, u as createConfigStore } from "./error-handler-ByMitiOr.js";
3
+ import { activateCertificate, createAuditLogger, createBackupConfig, createCommand, createDatabaseUser, createMonitor, createNginxTemplate, createRedirectRule, createScheduledJob, createSecurityRule, deleteBackupConfig, deleteDatabaseUser, deleteMonitor, deleteNginxTemplate, deleteRedirectRule, deleteScheduledJob, deleteSecurityRule, deploySiteAndWait, getBackupConfig, getCertificate, getCommand, getDaemon, getDatabase, getDatabaseUser, getEnv, getFirewallRule, getMonitor, getNginxConfig, getNginxTemplate, getRecipe, getRedirectRule, getScheduledJob, getSecurityRule, getServer, getSite, getSshKey, getUser, listBackupConfigs, listCommands, listDaemons, listDatabaseUsers, listDatabases, listDeployments, listFirewallRules, listMonitors, listNginxTemplates, listRecipes, listRedirectRules, listScheduledJobs, listSecurityRules, listServers, listSites, listSshKeys, matchByName, rebootServer, restartDaemon, runRecipe, updateBackupConfig, updateDaemon, updateDatabaseUser, updateEnv, updateNginxConfig, updateNginxTemplate, updateRecipe, updateSecurityRule, updateSite } from "@studiometa/forge-core";
4
4
  import { mkdirSync, writeFileSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { join } from "node:path";
@@ -18,7 +18,8 @@ function getCliAuditLogger() {
18
18
  */
19
19
  function createCommandRouter(config) {
20
20
  return async function(subcommand, args, options) {
21
- const formatter = new OutputFormatter(options.format ?? options.f ?? "human", options["no-color"] === true);
21
+ const rawFormat = options.format ?? options.f ?? "human";
22
+ const formatter = new OutputFormatter(isOutputFormat(rawFormat) ? rawFormat : "human", options["no-color"] === true);
22
23
  const ctx = createContext(options);
23
24
  const handler = config.handlers[subcommand];
24
25
  if (!handler) {
@@ -107,24 +108,24 @@ async function resolveSiteId(value, serverId, execCtx) {
107
108
  }
108
109
  async function backupsList(ctx) {
109
110
  const server = String(ctx.options.server ?? "");
110
- if (!server) exitWithValidationError("server_id", "forge-cli backups list --server <server_id>", ctx.formatter);
111
+ if (!server) exitWithValidationError("server_id", "forge backups list --server <server_id>", ctx.formatter);
111
112
  await runCommand(async () => {
112
113
  const token = ctx.getToken();
113
114
  const execCtx = ctx.createExecutorContext(token);
114
115
  const result = await listBackupConfigs({ server_id: await resolveServerId(server, execCtx) }, execCtx);
115
116
  ctx.formatter.outputList(result.data, [
116
117
  "id",
117
- "provider_name",
118
- "frequency",
118
+ "name",
119
+ "schedule",
119
120
  "status"
120
- ], "No backup configurations found.", (b) => `${String(b.id).padEnd(8)} ${b.provider_name.padEnd(20)} ${b.frequency.padEnd(12)} ${b.status}`);
121
+ ], "No backup configurations found.", (b) => `${String(b.id).padEnd(8)} ${b.name.padEnd(20)} ${b.schedule.padEnd(12)} ${b.status}`);
121
122
  }, ctx.formatter);
122
123
  }
123
124
  async function backupsGet(args, ctx) {
124
125
  const [id] = args;
125
126
  const server = String(ctx.options.server ?? "");
126
- if (!id) exitWithValidationError("backup_id", "forge-cli backups get <backup_id> --server <server_id>", ctx.formatter);
127
- if (!server) exitWithValidationError("server_id", "forge-cli backups get <backup_id> --server <server_id>", ctx.formatter);
127
+ if (!id) exitWithValidationError("backup_id", "forge backups get <backup_id> --server <server_id>", ctx.formatter);
128
+ if (!server) exitWithValidationError("server_id", "forge backups get <backup_id> --server <server_id>", ctx.formatter);
128
129
  await runCommand(async () => {
129
130
  const token = ctx.getToken();
130
131
  const execCtx = ctx.createExecutorContext(token);
@@ -134,49 +135,77 @@ async function backupsGet(args, ctx) {
134
135
  }, execCtx);
135
136
  ctx.formatter.outputOne(result.data, [
136
137
  "id",
138
+ "name",
137
139
  "provider",
138
- "provider_name",
139
- "frequency",
140
+ "schedule",
141
+ "displayable_schedule",
140
142
  "retention",
141
143
  "status",
142
- "last_backup_time"
144
+ "next_run_time"
143
145
  ]);
144
146
  }, ctx.formatter);
145
147
  }
146
148
  async function backupsCreate(ctx) {
147
149
  const server = String(ctx.options.server ?? "");
148
- const provider = String(ctx.options.provider ?? "");
150
+ const storageProviderId = Number(ctx.options.provider ?? 0);
149
151
  const frequency = String(ctx.options.frequency ?? "");
150
- const databasesRaw = ctx.options.databases;
151
- const databases = Array.isArray(databasesRaw) ? databasesRaw.map(Number) : databasesRaw ? [Number(databasesRaw)] : [];
152
- if (!server) exitWithValidationError("server_id", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
153
- if (!provider) exitWithValidationError("provider", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
154
- if (!frequency) exitWithValidationError("frequency", "forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
152
+ const databaseIdsRaw = ctx.options.databases;
153
+ const database_ids = Array.isArray(databaseIdsRaw) ? databaseIdsRaw.map(Number) : databaseIdsRaw ? [Number(databaseIdsRaw)] : [];
154
+ if (!server) exitWithValidationError("server_id", "forge backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
155
+ if (!storageProviderId) exitWithValidationError("provider", "forge backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
156
+ if (!frequency) exitWithValidationError("frequency", "forge backups create --server <server_id> --provider <provider> --frequency <frequency>", ctx.formatter);
155
157
  await runCommand(async () => {
156
158
  const token = ctx.getToken();
157
159
  const execCtx = ctx.createExecutorContext(token);
158
- const result = await createBackupConfig({
160
+ await createBackupConfig({
159
161
  server_id: await resolveServerId(server, execCtx),
160
- provider,
162
+ storage_provider_id: storageProviderId,
161
163
  frequency,
162
- credentials: {},
163
- databases
164
+ retention: 5,
165
+ database_ids
164
166
  }, execCtx);
165
- ctx.formatter.outputOne(result.data, [
166
- "id",
167
- "provider",
168
- "provider_name",
169
- "frequency",
170
- "retention",
171
- "status"
172
- ]);
167
+ ctx.formatter.success("Backup configuration created.");
168
+ }, ctx.formatter);
169
+ }
170
+ async function backupsUpdate(args, ctx) {
171
+ const [id] = args;
172
+ const server = String(ctx.options.server ?? "");
173
+ const storageProviderId = Number(ctx.options.provider ?? 0);
174
+ const frequency = String(ctx.options.frequency ?? "");
175
+ const retention = Number(ctx.options.retention ?? 0);
176
+ const databaseIdsRaw = ctx.options.databases;
177
+ const database_ids = Array.isArray(databaseIdsRaw) ? databaseIdsRaw.map(Number) : databaseIdsRaw ? [Number(databaseIdsRaw)] : [];
178
+ if (!id) exitWithValidationError("backup_id", "forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention>", ctx.formatter);
179
+ if (!server) exitWithValidationError("server_id", "forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention>", ctx.formatter);
180
+ if (!storageProviderId) exitWithValidationError("provider", "forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention>", ctx.formatter);
181
+ if (!frequency) exitWithValidationError("frequency", "forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention>", ctx.formatter);
182
+ if (!retention) exitWithValidationError("retention", "forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention>", ctx.formatter);
183
+ await runCommand(async () => {
184
+ const token = ctx.getToken();
185
+ const execCtx = ctx.createExecutorContext(token);
186
+ await updateBackupConfig({
187
+ server_id: await resolveServerId(server, execCtx),
188
+ id,
189
+ storage_provider_id: storageProviderId,
190
+ frequency,
191
+ retention,
192
+ database_ids,
193
+ ...ctx.options.name != null ? { name: String(ctx.options.name) } : {},
194
+ ...ctx.options.bucket != null ? { bucket: String(ctx.options.bucket) } : {},
195
+ ...ctx.options.directory != null ? { directory: String(ctx.options.directory) } : {},
196
+ ...ctx.options.day != null ? { day: String(ctx.options.day) } : {},
197
+ ...ctx.options.time != null ? { time: String(ctx.options.time) } : {},
198
+ ...ctx.options.cron != null ? { cron: String(ctx.options.cron) } : {},
199
+ ...ctx.options["notification-email"] != null ? { notification_email: String(ctx.options["notification-email"]) } : {}
200
+ }, execCtx);
201
+ ctx.formatter.success(`Backup configuration ${id} updated.`);
173
202
  }, ctx.formatter);
174
203
  }
175
204
  async function backupsDelete(args, ctx) {
176
205
  const [id] = args;
177
206
  const server = String(ctx.options.server ?? "");
178
- if (!id) exitWithValidationError("backup_id", "forge-cli backups delete <backup_id> --server <server_id>", ctx.formatter);
179
- if (!server) exitWithValidationError("server_id", "forge-cli backups delete <backup_id> --server <server_id>", ctx.formatter);
207
+ if (!id) exitWithValidationError("backup_id", "forge backups delete <backup_id> --server <server_id>", ctx.formatter);
208
+ if (!server) exitWithValidationError("server_id", "forge backups delete <backup_id> --server <server_id>", ctx.formatter);
180
209
  await runCommand(async () => {
181
210
  const token = ctx.getToken();
182
211
  const execCtx = ctx.createExecutorContext(token);
@@ -194,32 +223,37 @@ const handleBackupsCommand = createCommandRouter({
194
223
  ls: backupsList,
195
224
  get: [backupsGet, "args"],
196
225
  create: backupsCreate,
226
+ update: [backupsUpdate, "args"],
197
227
  delete: [backupsDelete, "args"]
198
228
  },
199
- writeSubcommands: ["create", "delete"]
229
+ writeSubcommands: [
230
+ "create",
231
+ "update",
232
+ "delete"
233
+ ]
200
234
  });
201
235
  function showBackupsHelp(subcommand) {
202
236
  if (subcommand === "list" || subcommand === "ls") console.log(`
203
- ${colors.bold("forge-cli backups list")} - List backup configurations on a server
237
+ ${colors.bold("forge backups list")} - List backup configurations on a server
204
238
 
205
239
  ${colors.bold("USAGE:")}
206
- forge-cli backups list --server <server_id> [options]
240
+ forge backups list --server <server_id> [options]
207
241
 
208
242
  ${colors.bold("OPTIONS:")}
209
243
  --server <id> Server ID (required)
210
244
  -f, --format <fmt> Output format: json, human, table
211
245
  `);
212
246
  else if (subcommand === "get") console.log(`
213
- ${colors.bold("forge-cli backups get")} - Get backup configuration details
247
+ ${colors.bold("forge backups get")} - Get backup configuration details
214
248
 
215
249
  ${colors.bold("USAGE:")}
216
- forge-cli backups get <backup_id> --server <server_id> [options]
250
+ forge backups get <backup_id> --server <server_id> [options]
217
251
  `);
218
252
  else if (subcommand === "create") console.log(`
219
- ${colors.bold("forge-cli backups create")} - Create a new backup configuration
253
+ ${colors.bold("forge backups create")} - Create a new backup configuration
220
254
 
221
255
  ${colors.bold("USAGE:")}
222
- forge-cli backups create --server <server_id> --provider <provider> --frequency <frequency> [options]
256
+ forge backups create --server <server_id> --provider <provider> --frequency <frequency> [options]
223
257
 
224
258
  ${colors.bold("OPTIONS:")}
225
259
  --server <id> Server ID (required)
@@ -227,30 +261,52 @@ ${colors.bold("OPTIONS:")}
227
261
  --frequency <freq> Backup frequency (required)
228
262
  --databases <ids> Comma-separated database IDs to back up (optional)
229
263
  -f, --format <fmt> Output format: json, human, table
264
+ `);
265
+ else if (subcommand === "update") console.log(`
266
+ ${colors.bold("forge backups update")} - Update a backup configuration
267
+
268
+ ${colors.bold("USAGE:")}
269
+ forge backups update <backup_id> --server <server_id> --provider <provider> --frequency <frequency> --retention <retention> [options]
270
+
271
+ ${colors.bold("OPTIONS:")}
272
+ --server <id> Server ID (required)
273
+ --provider <id> Storage provider ID (required)
274
+ --frequency <freq> Backup frequency (required)
275
+ --retention <n> Retention count (required)
276
+ --databases <ids> Comma-separated database IDs (optional)
277
+ --name <name> Backup name (optional)
278
+ --bucket <bucket> Bucket name (optional)
279
+ --directory <dir> Directory (optional)
280
+ --day <day> Day of week (optional)
281
+ --time <time> Time (optional)
282
+ --cron <cron> Cron expression (optional)
283
+ --notification-email <email> Notification email (optional)
284
+ -f, --format <fmt> Output format: json, human, table
230
285
  `);
231
286
  else if (subcommand === "delete") console.log(`
232
- ${colors.bold("forge-cli backups delete")} - Delete a backup configuration
287
+ ${colors.bold("forge backups delete")} - Delete a backup configuration
233
288
 
234
289
  ${colors.bold("USAGE:")}
235
- forge-cli backups delete <backup_id> --server <server_id> [options]
290
+ forge backups delete <backup_id> --server <server_id> [options]
236
291
  `);
237
292
  else console.log(`
238
- ${colors.bold("forge-cli backups")} - Manage backup configurations
293
+ ${colors.bold("forge backups")} - Manage backup configurations
239
294
 
240
295
  ${colors.bold("USAGE:")}
241
- forge-cli backups <subcommand> [options]
296
+ forge backups <subcommand> [options]
242
297
 
243
298
  ${colors.bold("SUBCOMMANDS:")}
244
299
  list, ls List backup configurations
245
300
  get <id> Get backup configuration details
246
301
  create Create a new backup configuration
302
+ update <id> Update a backup configuration
247
303
  delete <id> Delete a backup configuration
248
304
 
249
305
  ${colors.bold("OPTIONS:")}
250
306
  --server <id> Server ID (required)
251
307
  -f, --format <fmt> Output format: json, human, table
252
308
 
253
- Run ${colors.cyan("forge-cli backups <subcommand> --help")} for details.
309
+ Run ${colors.cyan("forge backups <subcommand> --help")} for details.
254
310
  `);
255
311
  }
256
312
  /**
@@ -258,7 +314,7 @@ Run ${colors.cyan("forge-cli backups <subcommand> --help")} for details.
258
314
  */
259
315
  var BASH_COMPLETION = `#!/usr/bin/env bash
260
316
 
261
- _forge_cli_completions() {
317
+ _forge_completions() {
262
318
  local cur prev commands subcommands options
263
319
 
264
320
  COMPREPLY=()
@@ -278,7 +334,7 @@ _forge_cli_completions() {
278
334
  local daemons_cmds="list ls get restart"
279
335
  local env_cmds="get update"
280
336
  local nginx_cmds="get update"
281
- local certificates_cmds="list ls get activate"
337
+ local certificates_cmds="get activate"
282
338
  local firewall_rules_cmds="list ls get"
283
339
  local ssh_keys_cmds="list ls get"
284
340
  local backups_cmds="list ls get create delete"
@@ -398,11 +454,11 @@ _forge_cli_completions() {
398
454
  return 0
399
455
  }
400
456
 
401
- complete -F _forge_cli_completions forge-cli
457
+ complete -F _forge_completions forge
402
458
  `;
403
- var ZSH_COMPLETION = `#compdef forge-cli
459
+ var ZSH_COMPLETION = `#compdef forge
404
460
 
405
- _forge_cli() {
461
+ _forge() {
406
462
  local line state
407
463
 
408
464
  _arguments -C \\
@@ -533,9 +589,7 @@ _forge_cli() {
533
589
  certificates|certs)
534
590
  local -a certificates_cmds
535
591
  certificates_cmds=(
536
- 'list:List certificates'
537
- 'ls:List certificates (alias)'
538
- 'get:Get certificate details'
592
+ 'get:Get certificate for a domain'
539
593
  'activate:Activate a certificate'
540
594
  )
541
595
  _describe 'certificates command' certificates_cmds
@@ -700,198 +754,197 @@ _forge_cli() {
700
754
  esac
701
755
  }
702
756
 
703
- _forge_cli "$@"
757
+ _forge "$@"
704
758
  `;
705
- var FISH_COMPLETION = `# Completions for forge-cli
759
+ var FISH_COMPLETION = `# Completions for forge
706
760
 
707
761
  # Main commands
708
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "config" -d "Manage CLI configuration"
709
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "servers" -d "Manage servers"
710
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "s" -d "Manage servers (alias)"
711
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "sites" -d "Manage sites"
712
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "deployments" -d "Manage deployments"
713
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "d" -d "Manage deployments (alias)"
714
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "databases" -d "Manage databases"
715
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "db" -d "Manage databases (alias)"
716
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "database-users" -d "Manage database users"
717
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "daemons" -d "Manage daemons"
718
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "env" -d "Manage environment variables"
719
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "nginx" -d "Manage nginx configuration"
720
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "certificates" -d "Manage SSL certificates"
721
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "certs" -d "Manage SSL certificates (alias)"
722
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "firewall-rules" -d "Manage firewall rules"
723
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "fw" -d "Manage firewall rules (alias)"
724
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "ssh-keys" -d "Manage SSH keys"
725
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "backups" -d "Manage backup configurations"
726
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "commands" -d "Manage site commands"
727
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "scheduled-jobs" -d "Manage scheduled jobs"
728
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "user" -d "Display authenticated user profile"
729
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "monitors" -d "Manage server monitors"
730
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "nginx-templates" -d "Manage Nginx templates"
731
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "security-rules" -d "Manage site security rules"
732
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "redirect-rules" -d "Manage site redirect rules"
733
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "recipes" -d "Manage recipes"
734
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "completion" -d "Generate shell completion script"
735
- complete -c forge-cli -f -n "__fish_use_subcommand" -a "help" -d "Show help"
762
+ complete -c forge -f -n "__fish_use_subcommand" -a "config" -d "Manage CLI configuration"
763
+ complete -c forge -f -n "__fish_use_subcommand" -a "servers" -d "Manage servers"
764
+ complete -c forge -f -n "__fish_use_subcommand" -a "s" -d "Manage servers (alias)"
765
+ complete -c forge -f -n "__fish_use_subcommand" -a "sites" -d "Manage sites"
766
+ complete -c forge -f -n "__fish_use_subcommand" -a "deployments" -d "Manage deployments"
767
+ complete -c forge -f -n "__fish_use_subcommand" -a "d" -d "Manage deployments (alias)"
768
+ complete -c forge -f -n "__fish_use_subcommand" -a "databases" -d "Manage databases"
769
+ complete -c forge -f -n "__fish_use_subcommand" -a "db" -d "Manage databases (alias)"
770
+ complete -c forge -f -n "__fish_use_subcommand" -a "database-users" -d "Manage database users"
771
+ complete -c forge -f -n "__fish_use_subcommand" -a "daemons" -d "Manage daemons"
772
+ complete -c forge -f -n "__fish_use_subcommand" -a "env" -d "Manage environment variables"
773
+ complete -c forge -f -n "__fish_use_subcommand" -a "nginx" -d "Manage nginx configuration"
774
+ complete -c forge -f -n "__fish_use_subcommand" -a "certificates" -d "Manage SSL certificates"
775
+ complete -c forge -f -n "__fish_use_subcommand" -a "certs" -d "Manage SSL certificates (alias)"
776
+ complete -c forge -f -n "__fish_use_subcommand" -a "firewall-rules" -d "Manage firewall rules"
777
+ complete -c forge -f -n "__fish_use_subcommand" -a "fw" -d "Manage firewall rules (alias)"
778
+ complete -c forge -f -n "__fish_use_subcommand" -a "ssh-keys" -d "Manage SSH keys"
779
+ complete -c forge -f -n "__fish_use_subcommand" -a "backups" -d "Manage backup configurations"
780
+ complete -c forge -f -n "__fish_use_subcommand" -a "commands" -d "Manage site commands"
781
+ complete -c forge -f -n "__fish_use_subcommand" -a "scheduled-jobs" -d "Manage scheduled jobs"
782
+ complete -c forge -f -n "__fish_use_subcommand" -a "user" -d "Display authenticated user profile"
783
+ complete -c forge -f -n "__fish_use_subcommand" -a "monitors" -d "Manage server monitors"
784
+ complete -c forge -f -n "__fish_use_subcommand" -a "nginx-templates" -d "Manage Nginx templates"
785
+ complete -c forge -f -n "__fish_use_subcommand" -a "security-rules" -d "Manage site security rules"
786
+ complete -c forge -f -n "__fish_use_subcommand" -a "redirect-rules" -d "Manage site redirect rules"
787
+ complete -c forge -f -n "__fish_use_subcommand" -a "recipes" -d "Manage recipes"
788
+ complete -c forge -f -n "__fish_use_subcommand" -a "completion" -d "Generate shell completion script"
789
+ complete -c forge -f -n "__fish_use_subcommand" -a "help" -d "Show help"
736
790
 
737
791
  # config subcommands
738
- complete -c forge-cli -f -n "__fish_seen_subcommand_from config" -a "set" -d "Save API token"
739
- complete -c forge-cli -f -n "__fish_seen_subcommand_from config" -a "get" -d "Show current token"
740
- complete -c forge-cli -f -n "__fish_seen_subcommand_from config" -a "delete" -d "Delete stored token"
792
+ complete -c forge -f -n "__fish_seen_subcommand_from config" -a "set" -d "Save API token"
793
+ complete -c forge -f -n "__fish_seen_subcommand_from config" -a "get" -d "Show current token"
794
+ complete -c forge -f -n "__fish_seen_subcommand_from config" -a "delete" -d "Delete stored token"
741
795
 
742
796
  # servers subcommands
743
- complete -c forge-cli -f -n "__fish_seen_subcommand_from servers s" -a "list" -d "List all servers"
744
- complete -c forge-cli -f -n "__fish_seen_subcommand_from servers s" -a "ls" -d "List all servers (alias)"
745
- complete -c forge-cli -f -n "__fish_seen_subcommand_from servers s" -a "get" -d "Get server details"
746
- complete -c forge-cli -f -n "__fish_seen_subcommand_from servers s" -a "reboot" -d "Reboot a server"
797
+ complete -c forge -f -n "__fish_seen_subcommand_from servers s" -a "list" -d "List all servers"
798
+ complete -c forge -f -n "__fish_seen_subcommand_from servers s" -a "ls" -d "List all servers (alias)"
799
+ complete -c forge -f -n "__fish_seen_subcommand_from servers s" -a "get" -d "Get server details"
800
+ complete -c forge -f -n "__fish_seen_subcommand_from servers s" -a "reboot" -d "Reboot a server"
747
801
 
748
802
  # sites subcommands
749
- complete -c forge-cli -f -n "__fish_seen_subcommand_from sites" -a "list" -d "List sites"
750
- complete -c forge-cli -f -n "__fish_seen_subcommand_from sites" -a "ls" -d "List sites (alias)"
751
- complete -c forge-cli -f -n "__fish_seen_subcommand_from sites" -a "get" -d "Get site details"
803
+ complete -c forge -f -n "__fish_seen_subcommand_from sites" -a "list" -d "List sites"
804
+ complete -c forge -f -n "__fish_seen_subcommand_from sites" -a "ls" -d "List sites (alias)"
805
+ complete -c forge -f -n "__fish_seen_subcommand_from sites" -a "get" -d "Get site details"
752
806
 
753
807
  # deployments subcommands
754
- complete -c forge-cli -f -n "__fish_seen_subcommand_from deployments d" -a "list" -d "List deployments"
755
- complete -c forge-cli -f -n "__fish_seen_subcommand_from deployments d" -a "ls" -d "List deployments (alias)"
756
- complete -c forge-cli -f -n "__fish_seen_subcommand_from deployments d" -a "deploy" -d "Trigger a deployment"
808
+ complete -c forge -f -n "__fish_seen_subcommand_from deployments d" -a "list" -d "List deployments"
809
+ complete -c forge -f -n "__fish_seen_subcommand_from deployments d" -a "ls" -d "List deployments (alias)"
810
+ complete -c forge -f -n "__fish_seen_subcommand_from deployments d" -a "deploy" -d "Trigger a deployment"
757
811
 
758
812
  # databases subcommands
759
- complete -c forge-cli -f -n "__fish_seen_subcommand_from databases db" -a "list" -d "List databases"
760
- complete -c forge-cli -f -n "__fish_seen_subcommand_from databases db" -a "ls" -d "List databases (alias)"
761
- complete -c forge-cli -f -n "__fish_seen_subcommand_from databases db" -a "get" -d "Get database details"
813
+ complete -c forge -f -n "__fish_seen_subcommand_from databases db" -a "list" -d "List databases"
814
+ complete -c forge -f -n "__fish_seen_subcommand_from databases db" -a "ls" -d "List databases (alias)"
815
+ complete -c forge -f -n "__fish_seen_subcommand_from databases db" -a "get" -d "Get database details"
762
816
 
763
817
  # database-users subcommands
764
- complete -c forge-cli -f -n "__fish_seen_subcommand_from database-users" -a "list" -d "List database users"
765
- complete -c forge-cli -f -n "__fish_seen_subcommand_from database-users" -a "ls" -d "List database users (alias)"
766
- complete -c forge-cli -f -n "__fish_seen_subcommand_from database-users" -a "get" -d "Get database user details"
767
- complete -c forge-cli -f -n "__fish_seen_subcommand_from database-users" -a "create" -d "Create a database user"
768
- complete -c forge-cli -f -n "__fish_seen_subcommand_from database-users" -a "delete" -d "Delete a database user"
818
+ complete -c forge -f -n "__fish_seen_subcommand_from database-users" -a "list" -d "List database users"
819
+ complete -c forge -f -n "__fish_seen_subcommand_from database-users" -a "ls" -d "List database users (alias)"
820
+ complete -c forge -f -n "__fish_seen_subcommand_from database-users" -a "get" -d "Get database user details"
821
+ complete -c forge -f -n "__fish_seen_subcommand_from database-users" -a "create" -d "Create a database user"
822
+ complete -c forge -f -n "__fish_seen_subcommand_from database-users" -a "delete" -d "Delete a database user"
769
823
 
770
824
  # daemons subcommands
771
- complete -c forge-cli -f -n "__fish_seen_subcommand_from daemons" -a "list" -d "List daemons"
772
- complete -c forge-cli -f -n "__fish_seen_subcommand_from daemons" -a "ls" -d "List daemons (alias)"
773
- complete -c forge-cli -f -n "__fish_seen_subcommand_from daemons" -a "get" -d "Get daemon details"
774
- complete -c forge-cli -f -n "__fish_seen_subcommand_from daemons" -a "restart" -d "Restart a daemon"
825
+ complete -c forge -f -n "__fish_seen_subcommand_from daemons" -a "list" -d "List daemons"
826
+ complete -c forge -f -n "__fish_seen_subcommand_from daemons" -a "ls" -d "List daemons (alias)"
827
+ complete -c forge -f -n "__fish_seen_subcommand_from daemons" -a "get" -d "Get daemon details"
828
+ complete -c forge -f -n "__fish_seen_subcommand_from daemons" -a "restart" -d "Restart a daemon"
775
829
 
776
830
  # env subcommands
777
- complete -c forge-cli -f -n "__fish_seen_subcommand_from env" -a "get" -d "Get env variables"
778
- complete -c forge-cli -f -n "__fish_seen_subcommand_from env" -a "update" -d "Update env variables"
831
+ complete -c forge -f -n "__fish_seen_subcommand_from env" -a "get" -d "Get env variables"
832
+ complete -c forge -f -n "__fish_seen_subcommand_from env" -a "update" -d "Update env variables"
779
833
 
780
834
  # nginx subcommands
781
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx" -a "get" -d "Get nginx config"
782
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx" -a "update" -d "Update nginx config"
835
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx" -a "get" -d "Get nginx config"
836
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx" -a "update" -d "Update nginx config"
783
837
 
784
838
  # certificates subcommands
785
- complete -c forge-cli -f -n "__fish_seen_subcommand_from certificates certs" -a "list" -d "List certificates"
786
- complete -c forge-cli -f -n "__fish_seen_subcommand_from certificates certs" -a "ls" -d "List certificates (alias)"
787
- complete -c forge-cli -f -n "__fish_seen_subcommand_from certificates certs" -a "get" -d "Get certificate details"
788
- complete -c forge-cli -f -n "__fish_seen_subcommand_from certificates certs" -a "activate" -d "Activate a certificate"
839
+ complete -c forge -f -n "__fish_seen_subcommand_from certificates certs" -a "get" -d "Get certificate for a domain"
840
+ complete -c forge -f -n "__fish_seen_subcommand_from certificates certs" -a "get" -d "Get certificate details"
841
+ complete -c forge -f -n "__fish_seen_subcommand_from certificates certs" -a "activate" -d "Activate a certificate"
789
842
 
790
843
  # firewall-rules subcommands
791
- complete -c forge-cli -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "list" -d "List firewall rules"
792
- complete -c forge-cli -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "ls" -d "List firewall rules (alias)"
793
- complete -c forge-cli -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "get" -d "Get firewall rule details"
844
+ complete -c forge -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "list" -d "List firewall rules"
845
+ complete -c forge -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "ls" -d "List firewall rules (alias)"
846
+ complete -c forge -f -n "__fish_seen_subcommand_from firewall-rules fw" -a "get" -d "Get firewall rule details"
794
847
 
795
848
  # ssh-keys subcommands
796
- complete -c forge-cli -f -n "__fish_seen_subcommand_from ssh-keys" -a "list" -d "List SSH keys"
797
- complete -c forge-cli -f -n "__fish_seen_subcommand_from ssh-keys" -a "ls" -d "List SSH keys (alias)"
798
- complete -c forge-cli -f -n "__fish_seen_subcommand_from ssh-keys" -a "get" -d "Get SSH key details"
849
+ complete -c forge -f -n "__fish_seen_subcommand_from ssh-keys" -a "list" -d "List SSH keys"
850
+ complete -c forge -f -n "__fish_seen_subcommand_from ssh-keys" -a "ls" -d "List SSH keys (alias)"
851
+ complete -c forge -f -n "__fish_seen_subcommand_from ssh-keys" -a "get" -d "Get SSH key details"
799
852
 
800
853
  # backups subcommands
801
- complete -c forge-cli -f -n "__fish_seen_subcommand_from backups" -a "list" -d "List backup configurations"
802
- complete -c forge-cli -f -n "__fish_seen_subcommand_from backups" -a "ls" -d "List backup configurations (alias)"
803
- complete -c forge-cli -f -n "__fish_seen_subcommand_from backups" -a "get" -d "Get backup configuration details"
804
- complete -c forge-cli -f -n "__fish_seen_subcommand_from backups" -a "create" -d "Create a backup configuration"
805
- complete -c forge-cli -f -n "__fish_seen_subcommand_from backups" -a "delete" -d "Delete a backup configuration"
854
+ complete -c forge -f -n "__fish_seen_subcommand_from backups" -a "list" -d "List backup configurations"
855
+ complete -c forge -f -n "__fish_seen_subcommand_from backups" -a "ls" -d "List backup configurations (alias)"
856
+ complete -c forge -f -n "__fish_seen_subcommand_from backups" -a "get" -d "Get backup configuration details"
857
+ complete -c forge -f -n "__fish_seen_subcommand_from backups" -a "create" -d "Create a backup configuration"
858
+ complete -c forge -f -n "__fish_seen_subcommand_from backups" -a "delete" -d "Delete a backup configuration"
806
859
 
807
860
  # commands subcommands
808
- complete -c forge-cli -f -n "__fish_seen_subcommand_from commands" -a "list" -d "List commands"
809
- complete -c forge-cli -f -n "__fish_seen_subcommand_from commands" -a "ls" -d "List commands (alias)"
810
- complete -c forge-cli -f -n "__fish_seen_subcommand_from commands" -a "get" -d "Get command details"
811
- complete -c forge-cli -f -n "__fish_seen_subcommand_from commands" -a "create" -d "Execute a command"
861
+ complete -c forge -f -n "__fish_seen_subcommand_from commands" -a "list" -d "List commands"
862
+ complete -c forge -f -n "__fish_seen_subcommand_from commands" -a "ls" -d "List commands (alias)"
863
+ complete -c forge -f -n "__fish_seen_subcommand_from commands" -a "get" -d "Get command details"
864
+ complete -c forge -f -n "__fish_seen_subcommand_from commands" -a "create" -d "Execute a command"
812
865
 
813
866
  # scheduled-jobs subcommands
814
- complete -c forge-cli -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "list" -d "List scheduled jobs"
815
- complete -c forge-cli -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "ls" -d "List scheduled jobs (alias)"
816
- complete -c forge-cli -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "get" -d "Get scheduled job details"
817
- complete -c forge-cli -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "create" -d "Create a scheduled job"
818
- complete -c forge-cli -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "delete" -d "Delete a scheduled job"
867
+ complete -c forge -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "list" -d "List scheduled jobs"
868
+ complete -c forge -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "ls" -d "List scheduled jobs (alias)"
869
+ complete -c forge -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "get" -d "Get scheduled job details"
870
+ complete -c forge -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "create" -d "Create a scheduled job"
871
+ complete -c forge -f -n "__fish_seen_subcommand_from scheduled-jobs" -a "delete" -d "Delete a scheduled job"
819
872
 
820
873
  # user subcommands
821
- complete -c forge-cli -f -n "__fish_seen_subcommand_from user" -a "get" -d "Get the authenticated user profile"
874
+ complete -c forge -f -n "__fish_seen_subcommand_from user" -a "get" -d "Get the authenticated user profile"
822
875
 
823
876
  # monitors subcommands
824
- complete -c forge-cli -f -n "__fish_seen_subcommand_from monitors" -a "list" -d "List monitors"
825
- complete -c forge-cli -f -n "__fish_seen_subcommand_from monitors" -a "ls" -d "List monitors (alias)"
826
- complete -c forge-cli -f -n "__fish_seen_subcommand_from monitors" -a "get" -d "Get monitor details"
827
- complete -c forge-cli -f -n "__fish_seen_subcommand_from monitors" -a "create" -d "Create a monitor"
828
- complete -c forge-cli -f -n "__fish_seen_subcommand_from monitors" -a "delete" -d "Delete a monitor"
877
+ complete -c forge -f -n "__fish_seen_subcommand_from monitors" -a "list" -d "List monitors"
878
+ complete -c forge -f -n "__fish_seen_subcommand_from monitors" -a "ls" -d "List monitors (alias)"
879
+ complete -c forge -f -n "__fish_seen_subcommand_from monitors" -a "get" -d "Get monitor details"
880
+ complete -c forge -f -n "__fish_seen_subcommand_from monitors" -a "create" -d "Create a monitor"
881
+ complete -c forge -f -n "__fish_seen_subcommand_from monitors" -a "delete" -d "Delete a monitor"
829
882
 
830
883
  # nginx-templates subcommands
831
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "list" -d "List Nginx templates"
832
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "ls" -d "List Nginx templates (alias)"
833
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "get" -d "Get Nginx template details"
834
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "create" -d "Create a Nginx template"
835
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "update" -d "Update a Nginx template"
836
- complete -c forge-cli -f -n "__fish_seen_subcommand_from nginx-templates" -a "delete" -d "Delete a Nginx template"
884
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "list" -d "List Nginx templates"
885
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "ls" -d "List Nginx templates (alias)"
886
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "get" -d "Get Nginx template details"
887
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "create" -d "Create a Nginx template"
888
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "update" -d "Update a Nginx template"
889
+ complete -c forge -f -n "__fish_seen_subcommand_from nginx-templates" -a "delete" -d "Delete a Nginx template"
837
890
 
838
891
  # security-rules subcommands
839
- complete -c forge-cli -f -n "__fish_seen_subcommand_from security-rules" -a "list" -d "List security rules"
840
- complete -c forge-cli -f -n "__fish_seen_subcommand_from security-rules" -a "ls" -d "List security rules (alias)"
841
- complete -c forge-cli -f -n "__fish_seen_subcommand_from security-rules" -a "get" -d "Get security rule details"
842
- complete -c forge-cli -f -n "__fish_seen_subcommand_from security-rules" -a "create" -d "Create a security rule"
843
- complete -c forge-cli -f -n "__fish_seen_subcommand_from security-rules" -a "delete" -d "Delete a security rule"
892
+ complete -c forge -f -n "__fish_seen_subcommand_from security-rules" -a "list" -d "List security rules"
893
+ complete -c forge -f -n "__fish_seen_subcommand_from security-rules" -a "ls" -d "List security rules (alias)"
894
+ complete -c forge -f -n "__fish_seen_subcommand_from security-rules" -a "get" -d "Get security rule details"
895
+ complete -c forge -f -n "__fish_seen_subcommand_from security-rules" -a "create" -d "Create a security rule"
896
+ complete -c forge -f -n "__fish_seen_subcommand_from security-rules" -a "delete" -d "Delete a security rule"
844
897
 
845
898
  # redirect-rules subcommands
846
- complete -c forge-cli -f -n "__fish_seen_subcommand_from redirect-rules" -a "list" -d "List redirect rules"
847
- complete -c forge-cli -f -n "__fish_seen_subcommand_from redirect-rules" -a "ls" -d "List redirect rules (alias)"
848
- complete -c forge-cli -f -n "__fish_seen_subcommand_from redirect-rules" -a "get" -d "Get redirect rule details"
849
- complete -c forge-cli -f -n "__fish_seen_subcommand_from redirect-rules" -a "create" -d "Create a redirect rule"
850
- complete -c forge-cli -f -n "__fish_seen_subcommand_from redirect-rules" -a "delete" -d "Delete a redirect rule"
899
+ complete -c forge -f -n "__fish_seen_subcommand_from redirect-rules" -a "list" -d "List redirect rules"
900
+ complete -c forge -f -n "__fish_seen_subcommand_from redirect-rules" -a "ls" -d "List redirect rules (alias)"
901
+ complete -c forge -f -n "__fish_seen_subcommand_from redirect-rules" -a "get" -d "Get redirect rule details"
902
+ complete -c forge -f -n "__fish_seen_subcommand_from redirect-rules" -a "create" -d "Create a redirect rule"
903
+ complete -c forge -f -n "__fish_seen_subcommand_from redirect-rules" -a "delete" -d "Delete a redirect rule"
851
904
 
852
905
  # recipes subcommands
853
- complete -c forge-cli -f -n "__fish_seen_subcommand_from recipes" -a "list" -d "List all recipes"
854
- complete -c forge-cli -f -n "__fish_seen_subcommand_from recipes" -a "ls" -d "List all recipes (alias)"
855
- complete -c forge-cli -f -n "__fish_seen_subcommand_from recipes" -a "get" -d "Get recipe details"
856
- complete -c forge-cli -f -n "__fish_seen_subcommand_from recipes" -a "run" -d "Run a recipe"
906
+ complete -c forge -f -n "__fish_seen_subcommand_from recipes" -a "list" -d "List all recipes"
907
+ complete -c forge -f -n "__fish_seen_subcommand_from recipes" -a "ls" -d "List all recipes (alias)"
908
+ complete -c forge -f -n "__fish_seen_subcommand_from recipes" -a "get" -d "Get recipe details"
909
+ complete -c forge -f -n "__fish_seen_subcommand_from recipes" -a "run" -d "Run a recipe"
857
910
 
858
911
  # completion subcommands
859
- complete -c forge-cli -f -n "__fish_seen_subcommand_from completion" -a "bash" -d "Install Bash completion"
860
- complete -c forge-cli -f -n "__fish_seen_subcommand_from completion" -a "zsh" -d "Install Zsh completion"
861
- complete -c forge-cli -f -n "__fish_seen_subcommand_from completion" -a "fish" -d "Install Fish completion"
912
+ complete -c forge -f -n "__fish_seen_subcommand_from completion" -a "bash" -d "Install Bash completion"
913
+ complete -c forge -f -n "__fish_seen_subcommand_from completion" -a "zsh" -d "Install Zsh completion"
914
+ complete -c forge -f -n "__fish_seen_subcommand_from completion" -a "fish" -d "Install Fish completion"
862
915
 
863
916
  # Global options
864
- complete -c forge-cli -l token -d "API token" -r
865
- complete -c forge-cli -l server -d "Server ID" -r
866
- complete -c forge-cli -l site -d "Site ID" -r
867
- complete -c forge-cli -s f -l format -d "Output format" -xa "json human table"
868
- complete -c forge-cli -l no-color -d "Disable colored output"
869
- complete -c forge-cli -s h -l help -d "Show help"
870
- complete -c forge-cli -s v -l version -d "Show version"
871
- complete -c forge-cli -l name -d "Name" -r
872
- complete -c forge-cli -l command -d "Command" -r
873
- complete -c forge-cli -l content -d "Content" -r
874
- complete -c forge-cli -l from -d "From" -r
875
- complete -c forge-cli -l to -d "To" -r
876
- complete -c forge-cli -l provider -d "Provider" -r
877
- complete -c forge-cli -l frequency -d "Frequency" -r
878
- complete -c forge-cli -l type -d "Type" -r
879
- complete -c forge-cli -l operator -d "Operator" -r
880
- complete -c forge-cli -l threshold -d "Threshold" -r
881
- complete -c forge-cli -l minutes -d "Minutes" -r
882
- complete -c forge-cli -l key -d "Key" -r
883
- complete -c forge-cli -l port -d "Port" -r
884
- complete -c forge-cli -l ip-address -d "IP address" -r
885
- complete -c forge-cli -l user -d "User" -r
886
- complete -c forge-cli -l script -d "Script" -r
887
- complete -c forge-cli -l servers -d "Servers" -r
888
- complete -c forge-cli -l domain -d "Domain" -r
889
- complete -c forge-cli -l password -d "Password" -r
890
- complete -c forge-cli -l credential-id -d "Credential ID" -r
891
- complete -c forge-cli -l region -d "Region" -r
892
- complete -c forge-cli -l size -d "Size" -r
893
- complete -c forge-cli -l project-type -d "Project type" -r
894
- complete -c forge-cli -l directory -d "Directory" -r
917
+ complete -c forge -l token -d "API token" -r
918
+ complete -c forge -l server -d "Server ID" -r
919
+ complete -c forge -l site -d "Site ID" -r
920
+ complete -c forge -s f -l format -d "Output format" -xa "json human table"
921
+ complete -c forge -l no-color -d "Disable colored output"
922
+ complete -c forge -s h -l help -d "Show help"
923
+ complete -c forge -s v -l version -d "Show version"
924
+ complete -c forge -l name -d "Name" -r
925
+ complete -c forge -l command -d "Command" -r
926
+ complete -c forge -l content -d "Content" -r
927
+ complete -c forge -l from -d "From" -r
928
+ complete -c forge -l to -d "To" -r
929
+ complete -c forge -l provider -d "Provider" -r
930
+ complete -c forge -l frequency -d "Frequency" -r
931
+ complete -c forge -l type -d "Type" -r
932
+ complete -c forge -l operator -d "Operator" -r
933
+ complete -c forge -l threshold -d "Threshold" -r
934
+ complete -c forge -l minutes -d "Minutes" -r
935
+ complete -c forge -l key -d "Key" -r
936
+ complete -c forge -l port -d "Port" -r
937
+ complete -c forge -l ip-address -d "IP address" -r
938
+ complete -c forge -l user -d "User" -r
939
+ complete -c forge -l script -d "Script" -r
940
+ complete -c forge -l servers -d "Servers" -r
941
+ complete -c forge -l domain -d "Domain" -r
942
+ complete -c forge -l password -d "Password" -r
943
+ complete -c forge -l credential-id -d "Credential ID" -r
944
+ complete -c forge -l region -d "Region" -r
945
+ complete -c forge -l size -d "Size" -r
946
+ complete -c forge -l project-type -d "Project type" -r
947
+ complete -c forge -l directory -d "Directory" -r
895
948
  `;
896
949
  /**
897
950
  * Get the appropriate completion file path for the shell
@@ -899,18 +952,18 @@ complete -c forge-cli -l directory -d "Directory" -r
899
952
  function getCompletionPath(shell) {
900
953
  const home = homedir();
901
954
  switch (shell) {
902
- case "bash": return join(home, ".local/share/bash-completion/completions/forge-cli");
903
- case "zsh": return join(home, ".zfunc/_forge-cli");
904
- case "fish": return join(process.env["XDG_CONFIG_HOME"] ?? join(home, ".config"), "fish/completions/forge-cli.fish");
955
+ case "bash": return join(home, ".local/share/bash-completion/completions/forge");
956
+ case "zsh": return join(home, ".zfunc/_forge");
957
+ case "fish": return join(process.env["XDG_CONFIG_HOME"] ?? join(home, ".config"), "fish/completions/forge.fish");
905
958
  default: throw new Error(`Unknown shell: ${shell}`);
906
959
  }
907
960
  }
908
961
  function showCompletionHelp() {
909
962
  console.log(`
910
- ${colors.bold("forge-cli completion")} - Install shell completion
963
+ ${colors.bold("forge completion")} - Install shell completion
911
964
 
912
965
  ${colors.bold("USAGE:")}
913
- forge-cli completion <shell> [--print]
966
+ forge completion <shell> [--print]
914
967
 
915
968
  ${colors.bold("SHELLS:")}
916
969
  bash Install Bash completion
@@ -926,27 +979,27 @@ ${colors.bold("INSTALLATION:")}
926
979
  shell to activate completions.
927
980
 
928
981
  ${colors.bold("Bash:")}
929
- forge-cli completion bash
930
- # Installs to: ~/.local/share/bash-completion/completions/forge-cli
982
+ forge completion bash
983
+ # Installs to: ~/.local/share/bash-completion/completions/forge
931
984
  # Then run: exec bash
932
985
 
933
986
  ${colors.bold("Zsh:")}
934
- forge-cli completion zsh
935
- # Installs to: ~/.zfunc/_forge-cli
987
+ forge completion zsh
988
+ # Installs to: ~/.zfunc/_forge
936
989
  # Ensure fpath includes ~/.zfunc (add to ~/.zshrc before compinit):
937
990
  # fpath=(~/.zfunc $fpath)
938
991
  # Then run: exec zsh
939
992
 
940
993
  ${colors.bold("Fish:")}
941
- forge-cli completion fish
942
- # Installs to: ~/.config/fish/completions/forge-cli.fish
994
+ forge completion fish
995
+ # Installs to: ~/.config/fish/completions/forge.fish
943
996
  # Completions are loaded automatically
944
997
 
945
998
  ${colors.bold("PRINT ONLY:")}
946
999
  Use --print to output the script without installing:
947
1000
 
948
- forge-cli completion bash --print > my-completion.sh
949
- forge-cli completion zsh --print | less
1001
+ forge completion bash --print > my-completion.sh
1002
+ forge completion zsh --print | less
950
1003
  `);
951
1004
  }
952
1005
  function handleCompletionCommand(shell, options = {}) {
@@ -965,7 +1018,7 @@ function handleCompletionCommand(shell, options = {}) {
965
1018
  break;
966
1019
  default:
967
1020
  console.error(`${colors.red("✗")} Unknown shell: ${shell}. Supported shells: bash, zsh, fish`);
968
- console.error(`Run ${colors.cyan("forge-cli completion --help")} for usage information.`);
1021
+ console.error(`Run ${colors.cyan("forge completion --help")} for usage information.`);
969
1022
  process.exit(1);
970
1023
  return;
971
1024
  }
@@ -980,7 +1033,7 @@ function handleCompletionCommand(shell, options = {}) {
980
1033
  writeFileSync(installPath, script, "utf8");
981
1034
  console.log(`${colors.green("✓")} Installed ${shell} completion to ${colors.cyan(installPath)}`);
982
1035
  console.log();
983
- console.log(`${colors.bold("Next steps:")}`);
1036
+ console.log(colors.bold("Next steps:"));
984
1037
  switch (shellLower) {
985
1038
  case "bash":
986
1039
  console.log(` 1. Restart your shell: ${colors.cyan("exec bash")}`);
@@ -1000,40 +1053,22 @@ function handleCompletionCommand(shell, options = {}) {
1000
1053
  process.exit(1);
1001
1054
  }
1002
1055
  }
1003
- function requireServerAndSiteRaw$3(ctx, usage) {
1056
+ function requireServerSiteDomainRaw(ctx, usage) {
1004
1057
  const server = String(ctx.options.server ?? "");
1005
1058
  const site = String(ctx.options.site ?? "");
1059
+ const domain = String(ctx.options.domain ?? "");
1006
1060
  if (!server) exitWithValidationError("server_id", usage, ctx.formatter);
1007
1061
  if (!site) exitWithValidationError("site_id", usage, ctx.formatter);
1062
+ if (!domain) exitWithValidationError("domain_id", usage, ctx.formatter);
1008
1063
  return {
1009
1064
  server,
1010
- site
1065
+ site,
1066
+ domain
1011
1067
  };
1012
1068
  }
1013
- async function certificatesList(ctx) {
1014
- const { server, site } = requireServerAndSiteRaw$3(ctx, "forge-cli certificates list --server <server_id> --site <site_id>");
1015
- await runCommand(async () => {
1016
- const token = ctx.getToken();
1017
- const execCtx = ctx.createExecutorContext(token);
1018
- const server_id = await resolveServerId(server, execCtx);
1019
- const result = await listCertificates({
1020
- server_id,
1021
- site_id: await resolveSiteId(site, server_id, execCtx)
1022
- }, execCtx);
1023
- ctx.formatter.outputList(result.data, [
1024
- "id",
1025
- "domain",
1026
- "type",
1027
- "status",
1028
- "active"
1029
- ], "No certificates found.", (c) => `${String(c.id).padEnd(8)} ${c.domain.padEnd(40)} ${c.type.padEnd(10)} ${c.status.padEnd(12)} ${c.active ? "active" : "—"}`);
1030
- }, ctx.formatter);
1031
- }
1032
1069
  async function certificatesGet(args, ctx) {
1033
- const [id] = args;
1034
- const usage = "forge-cli certificates get <cert_id> --server <server_id> --site <site_id>";
1035
- if (!id) exitWithValidationError("certificate_id", usage, ctx.formatter);
1036
- const { server, site } = requireServerAndSiteRaw$3(ctx, usage);
1070
+ const { server, site, domain } = requireServerSiteDomainRaw(ctx, "forge certificates get --server <server_id> --site <site_id> --domain <domain_id>");
1071
+ const domainId = args[0] || domain;
1037
1072
  await runCommand(async () => {
1038
1073
  const token = ctx.getToken();
1039
1074
  const execCtx = ctx.createExecutorContext(token);
@@ -1041,25 +1076,22 @@ async function certificatesGet(args, ctx) {
1041
1076
  const result = await getCertificate({
1042
1077
  server_id,
1043
1078
  site_id: await resolveSiteId(site, server_id, execCtx),
1044
- id
1079
+ domain_id: domainId
1045
1080
  }, execCtx);
1046
1081
  ctx.formatter.outputOne(result.data, [
1047
1082
  "id",
1048
- "domain",
1049
1083
  "type",
1084
+ "verification_method",
1085
+ "key_type",
1050
1086
  "status",
1051
1087
  "request_status",
1052
- "active",
1053
- "existing",
1054
1088
  "created_at"
1055
1089
  ]);
1056
1090
  }, ctx.formatter);
1057
1091
  }
1058
1092
  async function certificatesActivate(args, ctx) {
1059
- const [id] = args;
1060
- const usage = "forge-cli certificates activate <cert_id> --server <server_id> --site <site_id>";
1061
- if (!id) exitWithValidationError("certificate_id", usage, ctx.formatter);
1062
- const { server, site } = requireServerAndSiteRaw$3(ctx, usage);
1093
+ const { server, site, domain } = requireServerSiteDomainRaw(ctx, "forge certificates activate --server <server_id> --site <site_id> --domain <domain_id>");
1094
+ const domainId = args[0] || domain;
1063
1095
  await runCommand(async () => {
1064
1096
  const token = ctx.getToken();
1065
1097
  const execCtx = ctx.createExecutorContext(token);
@@ -1067,60 +1099,55 @@ async function certificatesActivate(args, ctx) {
1067
1099
  await activateCertificate({
1068
1100
  server_id,
1069
1101
  site_id: await resolveSiteId(site, server_id, execCtx),
1070
- id
1102
+ domain_id: domainId
1071
1103
  }, execCtx);
1072
- ctx.formatter.success(`Certificate ${id} activated.`);
1104
+ ctx.formatter.success(`Certificate for domain ${domainId} activated.`);
1073
1105
  }, ctx.formatter);
1074
1106
  }
1075
1107
  const handleCertificatesCommand = createCommandRouter({
1076
1108
  resource: "certificates",
1077
1109
  handlers: {
1078
- list: certificatesList,
1079
- ls: certificatesList,
1080
1110
  get: [certificatesGet, "args"],
1081
1111
  activate: [certificatesActivate, "args"]
1082
1112
  },
1083
1113
  writeSubcommands: ["activate"]
1084
1114
  });
1085
1115
  function showCertificatesHelp(subcommand) {
1086
- if (subcommand === "list" || subcommand === "ls") console.log(`
1087
- ${colors.bold("forge-cli certificates list")} - List certificates for a site
1088
-
1089
- ${colors.bold("USAGE:")}
1090
- forge-cli certificates list --server <server_id> --site <site_id> [options]
1091
- `);
1092
- else if (subcommand === "get") console.log(`
1093
- ${colors.bold("forge-cli certificates get")} - Get certificate details
1116
+ if (subcommand === "get") console.log(`
1117
+ ${colors.bold("forge certificates get")} - Get certificate for a domain
1094
1118
 
1095
1119
  ${colors.bold("USAGE:")}
1096
- forge-cli certificates get <cert_id> --server <server_id> --site <site_id>
1120
+ forge certificates get --server <server_id> --site <site_id> --domain <domain_id>
1097
1121
  `);
1098
1122
  else if (subcommand === "activate") console.log(`
1099
- ${colors.bold("forge-cli certificates activate")} - Activate a certificate
1123
+ ${colors.bold("forge certificates activate")} - Activate a certificate
1100
1124
 
1101
1125
  ${colors.bold("USAGE:")}
1102
- forge-cli certificates activate <cert_id> --server <server_id> --site <site_id>
1126
+ forge certificates activate --server <server_id> --site <site_id> --domain <domain_id>
1103
1127
  `);
1104
1128
  else console.log(`
1105
- ${colors.bold("forge-cli certificates")} - Manage SSL certificates
1129
+ ${colors.bold("forge certificates")} - Manage SSL certificates
1106
1130
 
1107
1131
  ${colors.bold("USAGE:")}
1108
- forge-cli certificates <subcommand> [options]
1132
+ forge certificates <subcommand> [options]
1109
1133
 
1110
1134
  ${colors.bold("ALIASES:")}
1111
- forge-cli certs
1135
+ forge certs
1112
1136
 
1113
1137
  ${colors.bold("SUBCOMMANDS:")}
1114
- list, ls List certificates
1115
- get <id> Get certificate details
1116
- activate <id> Activate a certificate
1138
+ get Get certificate for a domain
1139
+ activate Activate a certificate
1117
1140
 
1118
1141
  ${colors.bold("OPTIONS:")}
1119
1142
  --server <id> Server ID (required)
1120
1143
  --site <id> Site ID (required)
1144
+ --domain <id> Domain record ID (required)
1121
1145
  -f, --format <fmt> Output format: json, human, table
1122
1146
 
1123
- Run ${colors.cyan("forge-cli certificates <subcommand> --help")} for details.
1147
+ ${colors.bold("NOTE:")}
1148
+ In Forge v2, certificates are per-domain. Use domains to manage certificates.
1149
+
1150
+ Run ${colors.cyan("forge certificates <subcommand> --help")} for details.
1124
1151
  `);
1125
1152
  }
1126
1153
  function requireServerAndSiteRaw$2(ctx, usage) {
@@ -1134,7 +1161,7 @@ function requireServerAndSiteRaw$2(ctx, usage) {
1134
1161
  };
1135
1162
  }
1136
1163
  async function commandsList(ctx) {
1137
- const { server, site } = requireServerAndSiteRaw$2(ctx, "forge-cli commands list --server <server_id> --site <site_id>");
1164
+ const { server, site } = requireServerAndSiteRaw$2(ctx, "forge commands list --server <server_id> --site <site_id>");
1138
1165
  await runCommand(async () => {
1139
1166
  const token = ctx.getToken();
1140
1167
  const execCtx = ctx.createExecutorContext(token);
@@ -1153,7 +1180,7 @@ async function commandsList(ctx) {
1153
1180
  }
1154
1181
  async function commandsGet(args, ctx) {
1155
1182
  const [id] = args;
1156
- const usage = "forge-cli commands get <command_id> --server <server_id> --site <site_id>";
1183
+ const usage = "forge commands get <command_id> --server <server_id> --site <site_id>";
1157
1184
  if (!id) exitWithValidationError("command_id", usage, ctx.formatter);
1158
1185
  const { server, site } = requireServerAndSiteRaw$2(ctx, usage);
1159
1186
  await runCommand(async () => {
@@ -1169,13 +1196,14 @@ async function commandsGet(args, ctx) {
1169
1196
  "id",
1170
1197
  "command",
1171
1198
  "status",
1172
- "user_name",
1199
+ "user_id",
1200
+ "duration",
1173
1201
  "created_at"
1174
1202
  ]);
1175
1203
  }, ctx.formatter);
1176
1204
  }
1177
1205
  async function commandsCreate(ctx) {
1178
- const usage = "forge-cli commands create --server <server_id> --site <site_id> --command <command>";
1206
+ const usage = "forge commands create --server <server_id> --site <site_id> --command <command>";
1179
1207
  const { server, site } = requireServerAndSiteRaw$2(ctx, usage);
1180
1208
  const command = String(ctx.options.command ?? "");
1181
1209
  if (!command) exitWithValidationError("command", usage, ctx.formatter);
@@ -1183,17 +1211,12 @@ async function commandsCreate(ctx) {
1183
1211
  const token = ctx.getToken();
1184
1212
  const execCtx = ctx.createExecutorContext(token);
1185
1213
  const server_id = await resolveServerId(server, execCtx);
1186
- const result = await createCommand({
1214
+ await createCommand({
1187
1215
  server_id,
1188
1216
  site_id: await resolveSiteId(site, server_id, execCtx),
1189
1217
  command
1190
1218
  }, execCtx);
1191
- ctx.formatter.outputOne(result.data, [
1192
- "id",
1193
- "command",
1194
- "status",
1195
- "created_at"
1196
- ]);
1219
+ ctx.formatter.success("Command queued for execution.");
1197
1220
  }, ctx.formatter);
1198
1221
  }
1199
1222
  const handleCommandsCommand = createCommandRouter({
@@ -1208,10 +1231,10 @@ const handleCommandsCommand = createCommandRouter({
1208
1231
  });
1209
1232
  function showCommandsHelp(subcommand) {
1210
1233
  if (subcommand === "list" || subcommand === "ls") console.log(`
1211
- ${colors.bold("forge-cli commands list")} - List commands executed on a site
1234
+ ${colors.bold("forge commands list")} - List commands executed on a site
1212
1235
 
1213
1236
  ${colors.bold("USAGE:")}
1214
- forge-cli commands list --server <server_id> --site <site_id> [options]
1237
+ forge commands list --server <server_id> --site <site_id> [options]
1215
1238
 
1216
1239
  ${colors.bold("OPTIONS:")}
1217
1240
  --server <id> Server ID (required)
@@ -1219,16 +1242,16 @@ ${colors.bold("OPTIONS:")}
1219
1242
  -f, --format <fmt> Output format: json, human, table
1220
1243
  `);
1221
1244
  else if (subcommand === "get") console.log(`
1222
- ${colors.bold("forge-cli commands get")} - Get command details
1245
+ ${colors.bold("forge commands get")} - Get command details
1223
1246
 
1224
1247
  ${colors.bold("USAGE:")}
1225
- forge-cli commands get <command_id> --server <server_id> --site <site_id> [options]
1248
+ forge commands get <command_id> --server <server_id> --site <site_id> [options]
1226
1249
  `);
1227
1250
  else if (subcommand === "create") console.log(`
1228
- ${colors.bold("forge-cli commands create")} - Execute a command on a site
1251
+ ${colors.bold("forge commands create")} - Execute a command on a site
1229
1252
 
1230
1253
  ${colors.bold("USAGE:")}
1231
- forge-cli commands create --server <server_id> --site <site_id> --command <command> [options]
1254
+ forge commands create --server <server_id> --site <site_id> --command <command> [options]
1232
1255
 
1233
1256
  ${colors.bold("OPTIONS:")}
1234
1257
  --server <id> Server ID (required)
@@ -1237,10 +1260,10 @@ ${colors.bold("OPTIONS:")}
1237
1260
  -f, --format <fmt> Output format: json, human, table
1238
1261
  `);
1239
1262
  else console.log(`
1240
- ${colors.bold("forge-cli commands")} - Manage site commands
1263
+ ${colors.bold("forge commands")} - Manage site commands
1241
1264
 
1242
1265
  ${colors.bold("USAGE:")}
1243
- forge-cli commands <subcommand> [options]
1266
+ forge commands <subcommand> [options]
1244
1267
 
1245
1268
  ${colors.bold("SUBCOMMANDS:")}
1246
1269
  list, ls List commands
@@ -1252,70 +1275,96 @@ ${colors.bold("OPTIONS:")}
1252
1275
  --site <id> Site ID (required)
1253
1276
  -f, --format <fmt> Output format: json, human, table
1254
1277
 
1255
- Run ${colors.cyan("forge-cli commands <subcommand> --help")} for details.
1278
+ Run ${colors.cyan("forge commands <subcommand> --help")} for details.
1256
1279
  `);
1257
1280
  }
1258
1281
  /**
1259
- * Config command — manage forge-cli configuration
1282
+ * Config command — manage forge configuration
1260
1283
  */
1261
1284
  function showConfigHelp() {
1262
1285
  console.log(`
1263
- ${colors.bold("forge-cli config")} - Manage CLI configuration
1286
+ ${colors.bold("forge config")} - Manage CLI configuration
1264
1287
 
1265
1288
  ${colors.bold("USAGE:")}
1266
- forge-cli config <subcommand> [options]
1289
+ forge config <subcommand> [key] [value]
1267
1290
 
1268
1291
  ${colors.bold("SUBCOMMANDS:")}
1269
- set <token> Save API token to config file
1270
- get Show current API token (masked)
1271
- delete Delete stored API token
1292
+ set <key> <value> Save a config value
1293
+ get Show current configuration (masked)
1294
+ delete Delete all stored configuration
1295
+
1296
+ ${colors.bold("CONFIG KEYS:")}
1297
+ apiToken Forge API token (scoped, from Forge dashboard)
1298
+ organizationSlug Default organization slug (e.g. 'studio-meta')
1272
1299
 
1273
1300
  ${colors.bold("EXAMPLES:")}
1274
- forge-cli config set YOUR_FORGE_TOKEN
1275
- forge-cli config get
1276
- forge-cli config delete
1301
+ forge config set apiToken YOUR_FORGE_TOKEN
1302
+ forge config set organizationSlug studio-meta
1303
+ forge config get
1304
+ forge config delete
1277
1305
  `);
1278
1306
  }
1279
1307
  function handleConfigCommand(subcommand, args, options) {
1280
- const format = String(options.format ?? options.f ?? "human");
1308
+ const rawFormat = options.format ?? options.f ?? "human";
1309
+ const format = isOutputFormat(rawFormat) ? rawFormat : "human";
1281
1310
  const formatter = new OutputFormatter(format, options["no-color"] === true);
1282
1311
  const store = createConfigStore();
1283
1312
  switch (subcommand) {
1284
1313
  case "set": {
1285
- const [token] = args;
1286
- if (!token) {
1287
- formatter.error("Token is required. Usage: forge-cli config set <token>");
1314
+ const [key, value] = args;
1315
+ if (!key || !value) {
1316
+ formatter.error("Usage: forge config set <key> <value>");
1317
+ formatter.info("Keys: apiToken, organizationSlug");
1288
1318
  process.exit(1);
1289
1319
  return;
1290
1320
  }
1291
- setToken(token, store);
1292
- formatter.success("API token saved.");
1321
+ switch (key) {
1322
+ case "apiToken":
1323
+ setToken(value, store);
1324
+ formatter.success("API token saved.");
1325
+ break;
1326
+ case "organizationSlug":
1327
+ setOrganizationSlug(value, store);
1328
+ formatter.success(`Organization slug set to "${value}".`);
1329
+ break;
1330
+ default:
1331
+ formatter.error(`Unknown config key: ${key}`);
1332
+ formatter.info("Valid keys: apiToken, organizationSlug");
1333
+ process.exit(1);
1334
+ }
1293
1335
  break;
1294
1336
  }
1295
1337
  case "get": {
1296
1338
  const token = getToken(store);
1297
- if (!token) {
1298
- formatter.warning("No API token configured.");
1299
- formatter.info("Run: forge-cli config set <token>");
1300
- } else {
1301
- const masked = token.length > 8 ? `${token.slice(0, 4)}${"*".repeat(token.length - 8)}${token.slice(-4)}` : "****";
1302
- if (format === "json") formatter.output({ apiToken: masked });
1303
- else console.log(`apiToken: ${masked}`);
1339
+ const orgSlug = getOrganizationSlug(store);
1340
+ if (format === "json") formatter.output({
1341
+ apiToken: token ? maskToken(token) : null,
1342
+ organizationSlug: orgSlug ?? null
1343
+ });
1344
+ else {
1345
+ if (token) console.log(`apiToken: ${maskToken(token)}`);
1346
+ else formatter.warning("No API token configured.");
1347
+ if (orgSlug) console.log(`organizationSlug: ${orgSlug}`);
1348
+ else formatter.warning("No organization slug configured.");
1349
+ if (!token || !orgSlug) formatter.info("Run: forge config set <key> <value>");
1304
1350
  }
1305
1351
  break;
1306
1352
  }
1307
1353
  case "delete":
1308
1354
  deleteToken(store);
1309
- formatter.success("API token deleted.");
1355
+ formatter.success("Configuration deleted.");
1310
1356
  break;
1311
1357
  default:
1312
1358
  showConfigHelp();
1313
1359
  break;
1314
1360
  }
1315
1361
  }
1362
+ function maskToken(token) {
1363
+ return token.length > 8 ? `${token.slice(0, 4)}${"*".repeat(token.length - 8)}${token.slice(-4)}` : "****";
1364
+ }
1316
1365
  async function daemonsList(ctx) {
1317
1366
  const server = String(ctx.options.server ?? "");
1318
- if (!server) exitWithValidationError("server_id", "forge-cli daemons list --server <server_id>", ctx.formatter);
1367
+ if (!server) exitWithValidationError("server_id", "forge daemons list --server <server_id>", ctx.formatter);
1319
1368
  await runCommand(async () => {
1320
1369
  const token = ctx.getToken();
1321
1370
  const execCtx = ctx.createExecutorContext(token);
@@ -1331,8 +1380,8 @@ async function daemonsList(ctx) {
1331
1380
  async function daemonsGet(args, ctx) {
1332
1381
  const [id] = args;
1333
1382
  const server = String(ctx.options.server ?? "");
1334
- if (!id) exitWithValidationError("daemon_id", "forge-cli daemons get <daemon_id> --server <server_id>", ctx.formatter);
1335
- if (!server) exitWithValidationError("server_id", "forge-cli daemons get <daemon_id> --server <server_id>", ctx.formatter);
1383
+ if (!id) exitWithValidationError("daemon_id", "forge daemons get <daemon_id> --server <server_id>", ctx.formatter);
1384
+ if (!server) exitWithValidationError("server_id", "forge daemons get <daemon_id> --server <server_id>", ctx.formatter);
1336
1385
  await runCommand(async () => {
1337
1386
  const token = ctx.getToken();
1338
1387
  const execCtx = ctx.createExecutorContext(token);
@@ -1351,11 +1400,39 @@ async function daemonsGet(args, ctx) {
1351
1400
  ]);
1352
1401
  }, ctx.formatter);
1353
1402
  }
1403
+ async function daemonsUpdate(args, ctx) {
1404
+ const [id] = args;
1405
+ const server = String(ctx.options.server ?? "");
1406
+ const name = String(ctx.options.name ?? "");
1407
+ if (!id) exitWithValidationError("daemon_id", "forge daemons update <daemon_id> --server <server_id> --name <name>", ctx.formatter);
1408
+ if (!server) exitWithValidationError("server_id", "forge daemons update <daemon_id> --server <server_id> --name <name>", ctx.formatter);
1409
+ if (!name) exitWithValidationError("name", "forge daemons update <daemon_id> --server <server_id> --name <name>", ctx.formatter);
1410
+ await runCommand(async () => {
1411
+ const token = ctx.getToken();
1412
+ const execCtx = ctx.createExecutorContext(token);
1413
+ const options = {
1414
+ server_id: await resolveServerId(server, execCtx),
1415
+ id,
1416
+ name
1417
+ };
1418
+ if (ctx.options.config) options.config = String(ctx.options.config);
1419
+ const result = await updateDaemon(options, execCtx);
1420
+ ctx.formatter.outputOne(result.data, [
1421
+ "id",
1422
+ "command",
1423
+ "user",
1424
+ "directory",
1425
+ "processes",
1426
+ "status",
1427
+ "created_at"
1428
+ ]);
1429
+ }, ctx.formatter);
1430
+ }
1354
1431
  async function daemonsRestart(args, ctx) {
1355
1432
  const [id] = args;
1356
1433
  const server = String(ctx.options.server ?? "");
1357
- if (!id) exitWithValidationError("daemon_id", "forge-cli daemons restart <daemon_id> --server <server_id>", ctx.formatter);
1358
- if (!server) exitWithValidationError("server_id", "forge-cli daemons restart <daemon_id> --server <server_id>", ctx.formatter);
1434
+ if (!id) exitWithValidationError("daemon_id", "forge daemons restart <daemon_id> --server <server_id>", ctx.formatter);
1435
+ if (!server) exitWithValidationError("server_id", "forge daemons restart <daemon_id> --server <server_id>", ctx.formatter);
1359
1436
  await runCommand(async () => {
1360
1437
  const token = ctx.getToken();
1361
1438
  const execCtx = ctx.createExecutorContext(token);
@@ -1372,50 +1449,58 @@ const handleDaemonsCommand = createCommandRouter({
1372
1449
  list: daemonsList,
1373
1450
  ls: daemonsList,
1374
1451
  get: [daemonsGet, "args"],
1375
- restart: [daemonsRestart, "args"]
1452
+ restart: [daemonsRestart, "args"],
1453
+ update: [daemonsUpdate, "args"]
1376
1454
  },
1377
- writeSubcommands: ["restart"]
1455
+ writeSubcommands: ["restart", "update"]
1378
1456
  });
1379
1457
  function showDaemonsHelp(subcommand) {
1380
1458
  if (subcommand === "list" || subcommand === "ls") console.log(`
1381
- ${colors.bold("forge-cli daemons list")} - List daemons on a server
1459
+ ${colors.bold("forge daemons list")} - List daemons on a server
1382
1460
 
1383
1461
  ${colors.bold("USAGE:")}
1384
- forge-cli daemons list --server <server_id> [options]
1462
+ forge daemons list --server <server_id> [options]
1385
1463
  `);
1386
1464
  else if (subcommand === "get") console.log(`
1387
- ${colors.bold("forge-cli daemons get")} - Get daemon details
1465
+ ${colors.bold("forge daemons get")} - Get daemon details
1466
+
1467
+ ${colors.bold("USAGE:")}
1468
+ forge daemons get <daemon_id> --server <server_id>
1469
+ `);
1470
+ else if (subcommand === "update") console.log(`
1471
+ ${colors.bold("forge daemons update")} - Update a daemon
1388
1472
 
1389
1473
  ${colors.bold("USAGE:")}
1390
- forge-cli daemons get <daemon_id> --server <server_id>
1474
+ forge daemons update <daemon_id> --server <server_id> --name <name> [--config <config>]
1391
1475
  `);
1392
1476
  else if (subcommand === "restart") console.log(`
1393
- ${colors.bold("forge-cli daemons restart")} - Restart a daemon
1477
+ ${colors.bold("forge daemons restart")} - Restart a daemon
1394
1478
 
1395
1479
  ${colors.bold("USAGE:")}
1396
- forge-cli daemons restart <daemon_id> --server <server_id>
1480
+ forge daemons restart <daemon_id> --server <server_id>
1397
1481
  `);
1398
1482
  else console.log(`
1399
- ${colors.bold("forge-cli daemons")} - Manage daemons
1483
+ ${colors.bold("forge daemons")} - Manage daemons
1400
1484
 
1401
1485
  ${colors.bold("USAGE:")}
1402
- forge-cli daemons <subcommand> [options]
1486
+ forge daemons <subcommand> [options]
1403
1487
 
1404
1488
  ${colors.bold("SUBCOMMANDS:")}
1405
1489
  list, ls List daemons
1406
1490
  get <id> Get daemon details
1491
+ update <id> Update a daemon
1407
1492
  restart <id> Restart a daemon
1408
1493
 
1409
1494
  ${colors.bold("OPTIONS:")}
1410
1495
  --server <id> Server ID (required)
1411
1496
  -f, --format <fmt> Output format: json, human, table
1412
1497
 
1413
- Run ${colors.cyan("forge-cli daemons <subcommand> --help")} for details.
1498
+ Run ${colors.cyan("forge daemons <subcommand> --help")} for details.
1414
1499
  `);
1415
1500
  }
1416
1501
  async function databasesList(ctx) {
1417
1502
  const server = String(ctx.options.server ?? "");
1418
- if (!server) exitWithValidationError("server_id", "forge-cli databases list --server <server_id>", ctx.formatter);
1503
+ if (!server) exitWithValidationError("server_id", "forge databases list --server <server_id>", ctx.formatter);
1419
1504
  await runCommand(async () => {
1420
1505
  const token = ctx.getToken();
1421
1506
  const execCtx = ctx.createExecutorContext(token);
@@ -1430,8 +1515,8 @@ async function databasesList(ctx) {
1430
1515
  async function databasesGet(args, ctx) {
1431
1516
  const [id] = args;
1432
1517
  const server = String(ctx.options.server ?? "");
1433
- if (!id) exitWithValidationError("database_id", "forge-cli databases get <database_id> --server <server_id>", ctx.formatter);
1434
- if (!server) exitWithValidationError("server_id", "forge-cli databases get <database_id> --server <server_id>", ctx.formatter);
1518
+ if (!id) exitWithValidationError("database_id", "forge databases get <database_id> --server <server_id>", ctx.formatter);
1519
+ if (!server) exitWithValidationError("server_id", "forge databases get <database_id> --server <server_id>", ctx.formatter);
1435
1520
  await runCommand(async () => {
1436
1521
  const token = ctx.getToken();
1437
1522
  const execCtx = ctx.createExecutorContext(token);
@@ -1457,29 +1542,29 @@ const handleDatabasesCommand = createCommandRouter({
1457
1542
  });
1458
1543
  function showDatabasesHelp(subcommand) {
1459
1544
  if (subcommand === "list" || subcommand === "ls") console.log(`
1460
- ${colors.bold("forge-cli databases list")} - List databases on a server
1545
+ ${colors.bold("forge databases list")} - List databases on a server
1461
1546
 
1462
1547
  ${colors.bold("USAGE:")}
1463
- forge-cli databases list --server <server_id> [options]
1548
+ forge databases list --server <server_id> [options]
1464
1549
 
1465
1550
  ${colors.bold("OPTIONS:")}
1466
1551
  --server <id> Server ID (required)
1467
1552
  -f, --format <fmt> Output format: json, human, table
1468
1553
  `);
1469
1554
  else if (subcommand === "get") console.log(`
1470
- ${colors.bold("forge-cli databases get")} - Get database details
1555
+ ${colors.bold("forge databases get")} - Get database details
1471
1556
 
1472
1557
  ${colors.bold("USAGE:")}
1473
- forge-cli databases get <database_id> --server <server_id> [options]
1558
+ forge databases get <database_id> --server <server_id> [options]
1474
1559
  `);
1475
1560
  else console.log(`
1476
- ${colors.bold("forge-cli databases")} - Manage databases
1561
+ ${colors.bold("forge databases")} - Manage databases
1477
1562
 
1478
1563
  ${colors.bold("USAGE:")}
1479
- forge-cli databases <subcommand> [options]
1564
+ forge databases <subcommand> [options]
1480
1565
 
1481
1566
  ${colors.bold("ALIASES:")}
1482
- forge-cli db
1567
+ forge db
1483
1568
 
1484
1569
  ${colors.bold("SUBCOMMANDS:")}
1485
1570
  list, ls List databases
@@ -1489,12 +1574,12 @@ ${colors.bold("OPTIONS:")}
1489
1574
  --server <id> Server ID (required)
1490
1575
  -f, --format <fmt> Output format: json, human, table
1491
1576
 
1492
- Run ${colors.cyan("forge-cli databases <subcommand> --help")} for details.
1577
+ Run ${colors.cyan("forge databases <subcommand> --help")} for details.
1493
1578
  `);
1494
1579
  }
1495
1580
  async function databaseUsersList(ctx) {
1496
1581
  const server = String(ctx.options.server ?? "");
1497
- if (!server) exitWithValidationError("server_id", "forge-cli database-users list --server <server_id>", ctx.formatter);
1582
+ if (!server) exitWithValidationError("server_id", "forge database-users list --server <server_id>", ctx.formatter);
1498
1583
  await runCommand(async () => {
1499
1584
  const token = ctx.getToken();
1500
1585
  const execCtx = ctx.createExecutorContext(token);
@@ -1509,8 +1594,8 @@ async function databaseUsersList(ctx) {
1509
1594
  async function databaseUsersGet(args, ctx) {
1510
1595
  const [id] = args;
1511
1596
  const server = String(ctx.options.server ?? "");
1512
- if (!id) exitWithValidationError("user_id", "forge-cli database-users get <user_id> --server <server_id>", ctx.formatter);
1513
- if (!server) exitWithValidationError("server_id", "forge-cli database-users get <user_id> --server <server_id>", ctx.formatter);
1597
+ if (!id) exitWithValidationError("user_id", "forge database-users get <user_id> --server <server_id>", ctx.formatter);
1598
+ if (!server) exitWithValidationError("server_id", "forge database-users get <user_id> --server <server_id>", ctx.formatter);
1514
1599
  await runCommand(async () => {
1515
1600
  const token = ctx.getToken();
1516
1601
  const execCtx = ctx.createExecutorContext(token);
@@ -1522,7 +1607,6 @@ async function databaseUsersGet(args, ctx) {
1522
1607
  "id",
1523
1608
  "name",
1524
1609
  "status",
1525
- "databases",
1526
1610
  "created_at"
1527
1611
  ]);
1528
1612
  }, ctx.formatter);
@@ -1533,9 +1617,9 @@ async function databaseUsersCreate(ctx) {
1533
1617
  const password = String(ctx.options.password ?? "");
1534
1618
  const databasesRaw = ctx.options.databases;
1535
1619
  const databases = Array.isArray(databasesRaw) ? databasesRaw.map(Number) : databasesRaw ? [Number(databasesRaw)] : void 0;
1536
- if (!server) exitWithValidationError("server_id", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1537
- if (!name) exitWithValidationError("name", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1538
- if (!password) exitWithValidationError("password", "forge-cli database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1620
+ if (!server) exitWithValidationError("server_id", "forge database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1621
+ if (!name) exitWithValidationError("name", "forge database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1622
+ if (!password) exitWithValidationError("password", "forge database-users create --server <server_id> --name <name> --password <password>", ctx.formatter);
1539
1623
  await runCommand(async () => {
1540
1624
  const token = ctx.getToken();
1541
1625
  const execCtx = ctx.createExecutorContext(token);
@@ -1549,7 +1633,31 @@ async function databaseUsersCreate(ctx) {
1549
1633
  "id",
1550
1634
  "name",
1551
1635
  "status",
1552
- "databases",
1636
+ "created_at"
1637
+ ]);
1638
+ }, ctx.formatter);
1639
+ }
1640
+ async function databaseUsersUpdate(args, ctx) {
1641
+ const [id] = args;
1642
+ const server = String(ctx.options.server ?? "");
1643
+ const password = ctx.options.password != null ? String(ctx.options.password) : void 0;
1644
+ const databaseIdsRaw = ctx.options["database-ids"] ?? ctx.options.database_ids;
1645
+ const database_ids = Array.isArray(databaseIdsRaw) ? databaseIdsRaw.map(Number) : databaseIdsRaw ? [Number(databaseIdsRaw)] : void 0;
1646
+ if (!id) exitWithValidationError("user_id", "forge database-users update <user_id> --server <server_id> [--password <password>] [--database-ids <ids>]", ctx.formatter);
1647
+ if (!server) exitWithValidationError("server_id", "forge database-users update <user_id> --server <server_id> [--password <password>] [--database-ids <ids>]", ctx.formatter);
1648
+ await runCommand(async () => {
1649
+ const token = ctx.getToken();
1650
+ const execCtx = ctx.createExecutorContext(token);
1651
+ const result = await updateDatabaseUser({
1652
+ server_id: await resolveServerId(server, execCtx),
1653
+ id,
1654
+ ...password !== void 0 ? { password } : {},
1655
+ ...database_ids ? { database_ids } : {}
1656
+ }, execCtx);
1657
+ ctx.formatter.outputOne(result.data, [
1658
+ "id",
1659
+ "name",
1660
+ "status",
1553
1661
  "created_at"
1554
1662
  ]);
1555
1663
  }, ctx.formatter);
@@ -1557,8 +1665,8 @@ async function databaseUsersCreate(ctx) {
1557
1665
  async function databaseUsersDelete(args, ctx) {
1558
1666
  const [id] = args;
1559
1667
  const server = String(ctx.options.server ?? "");
1560
- if (!id) exitWithValidationError("user_id", "forge-cli database-users delete <user_id> --server <server_id>", ctx.formatter);
1561
- if (!server) exitWithValidationError("server_id", "forge-cli database-users delete <user_id> --server <server_id>", ctx.formatter);
1668
+ if (!id) exitWithValidationError("user_id", "forge database-users delete <user_id> --server <server_id>", ctx.formatter);
1669
+ if (!server) exitWithValidationError("server_id", "forge database-users delete <user_id> --server <server_id>", ctx.formatter);
1562
1670
  await runCommand(async () => {
1563
1671
  const token = ctx.getToken();
1564
1672
  const execCtx = ctx.createExecutorContext(token);
@@ -1576,32 +1684,37 @@ const handleDatabaseUsersCommand = createCommandRouter({
1576
1684
  ls: databaseUsersList,
1577
1685
  get: [databaseUsersGet, "args"],
1578
1686
  create: databaseUsersCreate,
1687
+ update: [databaseUsersUpdate, "args"],
1579
1688
  delete: [databaseUsersDelete, "args"]
1580
1689
  },
1581
- writeSubcommands: ["create", "delete"]
1690
+ writeSubcommands: [
1691
+ "create",
1692
+ "update",
1693
+ "delete"
1694
+ ]
1582
1695
  });
1583
1696
  function showDatabaseUsersHelp(subcommand) {
1584
1697
  if (subcommand === "list" || subcommand === "ls") console.log(`
1585
- ${colors.bold("forge-cli database-users list")} - List database users on a server
1698
+ ${colors.bold("forge database-users list")} - List database users on a server
1586
1699
 
1587
1700
  ${colors.bold("USAGE:")}
1588
- forge-cli database-users list --server <server_id> [options]
1701
+ forge database-users list --server <server_id> [options]
1589
1702
 
1590
1703
  ${colors.bold("OPTIONS:")}
1591
1704
  --server <id> Server ID (required)
1592
1705
  -f, --format <fmt> Output format: json, human, table
1593
1706
  `);
1594
1707
  else if (subcommand === "get") console.log(`
1595
- ${colors.bold("forge-cli database-users get")} - Get database user details
1708
+ ${colors.bold("forge database-users get")} - Get database user details
1596
1709
 
1597
1710
  ${colors.bold("USAGE:")}
1598
- forge-cli database-users get <user_id> --server <server_id> [options]
1711
+ forge database-users get <user_id> --server <server_id> [options]
1599
1712
  `);
1600
1713
  else if (subcommand === "create") console.log(`
1601
- ${colors.bold("forge-cli database-users create")} - Create a new database user
1714
+ ${colors.bold("forge database-users create")} - Create a new database user
1602
1715
 
1603
1716
  ${colors.bold("USAGE:")}
1604
- forge-cli database-users create --server <server_id> --name <name> --password <password> [options]
1717
+ forge database-users create --server <server_id> --name <name> --password <password> [options]
1605
1718
 
1606
1719
  ${colors.bold("OPTIONS:")}
1607
1720
  --server <id> Server ID (required)
@@ -1609,37 +1722,50 @@ ${colors.bold("OPTIONS:")}
1609
1722
  --password <pass> User password (required)
1610
1723
  --databases <ids> Comma-separated database IDs to grant access to (optional)
1611
1724
  -f, --format <fmt> Output format: json, human, table
1725
+ `);
1726
+ else if (subcommand === "update") console.log(`
1727
+ ${colors.bold("forge database-users update")} - Update a database user
1728
+
1729
+ ${colors.bold("USAGE:")}
1730
+ forge database-users update <user_id> --server <server_id> [options]
1731
+
1732
+ ${colors.bold("OPTIONS:")}
1733
+ --server <id> Server ID (required)
1734
+ --password <pass> New password (optional)
1735
+ --database-ids <ids> Comma-separated database IDs (optional)
1736
+ -f, --format <fmt> Output format: json, human, table
1612
1737
  `);
1613
1738
  else if (subcommand === "delete") console.log(`
1614
- ${colors.bold("forge-cli database-users delete")} - Delete a database user
1739
+ ${colors.bold("forge database-users delete")} - Delete a database user
1615
1740
 
1616
1741
  ${colors.bold("USAGE:")}
1617
- forge-cli database-users delete <user_id> --server <server_id> [options]
1742
+ forge database-users delete <user_id> --server <server_id> [options]
1618
1743
  `);
1619
1744
  else console.log(`
1620
- ${colors.bold("forge-cli database-users")} - Manage database users
1745
+ ${colors.bold("forge database-users")} - Manage database users
1621
1746
 
1622
1747
  ${colors.bold("USAGE:")}
1623
- forge-cli database-users <subcommand> [options]
1748
+ forge database-users <subcommand> [options]
1624
1749
 
1625
1750
  ${colors.bold("SUBCOMMANDS:")}
1626
1751
  list, ls List database users
1627
1752
  get <id> Get database user details
1628
1753
  create Create a new database user
1754
+ update <id> Update a database user
1629
1755
  delete <id> Delete a database user
1630
1756
 
1631
1757
  ${colors.bold("OPTIONS:")}
1632
1758
  --server <id> Server ID (required)
1633
1759
  -f, --format <fmt> Output format: json, human, table
1634
1760
 
1635
- Run ${colors.cyan("forge-cli database-users <subcommand> --help")} for details.
1761
+ Run ${colors.cyan("forge database-users <subcommand> --help")} for details.
1636
1762
  `);
1637
1763
  }
1638
1764
  async function deploymentsList(ctx) {
1639
1765
  const server = String(ctx.options.server ?? "");
1640
1766
  const site = String(ctx.options.site ?? "");
1641
- if (!server) exitWithValidationError("server_id", "forge-cli deployments list --server <server_id> --site <site_id>", ctx.formatter);
1642
- if (!site) exitWithValidationError("site_id", "forge-cli deployments list --server <server_id> --site <site_id>", ctx.formatter);
1767
+ if (!server) exitWithValidationError("server_id", "forge deployments list --server <server_id> --site <site_id>", ctx.formatter);
1768
+ if (!site) exitWithValidationError("site_id", "forge deployments list --server <server_id> --site <site_id>", ctx.formatter);
1643
1769
  await runCommand(async () => {
1644
1770
  const token = ctx.getToken();
1645
1771
  const execCtx = ctx.createExecutorContext(token);
@@ -1651,16 +1777,17 @@ async function deploymentsList(ctx) {
1651
1777
  ctx.formatter.outputList(result.data, [
1652
1778
  "id",
1653
1779
  "status",
1654
- "commit_hash",
1780
+ "commit",
1655
1781
  "started_at"
1656
- ], "No deployments found.", (d) => `${String(d.id).padEnd(8)} ${d.status.padEnd(12)} ${(d.commit_hash ?? "—").padEnd(10)} ${d.started_at}`);
1782
+ ], "No deployments found.", (d) => `${String(d.id).padEnd(8)} ${d.status.padEnd(12)} ${(d.commit.hash ?? "—").padEnd(10)} ${d.started_at}`);
1657
1783
  }, ctx.formatter);
1658
1784
  }
1659
1785
  async function deploymentsDeploy(ctx) {
1660
1786
  const server = String(ctx.options.server ?? "");
1661
1787
  const site = String(ctx.options.site ?? "");
1662
- if (!server) exitWithValidationError("server_id", "forge-cli deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
1663
- if (!site) exitWithValidationError("site_id", "forge-cli deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
1788
+ const streamLogs = Boolean(ctx.options.stream);
1789
+ if (!server) exitWithValidationError("server_id", "forge deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
1790
+ if (!site) exitWithValidationError("site_id", "forge deployments deploy --server <server_id> --site <site_id>", ctx.formatter);
1664
1791
  await runCommand(async () => {
1665
1792
  const token = ctx.getToken();
1666
1793
  const execCtx = ctx.createExecutorContext(token);
@@ -1669,15 +1796,18 @@ async function deploymentsDeploy(ctx) {
1669
1796
  const result = await deploySiteAndWait({
1670
1797
  server_id,
1671
1798
  site_id,
1672
- onProgress: ({ status, elapsed_ms }) => {
1799
+ onProgress: streamLogs ? void 0 : ({ status, elapsed_ms }) => {
1673
1800
  process.stderr.write(`\rDeploying… ${status} (${(elapsed_ms / 1e3).toFixed(1)}s)`);
1674
- }
1801
+ },
1802
+ onLog: streamLogs ? (chunk) => {
1803
+ process.stdout.write(chunk);
1804
+ } : void 0
1675
1805
  }, execCtx);
1676
- process.stderr.write("\n");
1806
+ if (!streamLogs) process.stderr.write("\n");
1677
1807
  const elapsedSec = (result.data.elapsed_ms / 1e3).toFixed(1);
1678
1808
  if (result.data.status === "success") ctx.formatter.success(`Deployment succeeded for site ${site_id} (${elapsedSec}s).`);
1679
- else ctx.formatter.success(`Deployment failed for site ${site_id} (${elapsedSec}s).`);
1680
- if (result.data.log) ctx.formatter.output(result.data.log);
1809
+ else ctx.formatter.error(`Deployment failed for site ${site_id} (${elapsedSec}s).`);
1810
+ if (!streamLogs && result.data.log) ctx.formatter.output(result.data.log);
1681
1811
  }, ctx.formatter);
1682
1812
  }
1683
1813
  const handleDeploymentsCommand = createCommandRouter({
@@ -1691,10 +1821,10 @@ const handleDeploymentsCommand = createCommandRouter({
1691
1821
  });
1692
1822
  function showDeploymentsHelp(subcommand) {
1693
1823
  if (subcommand === "list" || subcommand === "ls") console.log(`
1694
- ${colors.bold("forge-cli deployments list")} - List deployments for a site
1824
+ ${colors.bold("forge deployments list")} - List deployments for a site
1695
1825
 
1696
1826
  ${colors.bold("USAGE:")}
1697
- forge-cli deployments list --server <server_id> --site <site_id> [options]
1827
+ forge deployments list --server <server_id> --site <site_id> [options]
1698
1828
 
1699
1829
  ${colors.bold("OPTIONS:")}
1700
1830
  --server <id> Server ID (required)
@@ -1702,19 +1832,25 @@ ${colors.bold("OPTIONS:")}
1702
1832
  -f, --format <fmt> Output format: json, human, table
1703
1833
  `);
1704
1834
  else if (subcommand === "deploy") console.log(`
1705
- ${colors.bold("forge-cli deployments deploy")} - Trigger a deployment
1835
+ ${colors.bold("forge deployments deploy")} - Trigger a deployment
1706
1836
 
1707
1837
  ${colors.bold("USAGE:")}
1708
- forge-cli deployments deploy --server <server_id> --site <site_id>
1838
+ forge deployments deploy --server <server_id> --site <site_id> [options]
1839
+
1840
+ ${colors.bold("OPTIONS:")}
1841
+ --server <id> Server ID (required)
1842
+ --site <id> Site ID (required)
1843
+ --stream Stream deployment logs in real-time (default: show progress)
1844
+ -f, --format <fmt> Output format: json, human, table
1709
1845
  `);
1710
1846
  else console.log(`
1711
- ${colors.bold("forge-cli deployments")} - Manage deployments
1847
+ ${colors.bold("forge deployments")} - Manage deployments
1712
1848
 
1713
1849
  ${colors.bold("USAGE:")}
1714
- forge-cli deployments <subcommand> [options]
1850
+ forge deployments <subcommand> [options]
1715
1851
 
1716
1852
  ${colors.bold("ALIASES:")}
1717
- forge-cli d
1853
+ forge d
1718
1854
 
1719
1855
  ${colors.bold("SUBCOMMANDS:")}
1720
1856
  list, ls List deployments for a site
@@ -1725,14 +1861,14 @@ ${colors.bold("OPTIONS:")}
1725
1861
  --site <id> Site ID (required)
1726
1862
  -f, --format <fmt> Output format: json, human, table
1727
1863
 
1728
- Run ${colors.cyan("forge-cli deployments <subcommand> --help")} for details.
1864
+ Run ${colors.cyan("forge deployments <subcommand> --help")} for details.
1729
1865
  `);
1730
1866
  }
1731
1867
  async function envGet(ctx) {
1732
1868
  const server = String(ctx.options.server ?? "");
1733
1869
  const site = String(ctx.options.site ?? "");
1734
- if (!server) exitWithValidationError("server_id", "forge-cli env get --server <server_id> --site <site_id>", ctx.formatter);
1735
- if (!site) exitWithValidationError("site_id", "forge-cli env get --server <server_id> --site <site_id>", ctx.formatter);
1870
+ if (!server) exitWithValidationError("server_id", "forge env get --server <server_id> --site <site_id>", ctx.formatter);
1871
+ if (!site) exitWithValidationError("site_id", "forge env get --server <server_id> --site <site_id>", ctx.formatter);
1736
1872
  await runCommand(async () => {
1737
1873
  const token = ctx.getToken();
1738
1874
  const execCtx = ctx.createExecutorContext(token);
@@ -1749,9 +1885,9 @@ async function envUpdate(ctx) {
1749
1885
  const server = String(ctx.options.server ?? "");
1750
1886
  const site = String(ctx.options.site ?? "");
1751
1887
  const content = String(ctx.options.content ?? "");
1752
- if (!server) exitWithValidationError("server_id", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1753
- if (!site) exitWithValidationError("site_id", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1754
- if (!content) exitWithValidationError("content", "forge-cli env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1888
+ if (!server) exitWithValidationError("server_id", "forge env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1889
+ if (!site) exitWithValidationError("site_id", "forge env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1890
+ if (!content) exitWithValidationError("content", "forge env update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
1755
1891
  await runCommand(async () => {
1756
1892
  const token = ctx.getToken();
1757
1893
  const execCtx = ctx.createExecutorContext(token);
@@ -1774,22 +1910,22 @@ const handleEnvCommand = createCommandRouter({
1774
1910
  });
1775
1911
  function showEnvHelp(subcommand) {
1776
1912
  if (subcommand === "get") console.log(`
1777
- ${colors.bold("forge-cli env get")} - Get environment variables
1913
+ ${colors.bold("forge env get")} - Get environment variables
1778
1914
 
1779
1915
  ${colors.bold("USAGE:")}
1780
- forge-cli env get --server <server_id> --site <site_id>
1916
+ forge env get --server <server_id> --site <site_id>
1781
1917
  `);
1782
1918
  else if (subcommand === "update") console.log(`
1783
- ${colors.bold("forge-cli env update")} - Update environment variables
1919
+ ${colors.bold("forge env update")} - Update environment variables
1784
1920
 
1785
1921
  ${colors.bold("USAGE:")}
1786
- forge-cli env update --server <server_id> --site <site_id> --content <env_content>
1922
+ forge env update --server <server_id> --site <site_id> --content <env_content>
1787
1923
  `);
1788
1924
  else console.log(`
1789
- ${colors.bold("forge-cli env")} - Manage environment variables
1925
+ ${colors.bold("forge env")} - Manage environment variables
1790
1926
 
1791
1927
  ${colors.bold("USAGE:")}
1792
- forge-cli env <subcommand> [options]
1928
+ forge env <subcommand> [options]
1793
1929
 
1794
1930
  ${colors.bold("SUBCOMMANDS:")}
1795
1931
  get Get environment variables
@@ -1801,12 +1937,12 @@ ${colors.bold("OPTIONS:")}
1801
1937
  --content <str> New env content (for update)
1802
1938
  -f, --format <fmt> Output format: json, human
1803
1939
 
1804
- Run ${colors.cyan("forge-cli env <subcommand> --help")} for details.
1940
+ Run ${colors.cyan("forge env <subcommand> --help")} for details.
1805
1941
  `);
1806
1942
  }
1807
1943
  async function firewallRulesList(ctx) {
1808
1944
  const server = String(ctx.options.server ?? "");
1809
- if (!server) exitWithValidationError("server_id", "forge-cli firewall-rules list --server <server_id>", ctx.formatter);
1945
+ if (!server) exitWithValidationError("server_id", "forge firewall-rules list --server <server_id>", ctx.formatter);
1810
1946
  await runCommand(async () => {
1811
1947
  const token = ctx.getToken();
1812
1948
  const execCtx = ctx.createExecutorContext(token);
@@ -1824,8 +1960,8 @@ async function firewallRulesList(ctx) {
1824
1960
  async function firewallRulesGet(args, ctx) {
1825
1961
  const [id] = args;
1826
1962
  const server = String(ctx.options.server ?? "");
1827
- if (!id) exitWithValidationError("firewall_rule_id", "forge-cli firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
1828
- if (!server) exitWithValidationError("server_id", "forge-cli firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
1963
+ if (!id) exitWithValidationError("firewall_rule_id", "forge firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
1964
+ if (!server) exitWithValidationError("server_id", "forge firewall-rules get <rule_id> --server <server_id>", ctx.formatter);
1829
1965
  await runCommand(async () => {
1830
1966
  const token = ctx.getToken();
1831
1967
  const execCtx = ctx.createExecutorContext(token);
@@ -1854,25 +1990,25 @@ const handleFirewallRulesCommand = createCommandRouter({
1854
1990
  });
1855
1991
  function showFirewallRulesHelp(subcommand) {
1856
1992
  if (subcommand === "list" || subcommand === "ls") console.log(`
1857
- ${colors.bold("forge-cli firewall-rules list")} - List firewall rules on a server
1993
+ ${colors.bold("forge firewall-rules list")} - List firewall rules on a server
1858
1994
 
1859
1995
  ${colors.bold("USAGE:")}
1860
- forge-cli firewall-rules list --server <server_id> [options]
1996
+ forge firewall-rules list --server <server_id> [options]
1861
1997
  `);
1862
1998
  else if (subcommand === "get") console.log(`
1863
- ${colors.bold("forge-cli firewall-rules get")} - Get firewall rule details
1999
+ ${colors.bold("forge firewall-rules get")} - Get firewall rule details
1864
2000
 
1865
2001
  ${colors.bold("USAGE:")}
1866
- forge-cli firewall-rules get <rule_id> --server <server_id>
2002
+ forge firewall-rules get <rule_id> --server <server_id>
1867
2003
  `);
1868
2004
  else console.log(`
1869
- ${colors.bold("forge-cli firewall-rules")} - Manage firewall rules
2005
+ ${colors.bold("forge firewall-rules")} - Manage firewall rules
1870
2006
 
1871
2007
  ${colors.bold("USAGE:")}
1872
- forge-cli firewall-rules <subcommand> [options]
2008
+ forge firewall-rules <subcommand> [options]
1873
2009
 
1874
2010
  ${colors.bold("ALIASES:")}
1875
- forge-cli fw
2011
+ forge fw
1876
2012
 
1877
2013
  ${colors.bold("SUBCOMMANDS:")}
1878
2014
  list, ls List firewall rules
@@ -1882,12 +2018,12 @@ ${colors.bold("OPTIONS:")}
1882
2018
  --server <id> Server ID (required)
1883
2019
  -f, --format <fmt> Output format: json, human, table
1884
2020
 
1885
- Run ${colors.cyan("forge-cli firewall-rules <subcommand> --help")} for details.
2021
+ Run ${colors.cyan("forge firewall-rules <subcommand> --help")} for details.
1886
2022
  `);
1887
2023
  }
1888
2024
  async function monitorsList(ctx) {
1889
2025
  const server = String(ctx.options.server ?? "");
1890
- if (!server) exitWithValidationError("server_id", "forge-cli monitors list --server <server_id>", ctx.formatter);
2026
+ if (!server) exitWithValidationError("server_id", "forge monitors list --server <server_id>", ctx.formatter);
1891
2027
  await runCommand(async () => {
1892
2028
  const token = ctx.getToken();
1893
2029
  const execCtx = ctx.createExecutorContext(token);
@@ -1904,8 +2040,8 @@ async function monitorsList(ctx) {
1904
2040
  async function monitorsGet(args, ctx) {
1905
2041
  const [id] = args;
1906
2042
  const server = String(ctx.options.server ?? "");
1907
- if (!id) exitWithValidationError("monitor_id", "forge-cli monitors get <monitor_id> --server <server_id>", ctx.formatter);
1908
- if (!server) exitWithValidationError("server_id", "forge-cli monitors get <monitor_id> --server <server_id>", ctx.formatter);
2043
+ if (!id) exitWithValidationError("monitor_id", "forge monitors get <monitor_id> --server <server_id>", ctx.formatter);
2044
+ if (!server) exitWithValidationError("server_id", "forge monitors get <monitor_id> --server <server_id>", ctx.formatter);
1909
2045
  await runCommand(async () => {
1910
2046
  const token = ctx.getToken();
1911
2047
  const execCtx = ctx.createExecutorContext(token);
@@ -1929,10 +2065,11 @@ async function monitorsCreate(ctx) {
1929
2065
  const type = String(ctx.options.type ?? "");
1930
2066
  const operator = String(ctx.options.operator ?? "");
1931
2067
  const threshold = Number(ctx.options.threshold ?? 0);
2068
+ const notify = String(ctx.options.notify ?? "");
1932
2069
  const minutes = Number(ctx.options.minutes ?? 0);
1933
- if (!server) exitWithValidationError("server_id", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
1934
- if (!type) exitWithValidationError("type", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
1935
- if (!operator) exitWithValidationError("operator", "forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
2070
+ if (!server) exitWithValidationError("server_id", "forge monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
2071
+ if (!type) exitWithValidationError("type", "forge monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
2072
+ if (!operator) exitWithValidationError("operator", "forge monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes>", ctx.formatter);
1936
2073
  await runCommand(async () => {
1937
2074
  const token = ctx.getToken();
1938
2075
  const execCtx = ctx.createExecutorContext(token);
@@ -1941,6 +2078,7 @@ async function monitorsCreate(ctx) {
1941
2078
  type,
1942
2079
  operator,
1943
2080
  threshold,
2081
+ notify,
1944
2082
  minutes
1945
2083
  }, execCtx);
1946
2084
  ctx.formatter.outputOne(result.data, [
@@ -1956,8 +2094,8 @@ async function monitorsCreate(ctx) {
1956
2094
  async function monitorsDelete(args, ctx) {
1957
2095
  const [id] = args;
1958
2096
  const server = String(ctx.options.server ?? "");
1959
- if (!id) exitWithValidationError("monitor_id", "forge-cli monitors delete <monitor_id> --server <server_id>", ctx.formatter);
1960
- if (!server) exitWithValidationError("server_id", "forge-cli monitors delete <monitor_id> --server <server_id>", ctx.formatter);
2097
+ if (!id) exitWithValidationError("monitor_id", "forge monitors delete <monitor_id> --server <server_id>", ctx.formatter);
2098
+ if (!server) exitWithValidationError("server_id", "forge monitors delete <monitor_id> --server <server_id>", ctx.formatter);
1961
2099
  await runCommand(async () => {
1962
2100
  const token = ctx.getToken();
1963
2101
  const execCtx = ctx.createExecutorContext(token);
@@ -1981,26 +2119,26 @@ const handleMonitorsCommand = createCommandRouter({
1981
2119
  });
1982
2120
  function showMonitorsHelp(subcommand) {
1983
2121
  if (subcommand === "list" || subcommand === "ls") console.log(`
1984
- ${colors.bold("forge-cli monitors list")} - List monitors on a server
2122
+ ${colors.bold("forge monitors list")} - List monitors on a server
1985
2123
 
1986
2124
  ${colors.bold("USAGE:")}
1987
- forge-cli monitors list --server <server_id> [options]
2125
+ forge monitors list --server <server_id> [options]
1988
2126
 
1989
2127
  ${colors.bold("OPTIONS:")}
1990
2128
  --server <id> Server ID (required)
1991
2129
  -f, --format <fmt> Output format: json, human, table
1992
2130
  `);
1993
2131
  else if (subcommand === "get") console.log(`
1994
- ${colors.bold("forge-cli monitors get")} - Get monitor details
2132
+ ${colors.bold("forge monitors get")} - Get monitor details
1995
2133
 
1996
2134
  ${colors.bold("USAGE:")}
1997
- forge-cli monitors get <monitor_id> --server <server_id> [options]
2135
+ forge monitors get <monitor_id> --server <server_id> [options]
1998
2136
  `);
1999
2137
  else if (subcommand === "create") console.log(`
2000
- ${colors.bold("forge-cli monitors create")} - Create a new monitor
2138
+ ${colors.bold("forge monitors create")} - Create a new monitor
2001
2139
 
2002
2140
  ${colors.bold("USAGE:")}
2003
- forge-cli monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes> [options]
2141
+ forge monitors create --server <server_id> --type <type> --operator <operator> --threshold <threshold> --minutes <minutes> [options]
2004
2142
 
2005
2143
  ${colors.bold("OPTIONS:")}
2006
2144
  --server <id> Server ID (required)
@@ -2011,16 +2149,16 @@ ${colors.bold("OPTIONS:")}
2011
2149
  -f, --format <fmt> Output format: json, human, table
2012
2150
  `);
2013
2151
  else if (subcommand === "delete") console.log(`
2014
- ${colors.bold("forge-cli monitors delete")} - Delete a monitor
2152
+ ${colors.bold("forge monitors delete")} - Delete a monitor
2015
2153
 
2016
2154
  ${colors.bold("USAGE:")}
2017
- forge-cli monitors delete <monitor_id> --server <server_id> [options]
2155
+ forge monitors delete <monitor_id> --server <server_id> [options]
2018
2156
  `);
2019
2157
  else console.log(`
2020
- ${colors.bold("forge-cli monitors")} - Manage server monitors
2158
+ ${colors.bold("forge monitors")} - Manage server monitors
2021
2159
 
2022
2160
  ${colors.bold("USAGE:")}
2023
- forge-cli monitors <subcommand> [options]
2161
+ forge monitors <subcommand> [options]
2024
2162
 
2025
2163
  ${colors.bold("SUBCOMMANDS:")}
2026
2164
  list, ls List monitors
@@ -2032,14 +2170,14 @@ ${colors.bold("OPTIONS:")}
2032
2170
  --server <id> Server ID (required)
2033
2171
  -f, --format <fmt> Output format: json, human, table
2034
2172
 
2035
- Run ${colors.cyan("forge-cli monitors <subcommand> --help")} for details.
2173
+ Run ${colors.cyan("forge monitors <subcommand> --help")} for details.
2036
2174
  `);
2037
2175
  }
2038
2176
  async function nginxGet(ctx) {
2039
2177
  const server = String(ctx.options.server ?? "");
2040
2178
  const site = String(ctx.options.site ?? "");
2041
- if (!server) exitWithValidationError("server_id", "forge-cli nginx get --server <server_id> --site <site_id>", ctx.formatter);
2042
- if (!site) exitWithValidationError("site_id", "forge-cli nginx get --server <server_id> --site <site_id>", ctx.formatter);
2179
+ if (!server) exitWithValidationError("server_id", "forge nginx get --server <server_id> --site <site_id>", ctx.formatter);
2180
+ if (!site) exitWithValidationError("site_id", "forge nginx get --server <server_id> --site <site_id>", ctx.formatter);
2043
2181
  await runCommand(async () => {
2044
2182
  const token = ctx.getToken();
2045
2183
  const execCtx = ctx.createExecutorContext(token);
@@ -2056,9 +2194,9 @@ async function nginxUpdate(ctx) {
2056
2194
  const server = String(ctx.options.server ?? "");
2057
2195
  const site = String(ctx.options.site ?? "");
2058
2196
  const content = String(ctx.options.content ?? "");
2059
- if (!server) exitWithValidationError("server_id", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2060
- if (!site) exitWithValidationError("site_id", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2061
- if (!content) exitWithValidationError("content", "forge-cli nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2197
+ if (!server) exitWithValidationError("server_id", "forge nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2198
+ if (!site) exitWithValidationError("site_id", "forge nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2199
+ if (!content) exitWithValidationError("content", "forge nginx update --server <server_id> --site <site_id> --content <content>", ctx.formatter);
2062
2200
  await runCommand(async () => {
2063
2201
  const token = ctx.getToken();
2064
2202
  const execCtx = ctx.createExecutorContext(token);
@@ -2081,22 +2219,22 @@ const handleNginxCommand = createCommandRouter({
2081
2219
  });
2082
2220
  function showNginxHelp(subcommand) {
2083
2221
  if (subcommand === "get") console.log(`
2084
- ${colors.bold("forge-cli nginx get")} - Get nginx configuration
2222
+ ${colors.bold("forge nginx get")} - Get nginx configuration
2085
2223
 
2086
2224
  ${colors.bold("USAGE:")}
2087
- forge-cli nginx get --server <server_id> --site <site_id>
2225
+ forge nginx get --server <server_id> --site <site_id>
2088
2226
  `);
2089
2227
  else if (subcommand === "update") console.log(`
2090
- ${colors.bold("forge-cli nginx update")} - Update nginx configuration
2228
+ ${colors.bold("forge nginx update")} - Update nginx configuration
2091
2229
 
2092
2230
  ${colors.bold("USAGE:")}
2093
- forge-cli nginx update --server <server_id> --site <site_id> --content <nginx_config>
2231
+ forge nginx update --server <server_id> --site <site_id> --content <nginx_config>
2094
2232
  `);
2095
2233
  else console.log(`
2096
- ${colors.bold("forge-cli nginx")} - Manage nginx configuration
2234
+ ${colors.bold("forge nginx")} - Manage nginx configuration
2097
2235
 
2098
2236
  ${colors.bold("USAGE:")}
2099
- forge-cli nginx <subcommand> [options]
2237
+ forge nginx <subcommand> [options]
2100
2238
 
2101
2239
  ${colors.bold("SUBCOMMANDS:")}
2102
2240
  get Get nginx configuration
@@ -2107,12 +2245,12 @@ ${colors.bold("OPTIONS:")}
2107
2245
  --site <id> Site ID (required)
2108
2246
  --content <str> New nginx config (for update)
2109
2247
 
2110
- Run ${colors.cyan("forge-cli nginx <subcommand> --help")} for details.
2248
+ Run ${colors.cyan("forge nginx <subcommand> --help")} for details.
2111
2249
  `);
2112
2250
  }
2113
2251
  async function nginxTemplatesList(ctx) {
2114
2252
  const server = String(ctx.options.server ?? "");
2115
- if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates list --server <server_id>", ctx.formatter);
2253
+ if (!server) exitWithValidationError("server_id", "forge nginx-templates list --server <server_id>", ctx.formatter);
2116
2254
  await runCommand(async () => {
2117
2255
  const token = ctx.getToken();
2118
2256
  const execCtx = ctx.createExecutorContext(token);
@@ -2127,8 +2265,8 @@ async function nginxTemplatesList(ctx) {
2127
2265
  async function nginxTemplatesGet(args, ctx) {
2128
2266
  const [id] = args;
2129
2267
  const server = String(ctx.options.server ?? "");
2130
- if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates get <template_id> --server <server_id>", ctx.formatter);
2131
- if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates get <template_id> --server <server_id>", ctx.formatter);
2268
+ if (!id) exitWithValidationError("template_id", "forge nginx-templates get <template_id> --server <server_id>", ctx.formatter);
2269
+ if (!server) exitWithValidationError("server_id", "forge nginx-templates get <template_id> --server <server_id>", ctx.formatter);
2132
2270
  await runCommand(async () => {
2133
2271
  const token = ctx.getToken();
2134
2272
  const execCtx = ctx.createExecutorContext(token);
@@ -2148,9 +2286,9 @@ async function nginxTemplatesCreate(ctx) {
2148
2286
  const server = String(ctx.options.server ?? "");
2149
2287
  const name = String(ctx.options.name ?? "");
2150
2288
  const content = String(ctx.options.content ?? "");
2151
- if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2152
- if (!name) exitWithValidationError("name", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2153
- if (!content) exitWithValidationError("content", "forge-cli nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2289
+ if (!server) exitWithValidationError("server_id", "forge nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2290
+ if (!name) exitWithValidationError("name", "forge nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2291
+ if (!content) exitWithValidationError("content", "forge nginx-templates create --server <server_id> --name <name> --content <content>", ctx.formatter);
2154
2292
  await runCommand(async () => {
2155
2293
  const token = ctx.getToken();
2156
2294
  const execCtx = ctx.createExecutorContext(token);
@@ -2169,8 +2307,8 @@ async function nginxTemplatesCreate(ctx) {
2169
2307
  async function nginxTemplatesUpdate(args, ctx) {
2170
2308
  const [id] = args;
2171
2309
  const server = String(ctx.options.server ?? "");
2172
- if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates update <template_id> --server <server_id>", ctx.formatter);
2173
- if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates update <template_id> --server <server_id>", ctx.formatter);
2310
+ if (!id) exitWithValidationError("template_id", "forge nginx-templates update <template_id> --server <server_id>", ctx.formatter);
2311
+ if (!server) exitWithValidationError("server_id", "forge nginx-templates update <template_id> --server <server_id>", ctx.formatter);
2174
2312
  await runCommand(async () => {
2175
2313
  const token = ctx.getToken();
2176
2314
  const execCtx = ctx.createExecutorContext(token);
@@ -2190,8 +2328,8 @@ async function nginxTemplatesUpdate(args, ctx) {
2190
2328
  async function nginxTemplatesDelete(args, ctx) {
2191
2329
  const [id] = args;
2192
2330
  const server = String(ctx.options.server ?? "");
2193
- if (!id) exitWithValidationError("template_id", "forge-cli nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
2194
- if (!server) exitWithValidationError("server_id", "forge-cli nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
2331
+ if (!id) exitWithValidationError("template_id", "forge nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
2332
+ if (!server) exitWithValidationError("server_id", "forge nginx-templates delete <template_id> --server <server_id>", ctx.formatter);
2195
2333
  await runCommand(async () => {
2196
2334
  const token = ctx.getToken();
2197
2335
  const execCtx = ctx.createExecutorContext(token);
@@ -2220,26 +2358,26 @@ const handleNginxTemplatesCommand = createCommandRouter({
2220
2358
  });
2221
2359
  function showNginxTemplatesHelp(subcommand) {
2222
2360
  if (subcommand === "list" || subcommand === "ls") console.log(`
2223
- ${colors.bold("forge-cli nginx-templates list")} - List Nginx templates on a server
2361
+ ${colors.bold("forge nginx-templates list")} - List Nginx templates on a server
2224
2362
 
2225
2363
  ${colors.bold("USAGE:")}
2226
- forge-cli nginx-templates list --server <server_id> [options]
2364
+ forge nginx-templates list --server <server_id> [options]
2227
2365
 
2228
2366
  ${colors.bold("OPTIONS:")}
2229
2367
  --server <id> Server ID (required)
2230
2368
  -f, --format <fmt> Output format: json, human, table
2231
2369
  `);
2232
2370
  else if (subcommand === "get") console.log(`
2233
- ${colors.bold("forge-cli nginx-templates get")} - Get Nginx template details
2371
+ ${colors.bold("forge nginx-templates get")} - Get Nginx template details
2234
2372
 
2235
2373
  ${colors.bold("USAGE:")}
2236
- forge-cli nginx-templates get <template_id> --server <server_id> [options]
2374
+ forge nginx-templates get <template_id> --server <server_id> [options]
2237
2375
  `);
2238
2376
  else if (subcommand === "create") console.log(`
2239
- ${colors.bold("forge-cli nginx-templates create")} - Create a new Nginx template
2377
+ ${colors.bold("forge nginx-templates create")} - Create a new Nginx template
2240
2378
 
2241
2379
  ${colors.bold("USAGE:")}
2242
- forge-cli nginx-templates create --server <server_id> --name <name> --content <content> [options]
2380
+ forge nginx-templates create --server <server_id> --name <name> --content <content> [options]
2243
2381
 
2244
2382
  ${colors.bold("OPTIONS:")}
2245
2383
  --server <id> Server ID (required)
@@ -2248,10 +2386,10 @@ ${colors.bold("OPTIONS:")}
2248
2386
  -f, --format <fmt> Output format: json, human, table
2249
2387
  `);
2250
2388
  else if (subcommand === "update") console.log(`
2251
- ${colors.bold("forge-cli nginx-templates update")} - Update an Nginx template
2389
+ ${colors.bold("forge nginx-templates update")} - Update an Nginx template
2252
2390
 
2253
2391
  ${colors.bold("USAGE:")}
2254
- forge-cli nginx-templates update <template_id> --server <server_id> [options]
2392
+ forge nginx-templates update <template_id> --server <server_id> [options]
2255
2393
 
2256
2394
  ${colors.bold("OPTIONS:")}
2257
2395
  --server <id> Server ID (required)
@@ -2260,16 +2398,16 @@ ${colors.bold("OPTIONS:")}
2260
2398
  -f, --format <fmt> Output format: json, human, table
2261
2399
  `);
2262
2400
  else if (subcommand === "delete") console.log(`
2263
- ${colors.bold("forge-cli nginx-templates delete")} - Delete an Nginx template
2401
+ ${colors.bold("forge nginx-templates delete")} - Delete an Nginx template
2264
2402
 
2265
2403
  ${colors.bold("USAGE:")}
2266
- forge-cli nginx-templates delete <template_id> --server <server_id> [options]
2404
+ forge nginx-templates delete <template_id> --server <server_id> [options]
2267
2405
  `);
2268
2406
  else console.log(`
2269
- ${colors.bold("forge-cli nginx-templates")} - Manage Nginx templates
2407
+ ${colors.bold("forge nginx-templates")} - Manage Nginx templates
2270
2408
 
2271
2409
  ${colors.bold("USAGE:")}
2272
- forge-cli nginx-templates <subcommand> [options]
2410
+ forge nginx-templates <subcommand> [options]
2273
2411
 
2274
2412
  ${colors.bold("SUBCOMMANDS:")}
2275
2413
  list, ls List Nginx templates
@@ -2282,7 +2420,7 @@ ${colors.bold("OPTIONS:")}
2282
2420
  --server <id> Server ID (required)
2283
2421
  -f, --format <fmt> Output format: json, human, table
2284
2422
 
2285
- Run ${colors.cyan("forge-cli nginx-templates <subcommand> --help")} for details.
2423
+ Run ${colors.cyan("forge nginx-templates <subcommand> --help")} for details.
2286
2424
  `);
2287
2425
  }
2288
2426
  async function recipesList(ctx) {
@@ -2299,7 +2437,7 @@ async function recipesList(ctx) {
2299
2437
  }
2300
2438
  async function recipesGet(args, ctx) {
2301
2439
  const [id] = args;
2302
- if (!id) exitWithValidationError("id", "forge-cli recipes get <recipe_id>", ctx.formatter);
2440
+ if (!id) exitWithValidationError("id", "forge recipes get <recipe_id>", ctx.formatter);
2303
2441
  await runCommand(async () => {
2304
2442
  const token = ctx.getToken();
2305
2443
  const execCtx = ctx.createExecutorContext(token);
@@ -2313,11 +2451,35 @@ async function recipesGet(args, ctx) {
2313
2451
  ]);
2314
2452
  }, ctx.formatter);
2315
2453
  }
2454
+ async function recipesUpdate(args, ctx) {
2455
+ const [id] = args;
2456
+ if (!id) exitWithValidationError("id", "forge recipes update <recipe_id> [--name ...] [--user ...] [--script ...]", ctx.formatter);
2457
+ const name = ctx.options.name;
2458
+ const user = ctx.options.user;
2459
+ const script = ctx.options.script;
2460
+ await runCommand(async () => {
2461
+ const token = ctx.getToken();
2462
+ const execCtx = ctx.createExecutorContext(token);
2463
+ const result = await updateRecipe({
2464
+ id,
2465
+ name,
2466
+ user,
2467
+ script
2468
+ }, execCtx);
2469
+ ctx.formatter.outputOne(result.data, [
2470
+ "id",
2471
+ "name",
2472
+ "user",
2473
+ "created_at",
2474
+ "script"
2475
+ ]);
2476
+ }, ctx.formatter);
2477
+ }
2316
2478
  async function recipesRun(args, ctx) {
2317
2479
  const [id] = args;
2318
2480
  const serversRaw = String(ctx.options.servers ?? "");
2319
- if (!id) exitWithValidationError("id", "forge-cli recipes run <recipe_id> --servers <ids>", ctx.formatter);
2320
- if (!serversRaw) exitWithValidationError("servers", "forge-cli recipes run <recipe_id> --servers <server_id1,server_id2,...>", ctx.formatter);
2481
+ if (!id) exitWithValidationError("id", "forge recipes run <recipe_id> --servers <ids>", ctx.formatter);
2482
+ if (!serversRaw) exitWithValidationError("servers", "forge recipes run <recipe_id> --servers <server_id1,server_id2,...>", ctx.formatter);
2321
2483
  const servers = serversRaw.split(",").map((s) => Number(s.trim())).filter((n) => !isNaN(n));
2322
2484
  await runCommand(async () => {
2323
2485
  const token = ctx.getToken();
@@ -2335,47 +2497,60 @@ const handleRecipesCommand = createCommandRouter({
2335
2497
  list: recipesList,
2336
2498
  ls: recipesList,
2337
2499
  get: [recipesGet, "args"],
2500
+ update: [recipesUpdate, "args"],
2338
2501
  run: [recipesRun, "args"]
2339
2502
  },
2340
- writeSubcommands: ["run"]
2503
+ writeSubcommands: ["update", "run"]
2341
2504
  });
2342
2505
  function showRecipesHelp(subcommand) {
2343
2506
  if (subcommand === "list" || subcommand === "ls") console.log(`
2344
- ${colors.bold("forge-cli recipes list")} - List all recipes
2507
+ ${colors.bold("forge recipes list")} - List all recipes
2345
2508
 
2346
2509
  ${colors.bold("USAGE:")}
2347
- forge-cli recipes list [options]
2510
+ forge recipes list [options]
2348
2511
  `);
2349
2512
  else if (subcommand === "get") console.log(`
2350
- ${colors.bold("forge-cli recipes get")} - Get recipe details
2513
+ ${colors.bold("forge recipes get")} - Get recipe details
2351
2514
 
2352
2515
  ${colors.bold("USAGE:")}
2353
- forge-cli recipes get <recipe_id>
2516
+ forge recipes get <recipe_id>
2517
+ `);
2518
+ else if (subcommand === "update") console.log(`
2519
+ ${colors.bold("forge recipes update")} - Update a recipe
2520
+
2521
+ ${colors.bold("USAGE:")}
2522
+ forge recipes update <recipe_id> [options]
2523
+
2524
+ ${colors.bold("OPTIONS:")}
2525
+ --name <name> New recipe name
2526
+ --user <user> New recipe user
2527
+ --script <script> New recipe script
2354
2528
  `);
2355
2529
  else if (subcommand === "run") console.log(`
2356
- ${colors.bold("forge-cli recipes run")} - Run a recipe on servers
2530
+ ${colors.bold("forge recipes run")} - Run a recipe on servers
2357
2531
 
2358
2532
  ${colors.bold("USAGE:")}
2359
- forge-cli recipes run <recipe_id> --servers <server_id1,server_id2,...>
2533
+ forge recipes run <recipe_id> --servers <server_id1,server_id2,...>
2360
2534
 
2361
2535
  ${colors.bold("OPTIONS:")}
2362
2536
  --servers <ids> Comma-separated server IDs to run recipe on
2363
2537
  `);
2364
2538
  else console.log(`
2365
- ${colors.bold("forge-cli recipes")} - Manage recipes
2539
+ ${colors.bold("forge recipes")} - Manage recipes
2366
2540
 
2367
2541
  ${colors.bold("USAGE:")}
2368
- forge-cli recipes <subcommand> [options]
2542
+ forge recipes <subcommand> [options]
2369
2543
 
2370
2544
  ${colors.bold("SUBCOMMANDS:")}
2371
2545
  list, ls List all recipes
2372
2546
  get <id> Get recipe details
2547
+ update <id> Update a recipe
2373
2548
  run <id> Run a recipe on servers
2374
2549
 
2375
2550
  ${colors.bold("OPTIONS:")}
2376
2551
  -f, --format <fmt> Output format: json, human, table
2377
2552
 
2378
- Run ${colors.cyan("forge-cli recipes <subcommand> --help")} for details.
2553
+ Run ${colors.cyan("forge recipes <subcommand> --help")} for details.
2379
2554
  `);
2380
2555
  }
2381
2556
  function requireServerAndSiteRaw$1(ctx, usage) {
@@ -2389,7 +2564,7 @@ function requireServerAndSiteRaw$1(ctx, usage) {
2389
2564
  };
2390
2565
  }
2391
2566
  async function redirectRulesList(ctx) {
2392
- const { server, site } = requireServerAndSiteRaw$1(ctx, "forge-cli redirect-rules list --server <server_id> --site <site_id>");
2567
+ const { server, site } = requireServerAndSiteRaw$1(ctx, "forge redirect-rules list --server <server_id> --site <site_id>");
2393
2568
  await runCommand(async () => {
2394
2569
  const token = ctx.getToken();
2395
2570
  const execCtx = ctx.createExecutorContext(token);
@@ -2408,7 +2583,7 @@ async function redirectRulesList(ctx) {
2408
2583
  }
2409
2584
  async function redirectRulesGet(args, ctx) {
2410
2585
  const [id] = args;
2411
- const usage = "forge-cli redirect-rules get <rule_id> --server <server_id> --site <site_id>";
2586
+ const usage = "forge redirect-rules get <rule_id> --server <server_id> --site <site_id>";
2412
2587
  if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
2413
2588
  const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
2414
2589
  await runCommand(async () => {
@@ -2430,34 +2605,30 @@ async function redirectRulesGet(args, ctx) {
2430
2605
  }, ctx.formatter);
2431
2606
  }
2432
2607
  async function redirectRulesCreate(ctx) {
2433
- const usage = "forge-cli redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to>";
2608
+ const usage = "forge redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to>";
2434
2609
  const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
2435
2610
  const from = String(ctx.options.from ?? "");
2436
2611
  const to = String(ctx.options.to ?? "");
2612
+ const type = String(ctx.options.type ?? "redirect");
2437
2613
  if (!from) exitWithValidationError("from", usage, ctx.formatter);
2438
2614
  if (!to) exitWithValidationError("to", usage, ctx.formatter);
2439
2615
  await runCommand(async () => {
2440
2616
  const token = ctx.getToken();
2441
2617
  const execCtx = ctx.createExecutorContext(token);
2442
2618
  const server_id = await resolveServerId(server, execCtx);
2443
- const result = await createRedirectRule({
2619
+ await createRedirectRule({
2444
2620
  server_id,
2445
2621
  site_id: await resolveSiteId(site, server_id, execCtx),
2446
2622
  from,
2447
- to
2623
+ to,
2624
+ type
2448
2625
  }, execCtx);
2449
- ctx.formatter.outputOne(result.data, [
2450
- "id",
2451
- "from",
2452
- "to",
2453
- "type",
2454
- "created_at"
2455
- ]);
2626
+ ctx.formatter.success("Redirect rule created.");
2456
2627
  }, ctx.formatter);
2457
2628
  }
2458
2629
  async function redirectRulesDelete(args, ctx) {
2459
2630
  const [id] = args;
2460
- const usage = "forge-cli redirect-rules delete <rule_id> --server <server_id> --site <site_id>";
2631
+ const usage = "forge redirect-rules delete <rule_id> --server <server_id> --site <site_id>";
2461
2632
  if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
2462
2633
  const { server, site } = requireServerAndSiteRaw$1(ctx, usage);
2463
2634
  await runCommand(async () => {
@@ -2485,10 +2656,10 @@ const handleRedirectRulesCommand = createCommandRouter({
2485
2656
  });
2486
2657
  function showRedirectRulesHelp(subcommand) {
2487
2658
  if (subcommand === "list" || subcommand === "ls") console.log(`
2488
- ${colors.bold("forge-cli redirect-rules list")} - List redirect rules for a site
2659
+ ${colors.bold("forge redirect-rules list")} - List redirect rules for a site
2489
2660
 
2490
2661
  ${colors.bold("USAGE:")}
2491
- forge-cli redirect-rules list --server <server_id> --site <site_id> [options]
2662
+ forge redirect-rules list --server <server_id> --site <site_id> [options]
2492
2663
 
2493
2664
  ${colors.bold("OPTIONS:")}
2494
2665
  --server <id> Server ID (required)
@@ -2496,16 +2667,16 @@ ${colors.bold("OPTIONS:")}
2496
2667
  -f, --format <fmt> Output format: json, human, table
2497
2668
  `);
2498
2669
  else if (subcommand === "get") console.log(`
2499
- ${colors.bold("forge-cli redirect-rules get")} - Get redirect rule details
2670
+ ${colors.bold("forge redirect-rules get")} - Get redirect rule details
2500
2671
 
2501
2672
  ${colors.bold("USAGE:")}
2502
- forge-cli redirect-rules get <rule_id> --server <server_id> --site <site_id> [options]
2673
+ forge redirect-rules get <rule_id> --server <server_id> --site <site_id> [options]
2503
2674
  `);
2504
2675
  else if (subcommand === "create") console.log(`
2505
- ${colors.bold("forge-cli redirect-rules create")} - Create a new redirect rule
2676
+ ${colors.bold("forge redirect-rules create")} - Create a new redirect rule
2506
2677
 
2507
2678
  ${colors.bold("USAGE:")}
2508
- forge-cli redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to> [options]
2679
+ forge redirect-rules create --server <server_id> --site <site_id> --from <from> --to <to> [options]
2509
2680
 
2510
2681
  ${colors.bold("OPTIONS:")}
2511
2682
  --server <id> Server ID (required)
@@ -2515,16 +2686,16 @@ ${colors.bold("OPTIONS:")}
2515
2686
  -f, --format <fmt> Output format: json, human, table
2516
2687
  `);
2517
2688
  else if (subcommand === "delete") console.log(`
2518
- ${colors.bold("forge-cli redirect-rules delete")} - Delete a redirect rule
2689
+ ${colors.bold("forge redirect-rules delete")} - Delete a redirect rule
2519
2690
 
2520
2691
  ${colors.bold("USAGE:")}
2521
- forge-cli redirect-rules delete <rule_id> --server <server_id> --site <site_id> [options]
2692
+ forge redirect-rules delete <rule_id> --server <server_id> --site <site_id> [options]
2522
2693
  `);
2523
2694
  else console.log(`
2524
- ${colors.bold("forge-cli redirect-rules")} - Manage site redirect rules
2695
+ ${colors.bold("forge redirect-rules")} - Manage site redirect rules
2525
2696
 
2526
2697
  ${colors.bold("USAGE:")}
2527
- forge-cli redirect-rules <subcommand> [options]
2698
+ forge redirect-rules <subcommand> [options]
2528
2699
 
2529
2700
  ${colors.bold("SUBCOMMANDS:")}
2530
2701
  list, ls List redirect rules
@@ -2537,16 +2708,21 @@ ${colors.bold("OPTIONS:")}
2537
2708
  --site <id> Site ID (required)
2538
2709
  -f, --format <fmt> Output format: json, human, table
2539
2710
 
2540
- Run ${colors.cyan("forge-cli redirect-rules <subcommand> --help")} for details.
2711
+ Run ${colors.cyan("forge redirect-rules <subcommand> --help")} for details.
2541
2712
  `);
2542
2713
  }
2543
2714
  async function scheduledJobsList(ctx) {
2544
2715
  const server = String(ctx.options.server ?? "");
2545
- if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs list --server <server_id>", ctx.formatter);
2716
+ const site = ctx.options.site ? String(ctx.options.site) : void 0;
2717
+ if (!server) exitWithValidationError("server_id", "forge scheduled-jobs list --server <server_id>", ctx.formatter);
2546
2718
  await runCommand(async () => {
2547
2719
  const token = ctx.getToken();
2548
2720
  const execCtx = ctx.createExecutorContext(token);
2549
- const result = await listScheduledJobs({ server_id: await resolveServerId(server, execCtx) }, execCtx);
2721
+ const server_id = await resolveServerId(server, execCtx);
2722
+ const result = await listScheduledJobs({
2723
+ server_id,
2724
+ site_id: site ? await resolveSiteId(site, server_id, execCtx) : void 0
2725
+ }, execCtx);
2550
2726
  ctx.formatter.outputList(result.data, [
2551
2727
  "id",
2552
2728
  "command",
@@ -2558,14 +2734,17 @@ async function scheduledJobsList(ctx) {
2558
2734
  async function scheduledJobsGet(args, ctx) {
2559
2735
  const [id] = args;
2560
2736
  const server = String(ctx.options.server ?? "");
2561
- if (!id) exitWithValidationError("job_id", "forge-cli scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
2562
- if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
2737
+ const site = ctx.options.site ? String(ctx.options.site) : void 0;
2738
+ if (!id) exitWithValidationError("job_id", "forge scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
2739
+ if (!server) exitWithValidationError("server_id", "forge scheduled-jobs get <job_id> --server <server_id>", ctx.formatter);
2563
2740
  await runCommand(async () => {
2564
2741
  const token = ctx.getToken();
2565
2742
  const execCtx = ctx.createExecutorContext(token);
2743
+ const server_id = await resolveServerId(server, execCtx);
2566
2744
  const result = await getScheduledJob({
2567
- server_id: await resolveServerId(server, execCtx),
2568
- id
2745
+ server_id,
2746
+ id,
2747
+ site_id: site ? await resolveSiteId(site, server_id, execCtx) : void 0
2569
2748
  }, execCtx);
2570
2749
  ctx.formatter.outputOne(result.data, [
2571
2750
  "id",
@@ -2580,15 +2759,24 @@ async function scheduledJobsGet(args, ctx) {
2580
2759
  }
2581
2760
  async function scheduledJobsCreate(ctx) {
2582
2761
  const server = String(ctx.options.server ?? "");
2762
+ const site = ctx.options.site ? String(ctx.options.site) : void 0;
2583
2763
  const command = String(ctx.options.command ?? "");
2584
- if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs create --server <server_id> --command <command>", ctx.formatter);
2585
- if (!command) exitWithValidationError("command", "forge-cli scheduled-jobs create --server <server_id> --command <command>", ctx.formatter);
2764
+ const user = String(ctx.options.user ?? "forge");
2765
+ const frequency = String(ctx.options.frequency ?? "custom");
2766
+ const cron = ctx.options.cron ? String(ctx.options.cron) : void 0;
2767
+ if (!server) exitWithValidationError("server_id", "forge scheduled-jobs create --server <server_id> --command <command> --user <user> --frequency <frequency>", ctx.formatter);
2768
+ if (!command) exitWithValidationError("command", "forge scheduled-jobs create --server <server_id> --command <command> --user <user> --frequency <frequency>", ctx.formatter);
2586
2769
  await runCommand(async () => {
2587
2770
  const token = ctx.getToken();
2588
2771
  const execCtx = ctx.createExecutorContext(token);
2772
+ const server_id = await resolveServerId(server, execCtx);
2589
2773
  const result = await createScheduledJob({
2590
- server_id: await resolveServerId(server, execCtx),
2591
- command
2774
+ server_id,
2775
+ site_id: site ? await resolveSiteId(site, server_id, execCtx) : void 0,
2776
+ command,
2777
+ user,
2778
+ frequency,
2779
+ cron
2592
2780
  }, execCtx);
2593
2781
  ctx.formatter.outputOne(result.data, [
2594
2782
  "id",
@@ -2604,14 +2792,17 @@ async function scheduledJobsCreate(ctx) {
2604
2792
  async function scheduledJobsDelete(args, ctx) {
2605
2793
  const [id] = args;
2606
2794
  const server = String(ctx.options.server ?? "");
2607
- if (!id) exitWithValidationError("job_id", "forge-cli scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
2608
- if (!server) exitWithValidationError("server_id", "forge-cli scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
2795
+ const site = ctx.options.site ? String(ctx.options.site) : void 0;
2796
+ if (!id) exitWithValidationError("job_id", "forge scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
2797
+ if (!server) exitWithValidationError("server_id", "forge scheduled-jobs delete <job_id> --server <server_id>", ctx.formatter);
2609
2798
  await runCommand(async () => {
2610
2799
  const token = ctx.getToken();
2611
2800
  const execCtx = ctx.createExecutorContext(token);
2801
+ const server_id = await resolveServerId(server, execCtx);
2612
2802
  await deleteScheduledJob({
2613
- server_id: await resolveServerId(server, execCtx),
2614
- id
2803
+ server_id,
2804
+ id,
2805
+ site_id: site ? await resolveSiteId(site, server_id, execCtx) : void 0
2615
2806
  }, execCtx);
2616
2807
  ctx.formatter.success(`Scheduled job ${id} deleted.`);
2617
2808
  }, ctx.formatter);
@@ -2629,26 +2820,26 @@ const handleScheduledJobsCommand = createCommandRouter({
2629
2820
  });
2630
2821
  function showScheduledJobsHelp(subcommand) {
2631
2822
  if (subcommand === "list" || subcommand === "ls") console.log(`
2632
- ${colors.bold("forge-cli scheduled-jobs list")} - List scheduled jobs on a server
2823
+ ${colors.bold("forge scheduled-jobs list")} - List scheduled jobs on a server
2633
2824
 
2634
2825
  ${colors.bold("USAGE:")}
2635
- forge-cli scheduled-jobs list --server <server_id> [options]
2826
+ forge scheduled-jobs list --server <server_id> [options]
2636
2827
 
2637
2828
  ${colors.bold("OPTIONS:")}
2638
2829
  --server <id> Server ID (required)
2639
2830
  -f, --format <fmt> Output format: json, human, table
2640
2831
  `);
2641
2832
  else if (subcommand === "get") console.log(`
2642
- ${colors.bold("forge-cli scheduled-jobs get")} - Get scheduled job details
2833
+ ${colors.bold("forge scheduled-jobs get")} - Get scheduled job details
2643
2834
 
2644
2835
  ${colors.bold("USAGE:")}
2645
- forge-cli scheduled-jobs get <job_id> --server <server_id> [options]
2836
+ forge scheduled-jobs get <job_id> --server <server_id> [options]
2646
2837
  `);
2647
2838
  else if (subcommand === "create") console.log(`
2648
- ${colors.bold("forge-cli scheduled-jobs create")} - Create a new scheduled job
2839
+ ${colors.bold("forge scheduled-jobs create")} - Create a new scheduled job
2649
2840
 
2650
2841
  ${colors.bold("USAGE:")}
2651
- forge-cli scheduled-jobs create --server <server_id> --command <command> [options]
2842
+ forge scheduled-jobs create --server <server_id> --command <command> [options]
2652
2843
 
2653
2844
  ${colors.bold("OPTIONS:")}
2654
2845
  --server <id> Server ID (required)
@@ -2656,16 +2847,16 @@ ${colors.bold("OPTIONS:")}
2656
2847
  -f, --format <fmt> Output format: json, human, table
2657
2848
  `);
2658
2849
  else if (subcommand === "delete") console.log(`
2659
- ${colors.bold("forge-cli scheduled-jobs delete")} - Delete a scheduled job
2850
+ ${colors.bold("forge scheduled-jobs delete")} - Delete a scheduled job
2660
2851
 
2661
2852
  ${colors.bold("USAGE:")}
2662
- forge-cli scheduled-jobs delete <job_id> --server <server_id> [options]
2853
+ forge scheduled-jobs delete <job_id> --server <server_id> [options]
2663
2854
  `);
2664
2855
  else console.log(`
2665
- ${colors.bold("forge-cli scheduled-jobs")} - Manage scheduled jobs (cron)
2856
+ ${colors.bold("forge scheduled-jobs")} - Manage scheduled jobs (cron)
2666
2857
 
2667
2858
  ${colors.bold("USAGE:")}
2668
- forge-cli scheduled-jobs <subcommand> [options]
2859
+ forge scheduled-jobs <subcommand> [options]
2669
2860
 
2670
2861
  ${colors.bold("SUBCOMMANDS:")}
2671
2862
  list, ls List scheduled jobs
@@ -2677,7 +2868,7 @@ ${colors.bold("OPTIONS:")}
2677
2868
  --server <id> Server ID (required)
2678
2869
  -f, --format <fmt> Output format: json, human, table
2679
2870
 
2680
- Run ${colors.cyan("forge-cli scheduled-jobs <subcommand> --help")} for details.
2871
+ Run ${colors.cyan("forge scheduled-jobs <subcommand> --help")} for details.
2681
2872
  `);
2682
2873
  }
2683
2874
  function requireServerAndSiteRaw(ctx, usage) {
@@ -2691,7 +2882,7 @@ function requireServerAndSiteRaw(ctx, usage) {
2691
2882
  };
2692
2883
  }
2693
2884
  async function securityRulesList(ctx) {
2694
- const { server, site } = requireServerAndSiteRaw(ctx, "forge-cli security-rules list --server <server_id> --site <site_id>");
2885
+ const { server, site } = requireServerAndSiteRaw(ctx, "forge security-rules list --server <server_id> --site <site_id>");
2695
2886
  await runCommand(async () => {
2696
2887
  const token = ctx.getToken();
2697
2888
  const execCtx = ctx.createExecutorContext(token);
@@ -2709,7 +2900,7 @@ async function securityRulesList(ctx) {
2709
2900
  }
2710
2901
  async function securityRulesGet(args, ctx) {
2711
2902
  const [id] = args;
2712
- const usage = "forge-cli security-rules get <rule_id> --server <server_id> --site <site_id>";
2903
+ const usage = "forge security-rules get <rule_id> --server <server_id> --site <site_id>";
2713
2904
  if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
2714
2905
  const { server, site } = requireServerAndSiteRaw(ctx, usage);
2715
2906
  await runCommand(async () => {
@@ -2725,13 +2916,12 @@ async function securityRulesGet(args, ctx) {
2725
2916
  "id",
2726
2917
  "name",
2727
2918
  "path",
2728
- "credentials",
2729
2919
  "created_at"
2730
2920
  ]);
2731
2921
  }, ctx.formatter);
2732
2922
  }
2733
2923
  async function securityRulesCreate(ctx) {
2734
- const usage = "forge-cli security-rules create --server <server_id> --site <site_id> --name <name>";
2924
+ const usage = "forge security-rules create --server <server_id> --site <site_id> --name <name>";
2735
2925
  const { server, site } = requireServerAndSiteRaw(ctx, usage);
2736
2926
  const name = String(ctx.options.name ?? "");
2737
2927
  if (!name) exitWithValidationError("name", usage, ctx.formatter);
@@ -2753,9 +2943,35 @@ async function securityRulesCreate(ctx) {
2753
2943
  ]);
2754
2944
  }, ctx.formatter);
2755
2945
  }
2946
+ async function securityRulesUpdate(args, ctx) {
2947
+ const [id] = args;
2948
+ const usage = "forge security-rules update <rule_id> --server <server_id> --site <site_id> --name <name>";
2949
+ if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
2950
+ const { server, site } = requireServerAndSiteRaw(ctx, usage);
2951
+ const name = String(ctx.options.name ?? "");
2952
+ if (!name) exitWithValidationError("name", usage, ctx.formatter);
2953
+ await runCommand(async () => {
2954
+ const token = ctx.getToken();
2955
+ const execCtx = ctx.createExecutorContext(token);
2956
+ const server_id = await resolveServerId(server, execCtx);
2957
+ const result = await updateSecurityRule({
2958
+ server_id,
2959
+ site_id: await resolveSiteId(site, server_id, execCtx),
2960
+ id,
2961
+ name,
2962
+ credentials: []
2963
+ }, execCtx);
2964
+ ctx.formatter.outputOne(result.data, [
2965
+ "id",
2966
+ "name",
2967
+ "path",
2968
+ "created_at"
2969
+ ]);
2970
+ }, ctx.formatter);
2971
+ }
2756
2972
  async function securityRulesDelete(args, ctx) {
2757
2973
  const [id] = args;
2758
- const usage = "forge-cli security-rules delete <rule_id> --server <server_id> --site <site_id>";
2974
+ const usage = "forge security-rules delete <rule_id> --server <server_id> --site <site_id>";
2759
2975
  if (!id) exitWithValidationError("rule_id", usage, ctx.formatter);
2760
2976
  const { server, site } = requireServerAndSiteRaw(ctx, usage);
2761
2977
  await runCommand(async () => {
@@ -2777,16 +2993,21 @@ const handleSecurityRulesCommand = createCommandRouter({
2777
2993
  ls: securityRulesList,
2778
2994
  get: [securityRulesGet, "args"],
2779
2995
  create: securityRulesCreate,
2996
+ update: [securityRulesUpdate, "args"],
2780
2997
  delete: [securityRulesDelete, "args"]
2781
2998
  },
2782
- writeSubcommands: ["create", "delete"]
2999
+ writeSubcommands: [
3000
+ "create",
3001
+ "update",
3002
+ "delete"
3003
+ ]
2783
3004
  });
2784
3005
  function showSecurityRulesHelp(subcommand) {
2785
3006
  if (subcommand === "list" || subcommand === "ls") console.log(`
2786
- ${colors.bold("forge-cli security-rules list")} - List security rules for a site
3007
+ ${colors.bold("forge security-rules list")} - List security rules for a site
2787
3008
 
2788
3009
  ${colors.bold("USAGE:")}
2789
- forge-cli security-rules list --server <server_id> --site <site_id> [options]
3010
+ forge security-rules list --server <server_id> --site <site_id> [options]
2790
3011
 
2791
3012
  ${colors.bold("OPTIONS:")}
2792
3013
  --server <id> Server ID (required)
@@ -2794,16 +3015,28 @@ ${colors.bold("OPTIONS:")}
2794
3015
  -f, --format <fmt> Output format: json, human, table
2795
3016
  `);
2796
3017
  else if (subcommand === "get") console.log(`
2797
- ${colors.bold("forge-cli security-rules get")} - Get security rule details
3018
+ ${colors.bold("forge security-rules get")} - Get security rule details
2798
3019
 
2799
3020
  ${colors.bold("USAGE:")}
2800
- forge-cli security-rules get <rule_id> --server <server_id> --site <site_id> [options]
3021
+ forge security-rules get <rule_id> --server <server_id> --site <site_id> [options]
2801
3022
  `);
2802
3023
  else if (subcommand === "create") console.log(`
2803
- ${colors.bold("forge-cli security-rules create")} - Create a new security rule
3024
+ ${colors.bold("forge security-rules create")} - Create a new security rule
3025
+
3026
+ ${colors.bold("USAGE:")}
3027
+ forge security-rules create --server <server_id> --site <site_id> --name <name> [options]
3028
+
3029
+ ${colors.bold("OPTIONS:")}
3030
+ --server <id> Server ID (required)
3031
+ --site <id> Site ID (required)
3032
+ --name <name> Security rule name (required)
3033
+ -f, --format <fmt> Output format: json, human, table
3034
+ `);
3035
+ else if (subcommand === "update") console.log(`
3036
+ ${colors.bold("forge security-rules update")} - Update a security rule
2804
3037
 
2805
3038
  ${colors.bold("USAGE:")}
2806
- forge-cli security-rules create --server <server_id> --site <site_id> --name <name> [options]
3039
+ forge security-rules update <rule_id> --server <server_id> --site <site_id> --name <name> [options]
2807
3040
 
2808
3041
  ${colors.bold("OPTIONS:")}
2809
3042
  --server <id> Server ID (required)
@@ -2812,21 +3045,22 @@ ${colors.bold("OPTIONS:")}
2812
3045
  -f, --format <fmt> Output format: json, human, table
2813
3046
  `);
2814
3047
  else if (subcommand === "delete") console.log(`
2815
- ${colors.bold("forge-cli security-rules delete")} - Delete a security rule
3048
+ ${colors.bold("forge security-rules delete")} - Delete a security rule
2816
3049
 
2817
3050
  ${colors.bold("USAGE:")}
2818
- forge-cli security-rules delete <rule_id> --server <server_id> --site <site_id> [options]
3051
+ forge security-rules delete <rule_id> --server <server_id> --site <site_id> [options]
2819
3052
  `);
2820
3053
  else console.log(`
2821
- ${colors.bold("forge-cli security-rules")} - Manage site security rules
3054
+ ${colors.bold("forge security-rules")} - Manage site security rules
2822
3055
 
2823
3056
  ${colors.bold("USAGE:")}
2824
- forge-cli security-rules <subcommand> [options]
3057
+ forge security-rules <subcommand> [options]
2825
3058
 
2826
3059
  ${colors.bold("SUBCOMMANDS:")}
2827
3060
  list, ls List security rules
2828
3061
  get <id> Get security rule details
2829
3062
  create Create a new security rule
3063
+ update <id> Update a security rule
2830
3064
  delete <id> Delete a security rule
2831
3065
 
2832
3066
  ${colors.bold("OPTIONS:")}
@@ -2834,7 +3068,7 @@ ${colors.bold("OPTIONS:")}
2834
3068
  --site <id> Site ID (required)
2835
3069
  -f, --format <fmt> Output format: json, human, table
2836
3070
 
2837
- Run ${colors.cyan("forge-cli security-rules <subcommand> --help")} for details.
3071
+ Run ${colors.cyan("forge security-rules <subcommand> --help")} for details.
2838
3072
  `);
2839
3073
  }
2840
3074
  /**
@@ -2855,7 +3089,7 @@ async function serversList(ctx) {
2855
3089
  ctx.formatter.info("No servers found.");
2856
3090
  return;
2857
3091
  }
2858
- for (const server of result.data) console.log(`${String(server.id).padEnd(8)} ${server.name.padEnd(30)} ${server.ip_address.padEnd(16)} ${server.is_ready ? "ready" : "provisioning"}`);
3092
+ for (const server of result.data) console.log(`${String(server.id).padEnd(8)} ${server.name.padEnd(30)} ${(server.ip_address ?? "—").padEnd(16)} ${server.is_ready ? "ready" : "provisioning"}`);
2859
3093
  }
2860
3094
  }, ctx.formatter);
2861
3095
  }
@@ -2864,7 +3098,7 @@ async function serversList(ctx) {
2864
3098
  */
2865
3099
  async function serversGet(args, ctx) {
2866
3100
  const [server] = args;
2867
- if (!server) exitWithValidationError("server_id", "forge-cli servers get <server_id>", ctx.formatter);
3101
+ if (!server) exitWithValidationError("server_id", "forge servers get <server_id>", ctx.formatter);
2868
3102
  await runCommand(async () => {
2869
3103
  const token = ctx.getToken();
2870
3104
  const execCtx = ctx.createExecutorContext(token);
@@ -2877,7 +3111,7 @@ async function serversGet(args, ctx) {
2877
3111
  */
2878
3112
  async function serversReboot(args, ctx) {
2879
3113
  const [server] = args;
2880
- if (!server) exitWithValidationError("server_id", "forge-cli servers reboot <server_id>", ctx.formatter);
3114
+ if (!server) exitWithValidationError("server_id", "forge servers reboot <server_id>", ctx.formatter);
2881
3115
  await runCommand(async () => {
2882
3116
  const token = ctx.getToken();
2883
3117
  const execCtx = ctx.createExecutorContext(token);
@@ -2898,10 +3132,10 @@ const handleServersCommand = createCommandRouter({
2898
3132
  });
2899
3133
  function showServersHelp(subcommand) {
2900
3134
  if (subcommand === "list" || subcommand === "ls") console.log(`
2901
- ${colors.bold("forge-cli servers list")} - List all servers
3135
+ ${colors.bold("forge servers list")} - List all servers
2902
3136
 
2903
3137
  ${colors.bold("USAGE:")}
2904
- forge-cli servers list [options]
3138
+ forge servers list [options]
2905
3139
 
2906
3140
  ${colors.bold("OPTIONS:")}
2907
3141
  --token <token> Forge API token
@@ -2910,14 +3144,14 @@ ${colors.bold("OPTIONS:")}
2910
3144
  -h, --help Show this help
2911
3145
 
2912
3146
  ${colors.bold("EXAMPLES:")}
2913
- forge-cli servers list
2914
- forge-cli servers list --format json
3147
+ forge servers list
3148
+ forge servers list --format json
2915
3149
  `);
2916
3150
  else if (subcommand === "get") console.log(`
2917
- ${colors.bold("forge-cli servers get")} - Get server details
3151
+ ${colors.bold("forge servers get")} - Get server details
2918
3152
 
2919
3153
  ${colors.bold("USAGE:")}
2920
- forge-cli servers get <server_id> [options]
3154
+ forge servers get <server_id> [options]
2921
3155
 
2922
3156
  ${colors.bold("ARGUMENTS:")}
2923
3157
  <server_id> Server ID (required)
@@ -2926,29 +3160,29 @@ ${colors.bold("OPTIONS:")}
2926
3160
  -f, --format <fmt> Output format: json, human, table
2927
3161
 
2928
3162
  ${colors.bold("EXAMPLES:")}
2929
- forge-cli servers get 123
2930
- forge-cli servers get 123 --format json
3163
+ forge servers get 123
3164
+ forge servers get 123 --format json
2931
3165
  `);
2932
3166
  else if (subcommand === "reboot") console.log(`
2933
- ${colors.bold("forge-cli servers reboot")} - Reboot a server
3167
+ ${colors.bold("forge servers reboot")} - Reboot a server
2934
3168
 
2935
3169
  ${colors.bold("USAGE:")}
2936
- forge-cli servers reboot <server_id> [options]
3170
+ forge servers reboot <server_id> [options]
2937
3171
 
2938
3172
  ${colors.bold("ARGUMENTS:")}
2939
3173
  <server_id> Server ID (required)
2940
3174
 
2941
3175
  ${colors.bold("EXAMPLES:")}
2942
- forge-cli servers reboot 123
3176
+ forge servers reboot 123
2943
3177
  `);
2944
3178
  else console.log(`
2945
- ${colors.bold("forge-cli servers")} - Manage servers
3179
+ ${colors.bold("forge servers")} - Manage servers
2946
3180
 
2947
3181
  ${colors.bold("USAGE:")}
2948
- forge-cli servers <subcommand> [options]
3182
+ forge servers <subcommand> [options]
2949
3183
 
2950
3184
  ${colors.bold("ALIASES:")}
2951
- forge-cli s
3185
+ forge s
2952
3186
 
2953
3187
  ${colors.bold("SUBCOMMANDS:")}
2954
3188
  list, ls List all servers
@@ -2960,15 +3194,15 @@ ${colors.bold("OPTIONS:")}
2960
3194
  -h, --help Show help for a subcommand
2961
3195
 
2962
3196
  ${colors.bold("EXAMPLES:")}
2963
- forge-cli servers list
2964
- forge-cli servers get 123
3197
+ forge servers list
3198
+ forge servers get 123
2965
3199
 
2966
- Run ${colors.cyan("forge-cli servers <subcommand> --help")} for subcommand details.
3200
+ Run ${colors.cyan("forge servers <subcommand> --help")} for subcommand details.
2967
3201
  `);
2968
3202
  }
2969
3203
  async function sitesList(ctx) {
2970
3204
  const server = String(ctx.options.server ?? "");
2971
- if (!server) exitWithValidationError("server_id", "forge-cli sites list --server <server_id>", ctx.formatter);
3205
+ if (!server) exitWithValidationError("server_id", "forge sites list --server <server_id>", ctx.formatter);
2972
3206
  await runCommand(async () => {
2973
3207
  const token = ctx.getToken();
2974
3208
  const execCtx = ctx.createExecutorContext(token);
@@ -2984,8 +3218,8 @@ async function sitesList(ctx) {
2984
3218
  async function sitesGet(args, ctx) {
2985
3219
  const [site_id] = args;
2986
3220
  const server = String(ctx.options.server ?? "");
2987
- if (!site_id) exitWithValidationError("site_id", "forge-cli sites get <site_id> --server <server_id>", ctx.formatter);
2988
- if (!server) exitWithValidationError("server_id", "forge-cli sites get <site_id> --server <server_id>", ctx.formatter);
3221
+ if (!site_id) exitWithValidationError("site_id", "forge sites get <site_id> --server <server_id>", ctx.formatter);
3222
+ if (!server) exitWithValidationError("server_id", "forge sites get <site_id> --server <server_id>", ctx.formatter);
2989
3223
  await runCommand(async () => {
2990
3224
  const token = ctx.getToken();
2991
3225
  const execCtx = ctx.createExecutorContext(token);
@@ -2998,12 +3232,43 @@ async function sitesGet(args, ctx) {
2998
3232
  "name",
2999
3233
  "status",
3000
3234
  "php_version",
3001
- "project_type",
3235
+ "app_type",
3236
+ "repository",
3237
+ "quick_deploy",
3238
+ "deployment_status",
3239
+ "https",
3240
+ "created_at"
3241
+ ]);
3242
+ }, ctx.formatter);
3243
+ }
3244
+ async function sitesUpdate(args, ctx) {
3245
+ const [site_id] = args;
3246
+ const server = String(ctx.options.server ?? "");
3247
+ if (!site_id) exitWithValidationError("site_id", "forge sites update <site_id> --server <server_id>", ctx.formatter);
3248
+ if (!server) exitWithValidationError("server_id", "forge sites update <site_id> --server <server_id>", ctx.formatter);
3249
+ await runCommand(async () => {
3250
+ const token = ctx.getToken();
3251
+ const execCtx = ctx.createExecutorContext(token);
3252
+ const result = await updateSite({
3253
+ server_id: await resolveServerId(server, execCtx),
3254
+ site_id,
3255
+ root_path: ctx.options.root_path,
3256
+ directory: ctx.options.directory,
3257
+ type: ctx.options.type,
3258
+ php_version: ctx.options.php_version,
3259
+ push_to_deploy: ctx.options.push_to_deploy !== void 0 ? ctx.options.push_to_deploy === "true" || ctx.options.push_to_deploy === true : void 0,
3260
+ repository_branch: ctx.options.repository_branch
3261
+ }, execCtx);
3262
+ ctx.formatter.outputOne(result.data, [
3263
+ "id",
3264
+ "name",
3265
+ "status",
3266
+ "php_version",
3267
+ "app_type",
3002
3268
  "repository",
3003
- "repository_branch",
3004
3269
  "quick_deploy",
3005
3270
  "deployment_status",
3006
- "is_secured",
3271
+ "https",
3007
3272
  "created_at"
3008
3273
  ]);
3009
3274
  }, ctx.formatter);
@@ -3013,29 +3278,30 @@ const handleSitesCommand = createCommandRouter({
3013
3278
  handlers: {
3014
3279
  list: sitesList,
3015
3280
  ls: sitesList,
3016
- get: [sitesGet, "args"]
3281
+ get: [sitesGet, "args"],
3282
+ update: [sitesUpdate, "args"]
3017
3283
  }
3018
3284
  });
3019
3285
  function showSitesHelp(subcommand) {
3020
3286
  if (subcommand === "list" || subcommand === "ls") console.log(`
3021
- ${colors.bold("forge-cli sites list")} - List sites on a server
3287
+ ${colors.bold("forge sites list")} - List sites on a server
3022
3288
 
3023
3289
  ${colors.bold("USAGE:")}
3024
- forge-cli sites list --server <server_id> [options]
3290
+ forge sites list --server <server_id> [options]
3025
3291
 
3026
3292
  ${colors.bold("OPTIONS:")}
3027
3293
  --server <id> Server ID (required)
3028
3294
  -f, --format <fmt> Output format: json, human, table
3029
3295
 
3030
3296
  ${colors.bold("EXAMPLES:")}
3031
- forge-cli sites list --server 123
3032
- forge-cli sites list --server 123 --format json
3297
+ forge sites list --server 123
3298
+ forge sites list --server 123 --format json
3033
3299
  `);
3034
3300
  else if (subcommand === "get") console.log(`
3035
- ${colors.bold("forge-cli sites get")} - Get site details
3301
+ ${colors.bold("forge sites get")} - Get site details
3036
3302
 
3037
3303
  ${colors.bold("USAGE:")}
3038
- forge-cli sites get <site_id> --server <server_id> [options]
3304
+ forge sites get <site_id> --server <server_id> [options]
3039
3305
 
3040
3306
  ${colors.bold("ARGUMENTS:")}
3041
3307
  <site_id> Site ID (required)
@@ -3045,10 +3311,10 @@ ${colors.bold("OPTIONS:")}
3045
3311
  -f, --format <fmt> Output format: json, human, table
3046
3312
  `);
3047
3313
  else console.log(`
3048
- ${colors.bold("forge-cli sites")} - Manage sites
3314
+ ${colors.bold("forge sites")} - Manage sites
3049
3315
 
3050
3316
  ${colors.bold("USAGE:")}
3051
- forge-cli sites <subcommand> [options]
3317
+ forge sites <subcommand> [options]
3052
3318
 
3053
3319
  ${colors.bold("SUBCOMMANDS:")}
3054
3320
  list, ls List sites on a server
@@ -3060,15 +3326,15 @@ ${colors.bold("OPTIONS:")}
3060
3326
  -h, --help Show help for a subcommand
3061
3327
 
3062
3328
  ${colors.bold("EXAMPLES:")}
3063
- forge-cli sites list --server 123
3064
- forge-cli sites get 456 --server 123
3329
+ forge sites list --server 123
3330
+ forge sites get 456 --server 123
3065
3331
 
3066
- Run ${colors.cyan("forge-cli sites <subcommand> --help")} for subcommand details.
3332
+ Run ${colors.cyan("forge sites <subcommand> --help")} for subcommand details.
3067
3333
  `);
3068
3334
  }
3069
3335
  async function sshKeysList(ctx) {
3070
3336
  const server = String(ctx.options.server ?? "");
3071
- if (!server) exitWithValidationError("server_id", "forge-cli ssh-keys list --server <server_id>", ctx.formatter);
3337
+ if (!server) exitWithValidationError("server_id", "forge ssh-keys list --server <server_id>", ctx.formatter);
3072
3338
  await runCommand(async () => {
3073
3339
  const token = ctx.getToken();
3074
3340
  const execCtx = ctx.createExecutorContext(token);
@@ -3083,8 +3349,8 @@ async function sshKeysList(ctx) {
3083
3349
  async function sshKeysGet(args, ctx) {
3084
3350
  const [id] = args;
3085
3351
  const server = String(ctx.options.server ?? "");
3086
- if (!id) exitWithValidationError("ssh_key_id", "forge-cli ssh-keys get <key_id> --server <server_id>", ctx.formatter);
3087
- if (!server) exitWithValidationError("server_id", "forge-cli ssh-keys get <key_id> --server <server_id>", ctx.formatter);
3352
+ if (!id) exitWithValidationError("ssh_key_id", "forge ssh-keys get <key_id> --server <server_id>", ctx.formatter);
3353
+ if (!server) exitWithValidationError("server_id", "forge ssh-keys get <key_id> --server <server_id>", ctx.formatter);
3088
3354
  await runCommand(async () => {
3089
3355
  const token = ctx.getToken();
3090
3356
  const execCtx = ctx.createExecutorContext(token);
@@ -3110,22 +3376,22 @@ const handleSshKeysCommand = createCommandRouter({
3110
3376
  });
3111
3377
  function showSshKeysHelp(subcommand) {
3112
3378
  if (subcommand === "list" || subcommand === "ls") console.log(`
3113
- ${colors.bold("forge-cli ssh-keys list")} - List SSH keys on a server
3379
+ ${colors.bold("forge ssh-keys list")} - List SSH keys on a server
3114
3380
 
3115
3381
  ${colors.bold("USAGE:")}
3116
- forge-cli ssh-keys list --server <server_id> [options]
3382
+ forge ssh-keys list --server <server_id> [options]
3117
3383
  `);
3118
3384
  else if (subcommand === "get") console.log(`
3119
- ${colors.bold("forge-cli ssh-keys get")} - Get SSH key details
3385
+ ${colors.bold("forge ssh-keys get")} - Get SSH key details
3120
3386
 
3121
3387
  ${colors.bold("USAGE:")}
3122
- forge-cli ssh-keys get <key_id> --server <server_id>
3388
+ forge ssh-keys get <key_id> --server <server_id>
3123
3389
  `);
3124
3390
  else console.log(`
3125
- ${colors.bold("forge-cli ssh-keys")} - Manage SSH keys
3391
+ ${colors.bold("forge ssh-keys")} - Manage SSH keys
3126
3392
 
3127
3393
  ${colors.bold("USAGE:")}
3128
- forge-cli ssh-keys <subcommand> [options]
3394
+ forge ssh-keys <subcommand> [options]
3129
3395
 
3130
3396
  ${colors.bold("SUBCOMMANDS:")}
3131
3397
  list, ls List SSH keys
@@ -3135,7 +3401,7 @@ ${colors.bold("OPTIONS:")}
3135
3401
  --server <id> Server ID (required)
3136
3402
  -f, --format <fmt> Output format: json, human, table
3137
3403
 
3138
- Run ${colors.cyan("forge-cli ssh-keys <subcommand> --help")} for details.
3404
+ Run ${colors.cyan("forge ssh-keys <subcommand> --help")} for details.
3139
3405
  `);
3140
3406
  }
3141
3407
  async function userGet(ctx) {
@@ -3151,19 +3417,19 @@ const handleUserCommand = createCommandRouter({
3151
3417
  });
3152
3418
  function showUserHelp(subcommand) {
3153
3419
  if (subcommand === "get") console.log(`
3154
- ${colors.bold("forge-cli user get")} - Get the authenticated user profile
3420
+ ${colors.bold("forge user get")} - Get the authenticated user profile
3155
3421
 
3156
3422
  ${colors.bold("USAGE:")}
3157
- forge-cli user get [options]
3423
+ forge user get [options]
3158
3424
 
3159
3425
  ${colors.bold("OPTIONS:")}
3160
3426
  -f, --format <fmt> Output format: json, human, table
3161
3427
  `);
3162
3428
  else console.log(`
3163
- ${colors.bold("forge-cli user")} - Display authenticated user profile
3429
+ ${colors.bold("forge user")} - Display authenticated user profile
3164
3430
 
3165
3431
  ${colors.bold("USAGE:")}
3166
- forge-cli user [subcommand] [options]
3432
+ forge user [subcommand] [options]
3167
3433
 
3168
3434
  ${colors.bold("SUBCOMMANDS:")}
3169
3435
  get Get the authenticated user profile
@@ -3171,7 +3437,7 @@ ${colors.bold("SUBCOMMANDS:")}
3171
3437
  ${colors.bold("OPTIONS:")}
3172
3438
  -f, --format <fmt> Output format: json, human, table
3173
3439
 
3174
- Run ${colors.cyan("forge-cli user <subcommand> --help")} for details.
3440
+ Run ${colors.cyan("forge user <subcommand> --help")} for details.
3175
3441
  `);
3176
3442
  }
3177
3443
  function parseArgs(argv = process.argv.slice(2)) {
@@ -3210,13 +3476,13 @@ function parseArgs(argv = process.argv.slice(2)) {
3210
3476
  positional
3211
3477
  };
3212
3478
  }
3213
- var VERSION = "0.2.5";
3479
+ var VERSION = "0.4.0";
3214
3480
  function showHelp() {
3215
3481
  console.log(`
3216
- ${colors.bold("forge-cli")} v${VERSION}
3482
+ ${colors.bold("forge")} v${VERSION}
3217
3483
 
3218
3484
  ${colors.bold("USAGE:")}
3219
- forge-cli <command> [subcommand] [options]
3485
+ forge <command> [subcommand] [options]
3220
3486
 
3221
3487
  ${colors.bold("COMMANDS:")}
3222
3488
  config Manage CLI configuration
@@ -3260,8 +3526,8 @@ ${colors.bold("COMMANDS:")}
3260
3526
  get Get nginx config (requires --server --site)
3261
3527
  update Update nginx config (requires --server --site --content)
3262
3528
 
3263
- certificates, certs Manage SSL certificates
3264
- list, ls List certificates (requires --server --site)
3529
+ certificates, certs Manage SSL certificates (per-domain in v2)
3530
+ get Get certificate for a domain (requires --server --site --domain)
3265
3531
  get <id> Get certificate details (requires --server --site)
3266
3532
  activate <id> Activate a certificate (requires --server --site)
3267
3533
 
@@ -3330,8 +3596,10 @@ ${colors.bold("COMMANDS:")}
3330
3596
 
3331
3597
  ${colors.bold("OPTIONS:")}
3332
3598
  --token <token> Forge API token (overrides config and env)
3599
+ --org <slug> Organization slug (overrides config and FORGE_ORG)
3333
3600
  --server <id> Server ID (required for server-scoped commands)
3334
3601
  --site <id> Site ID (required for site-scoped commands)
3602
+ --domain <id> Domain record ID (for certificate commands)
3335
3603
  -f, --format <fmt> Output format: json, human, table (default: human)
3336
3604
  --no-color Disable colored output
3337
3605
  -h, --help Show help
@@ -3339,22 +3607,22 @@ ${colors.bold("OPTIONS:")}
3339
3607
 
3340
3608
  ${colors.bold("EXAMPLES:")}
3341
3609
  # Configure API token
3342
- forge-cli config set YOUR_TOKEN
3610
+ forge config set YOUR_TOKEN
3343
3611
 
3344
3612
  # Or pass token directly
3345
- forge-cli servers list --token YOUR_TOKEN
3613
+ forge servers list --token YOUR_TOKEN
3346
3614
 
3347
3615
  # List all servers
3348
- forge-cli servers list
3616
+ forge servers list
3349
3617
 
3350
3618
  # List sites on a server
3351
- forge-cli sites list --server 123
3619
+ forge sites list --server 123
3352
3620
 
3353
3621
  # Deploy a site
3354
- forge-cli deployments deploy --server 123 --site 456
3622
+ forge deployments deploy --server 123 --site 456
3355
3623
 
3356
3624
  # Get JSON output (for AI agents)
3357
- forge-cli servers list --format json
3625
+ forge servers list --format json
3358
3626
 
3359
3627
  ${colors.bold("CREDENTIAL PRIORITY:")}
3360
3628
  1. CLI argument (--token)
@@ -3363,6 +3631,7 @@ ${colors.bold("CREDENTIAL PRIORITY:")}
3363
3631
 
3364
3632
  ${colors.bold("ENVIRONMENT VARIABLES:")}
3365
3633
  FORGE_API_TOKEN API token
3634
+ FORGE_ORG Organization slug (e.g. studio-meta)
3366
3635
  NO_COLOR Disable colors
3367
3636
  XDG_CONFIG_HOME Config directory (respects XDG spec)
3368
3637
  `);
@@ -3547,7 +3816,7 @@ async function main() {
3547
3816
  break;
3548
3817
  default:
3549
3818
  console.error(colors.red(`Unknown command: ${mainCommand}`));
3550
- console.log(`Run ${colors.cyan("forge-cli --help")} for usage information`);
3819
+ console.log(`Run ${colors.cyan("forge --help")} for usage information`);
3551
3820
  process.exit(1);
3552
3821
  }
3553
3822
  } catch (error) {