insta 0.0.36 → 0.0.37

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.
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ const envCmd = program.command('env').description('Show or switch the deployment
74
74
  envCmd.command('show', { isDefault: true }).description('Show the current environment and its hosts')
75
75
  .option('--json').action(guard((o) => envCmd_.envShow(o)));
76
76
  envCmd.command('use <name>').description(`Switch environment (${ENV_NAMES.join(' | ')}) — drops the stored session, which is deployment-specific`)
77
- .action(guard((name) => envCmd_.envUse(name)));
77
+ .option('--json').action(guard((name, o) => envCmd_.envUse(name, o)));
78
78
  // ---- run (per-request secret injection — nothing written to disk) ----
79
79
  program.command('run <cmd> [args...]').description('Run a command with the branch credential bundle injected into its environment (no .env written)')
80
80
  .option('--branch <b>', 'branch bundle to inject (default: linked branch)')
@@ -82,7 +82,7 @@ program.command('run <cmd> [args...]').description('Run a command with the branc
82
82
  .action(guard((cmd, args, o) => runCmd.run([cmd, ...(args ?? [])], o)));
83
83
  // ---- agent setup (the `curl … | sh --agents` target) ----
84
84
  const setupCmd = program.command('setup').description('Set up this machine for InstaCloud agent workflows');
85
- setupCmd.command('agent').description('Install the insta skill user-globally for all coding agents')
85
+ setupCmd.command('agent').description('Install the insta CLI (if missing), the insta skill for all coding agents, and the MCP server')
86
86
  .option('-y, --yes', 'non-interactive')
87
87
  .option('--mcp-token', 'register the MCP server with a minted insta_ API token instead of OAuth (headless machines / CI)')
88
88
  .action(guard((o) => setup.setupAgent(o)));
@@ -95,21 +95,21 @@ mcpCmd.command('install').description('Register the remote MCP server with codin
95
95
  // ---- org ----
96
96
  const orgCmd = program.command('org').description('Manage organizations');
97
97
  orgCmd.command('list').option('--json').action(guard((o) => org.orgList(o)));
98
- orgCmd.command('create <name>').action(guard((name) => org.orgCreate(name)));
98
+ orgCmd.command('create <name>').option('--json').action(guard((name, o) => org.orgCreate(name, o)));
99
99
  // ---- project ----
100
100
  const pj = program.command('project').description('Manage projects');
101
- pj.command('create [name]').option('--org <id>', 'org to create under (default: personal)').action(guard((name, o) => project.projectCreate(name, o)));
101
+ pj.command('create [name]').option('--org <id>', 'org to create under (default: personal)').option('--json').action(guard((name, o) => project.projectCreate(name, o)));
102
102
  pj.command('list').option('--org <id>').option('--json').action(guard((o) => project.projectList(o)));
103
- pj.command('link <id>').description('Link a project to this directory').action(guard((id) => project.projectLink(id)));
104
- pj.command('delete').option('--project <id>').action(guard((o) => project.projectDelete(o)));
103
+ pj.command('link <id>').description('Link a project to this directory').option('--json').action(guard((id, o) => project.projectLink(id, o)));
104
+ pj.command('delete').option('--project <id>').option('--json').action(guard((o) => project.projectDelete(o)));
105
105
  // ---- branch ----
106
106
  const br = program.command('branch').description('Manage branch environments');
107
- br.command('create <name>').option('--from <branch>', 'parent branch (default: current)').action(guard((name, o) => branch.branchCreate(name, o)));
107
+ br.command('create <name>').option('--from <branch>', 'parent branch (default: current)').option('--json').action(guard((name, o) => branch.branchCreate(name, o)));
108
108
  br.command('list').option('--json').action(guard((o) => branch.branchList(o)));
109
- br.command('switch <name>').action(guard((name) => branch.branchSwitch(name)));
110
- br.command('delete <name>').action(guard((name) => branch.branchDelete(name)));
109
+ br.command('switch <name>').option('--json').action(guard((name, o) => branch.branchSwitch(name, o)));
110
+ br.command('delete <name>').option('--json').action(guard((name, o) => branch.branchDelete(name, o)));
111
111
  br.command('merge <source>').description('Merge a branch service set into another (structural, no data)')
112
- .option('--into <branch>', 'target branch (default: current)').action(guard((source, o) => branch.branchMerge(source, o)));
112
+ .option('--into <branch>', 'target branch (default: current)').option('--json').action(guard((source, o) => branch.branchMerge(source, o)));
113
113
  // ---- services (opt-in postgres/storage/compute/redis/mysql/mongodb) ----
114
114
  const svc = program.command('services').alias('svc').description('Manage project services (postgres|storage|compute|redis|mysql|mongodb)');
115
115
  // [type] [name] are optional so the command can answer "what can I add?" — a terminal is walked
@@ -131,7 +131,7 @@ svc.command('add [type] [name]').description('Provision a service on demand (ass
131
131
  svc.command('list').option('--json').option('--branch <branch>', 'branch (default: current)')
132
132
  .action(guard((o) => services.servicesList(o)));
133
133
  svc.command('remove <type> <name>').description('Remove a service and destroy its resources')
134
- .option('--branch <branch>', 'branch (default: current)')
134
+ .option('--branch <branch>', 'branch (default: current)').option('--json')
135
135
  .action(guard((type, name, o) => services.servicesRemove(type, name, o)));
136
136
  svc.command('rename <type> <name> <new-name>').description('Rename a service and re-key its managed secret names')
137
137
  .option('--json').option('--branch <branch>', 'branch (default: current)')
@@ -151,9 +151,9 @@ const sec = program.command('secrets').description('Fetch the credential bundle
151
151
  sec.command('list').description('List secret names, grouped by service').option('--branch <branch>').option('--json').action(guard((o) => secretsCmd.secretsList(o)));
152
152
  sec.command('set <name> [value]').description('Set a user secret (project-wide; value from stdin if omitted)')
153
153
  .option('--branch <branch>', 'scope to one branch').option('--service <type/name>', 'bind to a branch service (implies current branch)')
154
- .action(guard((n, v, o) => secretsCmd.secretsSet(n, v, o)));
154
+ .option('--json').action(guard((n, v, o) => secretsCmd.secretsSet(n, v, o)));
155
155
  sec.command('unset <name>').description('Remove a user secret')
156
- .option('--branch <branch>', 'scope to one branch').action(guard((n, o) => secretsCmd.secretsUnset(n, o)));
156
+ .option('--branch <branch>', 'scope to one branch').option('--json').action(guard((n, o) => secretsCmd.secretsUnset(n, o)));
157
157
  sec.command('bind <env-name> <source>').description('Bind a service credential into a compute env var')
158
158
  .option('--branch <branch>', 'branch (default: current)')
159
159
  .option('--to <compute-service>', 'target compute service, e.g. compute/api')
@@ -186,6 +186,7 @@ program.command('build [dir]').description('Verify a source directory would buil
186
186
  program.command('deploy [dir]').description('Deploy a source directory (built remotely on Fly) or a prebuilt --image to a branch compute group')
187
187
  .option('--image <url>', 'prebuilt container image to deploy (instead of a source dir)').option('--branch <b>').option('--group <g>').option('--port <p>')
188
188
  .option('--websocket', 'run a WebSocket app (larger guest + connection-based concurrency)')
189
+ .option('--json', 'print the deploy result as JSON (build progress goes to stderr)')
189
190
  .action(guard((dir, o) => deploy(dir, o)));
190
191
  // `insta compute exec` needs the command verbatim after a literal `--`; split it out of argv here,
191
192
  // before commander parses anything (see splitExecArgs's own comment for why `service` being
@@ -198,7 +199,7 @@ compute.command('set-domain <host>').description('Attach a custom domain to a br
198
199
  compute.command('check-domain <host>').description("Show a custom domain's cert status + required DNS records")
199
200
  .option('--branch <b>').option('--group <g>').option('--json').action(guard((host, o) => computeCmd.checkDomain(host, o)));
200
201
  compute.command('remove-domain <host>').description('Detach a custom domain (gated: deploy)')
201
- .option('--branch <b>').option('--group <g>').action(guard((host, o) => computeCmd.removeDomain(host, o)));
202
+ .option('--branch <b>').option('--group <g>').option('--json').action(guard((host, o) => computeCmd.removeDomain(host, o)));
202
203
  compute.command('start [service]').description('Bring a compute service online (persistent — re-enables auto-wake)')
203
204
  .option('--json').option('--branch <branch>', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStart(service, o)));
204
205
  compute.command('stop [service]').description('Take a compute service offline; traffic will NOT wake it until `start`')
@@ -264,6 +265,9 @@ program.command('metrics <target> [group]').description('Service metrics (target
264
265
  .action(guard((target, group, o) => obs.metrics(target, group, o)));
265
266
  program.command('logs <target> [group]').description('Service logs (runtime by default; --deploy = machine lifecycle events; target: db|compute|redis|mysql|mongodb)')
266
267
  .option('--branch <b>').option('--limit <n>').option('--region <r>').option('--instance <i>').option('--deploy', 'show deploy events (machine lifecycle) instead of runtime logs — Fly-backed targets only, not db').option('--json')
268
+ .option('--from <t>', 'window start: unix seconds or ISO-8601 — pages history (~7-day retention); without a window one recent provider page (~100 lines) is returned')
269
+ .option('--to <t>', 'window end: unix seconds or ISO-8601 (default: now)')
270
+ .option('--since <dur>', 'relative window start, e.g. 90s, 30m, 2h, 1d (shorthand for --from now-dur)')
267
271
  .action(guard((target, group, o) => obs.logs(target, group, o)));
268
272
  program.command('usage').description('Usage for the current billing cycle by billing dimension (org by default; --proj for one project)')
269
273
  .option('--from <unix>').option('--to <unix>').option('--proj [id]', 'show one project (the linked one, or a given id) instead of the whole org').option('--json')
@@ -282,8 +286,8 @@ program.command('events').description('Show the audit + agent-event timeline').o
282
286
  // ---- approvals ----
283
287
  const ap = program.command('approvals').description('Governance approvals (HITL)');
284
288
  ap.command('list').option('--status <s>', 'pending|granted|denied|consumed').option('--json').action(guard((o) => govern.approvalsList(o)));
285
- ap.command('approve <id>').option('--always', 'also set the policy to allow').action(guard((id, o) => govern.approvalsApprove(id, o)));
286
- ap.command('deny <id>').action(guard((id) => govern.approvalsDeny(id)));
289
+ ap.command('approve <id>').option('--always', 'also set the policy to allow').option('--json').action(guard((id, o) => govern.approvalsApprove(id, o)));
290
+ ap.command('deny <id>').option('--json').action(guard((id, o) => govern.approvalsDeny(id, o)));
287
291
  // ---- observe (local credential audit) ----
288
292
  const ob = program.command('observe').description('Local credential-audit hook');
289
293
  ob.command('install').description('Install the PostToolUse hook into this project').action(guard(() => observe.observeInstall()));
@@ -293,7 +297,7 @@ ob.command('sync').description('Upload findings into the project timeline').acti
293
297
  // ---- policy ----
294
298
  const pol = program.command('policy').description('Governance policy');
295
299
  pol.command('get').option('--json').action(guard((o) => govern.policyGet(o)));
296
- pol.command('set <action> <decision>').description('action: secrets.read|secrets.write|deploy|project.delete|branch.delete|service.add|service.remove|service.scale|service.upgrade|service.setAccess|storage.read|storage.write|storage.delete; decision: allow|deny|approve').action(guard((a, d) => govern.policySet(a, d)));
300
+ pol.command('set <action> <decision>').description('action: secrets.read|secrets.write|deploy|project.delete|branch.delete|service.add|service.remove|service.scale|service.upgrade|service.setAccess|storage.read|storage.write|storage.delete; decision: allow|deny|approve').option('--json').action(guard((a, d, o) => govern.policySet(a, d, o)));
297
301
  // ---- feedback (agent + human hurdle reports → the InstaCloud team) ----
298
302
  program.command('feedback')
299
303
  .description('Report an InstaCloud-side hurdle (bug / missing feature / friction) to the InstaCloud team — about the insta toolkit itself, NEVER about the app you are building. Works logged-out and unlinked.')
package/dist/util.js CHANGED
@@ -26,10 +26,17 @@ export function info(msg) {
26
26
  process.stdout.write(msg + '\n');
27
27
  }
28
28
  // If the platform gated the action (HTTP 202), tell the user how to get it approved. Returns
29
- // true when an approval is pending (caller should stop).
30
- export function handleApproval(res) {
29
+ // true when an approval is pending (caller should stop). The hint goes to STDERR and the exit
30
+ // code is set to 2: a pending gate is not success (redirected stdout must never swallow it as
31
+ // output), and not a plain error either (die() owns 1) — it's approvable and re-runnable, and
32
+ // scripts/agents branch on the distinct code. With json, stdout carries the platform's raw 202
33
+ // envelope so a scripted caller can lift approvalId/action.
34
+ export function handleApproval(res, json) {
31
35
  if (res.status === 202 && res.body?.status === 'approval_required') {
32
- info(`approval required for ${res.body.action} — run: insta approvals approve ${res.body.approvalId}`);
36
+ if (json)
37
+ printJson(res.body);
38
+ process.stderr.write(`approval required for ${res.body.action} — run: insta approvals approve ${res.body.approvalId}\n`);
39
+ process.exitCode = 2;
33
40
  return true;
34
41
  }
35
42
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insta",
3
- "version": "0.0.36",
3
+ "version": "0.0.37",
4
4
  "type": "module",
5
5
  "description": "InstaCloud CLI — a thin client of the platform control-plane API.",
6
6
  "keywords": [