Conversation
…_API_URL Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
… of --group Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ver runtime-health, query engine guard Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ess/upgrade/secrets verbs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…h move under domain Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ics, agent + config groups, global --api-url Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mmand paths Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…billing subscribe / service add Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…cture rules in the dev skill Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…y live paths Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…--api-url; spawn-test timeouts; wording - billing/secrets group commands now set allowExcessArguments(false), so a retired/mistyped subcommand under either group (`billing upgrade pro`, `secrets lst`) fails instead of silently running the group's own default action (commander 12 defaults allowExcessArguments to true). - `insta config autoupdate <on|off>` now reads via readPersistedGlobal() before its read-modify-write, instead of readGlobal() — readGlobal() folds in a runtime --api-url/INSTA_API_URL override and scrubs the stored session when it points elsewhere, so writing it back re-pointed ~/.insta/config.json and logged the user out just from toggling autoupdate. - Add explicit 30s timeouts to the remaining spawnSync-backed vitest `it` cases in help-surface.test.ts and retired-policy.test.ts (CI's windows-latest spawns are 3-5x slower than the 5s vitest default). - Wording: SKILL.md's observe hook reference, the root --api-url description (compute exec needs it before `compute`), volumeWriteLine and serviceLimits now say "database" instead of implying every managed type has a deploy step. - Tests: pin `billing upgrade` as retired and `secrets lst` as loud-failing; broaden the retired-path stderr regex to also accept commander's "too many arguments"; add a managedStatus-level (not just statusLine-level) test for runtime-health omitting the resolved service. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
16 issues found across 59 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="README.md">
<violation number="1" location="README.md:233">
P2: `compute exec` is the documented exception to this flag placement, so this sentence tells users an invocation that the CLI rejects. Document the exception and instruct users to place `--api-url` before `compute` for `compute exec`.</violation>
</file>
<file name="test/help-surface.test.ts">
<violation number="1" location="test/help-surface.test.ts:122">
P2: This test covers `--api-url` placement only for hidden `env`, so a leaf omitted from `addApiUrlEverywhere` can regress unnoticed. Add representative post-subcommand invocations for each command group, including nested leaves.</violation>
</file>
<file name="src/config.ts">
<violation number="1" location="src/config.ts:63">
P3: When the supplied `env` object omits `INSTA_ENV` but the process has one set, `pickApiUrl` reads the ambient variable through `envFromEnvVar`'s default parameter. Treat an omitted property as `null` before calling `envFromEnvVar` so the helper remains pure.</violation>
<violation number="2" location="src/config.ts:75">
P2: When a command using a same-deployment `--api-url` override refreshes an expired session, `ApiClient.refresh()` persists this returned config and rewrites the stored `apiUrl`. Keep refresh persistence tied to the persisted config so a runtime debugging override cannot alter the machine's login configuration.</violation>
<violation number="3" location="src/config.ts:85">
P1: When `logout` runs with `--api-url` for another deployment, `readGlobal()` returns the scrubbed runtime view and `logout()` persists it. This permanently switches the stored API URL and deletes the original session, violating the flag's runtime-only contract; persist the stored config instead.</violation>
</file>
<file name="src/commands/compute.ts">
<violation number="1" location="src/commands/compute.ts:660">
P3: The no-volume guidance for managed databases tells users `insta redis volume <name> --size <gi>` will attach a volume, but the redis/mysql/mongodb `volume` command's declared surface in src/index.ts only documents grow and delete ("--size grows it (paid plans; grow-only)") — no attach. One of the two surfaces is wrong for the user: if --size cannot attach a disk to a volumeless managed DB, this newly added line sends users into a failing command; if it can, the new command help is missing the attach semantics. Align the message and the --help text with the actual platform behavior for managed-DB volume attach.</violation>
<violation number="2" location="src/commands/compute.ts:687">
P3: When deleting a managed-database volume, the success message claims that compute-only constraints—suspend fast-wake and scale-out—are restored. Render a type-specific message instead of reusing this compute-only text for Redis, MySQL, and MongoDB.</violation>
</file>
<file name="src/commands/services.ts">
<violation number="1" location="src/commands/services.ts:116">
P2: When `insta service add redis|mysql|mongodb ... --always-on` is rejected, the error points to the Postgres command instead of the managed database's own `always-on` command. Give `postgres`, `redis`, `mysql`, and `mongodb` service-specific guidance, or omit the database hint for unsupported types.</violation>
<violation number="2" location="src/commands/services.ts:119">
P2: When `insta service add redis|mysql|mongodb ... --volume` is rejected, the error sends users to the Postgres volume command, which resolves the wrong service type. Point managed database users to their matching `redis|mysql|mongodb volume --size` command, and keep the Postgres hint only for Postgres.</violation>
</file>
<file name="src/commands/setup.ts">
<violation number="1" location="src/commands/setup.ts:1">
P3: The comment calls `insta agent setup` the `railway setup agent` pattern, but those command orders differ. Remove or correct the parenthetical so maintainers do not infer the wrong CLI convention.</violation>
</file>
<file name=".claude/skills/developing-insta-cli/SKILL.md">
<violation number="1" location=".claude/skills/developing-insta-cli/SKILL.md:52">
P2: The command-shape rule is false for managed-database `query`: it requires `<service>`, unlike the documented optional `[service]`. Qualify this exception so future commands do not copy the wrong positional contract.</violation>
<violation number="2" location=".claude/skills/developing-insta-cli/SKILL.md:62">
P3: This says `addApiUrlEverywhere()` covers every command, but `compute exec` is deliberately skipped and the root/login options are declared manually. State these exceptions here so the architecture rule does not contradict the implementation and the exec gotcha below.</violation>
</file>
<file name="src/commands/upgrade.ts">
<violation number="1" location="src/commands/upgrade.ts:377">
P2: When `insta config autoupdate off` runs with a newer cached release, startup can auto-upgrade before this handler changes the preference. Extend the update-check exemption to recognize the nested `config autoupdate` path.</violation>
</file>
<file name="src/commands/domain.ts">
<violation number="1" location="src/commands/domain.ts:201">
P3: `domain check`/`domain detach` now forward the hostname verbatim, while `domain attach` in this same change lowercases and trims before delegating to `setDomain`. `insta domain attach Docs.MyApp.com` binds `docs.myapp.com`, but `insta domain check Docs.MyApp.com` queries `Docs.MyApp.com` as typed. If the plane stores hostnames lowercase, a mixed-case check/detach misses the binding the attach just created. Normalize in the aliases to match the attach path.</violation>
<violation number="2" location="src/commands/domain.ts:202">
P2: `domain detach` is now the only detach verb for every hostname, but bought-domain attachments were created through a different surface that `removeDomain` never touches. `domain attach myapp.com` binds two hostnames (apex and www) via `POST /projects/{id}/domains/{owner}/attach` and its output points the user to `insta domain status`, while `domainDetach` sends `DELETE /projects/{id}/compute/domain` for a single `hostname` only. Verify the compute-plane DELETE covers hostnames that arrived via `attach`; if it does, the following still needs handling: detaching the apex leaves `www.myapp.com` bound, and a detach of a hostname never attached through the compute plane may silently no-op. If bought bindings need a different endpoint, route `domainDetach` accordingly or refuse with a clear message.</violation>
</file>
<file name="test/retired-policy.test.ts">
<violation number="1" location="test/retired-policy.test.ts:20">
P3: The first test now serializes 4 child-process spawns (second test 2 more), each still capped at 10s by `run`'s `timeout: 10000`, inside one 30s budget. On a cold Windows runner, a single tsx cold-start can exceed 10s (matching the PR's own note about needing explicit Windows spawn timeouts), and a per-spawn timeout yields `status: null` with empty `stderr`, failing the assertion in a way that hides the real result. Raise the per-call timeout in `run`, or count each spawn's elapsed time against the budget instead of relying on 30s for all of them.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| return { apiUrl: override ?? DEFAULT_API } | ||
| parsed = null | ||
| } | ||
| return pickApiUrl(parsed, process.env, cliApiUrlOverride) |
There was a problem hiding this comment.
P1: When logout runs with --api-url for another deployment, readGlobal() returns the scrubbed runtime view and logout() persists it. This permanently switches the stored API URL and deletes the original session, violating the flag's runtime-only contract; persist the stored config instead.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/config.ts, line 85:
<comment>When `logout` runs with `--api-url` for another deployment, `readGlobal()` returns the scrubbed runtime view and `logout()` persists it. This permanently switches the stored API URL and deletes the original session, violating the flag's runtime-only contract; persist the stored config instead.</comment>
<file context>
@@ -33,41 +33,56 @@ export type ProjectConfig = { projectId: string; orgId: string; branch: string }
- return { apiUrl: override ?? DEFAULT_API }
+ parsed = null
}
+ return pickApiUrl(parsed, process.env, cliApiUrlOverride)
}
</file context>
| | `insta upgrade` · `autoupdate` | Update the CLI; show or set auto-update | | ||
| | `insta upgrade` | Update the CLI | | ||
|
|
||
| Every command accepts `--api-url <url>` for this invocation only (internal debugging); `insta --help` documents it. |
There was a problem hiding this comment.
P2: compute exec is the documented exception to this flag placement, so this sentence tells users an invocation that the CLI rejects. Document the exception and instruct users to place --api-url before compute for compute exec.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 233:
<comment>`compute exec` is the documented exception to this flag placement, so this sentence tells users an invocation that the CLI rejects. Document the exception and instruct users to place `--api-url` before `compute` for `compute exec`.</comment>
<file context>
@@ -211,28 +211,26 @@ build never reaches a production installer.
-| `insta upgrade` · `autoupdate` | Update the CLI; show or set auto-update |
+| `insta upgrade` | Update the CLI |
+
+Every command accepts `--api-url <url>` for this invocation only (internal debugging); `insta --help` documents it.
## Configuration
</file context>
| Every command accepts `--api-url <url>` for this invocation only (internal debugging); `insta --help` documents it. | |
| Every command accepts `--api-url <url>` for this invocation only (internal debugging); for `compute exec`, place it before `compute`. `insta --help` documents it. |
| const URL_A = 'http://127.0.0.1:1' | ||
| const URL_B = 'http://127.0.0.1:2' | ||
| // `env --json` reads config and prints the resolved apiUrl without touching the network. | ||
| it('is honoured after the subcommand, before it, and over INSTA_API_URL', () => { |
There was a problem hiding this comment.
P2: This test covers --api-url placement only for hidden env, so a leaf omitted from addApiUrlEverywhere can regress unnoticed. Add representative post-subcommand invocations for each command group, including nested leaves.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/help-surface.test.ts, line 122:
<comment>This test covers `--api-url` placement only for hidden `env`, so a leaf omitted from `addApiUrlEverywhere` can regress unnoticed. Add representative post-subcommand invocations for each command group, including nested leaves.</comment>
<file context>
@@ -0,0 +1,127 @@
+ const URL_A = 'http://127.0.0.1:1'
+ const URL_B = 'http://127.0.0.1:2'
+ // `env --json` reads config and prints the resolved apiUrl without touching the network.
+ it('is honoured after the subcommand, before it, and over INSTA_API_URL', () => {
+ expect(JSON.parse(run(['env', '--json', '--api-url', URL_A]).stdout).apiUrl).toBe(URL_A)
+ expect(JSON.parse(run(['--api-url', URL_A, 'env', '--json']).stdout).apiUrl).toBe(URL_A)
</file context>
| delete scrubbed.agentCredential | ||
| return scrubbed | ||
| } | ||
| return { ...parsed, apiUrl: override ?? persisted } |
There was a problem hiding this comment.
P2: When a command using a same-deployment --api-url override refreshes an expired session, ApiClient.refresh() persists this returned config and rewrites the stored apiUrl. Keep refresh persistence tied to the persisted config so a runtime debugging override cannot alter the machine's login configuration.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/config.ts, line 75:
<comment>When a command using a same-deployment `--api-url` override refreshes an expired session, `ApiClient.refresh()` persists this returned config and rewrites the stored `apiUrl`. Keep refresh persistence tied to the persisted config so a runtime debugging override cannot alter the machine's login configuration.</comment>
<file context>
@@ -33,41 +33,56 @@ export type ProjectConfig = { projectId: string; orgId: string; branch: string }
+ delete scrubbed.agentCredential
+ return scrubbed
+ }
+ return { ...parsed, apiUrl: override ?? persisted }
+}
+
</file context>
| } | ||
| // Presence, not truthiness: `--no-always-on` is an explicit false and is just as compute-only. | ||
| if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error('--always-on / --no-always-on is only valid for compute services (for postgres, use `insta db always-on on|off` after creation)') | ||
| if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error('--always-on / --no-always-on is only valid for compute services (for postgres, use `insta postgres always-on on|off` after creation)') |
There was a problem hiding this comment.
P2: When insta service add redis|mysql|mongodb ... --always-on is rejected, the error points to the Postgres command instead of the managed database's own always-on command. Give postgres, redis, mysql, and mongodb service-specific guidance, or omit the database hint for unsupported types.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/commands/services.ts, line 116:
<comment>When `insta service add redis|mysql|mongodb ... --always-on` is rejected, the error points to the Postgres command instead of the managed database's own `always-on` command. Give `postgres`, `redis`, `mysql`, and `mongodb` service-specific guidance, or omit the database hint for unsupported types.</comment>
<file context>
@@ -113,10 +113,10 @@ export async function servicesAdd(type: string, name: string, opts: ServicesAddO
}
// Presence, not truthiness: `--no-always-on` is an explicit false and is just as compute-only.
- if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error('--always-on / --no-always-on is only valid for compute services (for postgres, use `insta db always-on on|off` after creation)')
+ if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error('--always-on / --no-always-on is only valid for compute services (for postgres, use `insta postgres always-on on|off` after creation)')
if (opts.mountPath !== undefined && (type !== 'compute' || opts.volume === undefined)) throw new Error('--mount-path requires --volume on a compute service')
if (opts.volume !== undefined) {
</file context>
| if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error('--always-on / --no-always-on is only valid for compute services (for postgres, use `insta postgres always-on on|off` after creation)') | |
| if (opts.alwaysOn !== undefined && type !== 'compute') throw new Error(type === 'postgres' || ['redis', 'mysql', 'mongodb'].includes(type) ? `--always-on / --no-always-on is only valid for compute services; use ${type} always-on on|off after creation` : '--always-on / --no-always-on is only valid for compute services') |
| order the design's §9 gives (docs/copy merge right after the CLI release, never before). | ||
|
|
||
| Where things go: settings (limits/volume/always-on/scale) live under the service type; | ||
| `logs`/`metrics` live under the service type via `addObservability()` in `index.ts`; anything |
There was a problem hiding this comment.
P3: This says addApiUrlEverywhere() covers every command, but compute exec is deliberately skipped and the root/login options are declared manually. State these exceptions here so the architecture rule does not contradict the implementation and the exec gotcha below.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .claude/skills/developing-insta-cli/SKILL.md, line 62:
<comment>This says `addApiUrlEverywhere()` covers every command, but `compute exec` is deliberately skipped and the root/login options are declared manually. State these exceptions here so the architecture rule does not contradict the implementation and the exec gotcha below.</comment>
<file context>
@@ -37,6 +37,34 @@ npx tsx src/index.ts --help # run the CLI from source
+ order the design's §9 gives (docs/copy merge right after the CLI release, never before).
+
+Where things go: settings (limits/volume/always-on/scale) live under the service type;
+`logs`/`metrics` live under the service type via `addObservability()` in `index.ts`; anything
+about this machine's agents or the project's agent governance lives under `agent`; anything about
+this machine's CLI configuration lives under `config`. `--api-url` is injected on every command by
</file context>
| export const domainCheck = checkDomain | ||
| export const domainDetach = removeDomain |
There was a problem hiding this comment.
P3: domain check/domain detach now forward the hostname verbatim, while domain attach in this same change lowercases and trims before delegating to setDomain. insta domain attach Docs.MyApp.com binds docs.myapp.com, but insta domain check Docs.MyApp.com queries Docs.MyApp.com as typed. If the plane stores hostnames lowercase, a mixed-case check/detach misses the binding the attach just created. Normalize in the aliases to match the attach path.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/commands/domain.ts, line 201:
<comment>`domain check`/`domain detach` now forward the hostname verbatim, while `domain attach` in this same change lowercases and trims before delegating to `setDomain`. `insta domain attach Docs.MyApp.com` binds `docs.myapp.com`, but `insta domain check Docs.MyApp.com` queries `Docs.MyApp.com` as typed. If the plane stores hostnames lowercase, a mixed-case check/detach misses the binding the attach just created. Normalize in the aliases to match the attach path.</comment>
<file context>
@@ -193,3 +195,8 @@ export async function domainRecordsRemove(domainName: string, id: string, opts:
+
+// `insta domain check|detach <hostname>` — the hostname-level reads and writes, for bought and
+// bring-your-own names alike (both are routed through the compute plane's custom-domain surface).
+export const domainCheck = checkDomain
+export const domainDetach = removeDomain
</file context>
| export const domainCheck = checkDomain | |
| export const domainDetach = removeDomain | |
| export const domainCheck = (host: string, opts: { branch?: string; group?: string; json?: boolean }, deps?: DomainDeps) => checkDomain(host.trim().toLowerCase(), opts, deps) | |
| export const domainDetach = (host: string, opts: { branch?: string; group?: string; json?: boolean }, deps?: DomainDeps) => removeDomain(host.trim().toLowerCase(), opts, deps) |
| expect(r.stderr).toContain(`unknown command '${retired[0]}'`) | ||
| } | ||
| expect(run('agent', 'policy', 'get', '--help').status).toBe(0) | ||
| }, 30_000) |
There was a problem hiding this comment.
P3: The first test now serializes 4 child-process spawns (second test 2 more), each still capped at 10s by run's timeout: 10000, inside one 30s budget. On a cold Windows runner, a single tsx cold-start can exceed 10s (matching the PR's own note about needing explicit Windows spawn timeouts), and a per-spawn timeout yields status: null with empty stderr, failing the assertion in a way that hides the real result. Raise the per-call timeout in run, or count each spawn's elapsed time against the budget instead of relying on 30s for all of them.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At test/retired-policy.test.ts, line 20:
<comment>The first test now serializes 4 child-process spawns (second test 2 more), each still capped at 10s by `run`'s `timeout: 10000`, inside one 30s budget. On a cold Windows runner, a single tsx cold-start can exceed 10s (matching the PR's own note about needing explicit Windows spawn timeouts), and a per-spawn timeout yields `status: null` with empty `stderr`, failing the assertion in a way that hides the real result. Raise the per-call timeout in `run`, or count each spawn's elapsed time against the budget instead of relying on 30s for all of them.</comment>
<file context>
@@ -5,21 +5,25 @@ import { expect, it } from 'vitest'
+ expect(r.stderr).toContain(`unknown command '${retired[0]}'`)
+ }
+ expect(run('agent', 'policy', 'get', '--help').status).toBe(0)
+}, 30_000)
it('rejects approval --always instead of promising a permanent grant', () => {
</file context>
| * the file keeps the real login, so unsetting the override restores it. A custom host (insta-oss, | ||
| * a preview) is treated the same way — its session is equally foreign. */ | ||
| export function pickApiUrl(parsed: GlobalConfig | null, env: NodeJS.ProcessEnv, cliOverride?: string): GlobalConfig { | ||
| const named = envFromEnvVar(env.INSTA_ENV) |
There was a problem hiding this comment.
P3: When the supplied env object omits INSTA_ENV but the process has one set, pickApiUrl reads the ambient variable through envFromEnvVar's default parameter. Treat an omitted property as null before calling envFromEnvVar so the helper remains pure.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/config.ts, line 63:
<comment>When the supplied `env` object omits `INSTA_ENV` but the process has one set, `pickApiUrl` reads the ambient variable through `envFromEnvVar`'s default parameter. Treat an omitted property as `null` before calling `envFromEnvVar` so the helper remains pure.</comment>
<file context>
@@ -33,41 +33,56 @@ export type ProjectConfig = { projectId: string; orgId: string; branch: string }
+ * the file keeps the real login, so unsetting the override restores it. A custom host (insta-oss,
+ * a preview) is treated the same way — its session is equally foreign. */
+export function pickApiUrl(parsed: GlobalConfig | null, env: NodeJS.ProcessEnv, cliOverride?: string): GlobalConfig {
+ const named = envFromEnvVar(env.INSTA_ENV)
+ const override = cliOverride ?? env.INSTA_API_URL ?? (named ? ENVS[named].api : undefined)
+ if (!parsed) return { apiUrl: override ?? DEFAULT_API }
</file context>
| const named = envFromEnvVar(env.INSTA_ENV) | |
| const named = env.INSTA_ENV === undefined ? null : envFromEnvVar(env.INSTA_ENV) |
| `compute ${name}: no volume attached (attach one: \`insta compute volume ${name} --size <gi>\` — it mounts at /data on the next deploy)`, | ||
| type === 'compute' | ||
| ? `compute ${name}: no volume attached (attach one: \`insta compute volume ${name} --size <gi>\` — it mounts at /data on the next deploy)` | ||
| : `${type} ${name}: no volume attached (attach one: \`insta ${type} volume ${name} --size <gi>\` — it mounts at the image's data directory)`, |
There was a problem hiding this comment.
P3: The no-volume guidance for managed databases tells users insta redis volume <name> --size <gi> will attach a volume, but the redis/mysql/mongodb volume command's declared surface in src/index.ts only documents grow and delete ("--size grows it (paid plans; grow-only)") — no attach. One of the two surfaces is wrong for the user: if --size cannot attach a disk to a volumeless managed DB, this newly added line sends users into a failing command; if it can, the new command help is missing the attach semantics. Align the message and the --help text with the actual platform behavior for managed-DB volume attach.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/commands/compute.ts, line 660:
<comment>The no-volume guidance for managed databases tells users `insta redis volume <name> --size <gi>` will attach a volume, but the redis/mysql/mongodb `volume` command's declared surface in src/index.ts only documents grow and delete ("--size grows it (paid plans; grow-only)") — no attach. One of the two surfaces is wrong for the user: if --size cannot attach a disk to a volumeless managed DB, this newly added line sends users into a failing command; if it can, the new command help is missing the attach semantics. Align the message and the --help text with the actual platform behavior for managed-DB volume attach.</comment>
<file context>
@@ -627,31 +653,38 @@ export function parseCpu(raw: string): number {
- `compute ${name}: no volume attached (attach one: \`insta compute volume ${name} --size <gi>\` — it mounts at /data on the next deploy)`,
+ type === 'compute'
+ ? `compute ${name}: no volume attached (attach one: \`insta compute volume ${name} --size <gi>\` — it mounts at /data on the next deploy)`
+ : `${type} ${name}: no volume attached (attach one: \`insta ${type} volume ${name} --size <gi>\` — it mounts at the image's data directory)`,
]
return [
</file context>
…iner) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/index.ts">
<violation number="1" location="src/index.ts:494">
P2: When `setup agent --api-url` runs on a machine persisted to staging, `setupAgent` can switch and persist production before setup because its environment planner cannot see the runtime URL. Pass the CLI override into setup’s environment planning, or prevent this alias from accepting the global flag.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| // and third-party docs; it must keep working on every release. Permanent, like `services|svc`; | ||
| // hidden so the canonical `agent setup` is the only one help advertises. | ||
| const setupCompat = program.command('setup', { hidden: true }).description('Compatibility alias: `insta setup agent` is `insta agent setup`') | ||
| withSetupAgentOptions(setupCompat.command('agent').description('Alias of `insta agent setup`, kept for the console one-liner')) |
There was a problem hiding this comment.
P2: When setup agent --api-url runs on a machine persisted to staging, setupAgent can switch and persist production before setup because its environment planner cannot see the runtime URL. Pass the CLI override into setup’s environment planning, or prevent this alias from accepting the global flag.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/index.ts, line 494:
<comment>When `setup agent --api-url` runs on a machine persisted to staging, `setupAgent` can switch and persist production before setup because its environment planner cannot see the runtime URL. Pass the CLI override into setup’s environment planning, or prevent this alias from accepting the global flag.</comment>
<file context>
@@ -480,6 +486,13 @@ cfg.command('install-mcp').description('Register the remote MCP server with codi
+// and third-party docs; it must keep working on every release. Permanent, like `services|svc`;
+// hidden so the canonical `agent setup` is the only one help advertises.
+const setupCompat = program.command('setup', { hidden: true }).description('Compatibility alias: `insta setup agent` is `insta agent setup`')
+withSetupAgentOptions(setupCompat.command('agent').description('Alias of `insta agent setup`, kept for the console one-liner'))
+
// ---- feedback (agent + human hurdle reports → the InstaCloud team) ----
</file context>
… — the volume is the data directory) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/index.ts">
<violation number="1" location="src/index.ts:355">
P2: After this change, managed database volume reads still tell users to delete with `--delete`, but Commander rejects that option because it was removed here. Update `volumeLines()` to omit the delete instruction for managed database types while retaining it for compute.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| .option('--memory <size>', 'memory ceiling, e.g. 512mb or 1gb').option('--cpu <n>', 'vCPU ceiling override (provider sizes: 1, 2, 4, 6, 8)') | ||
| .option('--json').option('--branch <branch>', 'branch (default: current)') | ||
| .action(guard((service, o) => computeCmd.serviceLimits(type, service, o))) | ||
| g.command('volume [service]').description(`Show or grow a ${type} service's data volume (the image's data directory). No flag: size and the plan cap (any plan). --size grows it (paid plans; grow-only). A managed database's volume cannot be deleted — remove the service instead. Billing is actual data stored — the size is a cap, not a price`) |
There was a problem hiding this comment.
P2: After this change, managed database volume reads still tell users to delete with --delete, but Commander rejects that option because it was removed here. Update volumeLines() to omit the delete instruction for managed database types while retaining it for compute.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/index.ts, line 355:
<comment>After this change, managed database volume reads still tell users to delete with `--delete`, but Commander rejects that option because it was removed here. Update `volumeLines()` to omit the delete instruction for managed database types while retaining it for compute.</comment>
<file context>
@@ -352,9 +352,8 @@ for (const type of ['redis', 'mysql', 'mongodb'] as const) {
.option('--json').option('--branch <branch>', 'branch (default: current)')
.action(guard((service, o) => computeCmd.serviceLimits(type, service, o)))
- g.command('volume [service]').description(`Show, grow, or delete a ${type} service's data volume (mounted at the image's data directory). No flag: size and the plan cap (any plan). --size grows it (paid plans; grow-only). --delete DESTROYS the disk and ALL its data immediately (no undo). Billing is actual data stored — the size is a cap, not a price`)
+ g.command('volume [service]').description(`Show or grow a ${type} service's data volume (the image's data directory). No flag: size and the plan cap (any plan). --size grows it (paid plans; grow-only). A managed database's volume cannot be deleted — remove the service instead. Billing is actual data stored — the size is a cap, not a price`)
.option('--size <gi>', 'new size in whole Gi, e.g. 10 (must be ≥ the current size)')
- .option('--delete', 'destroy the volume and ALL its data (irreversible; back up first)')
</file context>
Implements superproject
docs/superpowers/specs/2026-09-17-cli-command-reorg-design.md(plan:docs/superpowers/plans/2026-09-17-cli-command-reorg.md, Tasks 1–8 and 17).What changes
Hard cutover, 32 → 24 top-level commands. Retired paths answer
unknown command(ortoo many argumentsfor the two groups that carry their own action):services scale|upgrade|set-access|secrets,compute set-domain|check-domain|remove-domain,db …, and top-levelmetrics|logs|usage|manifest|approvals|agent-policy|observe|events|mcp|regions|autoupdate|billing upgrade.services/svcstay as permanent aliases ofservice;envis hidden but unchanged;setup agentstays as a permanent hidden alias ofagent setup(identical options) becausenpx -y insta@latest setup agent …is the onboarding one-liner printed by the console, the landing page and third-party docs.New / moved surface (
insta --help):service(services,svc)addlistremoverenamedomainattach(bought and bring-your-own, one verb)checkdetach+searchbuyliststatusrecords …computescale <count> [service]logsmetrics; domain verbs leavepostgresurlconnectstatslimitsvolumealways-onlogsmetrics— every verb takes[service](wasdb … --group)redismysqlmongodbquerystatuslimitsvolumealways-onlogsmetrics(statusreads/projects/:id/runtime-health)storageset-access <public|private> --service <name>billingsubscribe(wasupgrade)portalusageagentsetupmanifestpolicy …approvals …observe …eventsconfiginstall-mcpregionsautoupdateEvery command accepts
--api-url <url>(runtime only; beatsINSTA_API_URL; a URL for another host runs logged-out).install.shkeeps callingsetup agent, which works on every release thanks to the alias (no probe). The developer skill gains the command-level rules;test/help-surface.test.tspins the visible surface.Platform facts relied on (checked at insta-platform 56b6482)
/services/:id/{limits,volume,always-on}accept managed databases (openapi.yamlsummaries);/services/:id/stateis compute-only (src/provisioning/services.tsstate), henceruntime-healthfor managed-DBstatus; the metrics/logs component enum has no storage (src/observability/service.tsCOMPONENT_ENUM_MSG).Review
Eight task-scoped reviews plus one whole-branch review; every Critical/Important finding fixed in-branch (notably:
billing upgradeno longer falls through to the overview;config autoupdatenever persists a--api-urloverride; spawn tests carry explicit timeouts for the Windows job).npm run typecheckclean;npm test185 files / 3449 tests green.Rollout — read before merging
Do not MERGE this PR yet. Its README documents
npx -y insta@latest agent setup, which fails on every published binary until the release exists (the console'ssetup agentline keeps working). Sequence (design §9): get this PR approved and hold it → prepare the skills / e2e / frontend (one policy-hint string) / mcp / platform-copy PRs → merge this PR, the0.1.0version-bump PR, and tag in one sitting → merge the downstream PRs minutes after the tag (skills first: agents fetch that text at setup time).🤖 Generated with Claude Code