@keystrokehq/cli 0.0.132 → 0.0.133

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.mjs CHANGED
@@ -1852,6 +1852,8 @@ const OrganizationSlugSchema = string().trim().toLowerCase().min(2, "Slug must b
1852
1852
  * fail to load.
1853
1853
  */
1854
1854
  const ClaimableOrganizationSlugSchema = OrganizationSlugSchema.refine((slug) => !RESERVED_ORGANIZATION_SLUGS.has(slug), "This slug is reserved");
1855
+ /** Same format as organization slugs — org-scoped, no global reserved list. */
1856
+ const ProjectSlugSchema = OrganizationSlugSchema;
1855
1857
  /** Browser→platform request budget (ping + small platform overhead). */
1856
1858
  const PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS = 17e3;
1857
1859
  /** Normalize a public origin URL (no trailing slash). */
@@ -2053,6 +2055,17 @@ object({
2053
2055
  slug: string().trim().min(1),
2054
2056
  excludeOrganizationId: string().min(1).optional()
2055
2057
  });
2058
+ const ProjectSlugAvailabilityReasonSchema = _enum(["taken", "invalid"]);
2059
+ const ProjectSlugAvailabilityResponseSchema = object({
2060
+ slug: string(),
2061
+ available: boolean(),
2062
+ reason: ProjectSlugAvailabilityReasonSchema.optional(),
2063
+ suggestion: ProjectSlugSchema.optional()
2064
+ });
2065
+ object({
2066
+ slug: string().trim().min(1),
2067
+ excludeProjectId: string().min(1).optional()
2068
+ });
2056
2069
  const ProjectStatusSchema = _enum([
2057
2070
  "inactive",
2058
2071
  "starting",
@@ -2076,6 +2089,7 @@ const ProjectSchema = object({
2076
2089
  id: string(),
2077
2090
  organizationId: string(),
2078
2091
  name: string(),
2092
+ slug: ProjectSlugSchema,
2079
2093
  description: string().nullable(),
2080
2094
  status: ProjectStatusSchema,
2081
2095
  baseUrl: string().nullable(),
@@ -2116,8 +2130,9 @@ const CreateProjectRequestSchema = object({
2116
2130
  });
2117
2131
  const UpdateProjectRequestSchema = object({
2118
2132
  name: string().trim().min(1).optional(),
2119
- description: string().trim().optional()
2120
- }).refine((data) => data.name !== void 0 || data.description !== void 0, { message: "At least one field is required" });
2133
+ description: string().trim().optional(),
2134
+ slug: ProjectSlugSchema.optional()
2135
+ }).refine((data) => data.name !== void 0 || data.description !== void 0 || data.slug !== void 0, { message: "At least one field is required" });
2121
2136
  const CreateProjectResponseSchema = object({ project: ProjectSchema });
2122
2137
  const ProjectResponseSchema = object({ project: ProjectSchema });
2123
2138
  const ProjectReachabilityResponseSchema = object({ reachable: boolean() });
@@ -5174,6 +5189,16 @@ function createProjectsResource(http) {
5174
5189
  } catch (error) {
5175
5190
  throw await toPlatformError(error);
5176
5191
  }
5192
+ },
5193
+ async checkSlug(slug, options = {}) {
5194
+ const searchParams = new URLSearchParams({ slug });
5195
+ if (options.excludeProjectId) searchParams.set("excludeProjectId", options.excludeProjectId);
5196
+ try {
5197
+ const data = await http.get(`/api/projects/slug-available?${searchParams}`).json();
5198
+ return ProjectSlugAvailabilityResponseSchema.parse(data);
5199
+ } catch (error) {
5200
+ throw await toPlatformError(error);
5201
+ }
5177
5202
  }
5178
5203
  };
5179
5204
  }
@@ -8587,6 +8612,33 @@ function createCliPlatformClient(config) {
8587
8612
  });
8588
8613
  }
8589
8614
  //#endregion
