@buildspacestudio/cli 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -122,7 +122,7 @@ Behavior:
122
122
 
123
123
  - `list` shows masked values
124
124
  - `set` creates or updates a variable, and uppercases the key automatically
125
- - `pull` writes system vars plus non-secret vars to a local env file
125
+ - `pull` writes non-secret vars plus the managed database credentials (`BUILDSPACE_DB_URL` and `BUILDSPACE_DB_TOKEN`) to a local env file
126
126
  - keys with the `BUILDSPACE_` prefix are reserved
127
127
  - `NEXT_PUBLIC_*` keys default to non-secret unless you override them
128
128
 
@@ -0,0 +1,2 @@
1
+ export declare function runAgentCommand(args: string[]): Promise<number>;
2
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAwTA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B/D"}
@@ -0,0 +1,285 @@
1
+ import { acceptHostedWorkspaceChanges, getHostedAgent, inspectHostedWorkspace, resetHostedWorkspace, setHostedAgentProviderKey, } from "../lib/api.js";
2
+ import { resolveAppContext } from "../lib/app.js";
3
+ import { hasFlag, readFlag } from "../lib/args.js";
4
+ import { resolveStoredAuth } from "../lib/auth.js";
5
+ import { openBrowser } from "../lib/browser.js";
6
+ import { trackEvent } from "../lib/telemetry.js";
7
+ const PROVIDERS = ["anthropic", "google", "openai", "openrouter"];
8
+ const PROVIDER_LABELS = {
9
+ anthropic: "Anthropic",
10
+ google: "Google Gemini",
11
+ openai: "OpenAI",
12
+ openrouter: "OpenRouter",
13
+ };
14
+ function printUsage() {
15
+ console.log("Usage: buildspace agent <subcommand> [options]");
16
+ console.log("");
17
+ console.log("Manage the hosted dev agent (OpenCode) attached to your app's dev workspace.");
18
+ console.log("");
19
+ console.log("Subcommands:");
20
+ console.log(" status Show the hosted agent URL, status, and provider");
21
+ console.log(" open Open the hosted agent workspace in your browser");
22
+ console.log(" inspect Show pending file changes in the workspace");
23
+ console.log(" accept Commit and push workspace changes to the tracked branch");
24
+ console.log(" reset Reset the workspace to match the tracked branch");
25
+ console.log(" key set Set the AI provider key the agent runs with");
26
+ console.log("");
27
+ console.log("Options:");
28
+ console.log(" --app <slug> App slug (default: git remote or active app)");
29
+ console.log(" --json Output as JSON (status, inspect only)");
30
+ console.log(" --no-open Print the URL instead of opening a browser (open only)");
31
+ console.log(" --message <text> Commit message for `accept` (default: auto-generated)");
32
+ console.log(" --provider <name> Provider for `key set`: anthropic, google, openai, openrouter");
33
+ console.log(" --key <value> Provider API key (omit to read from stdin)");
34
+ console.log("");
35
+ console.log("Examples:");
36
+ console.log(" buildspace agent status");
37
+ console.log(" buildspace agent open");
38
+ console.log(" buildspace agent inspect");
39
+ console.log(" buildspace agent accept --message 'Add auth flow'");
40
+ console.log(" buildspace agent reset");
41
+ console.log(" buildspace agent key set --provider anthropic --key sk-ant-...");
42
+ console.log(" cat key.txt | buildspace agent key set --provider openai");
43
+ }
44
+ const NOT_ENABLED_HINT = "Hosted dev agent is not enabled. Run `buildspace app hosting enable` to provision it.";
45
+ function resolveDevEnvId(context) {
46
+ return context.environments.find((env) => env.type === "dev")?.id ?? null;
47
+ }
48
+ function agentUrl(agent) {
49
+ return agent.url ?? (agent.domain ? `https://${agent.domain}` : null);
50
+ }
51
+ async function runStatus(args) {
52
+ const json = hasFlag(args, "--json");
53
+ const auth = await resolveStoredAuth();
54
+ try {
55
+ const context = await resolveAppContext(args, auth);
56
+ const agent = await getHostedAgent(context.app.id, auth);
57
+ if (json) {
58
+ console.log(JSON.stringify({ hostedAgent: agent }, null, 2));
59
+ return 0;
60
+ }
61
+ console.log(`App: ${context.app.name} (${context.app.slug})`);
62
+ if (!agent) {
63
+ console.log(NOT_ENABLED_HINT);
64
+ return 0;
65
+ }
66
+ console.log(` status: ${agent.status ?? "pending"}`);
67
+ console.log(` url: ${agentUrl(agent) ?? "pending"}`);
68
+ console.log(` branch: ${agent.trackedGitBranch ?? "buildspace/dev"}`);
69
+ console.log(` provider: ${agent.providerConfigured
70
+ ? `configured${agent.configuredProvider ? ` (${agent.configuredProvider})` : ""}`
71
+ : "not configured — run `buildspace agent key set`"}`);
72
+ return 0;
73
+ }
74
+ catch (error) {
75
+ const message = error instanceof Error ? error.message : "Failed to get agent status";
76
+ console.error(`Error: ${message}`);
77
+ return 1;
78
+ }
79
+ }
80
+ async function runOpen(args) {
81
+ const noOpen = hasFlag(args, "--no-open");
82
+ const auth = await resolveStoredAuth();
83
+ try {
84
+ const context = await resolveAppContext(args, auth);
85
+ const agent = await getHostedAgent(context.app.id, auth);
86
+ if (!agent) {
87
+ console.error(NOT_ENABLED_HINT);
88
+ return 1;
89
+ }
90
+ const url = agentUrl(agent);
91
+ if (!url) {
92
+ console.error("Agent URL is not ready yet. Check `buildspace agent status` and retry.");
93
+ return 1;
94
+ }
95
+ if (noOpen) {
96
+ console.log(url);
97
+ return 0;
98
+ }
99
+ const opened = await openBrowser(url);
100
+ trackEvent("cli.agent.opened");
101
+ if (opened) {
102
+ console.log(`Opening ${url}`);
103
+ }
104
+ else {
105
+ console.log("Could not open a browser automatically. Open this URL manually:");
106
+ console.log(` ${url}`);
107
+ }
108
+ return 0;
109
+ }
110
+ catch (error) {
111
+ const message = error instanceof Error ? error.message : "Failed to open agent";
112
+ console.error(`Error: ${message}`);
113
+ return 1;
114
+ }
115
+ }
116
+ function readStdin() {
117
+ return new Promise((resolve, reject) => {
118
+ let data = "";
119
+ process.stdin.setEncoding("utf8");
120
+ process.stdin.on("data", (chunk) => {
121
+ data += chunk;
122
+ });
123
+ process.stdin.on("end", () => resolve(data));
124
+ process.stdin.on("error", reject);
125
+ });
126
+ }
127
+ function isHostedAgentProvider(value) {
128
+ return PROVIDERS.includes(value);
129
+ }
130
+ async function runKeySet(args) {
131
+ const provider = readFlag(args, "--provider")?.trim().toLowerCase();
132
+ if (!provider) {
133
+ console.error("Missing required --provider.");
134
+ console.error(`Valid providers: ${PROVIDERS.join(", ")}`);
135
+ return 1;
136
+ }
137
+ if (!isHostedAgentProvider(provider)) {
138
+ console.error(`Invalid --provider '${provider}'. Valid providers: ${PROVIDERS.join(", ")}`);
139
+ return 1;
140
+ }
141
+ let apiKey = readFlag(args, "--key")?.trim();
142
+ if (!apiKey) {
143
+ if (process.stdin.isTTY) {
144
+ console.error("Missing API key. Pass --key <value> or pipe it via stdin.");
145
+ return 1;
146
+ }
147
+ apiKey = (await readStdin()).trim();
148
+ }
149
+ if (!apiKey) {
150
+ console.error("Provider API key is empty.");
151
+ return 1;
152
+ }
153
+ const auth = await resolveStoredAuth();
154
+ try {
155
+ const context = await resolveAppContext(args, auth);
156
+ const envId = resolveDevEnvId(context);
157
+ if (!envId) {
158
+ console.error(`No dev environment found for app '${context.app.slug}'.`);
159
+ return 1;
160
+ }
161
+ await setHostedAgentProviderKey({ appId: context.app.id, envId, provider, apiKey }, auth);
162
+ trackEvent("cli.agent.key_set");
163
+ console.log(`Saved ${PROVIDER_LABELS[provider]} key for ${context.app.slug}.`);
164
+ console.log("Restart the workspace for the agent to pick up the new key.");
165
+ return 0;
166
+ }
167
+ catch (error) {
168
+ const message = error instanceof Error ? error.message : "Failed to save agent key";
169
+ console.error(`Error: ${message}`);
170
+ return 1;
171
+ }
172
+ }
173
+ async function runInspect(args) {
174
+ const json = hasFlag(args, "--json");
175
+ const auth = await resolveStoredAuth();
176
+ try {
177
+ const context = await resolveAppContext(args, auth);
178
+ const status = await inspectHostedWorkspace(context.app.id, auth);
179
+ if (json) {
180
+ console.log(JSON.stringify({ status }, null, 2));
181
+ return 0;
182
+ }
183
+ console.log(`App: ${context.app.name} (${context.app.slug})`);
184
+ console.log(` branch: ${status.branch}`);
185
+ console.log(` clean: ${status.clean}`);
186
+ if (status.files.length === 0) {
187
+ console.log(" No pending changes.");
188
+ }
189
+ else {
190
+ console.log(` ${status.files.length} changed file(s):`);
191
+ for (const f of status.files) {
192
+ console.log(` ${f.status} ${f.path}`);
193
+ }
194
+ }
195
+ return 0;
196
+ }
197
+ catch (error) {
198
+ const message = error instanceof Error ? error.message : "Failed to inspect workspace";
199
+ console.error(`Error: ${message}`);
200
+ return 1;
201
+ }
202
+ }
203
+ async function runAccept(args) {
204
+ const commitMessage = readFlag(args, "--message")?.trim();
205
+ const auth = await resolveStoredAuth();
206
+ try {
207
+ const context = await resolveAppContext(args, auth);
208
+ const result = await acceptHostedWorkspaceChanges({ appId: context.app.id, commitMessage }, auth);
209
+ trackEvent("cli.agent.accept");
210
+ if (result.committed) {
211
+ console.log(`Accepted ${result.fileCount} file(s) on branch ${result.branch}.`);
212
+ console.log(` ${result.summary}`);
213
+ }
214
+ else {
215
+ console.log("No changes to accept — workspace is already clean.");
216
+ }
217
+ return 0;
218
+ }
219
+ catch (error) {
220
+ const message = error instanceof Error ? error.message : "Failed to accept workspace changes";
221
+ console.error(`Error: ${message}`);
222
+ return 1;
223
+ }
224
+ }
225
+ async function runReset(args) {
226
+ const auth = await resolveStoredAuth();
227
+ try {
228
+ const context = await resolveAppContext(args, auth);
229
+ const result = await resetHostedWorkspace(context.app.id, auth);
230
+ trackEvent("cli.agent.reset");
231
+ if (result.reset) {
232
+ console.log(`Workspace reset to branch ${result.branch}.`);
233
+ }
234
+ else {
235
+ console.log("Workspace was already clean — nothing to reset.");
236
+ }
237
+ return 0;
238
+ }
239
+ catch (error) {
240
+ const message = error instanceof Error ? error.message : "Failed to reset workspace";
241
+ console.error(`Error: ${message}`);
242
+ return 1;
243
+ }
244
+ }
245
+ function runKey(args) {
246
+ const subcommand = args[0];
247
+ if (!subcommand || hasFlag(args, "--help", "-h", "help")) {
248
+ console.log("Usage: buildspace agent key set --provider <name> [--key <value>]");
249
+ return Promise.resolve(subcommand ? 0 : 1);
250
+ }
251
+ switch (subcommand) {
252
+ case "set":
253
+ return runKeySet(args.slice(1));
254
+ default:
255
+ console.error(`Unknown agent key subcommand: ${subcommand}`);
256
+ console.log("Usage: buildspace agent key set --provider <name> [--key <value>]");
257
+ return Promise.resolve(1);
258
+ }
259
+ }
260
+ export function runAgentCommand(args) {
261
+ const subcommand = args[0];
262
+ if (!subcommand || hasFlag(args, "--help", "-h", "help")) {
263
+ printUsage();
264
+ return Promise.resolve(subcommand ? 0 : 1);
265
+ }
266
+ switch (subcommand) {
267
+ case "status":
268
+ return runStatus(args.slice(1));
269
+ case "open":
270
+ return runOpen(args.slice(1));
271
+ case "inspect":
272
+ return runInspect(args.slice(1));
273
+ case "accept":
274
+ return runAccept(args.slice(1));
275
+ case "reset":
276
+ return runReset(args.slice(1));
277
+ case "key":
278
+ return runKey(args.slice(1));
279
+ default:
280
+ console.error(`Unknown agent subcommand: ${subcommand}`);
281
+ printUsage();
282
+ return Promise.resolve(1);
283
+ }
284
+ }
285
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAuhBA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B7D"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAmqBA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B7D"}
@@ -1,4 +1,4 @@
1
- import { createApp, deleteApp, disableHosting, enableHosting, getHostingState, getProvisioningStatus, } from "../lib/api.js";
1
+ import { ApiError, createApp, deleteApp, disableHosting, enableHosting, getHostingState, getProvisioningStatus, } from "../lib/api.js";
2
2
  import { clearActiveApp, getActiveApp, listAppsWithActive, resolveAppContext, setActiveApp, validateAppForSelection, } from "../lib/app.js";
