From e0a2ec578c68d31d496b4c82370559d74f3b23e8 Mon Sep 17 00:00:00 2001 From: Lyu Date: Wed, 7 Oct 2026 16:43:33 -0700 Subject: [PATCH 1/2] docs: compute scale sets a replica cap Co-Authored-By: Claude Opus 5.5 --- src/commands/compute.ts | 10 +++++----- src/index.ts | 4 ++-- test/compute-scale-remove.test.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/commands/compute.ts b/src/commands/compute.ts index 06dc623..38126eb 100644 --- a/src/commands/compute.ts +++ b/src/commands/compute.ts @@ -634,7 +634,7 @@ export async function serviceAlwaysOn(type: ManagedType, mode: string, serviceNa } export const computeAlwaysOn = (mode: string, serviceName: string | undefined, opts: LifeOpts): Promise => serviceAlwaysOn('compute', mode, serviceName, opts) -// ---- scale (same-region replica count; paid plans) ---- +// ---- scale (same-region replica cap; paid plans) ---- type ScaleOpts = LifeOpts & { region?: string; remove?: string } const INSTANCE_ID = /^inst-[a-f0-9]{12}$/ @@ -644,7 +644,7 @@ export function removeTarget(count: string | undefined, service: string | undefi if (!INSTANCE_ID.test(opts.remove)) throw new Error(`invalid instance id: ${opts.remove} (expected inst-<12 hex digits>, the \`instance\` field of \`insta compute logs --json\`)`) if (opts.region !== undefined) throw new Error('--region does not apply to --remove') if (service !== undefined) { - throw new Error(count !== undefined && count.trim() !== '' && Number.isFinite(Number(count)) ? '--remove lowers the replica count by one; pass no count' : `unexpected argument: ${service} (usage: insta compute scale [service] --remove )`) + throw new Error(count !== undefined && count.trim() !== '' && Number.isFinite(Number(count)) ? '--remove names one instance; pass no count' : `unexpected argument: ${service} (usage: insta compute scale [service] --remove )`) } return count } @@ -653,7 +653,7 @@ export function removeTarget(count: string | undefined, service: string | undefi // validated locally (1..10); the paid-plan gate is the backend's and its 403 flows verbatim. export async function computeScale(count: string | undefined, serviceName: string | undefined, opts: ScaleOpts): Promise { if (opts.remove !== undefined) return computeRemoveInstance(removeTarget(count, serviceName, { remove: opts.remove, region: opts.region }), opts.remove, opts) - if (count === undefined) throw new Error('a replica count is required (or --remove to drop one named instance)') + if (count === undefined) throw new Error('a replica cap is required (or --remove to drop one named instance)') const machineCount = parseCount(count) const api = await ApiClient.load() const p = await requireProject() @@ -663,7 +663,7 @@ export async function computeScale(count: string | undefined, serviceName: strin const res = await api.rawRequest('POST', `/projects/${p.projectId}/services/${svc.id}/scale`, { machineCount, region: opts.region }) if (handleApproval(res, opts.json)) return if (opts.json) return printJson(res.body.service) - info(`scaled compute ${svc.name} to ${machineCount} replica(s)${opts.region ? ` in ${opts.region}` : ''}`) + info(`set compute ${svc.name} replica cap to ${machineCount}${opts.region ? ` in ${opts.region}` : ''}`) } // `insta compute scale [service] --remove ` — DELETE /services/:id/instances/:instance. @@ -676,7 +676,7 @@ async function computeRemoveInstance(serviceName: string | undefined, instance: const res = await api.rawRequest('DELETE', `/projects/${p.projectId}/services/${svc.id}/instances/${instance}`) if (handleApproval(res, opts.json)) return if (opts.json) return printJson(res.body.service) - info(`removed ${instance} from compute ${svc.name}; ${res.body.service?.machine_count ?? '?'} replica(s) remain`) + info(`removed ${instance} from compute ${svc.name}`) } // ---- limits (the resource ceiling; paid plans) ---- diff --git a/src/index.ts b/src/index.ts index 5b0f0f4..51b5d0b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -395,9 +395,9 @@ compute.command('restart [service]').description("Restart a compute service by r .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o))) compute.command('status [service]').description("Show a compute service's desired vs. live state") .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStatus(service, o))) -compute.command('scale [count] [service]').description('Set a compute service same-region replica count, 1 to 10 (paid plans only). --remove instead drops that one instance and runs one fewer; instance ids are the `instance` field of `insta compute logs --json`. The last instance cannot be removed') +compute.command('scale [count] [service]').description('Set a compute service same-region replica cap, 1 to 10 (paid plans only). A scale-to-zero service runs 1 up to the cap on demand; an always-on service runs exactly the cap, so turn always-on on to hold a fixed count. --remove instead drops that one instance; instance ids are the `instance` field of `insta compute logs --json`. The last instance cannot be removed') .option('--region ', 'region to scale in (default: the service region)') - .option('--remove ', 'drop this instance (inst-<12 hex>) and run one fewer replica') + .option('--remove ', 'drop this instance (inst-<12 hex>)') .option('--json').option('--branch ', 'branch (default: current)') .action(guard((count, service, o) => computeCmd.computeScale(count, service, o))) compute.command('limits [service]').description("Show or set a compute service's resource ceiling (any plan within the free cap; raising above it needs a paid plan). --memory is the dial; cpu derives from it unless --cpu is given. Billing is actual usage — the ceiling caps what the app may burn, it is not a price") diff --git a/test/compute-scale-remove.test.ts b/test/compute-scale-remove.test.ts index 1ce4101..84aa9f9 100644 --- a/test/compute-scale-remove.test.ts +++ b/test/compute-scale-remove.test.ts @@ -34,6 +34,6 @@ describe('removeTarget', () => { describe('computeScale', () => { it('needs a count unless --remove names an instance', async () => { - await expect(computeScale(undefined, undefined, {})).rejects.toThrow(/replica count is required/) + await expect(computeScale(undefined, undefined, {})).rejects.toThrow(/replica cap is required/) }) }) From 9993349447879594b24d8f76f38ef18104a4924f Mon Sep 17 00:00:00 2001 From: Lyu Date: Wed, 7 Oct 2026 17:31:21 -0700 Subject: [PATCH 2/2] compute scale --remove: say what happens to the cap, print it Co-Authored-By: Claude Opus 5.5 --- src/commands/compute.ts | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/compute.ts b/src/commands/compute.ts index 38126eb..2fc911b 100644 --- a/src/commands/compute.ts +++ b/src/commands/compute.ts @@ -676,7 +676,7 @@ async function computeRemoveInstance(serviceName: string | undefined, instance: const res = await api.rawRequest('DELETE', `/projects/${p.projectId}/services/${svc.id}/instances/${instance}`) if (handleApproval(res, opts.json)) return if (opts.json) return printJson(res.body.service) - info(`removed ${instance} from compute ${svc.name}`) + info(`removed ${instance} from compute ${svc.name}; replica cap is now ${res.body.service?.machine_count ?? '?'}`) } // ---- limits (the resource ceiling; paid plans) ---- diff --git a/src/index.ts b/src/index.ts index 51b5d0b..bb503e0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -395,7 +395,7 @@ compute.command('restart [service]').description("Restart a compute service by r .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o))) compute.command('status [service]').description("Show a compute service's desired vs. live state") .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStatus(service, o))) -compute.command('scale [count] [service]').description('Set a compute service same-region replica cap, 1 to 10 (paid plans only). A scale-to-zero service runs 1 up to the cap on demand; an always-on service runs exactly the cap, so turn always-on on to hold a fixed count. --remove instead drops that one instance; instance ids are the `instance` field of `insta compute logs --json`. The last instance cannot be removed') +compute.command('scale [count] [service]').description('Set a compute service same-region replica cap, 1 to 10 (paid plans only). A scale-to-zero service runs 1 up to the cap on demand; an always-on service runs exactly the cap, so turn always-on on to hold a fixed count. --remove instead drops that one instance: an always-on service runs one fewer, a scale-to-zero one keeps its cap; instance ids are the `instance` field of `insta compute logs --json`. The last instance cannot be removed') .option('--region ', 'region to scale in (default: the service region)') .option('--remove ', 'drop this instance (inst-<12 hex>)') .option('--json').option('--branch ', 'branch (default: current)')