8615
+ //#region src/resolve-resource-ref.ts
8616
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8617
+ function looksLikeUuid(value) {
8618
+ return UUID_PATTERN.test(value);
8619
+ }
8620
+ function formatProjectLabel(project) {
8621
+ return project.slug;
8622
+ }
8623
+ async function resolveProjectRef(platform, ref) {
8624
+ if (looksLikeUuid(ref)) try {
8625
+ return await platform.projects.get(ref);
8626
+ } catch (error) {
8627
+ if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${ref} not found in the active organization. Run \`keystroke project list\`, then \`keystroke config use project <slug>\`.`);
8628
+ throw error;
8629
+ }
8630
+ const match = (await platform.projects.list()).find((project) => project.slug === ref);
8631
+ if (!match) throw new Error(`Project "${ref}" not found in the active organization. Run \`keystroke project list\`.`);
8632
+ return match;
8633
+ }
8634
+ function resolveOrganizationRef(organizations, ref) {
8635
+ const byId = organizations.find((entry) => entry.organization.id === ref);
8636
+ if (byId) return byId;
8637
+ const bySlug = organizations.find((entry) => entry.organization.slug === ref);
8638
+ if (bySlug) return bySlug;
8639
+ throw new Error(`Organization "${ref}" was not found or you do not have access`);
8640
+ }
8641
+ //#endregion
8590
8642
  //#region src/organization/active-organization.ts