3
3
  import { hasFlag, readFlag } from "../lib/args.js";
4
4
  import { resolveStoredAuth } from "../lib/auth.js";
@@ -18,6 +18,7 @@ const ACTIVE_PROVISIONING_STATUSES = new Set(["pending", "running"]);
18
18
  const TERMINAL_PROVISIONING_STATUSES = new Set(["completed", "completed_with_warnings", "failed"]);
19
19
  const PROVISIONING_POLL_INTERVAL_MS = 1500;
20
20
  const PROVISIONING_WAIT_WINDOW_MS = 30_000;
21
+ const REPO_STEP_KEY = "repository";
21
22
  function printUsage() {
22
23
  console.log("Usage: buildspace app <subcommand> [options]");
23
24
  console.log("");
@@ -26,6 +27,7 @@ function printUsage() {
26
27
  console.log(" current Show the current resolved app");
27
28
  console.log(" use <slug> Set the active app");
28
29
  console.log(" create Create a new app");
30
+ console.log(" status [<slug>] Show hosting status for an app");
29
31
  console.log(" delete <slug> Soft-delete an app");
30
32
  console.log(" hosting <status|enable|disable> Manage hosting per environment");
31
33
  }
@@ -37,6 +39,8 @@ function printCreateUsage() {
37
39
  console.log(" --slug <slug> Optional app slug override");
38
40
  console.log(" --description <text> Optional description");
39
41
  console.log(" --category <value> Optional category");
42
+ console.log(" --json Output result as JSON and skip provisioning wait");
43
+ console.log(" --no-wait Skip provisioning wait entirely");
40
44
  }
41
45
  function printDeleteUsage() {
42
46
  console.log("Usage: buildspace app delete <slug> --confirm <slug> [--note <text>]");
@@ -95,31 +99,138 @@ function formatProvisioningLine(session) {
95
99
  const label = activeStep?.label ?? "Finalizing provisioning";
96
100
  return `${label} (${session.percent}%)`;
97
101
  }
98
- async function waitForProvisioning(sessionId, auth) {
99
- const startedAt = Date.now();
102
+ async function pollUntilRepoReady(sessionId, auth, deadlineMs) {
100
103
  let lastLine = null;
101
- let lastSession = null;
102
- while (Date.now() - startedAt <= PROVISIONING_WAIT_WINDOW_MS) {
103
- const result = await getProvisioningStatus(sessionId, auth);
104
- const { session } = result;
105
- lastSession = session;
104
+ while (Date.now() < deadlineMs) {
105
+ const { session } = await getProvisioningStatus(sessionId, auth);
106
106
  const line = formatProvisioningLine(session);
107
107
  if (line !== lastLine) {
108
108
  console.log(` ${line}`);
109
109
  lastLine = line;
110
110
  }
111
111
  if (TERMINAL_PROVISIONING_STATUSES.has(session.status)) {
112
- return session;
112
+ return { reachedTerminal: true, session };
113
113
  }
114
114
  if (!ACTIVE_PROVISIONING_STATUSES.has(session.status)) {
115
- return session;
115
+ return { reachedTerminal: false, session };
116
+ }
117
+ const repoStep = session.steps.find((s) => s.key === REPO_STEP_KEY);
118
+ if (repoStep?.status === "complete" || repoStep?.status === "warning") {
119
+ return { reachedTerminal: false, session };
120
+ }
121
+ await sleep(PROVISIONING_POLL_INTERVAL_MS);
122
+ }
123
+ // Deadline expired — do one final fetch to return current state
124
+ const { session } = await getProvisioningStatus(sessionId, auth);
125
+ return { reachedTerminal: TERMINAL_PROVISIONING_STATUSES.has(session.status), session };
126
+ }
127
+ async function pollUntilTerminal(sessionId, auth, deadlineMs) {
128
+ while (Date.now() < deadlineMs) {
129
+ const { session } = await getProvisioningStatus(sessionId, auth);
130
+ if (TERMINAL_PROVISIONING_STATUSES.has(session.status)) {
131
+ return { session, timedOut: false };
132
+ }
133
+ if (!ACTIVE_PROVISIONING_STATUSES.has(session.status)) {
134
+ return { session, timedOut: false };
116
135
  }
117
136
  await sleep(PROVISIONING_POLL_INTERVAL_MS);
118
137
  }
119
- if (!lastSession) {
120
- throw new Error("Provisioning started, but status could not be loaded");
138
+ const { session } = await getProvisioningStatus(sessionId, auth).catch(() => ({
139
+ session: null,
140
+ }));
141
+ return { session, timedOut: true };
142
+ }
143
+ function buildCreateAppInput(name, args) {
144
+ const slug = readFlag(args, "--slug")?.trim();
145
+ const description = readFlag(args, "--description")?.trim();
146
+ const category = readFlag(args, "--category")?.trim();
147
+ return {
148
+ name,
149
+ ...(slug ? { slug } : {}),
150
+ ...(description ? { description } : {}),
151
+ ...(category ? { category } : {}),
152
+ };
153
+ }
154
+ function writeJsonCommandError(error, fallback) {
155
+ const code = error instanceof ApiError ? error.code : "NETWORK_ERROR";
156
+ const message = error instanceof Error ? error.message : fallback;
157
+ process.stderr.write(`${JSON.stringify({ error: message, code })}\n`);
158
+ }
159
+ async function printCreateResultHuman(result, noWait, auth) {
160
+ console.log(`Created app ${result.app.name} (${result.app.slug})`);
161
+ console.log("Active app updated.");
162
+ if (result.keys.length > 0) {
163
+ console.log("");
164
+ console.log("Initial API keys:");
165
+ for (const key of result.keys) {
166
+ console.log(` ${key.environment}/${key.type}: ${key.key}`);
167
+ }
168
+ }
169
+ if (noWait) {
170
+ console.log("");
171
+ console.log("Provisioning is running in the background.");
172
+ console.log(`Run \`buildspace app status ${result.app.slug}\` to check progress.`);
173
+ }
174
+ else {
175
+ console.log("");
176
+ await waitAndPrintCreateProgress(result.provisioningSession.id, result.app.slug, auth);
177
+ }
178
+ console.log("");
179
+ console.log(" Run your coding agent of choice to build your app.");
180
+ console.log(" buildspace deploy # when you're ready to ship a dev deploy");
181
+ await maybeShowSkillsHint();
182
+ }
183
+ function printCreateNextSteps(slug) {
184
+ console.log("Next steps:");
185
+ console.log(` buildspace init --app ${slug} # clone repo and pull dev env vars`);
186
+ console.log(` cd ${slug}`);
187
+ console.log(" bun dev");
188
+ }
189
+ async function waitAndPrintCreateProgress(sessionId, slug, auth) {
190
+ console.log("Provisioning infrastructure...");
191
+ const deadline = Date.now() + PROVISIONING_WAIT_WINDOW_MS;
192
+ const phase1 = await pollUntilRepoReady(sessionId, auth, deadline);
193
+ if (phase1.reachedTerminal) {
194
+ printProvisioningFinalStatus(phase1.session);
195
+ console.log("");
196
+ printCreateNextSteps(slug);
197
+ return;
198
+ }
199
+ console.log("");
200
+ console.log("Repository ready.");
201
+ console.log("");
202
+ printCreateNextSteps(slug);
203
+ console.log("");
204
+ console.log("Hosting, database, and storage are finishing setup in the background (~30s).");
205
+ const phase2 = await pollUntilTerminal(sessionId, auth, deadline);
206
+ if (phase2.timedOut || !phase2.session) {
207
+ console.log(`Run \`buildspace app status ${slug}\` to check when setup is complete.`);
208
+ }
209
+ else {
210
+ printProvisioningFinalStatus(phase2.session);
211
+ }
212
+ }
213
+ function printProvisioningFinalStatus(session) {
214
+ if (session.status === "completed") {
215
+ console.log("Infrastructure setup complete.");
216
+ }
217
+ else if (session.status === "completed_with_warnings") {
218
+ console.log("Infrastructure setup complete with warnings.");
219
+ }
220
+ else if (session.status === "failed") {
221
+ console.log("Infrastructure setup failed.");
222
+ }
223
+ if (session.warnings.length > 0) {
224
+ console.log("");
225
+ console.log("Setup warnings:");
226
+ for (const warning of session.warnings) {
227
+ console.log(` - ${warning}`);
228
+ }
229
+ }
230
+ if (session.errorMessage) {
231
+ console.log("");
232
+ console.log(`Setup error: ${session.errorMessage}`);
121
233
  }
122
- return lastSession;
123
234
  }
124
235
  async function runList(args) {
125
236
  const json = hasFlag(args, "--json");
@@ -187,23 +298,21 @@ async function runCreate(args) {
187
298
  return 0;
188
299
  }
189
300
  const json = hasFlag(args, "--json");
301
+ const noWait = json || hasFlag(args, "--no-wait");
190
302
  const name = readFlag(args, "--name")?.trim();
191
- const slug = readFlag(args, "--slug")?.trim();
192
- const description = readFlag(args, "--description")?.trim();
193
- const category = readFlag(args, "--category")?.trim();
194
303
  if (!name) {
195
- console.error("Missing required --name.");
196
- printCreateUsage();
304
+ if (json) {
305
+ process.stderr.write(`${JSON.stringify({ error: "Missing required --name.", code: "VALIDATION_ERROR" })}\n`);
306
+ }
307
+ else {
308
+ console.error("Missing required --name.");
309
+ printCreateUsage();
310
+ }
197
311
  return 1;
198
312
  }
199
313
  const auth = await resolveStoredAuth();
200
314
  try {
201
- const result = await createApp({
202
- name,
203
- ...(slug ? { slug } : {}),
204
- ...(description ? { description } : {}),
205
- ...(category ? { category } : {}),
206
- }, auth);
315
+ const result = await createApp(buildCreateAppInput(name, args), auth);
207
316
  await setActiveApp(result.app);
208
317
  trackEvent("cli.app.created");
209
318
  if (json) {
@@ -211,62 +320,60 @@ async function runCreate(args) {
211
320
  app: { id: result.app.id, slug: result.app.slug, name: result.app.name },
212
321
  environments: result.environments,
213
322
  keys: result.keys,
323
+ provisioningSession: {
324
+ id: result.provisioningSession.id,
325
+ status: result.provisioningSession.status,
326
+ },
214
327
  }, null, 2));
215
328
  return 0;
216
329
  }
217
- console.log(`Created app ${result.app.name} (${result.app.slug})`);
218
- console.log("Active app updated.");
219
- if (result.keys.length > 0) {
220
- console.log("");
221
- console.log("Initial API keys:");
222
- for (const key of result.keys) {
223
- console.log(` ${key.environment}/${key.type}: ${key.key}`);
224
- }
225
- }
226
- console.log("");
227
- console.log("Provisioning infrastructure. This usually takes around 30 seconds.");
228
- const provisioningSession = await waitForProvisioning(result.provisioningSession.id, auth);
229
- if (provisioningSession.status === "completed") {
230
- console.log("Provisioning finished successfully.");
231
- }
232
- else if (provisioningSession.status === "completed_with_warnings") {
233
- console.log("Provisioning finished with warnings.");
234
- }
235
- else if (provisioningSession.status === "failed") {
236
- console.log("Provisioning failed.");
330
+ await printCreateResultHuman(result, noWait, auth);
331
+ return 0;
332
+ }
333
+ catch (error) {
334
+ if (json) {
335
+ writeJsonCommandError(error, "Failed to create app");
237
336
  }
238
337
  else {
239
- console.log("Provisioning is still running in the background.");
240
- console.log(`Check the dashboard or run \`buildspace app hosting status ${result.app.slug}\` in a moment for the latest state.`);
338
+ console.error(error instanceof Error ? error.message : "Failed to create app");
241
339
  }
242
- if (provisioningSession.warnings.length > 0) {
243
- console.log("");
244
- console.log("Setup warnings:");
245
- for (const warning of provisioningSession.warnings) {
246
- console.log(` - ${warning}`);
247
- }
248
- }
249
- if (provisioningSession.errorMessage) {
250
- console.log("");
251
- console.log(`Provisioning error: ${provisioningSession.errorMessage}`);
340
+ return 1;
341
+ }
342
+ }
343
+ function buildHostingEnvMap(hosting) {
344
+ const envMap = {};
345
+ for (const env of hosting.environments) {
346
+ const url = env.hosting?.managedDomain
347
+ ? `https://${env.hosting.managedDomain}`
348
+ : (env.hosting?.publicUrl ?? null);
349
+ envMap[env.envType] = { status: env.hosting?.status ?? "disabled", url };
350
+ }
351
+ return envMap;
352
+ }
353
+ async function runStatus(args) {
354
+ const json = hasFlag(args, "--json");
355
+ const auth = await resolveStoredAuth();
356
+ try {
357
+ const context = await resolveAppContext(normalizeAppArgs(args), auth);
358
+ const hosting = await getHostingState(context.app.id, auth);
359
+ if (json) {
360
+ const { app } = context;
361
+ console.log(JSON.stringify({
362
+ app: { id: app.id, slug: app.slug, name: app.name },
363
+ hosting: buildHostingEnvMap(hosting),
364
+ }, null, 2));
365
+ return 0;
252
366
  }
253
- console.log("");
254
- console.log("Next steps:");
255
- console.log(" To connect this app locally and get it running in your terminal:");
256
- console.log(` buildspace init --app ${result.app.slug} # clone, set up Bun, and pull dev env vars`);
257
- console.log(` cd ${result.app.slug}`);
258
- console.log(" bun dev # start local development");
259
- console.log("");
260
- console.log(" Run your coding agent of choice to build your app.");
261
- console.log("");
262
- console.log(" When you're ready to ship a dev deploy:");
263
- console.log(" buildspace deploy");
264
- await maybeShowSkillsHint();
367
+ printHostingStatus(hosting);
265
368
  return 0;
266
369
  }
267
370
  catch (error) {
268
- const message = error instanceof Error ? error.message : "Failed to create app";
269
- console.error(message);
371
+ if (json) {
372
+ writeJsonCommandError(error, "Failed to get status");
373
+ }
374
+ else {
375
+ console.error(error instanceof Error ? error.message : "Failed to get status");
376
+ }
270
377
  return 1;
271
378
  }
272
379
  }
@@ -417,6 +524,8 @@ export function runAppCommand(args) {
417
524
  return runUse(args.slice(1));
418
525
  case "create":
419
526
  return runCreate(args.slice(1));
527
+ case "status":
528
+ return runStatus(args.slice(1));
420
529
  case "delete":
421
530
  return runDelete(args.slice(1));
422
531
  case "hosting":