@stigmer/cli 3.38.2 → 3.39.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.
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/commands/bootstrap.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQxD"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/commands/bootstrap.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQxD"}
@@ -7,9 +7,13 @@
7
7
  // one instead (`stigmer config context set --org`) and needs no bootstrap.
8
8
  //
9
9
  // Flagless on purpose: the act is idempotent, so there is nothing to force;
10
- // a second run changes nothing and says so. It never deletes anything.
10
+ // a second run changes nothing and says so. It never deletes anything. When
11
+ // the default organization was deleted, its slug is never reused and the
12
+ // backend cannot be made ready under it: the verb fails, naming how to
13
+ // choose another organization.
11
14
  // Heavy modules load lazily inside the action so `--help` stays fast.
12
15
  import { DEFAULT_LOCAL_ORG, ensureAuthenticated } from "../config/index.js";
16
+ import { CliExitError, ExitCode } from "../errors/index.js";
13
17
  import { CommandResult, renderResult } from "../output/index.js";
14
18
  import { addResultFlags, resultFormat } from "./shared.js";
15
19
  export function registerBootstrap(program) {
@@ -20,13 +24,16 @@ export function registerBootstrap(program) {
20
24
  addResultFlags(bootstrap);
21
25
  }
22
26
  async function runBootstrapCommand(flags) {
23
- const [{ connectBackend }, { bootstrapBackend }] = await Promise.all([
27
+ const [{ connectBackend }, { bootstrapBackend, RESERVED_DEFAULT_ORG_HINTS, RESERVED_DEFAULT_ORG_MESSAGE },] = await Promise.all([
24
28
  import("../backend.js"),
25
29
  import("../local/bootstrap.js"),
26
30
  ]);
27
31
  const client = connectBackend();
28
32
  ensureAuthenticated(client.config);
29
33
  const state = await bootstrapBackend(client.stigmer);
34
+ if (state === "reserved") {
35
+ throw new CliExitError(RESERVED_DEFAULT_ORG_MESSAGE, ExitCode.Usage, RESERVED_DEFAULT_ORG_HINTS);
36
+ }
30
37
  const out = CommandResult.success("Backend is ready");
31
38
  out.addSection("Organization").field("Slug", DEFAULT_LOCAL_ORG).field("State", state);
32
39
  renderResult(out, resultFormat(flags));
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/commands/bootstrap.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,uEAAuE;AACvE,4EAA4E;AAC5E,0EAA0E;AAC1E,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,sEAAsE;AAGtE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAoB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CACV,4FAA4F,CAC7F;SACA,MAAM,CAAC,CAAC,OAAoB,EAAE,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,cAAc,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,KAAkB;IACnD,MAAM,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnE,MAAM,CAAC,eAAe,CAAC;QACvB,MAAM,CAAC,uBAAuB,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtF,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/commands/bootstrap.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,uEAAuE;AACvE,4EAA4E;AAC5E,0EAA0E;AAC1E,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,yEAAyE;AACzE,uEAAuE;AACvE,+BAA+B;AAC/B,sEAAsE;AAGtE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAoB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CACV,4FAA4F,CAC7F;SACA,MAAM,CAAC,CAAC,OAAoB,EAAE,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,cAAc,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,KAAkB;IACnD,MAAM,CACJ,EAAE,cAAc,EAAE,EAClB,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,EAC/E,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpB,MAAM,CAAC,eAAe,CAAC;QACvB,MAAM,CAAC,uBAAuB,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,YAAY,CAAC,4BAA4B,EAAE,QAAQ,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;IACnG,CAAC;IAED,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtF,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -1,7 +1,11 @@
1
1
  import { type Stigmer } from "@stigmer/sdk";
2
2
  import type { BackendClient } from "../client/index.js";
3
3
  export type Say = (line: string) => void;
4
- export type BootstrapOutcome = "present" | "created";
4
+ export type BootstrapOutcome = "present" | "created" | "reserved";
5
+ /** What the CLI says when the default organization was deleted and its slug is reserved. */
6
+ export declare const RESERVED_DEFAULT_ORG_MESSAGE = "The 'stigmer' organization was deleted, and an organization's slug is never reused, so it cannot be created again.";
7
+ /** How to choose another organization, in the order the CLI resolves one (config/resolve.ts). */
8
+ export declare const RESERVED_DEFAULT_ORG_HINTS: readonly string[];
5
9
  /**
6
10
  * Make sure the organization the CLI falls back to exists on the backend
7
11
  * `stigmer` is bound to: what `stigmer bootstrap` runs. Idempotent; a lost
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/local/bootstrap.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsBlF;AAED,oHAAoH;AACpH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACnB,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACtE;AAMD,+FAA+F;AAC/F,wBAAsB,qBAAqB,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnF"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/local/bootstrap.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAkB,KAAK,OAAO,EAAgB,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAQlE,4FAA4F;AAC5F,eAAO,MAAM,4BAA4B,uHAAoI,CAAC;AAE9K,iGAAiG;AACjG,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAKvD,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAwBlF;AAED,oHAAoH;AACpH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACnB,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACtE;AAMD,+FAA+F;AAC/F,wBAAsB,qBAAqB,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBnF"}
@@ -13,6 +13,14 @@
13
13
  // other refusal propagates with the server's sentence; the caller decides
14
14
  // how loud to be.
15
15
  //
16
+ // One `already-exists` is not that race. An organization's slug is never
17
+ // reused, so once `stigmer` has been deleted no create can take it again,
18
+ // and the server says so with the ORGANIZATION_SLUG_RESERVED reason. That
19
+ // is `reserved`: the default organization is gone for good, and the person
20
+ // must name another (RESERVED_DEFAULT_ORG_HINTS says how). Reporting it as
21
+ // `present` would leave every command that falls back to `stigmer` failing
22
+ // with no explanation.
23
+ //
16
24
  // The create carries no label. Writing a label in the reserved `stigmer.ai/`
17
25
  // namespace needs a platform permission that a self-hosted server with
18
26
  // authentication on grants to nobody, and nothing reads one on an
@@ -28,9 +36,23 @@
28
36
  // client is pinned to a fresh local config (localhost:SERVER_PORT) with no
29
37
  // auth, the trusted-local identity.
30
38
  import { ManagementMode } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/enum_pb";
31
- import { StigmerError } from "@stigmer/sdk";
39
+ import { getErrorReason, StigmerError } from "@stigmer/sdk";
32
40
  import { DEFAULT_LOCAL_ORG } from "../config/resolve.js";
33
41
  import { log } from "../logger.js";
42
+ /**
43
+ * The refusal reason of a create whose slug a deleted organization held
44
+ * (OrganizationCommandController.create's contract): a slug is never reused.
45
+ */
46
+ const REASON_ORGANIZATION_SLUG_RESERVED = "ORGANIZATION_SLUG_RESERVED";
47
+ /** What the CLI says when the default organization was deleted and its slug is reserved. */
48
+ export const RESERVED_DEFAULT_ORG_MESSAGE = `The '${DEFAULT_LOCAL_ORG}' organization was deleted, and an organization's slug is never reused, so it cannot be created again.`;
49
+ /** How to choose another organization, in the order the CLI resolves one (config/resolve.ts). */
50
+ export const RESERVED_DEFAULT_ORG_HINTS = [
51
+ "Name the organization to use, in any of these ways:",
52
+ " --org <slug> on a command",
53
+ " STIGMER_ORG_ID=<slug> in the environment",
54
+ " stigmer config context set --org <slug>",
55
+ ];
34
56
  /**
35
57
  * Make sure the organization the CLI falls back to exists on the backend
36
58
  * `stigmer` is bound to: what `stigmer bootstrap` runs. Idempotent; a lost
@@ -55,7 +77,9 @@ export async function bootstrapBackend(stigmer) {
55
77
  }
56
78
  catch (error) {
57
79
  if (error instanceof StigmerError && error.code === "already-exists") {
58
- return "present";
80
+ return getErrorReason(error)?.reason === REASON_ORGANIZATION_SLUG_RESERVED
81
+ ? "reserved"
82
+ : "present";
59
83
  }
60
84
  throw error;
61
85
  }
@@ -79,6 +103,11 @@ export async function bootstrapLocalBackend(deps = {}) {
79
103
  log.debug("bootstrap complete", { org: outcome });
80
104
  if (outcome === "created")
81
105
  say(`Created the '${DEFAULT_LOCAL_ORG}' organization`);
106
+ if (outcome === "reserved") {
107
+ say(`Warning: ${RESERVED_DEFAULT_ORG_MESSAGE}`);
108
+ for (const hint of RESERVED_DEFAULT_ORG_HINTS)
109
+ say(hint);
110
+ }
82
111
  }
83
112
  async function freshLocalClient() {
84
113
  const [{ createBackendClient }, { getDefault }] = await Promise.all([
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/local/bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/local/bootstrap.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/cli",
3
- "version": "3.38.2",
3
+ "version": "3.39.0",
4
4
  "description": "Stigmer command-line interface — manage agents, workflows, MCP servers, skills, and executions from the terminal",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -35,12 +35,12 @@
35
35
  "@connectrpc/connect": "^2.0.0",
36
36
  "@connectrpc/connect-node": "^2.1.1",
37
37
  "@modelcontextprotocol/sdk": "^1.26.0",
38
- "@stigmer/ink": "3.38.2",
39
- "@stigmer/mcp-server": "3.38.2",
40
- "@stigmer/plugin-package": "3.38.2",
41
- "@stigmer/protos": "3.38.2",
42
- "@stigmer/sdk": "3.38.2",
43
- "@stigmer/zip-structure": "3.38.2",
38
+ "@stigmer/ink": "3.39.0",
39
+ "@stigmer/mcp-server": "3.39.0",
40
+ "@stigmer/plugin-package": "3.39.0",
41
+ "@stigmer/protos": "3.39.0",
42
+ "@stigmer/sdk": "3.39.0",
43
+ "@stigmer/zip-structure": "3.39.0",
44
44
  "commander": "^12.1.0",
45
45
  "fflate": "^0.8.3",
46
46
  "ink": "^7.0.0",
@@ -7,11 +7,15 @@
7
7
  // one instead (`stigmer config context set --org`) and needs no bootstrap.
8
8
  //
9
9
  // Flagless on purpose: the act is idempotent, so there is nothing to force;
10
- // a second run changes nothing and says so. It never deletes anything.
10
+ // a second run changes nothing and says so. It never deletes anything. When
11
+ // the default organization was deleted, its slug is never reused and the
12
+ // backend cannot be made ready under it: the verb fails, naming how to
13
+ // choose another organization.
11
14
  // Heavy modules load lazily inside the action so `--help` stays fast.
12
15
 
13
16
  import type { Command } from "commander";
14
17
  import { DEFAULT_LOCAL_ORG, ensureAuthenticated } from "../config/index.js";
18
+ import { CliExitError, ExitCode } from "../errors/index.js";
15
19
  import { CommandResult, type OutputFlags, renderResult } from "../output/index.js";
16
20
  import { addResultFlags, resultFormat } from "./shared.js";
17
21
 
@@ -26,7 +30,10 @@ export function registerBootstrap(program: Command): void {
26
30
  }
27
31
 
28
32
  async function runBootstrapCommand(flags: OutputFlags): Promise<void> {
29
- const [{ connectBackend }, { bootstrapBackend }] = await Promise.all([
33
+ const [
34
+ { connectBackend },
35
+ { bootstrapBackend, RESERVED_DEFAULT_ORG_HINTS, RESERVED_DEFAULT_ORG_MESSAGE },
36
+ ] = await Promise.all([
30
37
  import("../backend.js"),
31
38
  import("../local/bootstrap.js"),
32
39
  ]);
@@ -35,6 +42,9 @@ async function runBootstrapCommand(flags: OutputFlags): Promise<void> {
35
42
  ensureAuthenticated(client.config);
36
43
 
37
44
  const state = await bootstrapBackend(client.stigmer);
45
+ if (state === "reserved") {
46
+ throw new CliExitError(RESERVED_DEFAULT_ORG_MESSAGE, ExitCode.Usage, RESERVED_DEFAULT_ORG_HINTS);
47
+ }
38
48
 
39
49
  const out = CommandResult.success("Backend is ready");
40
50
  out.addSection("Organization").field("Slug", DEFAULT_LOCAL_ORG).field("State", state);
@@ -13,6 +13,14 @@
13
13
  // other refusal propagates with the server's sentence; the caller decides
14
14
  // how loud to be.
15
15
  //
16
+ // One `already-exists` is not that race. An organization's slug is never
17
+ // reused, so once `stigmer` has been deleted no create can take it again,
18
+ // and the server says so with the ORGANIZATION_SLUG_RESERVED reason. That
19
+ // is `reserved`: the default organization is gone for good, and the person
20
+ // must name another (RESERVED_DEFAULT_ORG_HINTS says how). Reporting it as
21
+ // `present` would leave every command that falls back to `stigmer` failing
22
+ // with no explanation.
23
+ //
16
24
  // The create carries no label. Writing a label in the reserved `stigmer.ai/`
17
25
  // namespace needs a platform permission that a self-hosted server with
18
26
  // authentication on grants to nobody, and nothing reads one on an
@@ -29,14 +37,31 @@
29
37
  // auth, the trusted-local identity.
30
38
 
31
39
  import { ManagementMode } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/enum_pb";
32
- import { type Stigmer, StigmerError } from "@stigmer/sdk";
40
+ import { getErrorReason, type Stigmer, StigmerError } from "@stigmer/sdk";
33
41
  import type { BackendClient } from "../client/index.js";
34
42
  import { DEFAULT_LOCAL_ORG } from "../config/resolve.js";
35
43
  import { log } from "../logger.js";
36
44
 
37
45
  export type Say = (line: string) => void;
38
46
 
39
- export type BootstrapOutcome = "present" | "created";
47
+ export type BootstrapOutcome = "present" | "created" | "reserved";
48
+
49
+ /**
50
+ * The refusal reason of a create whose slug a deleted organization held
51
+ * (OrganizationCommandController.create's contract): a slug is never reused.
52
+ */
53
+ const REASON_ORGANIZATION_SLUG_RESERVED = "ORGANIZATION_SLUG_RESERVED";
54
+
55
+ /** What the CLI says when the default organization was deleted and its slug is reserved. */
56
+ export const RESERVED_DEFAULT_ORG_MESSAGE = `The '${DEFAULT_LOCAL_ORG}' organization was deleted, and an organization's slug is never reused, so it cannot be created again.`;
57
+
58
+ /** How to choose another organization, in the order the CLI resolves one (config/resolve.ts). */
59
+ export const RESERVED_DEFAULT_ORG_HINTS: readonly string[] = [
60
+ "Name the organization to use, in any of these ways:",
61
+ " --org <slug> on a command",
62
+ " STIGMER_ORG_ID=<slug> in the environment",
63
+ " stigmer config context set --org <slug>",
64
+ ];
40
65
 
41
66
  /**
42
67
  * Make sure the organization the CLI falls back to exists on the backend
@@ -61,7 +86,9 @@ export async function bootstrapBackend(stigmer: Stigmer): Promise<BootstrapOutco
61
86
  return "created";
62
87
  } catch (error) {
63
88
  if (error instanceof StigmerError && error.code === "already-exists") {
64
- return "present";
89
+ return getErrorReason(error)?.reason === REASON_ORGANIZATION_SLUG_RESERVED
90
+ ? "reserved"
91
+ : "present";
65
92
  }
66
93
  throw error;
67
94
  }
@@ -93,6 +120,10 @@ export async function bootstrapLocalBackend(deps: BootstrapDeps = {}): Promise<v
93
120
  }
94
121
  log.debug("bootstrap complete", { org: outcome });
95
122
  if (outcome === "created") say(`Created the '${DEFAULT_LOCAL_ORG}' organization`);
123
+ if (outcome === "reserved") {
124
+ say(`Warning: ${RESERVED_DEFAULT_ORG_MESSAGE}`);
125
+ for (const hint of RESERVED_DEFAULT_ORG_HINTS) say(hint);
126
+ }
96
127
  }
97
128
 
98
129
  async function freshLocalClient(): Promise<BackendClient> {