8591
8643
  function formatOrganization(membership) {
8592
8644
  return `${membership.organization.name} (${membership.role})`;
@@ -8600,15 +8652,11 @@ async function activateOrganization(config, organizationId) {
8600
8652
  platform.setActiveOrganizationId(membership.organization.id);
8601
8653
  return membership;
8602
8654
  }
8603
- async function pickOrganization(config, organizations, organizationId) {
8604
- if (organizationId) {
8605
- const membership = organizations.find((entry) => entry.organization.id === organizationId);
8606
- if (!membership) throw new Error(`Organization ${organizationId} was not found or you do not have access`);
8607
- return activateOrganization(config, membership.organization.id);
8608
- }
8655
+ async function pickOrganization(config, organizations, organizationRef) {
8656
+ if (organizationRef) return activateOrganization(config, resolveOrganizationRef(organizations, organizationRef).organization.id);
8609
8657
  if (!process.stdin.isTTY) {
8610
- const names = organizations.map((entry) => entry.organization.id).join(", ");
8611
- throw new Error(`Multiple organizations found. Run \`keystroke config use org <id>\`. Options: ${names}`);
8658
+ const names = organizations.map((entry) => entry.organization.slug).join(", ");
8659
+ throw new Error(`Multiple organizations found. Run \`keystroke config use org <slug>\`. Options: ${names}`);
8612
8660
  }
8613
8661
  return activateOrganization(config, await select({
8614
8662
  message: "Select an organization",
@@ -8622,7 +8670,7 @@ async function selectActiveOrganization(config, options = {}) {
8622
8670
  const organizations = await listOrganizations(config);
8623
8671
  if (organizations.length === 0) throw new Error(`No organization found — create one at ${getWebUrl(config)}`);
8624
8672
  if (organizations.length === 1) return activateOrganization(config, organizations[0].organization.id);
8625
- return pickOrganization(config, organizations, options.organizationId);
8673
+ return pickOrganization(config, organizations, options.organizationRef ?? options.organizationId);
8626
8674
  }
8627
8675
  async function syncActiveOrganizationAfterLogin(config, options = {}) {
8628
8676
  const organizations = await listOrganizations(config);
@@ -8638,8 +8686,8 @@ async function syncActiveOrganizationAfterLogin(config, options = {}) {
8638
8686
  process.stdout.write(`Using organization ${membership.organization.name}\n`);
8639
8687
  return membership;
8640
8688
  }
8641
- if (options.organizationId) {
8642
- const membership = await pickOrganization(config, organizations, options.organizationId);
8689
+ if (options.organizationRef ?? options.organizationId) {
8690
+ const membership = await pickOrganization(config, organizations, options.organizationRef ?? options.organizationId);
8643
8691
  process.stdout.write(`Using organization ${membership.organization.name}\n`);
8644
8692
  return membership;
8645
8693
  }
@@ -8712,19 +8760,19 @@ function resolveOrgPlatformTarget(config) {
8712
8760
  mode: "platform"
8713
8761
  };
8714
8762
  }
8715
- async function resolvePlatformTarget(config, projectId) {
8763
+ async function resolvePlatformTarget(config, projectRef) {
8716
8764
  const platform = createCliPlatformClient(config);
8717
8765
  let project;
8718
8766
  try {
8719
- project = await platform.projects.get(projectId);
8767
+ project = await resolveProjectRef(platform, projectRef);
8720
8768
  } catch (error) {
8721
- if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${projectId} not found in the active organization. Run \`keystroke config use project <id>\` or pass \`--project\` with a valid project id.`);
8769
+ if (error instanceof Error) throw error;
8722
8770
  throw error;
8723
8771
  }
8724
- if (project.status !== "active") throw new Error(`Project ${projectId} is not active (${project.status})`);
8772
+ if (project.status !== "active") throw new Error(`Project ${formatProjectLabel(project)} is not active (${project.status})`);
8725
8773
  return {
8726
- baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api/projects/${encodeURIComponent(projectId)}`,
8727
- projectId,
8774
+ baseUrl: `${getPlatformUrl(config).replace(/\/+$/, "")}/api/projects/${encodeURIComponent(project.id)}`,
8775
+ projectId: project.id,
8728
8776
  mode: "platform"
8729
8777
  };
8730
8778
  }
@@ -8742,9 +8790,9 @@ async function resolveApiTarget(config, options = {}) {
8742
8790
  if (options.projectId) return resolvePlatformTarget(config, options.projectId);
8743
8791
  if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(config);
8744
8792
  if (!options.projectScoped) return resolveOrgPlatformTarget(config);
8745
- const projectId = options.projectId ?? config.get("activeProjectId");
8746
- if (!projectId) throw new Error("No project selected. Pass `--project <id>` or run `keystroke config use project <id>`.");
8747
- return resolvePlatformTarget(config, projectId);
8793
+ const projectRef = options.projectId ?? config.get("activeProjectId");
8794
+ if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke config use project <slug>`.");
8795
+ return resolvePlatformTarget(config, projectRef);
8748
8796
  }
8749
8797
  //#endregion
8750
8798
  //#region src/target-options.ts
@@ -8755,9 +8803,6 @@ function setCliTargetOptions(options) {
8755
8803
  function getCliTargetOptions() {
8756
8804
  return targetOptions;
8757
8805
  }
8758
- function resolveActiveProjectId(config) {
8759
- return getCliTargetOptions().projectId ?? config.get("activeProjectId");
8760
- }
8761
8806
  //#endregion
8762
8807
  //#region src/errors/example-input.ts
8763
8808
  function exampleValueFromValidationMessage(message) {
@@ -9232,7 +9277,7 @@ function resolveAuthLoginTargets(options, config) {
9232
9277
  //#endregion
9233
9278
  //#region src/commands/auth/login.ts
9234
9279
  function registerAuthLoginCommand(auth) {
9235
- auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <id>", "Active organization id (skips prompt when you belong to several)").action(async (options) => {
9280
+ auth.command("login").description("Authenticate via browser device flow").option("--web-url <url>", "Web dashboard origin (omit to use production defaults; local dev: http://localhost:3000)").option("--platform-url <url>", "Platform API origin (derived from web URL when omitted)").option("--org <slug>", "Active organization slug (skips prompt when you belong to several)").action(async (options) => {
9236
9281
  const config = createCliConfig();
9237
9282
  const { webUrl, platformUrl } = resolveAuthLoginTargets(options, config);
9238
9283
  config.set("webUrl", webUrl);
@@ -9247,7 +9292,7 @@ function registerAuthLoginCommand(auth) {
9247
9292
  const user = await getSessionWithBearer(platformUrl, result.accessToken);
9248
9293
  if (user) process.stdout.write(`Logged in as ${user.name} (${user.email})\n`);
9249
9294
  else process.stdout.write(`Logged in to ${webUrl}\n`);
9250
- await syncActiveOrganizationAfterLogin(config, { organizationId: options.org });
9295
+ await syncActiveOrganizationAfterLogin(config, { organizationRef: options.org });
9251
9296
  } catch (error) {
9252
9297
  process.stderr.write(`${formatCliError(error, "Login failed", {
9253
9298
  webUrl,
@@ -9467,6 +9512,18 @@ function collectProjectSource(root) {
9467
9512
  };
9468
9513
  }
9469
9514
  //#endregion
9515
+ //#region src/resolve-project-target.ts
9516
+ async function resolveActiveProject(config, platform) {
9517
+ const ref = getCliTargetOptions().projectId ?? config.get("activeProjectId");
9518
+ if (!ref) return;
9519
+ const client = platform ?? createCliPlatformClient(config);
9520
+ if (!getCliTargetOptions().projectId && looksLikeUuid(ref)) return resolveProjectRef(client, ref);
9521
+ return resolveProjectRef(client, ref);
9522
+ }
9523
+ async function resolveActiveProjectId(config) {
9524
+ return (await resolveActiveProject(config))?.id;
9525
+ }
9526
+ //#endregion
9470
9527
  //#region src/commands/deploy.ts
9471
9528
  const POLL_INTERVAL_MS = 2e3;
9472
9529
  const DEPLOY_TIMEOUT_MS = 12e4;
@@ -9557,8 +9614,8 @@ async function runDeploy(options) {
9557
9614
  function registerDeployCommand(program) {
9558
9615
  program.command("deploy").description("Build, upload, and deploy the project to the platform").option("--dir <path>", "Project directory", process.cwd()).option("--skip-build", "Upload the existing dist/ without rebuilding").action(async (options) => {
9559
9616
  try {
9560
- const projectId = resolveActiveProjectId(createCliConfig());
9561
- if (!projectId) throw new Error("Usage: keystroke deploy --project <id>");
9617
+ const projectId = await resolveActiveProjectId(createCliConfig());
9618
+ if (!projectId) throw new Error("Usage: keystroke deploy --project <slug>");
9562
9619
  await runDeploy({
9563
9620
  dir: options.dir,
9564
9621
  projectId,
@@ -10118,7 +10175,7 @@ function writeInactiveDeployHints(projects) {
10118
10175
  const bin = cliBinaryName();
10119
10176
  for (const project of projects) {
10120
10177
  if (project.status !== "inactive") continue;
10121
- process.stderr.write(`Project ${project.id} is inactive. Deploy with: ${bin} deploy --project ${project.id}\n`);
10178
+ process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} deploy --project ${formatProjectLabel(project)}\n`);
10122
10179
  }
10123
10180
  }
10124
10181
  async function runProjectList(config) {
@@ -10136,13 +10193,19 @@ async function runProjectList(config) {
10136
10193
  async function runProjectMetrics(config, options) {
10137
10194
  await withActivePlatformClient(config, async (platform) => {
10138
10195
  const metrics = await platform.projectMetrics.list();
10139
- const output = options.projectId === void 0 ? metrics : Object.fromEntries(Object.entries(metrics).filter(([projectId]) => projectId === options.projectId));
10196
+ if (options.projectRef === void 0) {
10197
+ process.stdout.write(`${JSON.stringify(metrics, null, 2)}\n`);
10198
+ return;
10199
+ }
10200
+ const project = await resolveProjectRef(platform, options.projectRef);
10201
+ const output = Object.fromEntries(Object.entries(metrics).filter(([projectId]) => projectId === project.id));
10140
10202
  process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
10141
10203
  });
10142
10204
  }
10143
10205
  async function runProjectDeploymentsList(config, options) {
10144
10206
  await withActivePlatformClient(config, async (platform) => {
10145
- const deployments = await platform.deployments.listForProject(options.projectId);
10207
+ const project = await resolveProjectRef(platform, options.projectRef);
10208
+ const deployments = await platform.deployments.listForProject(project.id);
10146
10209
  process.stdout.write(`${JSON.stringify({ deployments }, null, 2)}\n`);
10147
10210
  });
10148
10211
  }
@@ -10206,10 +10269,10 @@ function registerProjectCommand(program) {
10206
10269
  process.exitCode = 1;
10207
10270
  }
10208
10271
  });
10209
- project.command("metrics").description("List rollup metrics for projects in the active organization").option("--project <id>", "Return metrics for a single project").action(async (options) => {
10272
+ project.command("metrics").description("List rollup metrics for projects in the active organization").option("--project <slug>", "Return metrics for a single project").action(async (options) => {
10210
10273
  const config = createCliConfig();
10211
10274
  try {
10212
- await runProjectMetrics(config, { ...options.project ? { projectId: options.project } : {} });
10275
+ await runProjectMetrics(config, { ...options.project ? { projectRef: options.project } : {} });
10213
10276
  } catch (error) {
10214
10277
  process.stderr.write(`${formatCliError(error, "List project metrics failed", {
10215
10278
  serverUrl: getPlatformUrl(config),
@@ -10218,12 +10281,12 @@ function registerProjectCommand(program) {
10218
10281
  process.exitCode = 1;
10219
10282
  }
10220
10283
  });
10221
- project.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").option("--project <id>", "Project ID").action(async (options) => {
10284
+ project.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").option("--project <slug>", "Project slug").action(async (options) => {
10222
10285
  const config = createCliConfig();
10223
10286
  try {
10224
- const projectId = options.project ?? resolveActiveProjectId(config);
10225
- if (!projectId) throw new Error("Usage: keystroke project deployments list --project <id>");
10226
- await runProjectDeploymentsList(config, { projectId });
10287
+ const projectRef = options.project ?? getCliTargetOptions().projectId ?? config.get("activeProjectId");
10288
+ if (!projectRef) throw new Error("Usage: keystroke project deployments list --project <slug>");
10289
+ await runProjectDeploymentsList(config, { projectRef });
10227
10290
  } catch (error) {
10228
10291
  process.stderr.write(`${formatCliError(error, "List deployments failed", {
10229
10292
  serverUrl: getPlatformUrl(config),
@@ -10250,8 +10313,8 @@ function registerProjectCommand(program) {
10250
10313
  project.command("update").description("Update a platform project's name and/or description").option("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
10251
10314
  const config = createCliConfig();
10252
10315
  try {
10253
- const projectId = resolveActiveProjectId(config);
10254
- if (!projectId) throw new Error("Usage: keystroke --project <id> project update --name <name>");
10316
+ const projectId = await resolveActiveProjectId(config);
10317
+ if (!projectId) throw new Error("Usage: keystroke --project <slug> project update --name <name>");
10255
10318
  if (!options.name && options.description === void 0) throw new Error("At least one of --name or --description is required");
10256
10319
  await runProjectUpdate(config, {
10257
10320
  projectId,
@@ -10269,8 +10332,8 @@ function registerProjectCommand(program) {
10269
10332
  project.command("delete").description("Delete a platform project").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
10270
10333
  const config = createCliConfig();
10271
10334
  try {
10272
- const projectId = resolveActiveProjectId(config);
10273
- if (!projectId) throw new Error("Usage: keystroke --project <id> project delete");
10335
+ const projectId = await resolveActiveProjectId(config);
10336
+ if (!projectId) throw new Error("Usage: keystroke --project <slug> project delete");
10274
10337
  if (!options.yes) throw new Error("Pass --yes to confirm project deletion");
10275
10338
  await runProjectDelete(config, projectId);
10276
10339
  } catch (error) {
@@ -10431,27 +10494,23 @@ function registerWorkflowCommand(program) {
10431
10494
  }
10432
10495
  //#endregion
10433
10496
  //#region src/commands/config/use-project.ts
10434
- async function fetchProjectInOrg(config, projectId) {
10435
- const platform = createCliPlatformClient(config);
10436
- try {
10437
- return await platform.projects.get(projectId);
10438
- } catch (error) {
10439
- if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${projectId} not found in the active organization. Run \`keystroke project list\`, then \`keystroke config use project <id>\`.`);
10440
- throw error;
10441
- }
10497
+ async function fetchProjectInOrg(config, projectRef) {
10498
+ return resolveProjectRef(createCliPlatformClient(config), projectRef);
10442
10499
  }
10443
10500
  function assertProjectReadyForConfig(project) {
10444
- if (project.status === "failed") throw new Error(project.lastError ? `Project ${project.id} deploy failed: ${project.lastError}` : `Project ${project.id} deploy failed`);
10445
- if (project.status === "starting") throw new Error(`Project ${project.id} is still starting. Wait for deploy to finish, then run \`keystroke config use project ${project.id}\`.`);
10501
+ const label = formatProjectLabel(project);
10502
+ if (project.status === "failed") throw new Error(project.lastError ? `Project ${label} deploy failed: ${project.lastError}` : `Project ${label} deploy failed`);
10503
+ if (project.status === "starting") throw new Error(`Project ${label} is still starting. Wait for deploy to finish, then run \`keystroke config use project ${label}\`.`);
10446
10504
  }
10447
- async function runConfigUseProject(config, projectId) {
10448
- const project = await fetchProjectInOrg(config, projectId);
10505
+ async function runConfigUseProject(config, projectRef) {
10506
+ const project = await fetchProjectInOrg(config, projectRef);
10449
10507
  assertProjectReadyForConfig(project);
10450
- config.set("activeProjectId", projectId);
10508
+ config.set("activeProjectId", project.id);
10451
10509
  config.set("apiTarget", "platform");
10510
+ const label = formatProjectLabel(project);
10452
10511
  return {
10453
- stdout: project.status === "active" ? `Using platform project ${projectId}\n` : `Using platform project ${projectId} (${project.status})\n`,
10454
- stderr: project.status === "inactive" ? `Project is not active yet. Deploy with: ${cliBinaryName()} deploy --project ${projectId}\n` : void 0
10512
+ stdout: project.status === "active" ? `Using platform project ${label}\n` : `Using platform project ${label} (${project.status})\n`,
10513
+ stderr: project.status === "inactive" ? `Project is not active yet. Deploy with: ${cliBinaryName()} deploy --project ${label}\n` : void 0
10455
10514
  };
10456
10515
  }
10457
10516
  //#endregion
@@ -10480,7 +10539,7 @@ function registerConfigCommand(program) {
10480
10539
  return;
10481
10540
  }
10482
10541
  if (mode === "org") {
10483
- const membership = await selectActiveOrganization(cliConfig, { organizationId: id });
10542
+ const membership = await selectActiveOrganization(cliConfig, { organizationRef: id });
10484
10543
  process.stdout.write(`Using organization ${membership.organization.name}\n`);
10485
10544
  return;
10486
10545
  }
@@ -10490,9 +10549,9 @@ function registerConfigCommand(program) {
10490
10549
  process.stdout.write(activeProjectId ? `Using platform API (default project ${activeProjectId} for project-scoped commands)\n` : "Using platform API\n");
10491
10550
  return;
10492
10551
  }
10493
- if (mode !== "project") throw new Error("Usage: keystroke config use [local|cloud|project [projectId]|org [organizationId]]");
10552
+ if (mode !== "project") throw new Error("Usage: keystroke config use [local|cloud|project [slug]|org [slug]]");
10494
10553
  const targetProjectId = id ?? cliConfig.get("activeProjectId");
10495
- if (!targetProjectId) throw new Error("Usage: keystroke config use project <projectId>");
10554
+ if (!targetProjectId) throw new Error("Usage: keystroke config use project <slug>");
10496
10555
  const result = await runConfigUseProject(cliConfig, targetProjectId);
10497
10556
  process.stdout.write(result.stdout);
10498
10557
  if (result.stderr) process.stderr.write(result.stderr);
@@ -10566,7 +10625,7 @@ async function syncSkills(command) {
10566
10625
  //#endregion
10567
10626
  //#region src/program.ts
10568
10627
  function createProgram() {
10569
- const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <id>", "Platform project id (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
10628
+ const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <slug>", "Platform project slug (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
10570
10629
  const opts = thisCommand.opts();
10571
10630
  setCliTargetOptions({
10572
10631
  projectId: opts.project,